mirror of
https://github.com/makayabou/asg-server.git
synced 2026-05-02 17:43:36 +02:00
160 lines
3.4 KiB
Go
160 lines
3.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/android-sms-gateway/server/internal/sms-gateway/models"
|
|
"github.com/android-sms-gateway/server/internal/sms-gateway/modules/devices"
|
|
"github.com/android-sms-gateway/server/pkg/crypto"
|
|
"github.com/android-sms-gateway/server/pkg/types/cache"
|
|
"github.com/jaevor/go-nanoid"
|
|
"go.uber.org/fx"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type Config struct {
|
|
Mode Mode
|
|
PrivateToken string
|
|
}
|
|
|
|
type Params struct {
|
|
fx.In
|
|
|
|
Config Config
|
|
|
|
Users *repository
|
|
DevicesSvc *devices.Service
|
|
|
|
Logger *zap.Logger
|
|
}
|
|
|
|
type Service struct {
|
|
config Config
|
|
|
|
users *repository
|
|
usersCache *cache.Cache[models.User]
|
|
|
|
devicesSvc *devices.Service
|
|
devicesCache *cache.Cache[models.Device]
|
|
|
|
logger *zap.Logger
|
|
|
|
idgen func() string
|
|
}
|
|
|
|
func New(params Params) *Service {
|
|
idgen, _ := nanoid.Standard(21)
|
|
|
|
return &Service{
|
|
config: params.Config,
|
|
users: params.Users,
|
|
devicesSvc: params.DevicesSvc,
|
|
logger: params.Logger.Named("Service"),
|
|
idgen: idgen,
|
|
|
|
usersCache: cache.New[models.User](cache.Config{TTL: 1 * time.Hour}),
|
|
devicesCache: cache.New[models.Device](cache.Config{TTL: 10 * time.Minute}),
|
|
}
|
|
}
|
|
|
|
func (s *Service) RegisterUser(login, password string) (models.User, error) {
|
|
user := models.User{
|
|
ID: login,
|
|
}
|
|
|
|
var err error
|
|
if user.PasswordHash, err = crypto.MakeBCryptHash(password); err != nil {
|
|
return user, fmt.Errorf("can't hash password: %w", err)
|
|
}
|
|
|
|
if err = s.users.Insert(&user); err != nil {
|
|
return user, fmt.Errorf("can't create user")
|
|
}
|
|
|
|
return user, nil
|
|
}
|
|
|
|
func (s *Service) RegisterDevice(user models.User, name, pushToken *string) (models.Device, error) {
|
|
device := models.Device{
|
|
Name: name,
|
|
PushToken: pushToken,
|
|
}
|
|
|
|
return device, s.devicesSvc.Insert(user, &device)
|
|
}
|
|
|
|
func (s *Service) UpdateDevice(id, pushToken string) error {
|
|
return s.devicesSvc.UpdateToken(id, pushToken)
|
|
}
|
|
|
|
func (s *Service) IsPublic() bool {
|
|
return s.config.Mode == ModePublic
|
|
}
|
|
|
|
func (s *Service) AuthorizeRegistration(token string) error {
|
|
if s.IsPublic() {
|
|
return nil
|
|
}
|
|
|
|
if token == s.config.PrivateToken {
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("invalid token")
|
|
}
|
|
|
|
func (s *Service) AuthorizeDevice(token string) (models.Device, error) {
|
|
hash := sha256.Sum256([]byte(token))
|
|
cacheKey := hex.EncodeToString(hash[:])
|
|
|
|
device, err := s.devicesCache.Get(cacheKey)
|
|
if err != nil {
|
|
device, err = s.devicesSvc.Get(devices.WithToken(token))
|
|
if err != nil {
|
|
return device, fmt.Errorf("can't get device: %w", err)
|
|
}
|
|
|
|
if err := s.devicesCache.Set(cacheKey, device); err != nil {
|
|
s.logger.Error("can't cache device", zap.Error(err))
|
|
}
|
|
}
|
|
|
|
go func(id string) {
|
|
if err := s.devicesSvc.UpdateLastSeen(id); err != nil {
|
|
s.logger.Error("can't update last seen", zap.Error(err))
|
|
}
|
|
}(device.ID)
|
|
|
|
device.LastSeen = time.Now()
|
|
|
|
return device, nil
|
|
}
|
|
|
|
func (s *Service) AuthorizeUser(username, password string) (models.User, error) {
|
|
hash := sha256.Sum256([]byte(username + password))
|
|
cacheKey := hex.EncodeToString(hash[:])
|
|
|
|
user, err := s.usersCache.Get(cacheKey)
|
|
if err == nil {
|
|
return user, nil
|
|
}
|
|
|
|
user, err = s.users.GetByLogin(username)
|
|
if err != nil {
|
|
return user, err
|
|
}
|
|
|
|
if err := crypto.CompareBCryptHash(user.PasswordHash, password); err != nil {
|
|
return models.User{}, err
|
|
}
|
|
|
|
if err := s.usersCache.Set(cacheKey, user); err != nil {
|
|
s.logger.Error("can't cache user", zap.Error(err))
|
|
}
|
|
|
|
return user, nil
|
|
}
|