105 lines
2.6 KiB
Go
105 lines
2.6 KiB
Go
package users
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"git.kanopo.dev/rhythm/rhythm-backend/internal/config"
|
|
usersdb "git.kanopo.dev/rhythm/rhythm-backend/internal/db/users"
|
|
"git.kanopo.dev/rhythm/rhythm-backend/internal/jwt"
|
|
"git.kanopo.dev/rhythm/rhythm-backend/internal/password"
|
|
)
|
|
|
|
var ErrInvalidCredentials = errors.New("invalid credentials")
|
|
|
|
type AuthResult struct {
|
|
AccessToken string
|
|
RefreshToken string
|
|
}
|
|
|
|
type Service interface {
|
|
Login(ctx context.Context, email, password string) (*AuthResult, error)
|
|
Register(ctx context.Context, email, password string) (*AuthResult, error)
|
|
GetUserByEmail(ctx context.Context, email string) (usersdb.User, error)
|
|
}
|
|
|
|
type service struct {
|
|
repo usersdb.Querier
|
|
cfg *config.Config
|
|
log *zap.SugaredLogger
|
|
}
|
|
|
|
func NewService(repo usersdb.Querier, cfg *config.Config, log *zap.SugaredLogger) Service {
|
|
return &service{
|
|
repo: repo,
|
|
cfg: cfg,
|
|
log: log,
|
|
}
|
|
}
|
|
|
|
func (s *service) Login(ctx context.Context, email, passwordPlain string) (*AuthResult, error) {
|
|
user, err := s.repo.GetUserByEmail(ctx, email)
|
|
if err != nil {
|
|
s.log.Infof("login failed: user not found with email %v", email)
|
|
return nil, ErrInvalidCredentials
|
|
}
|
|
|
|
if !password.CheckPassword(passwordPlain, user.Password) {
|
|
s.log.Infof("login failed: invalid password for email %v", email)
|
|
return nil, ErrInvalidCredentials
|
|
}
|
|
|
|
tokenPair, err := jwt.GenerateTokenPair(user.ID.String(), s.cfg)
|
|
if err != nil {
|
|
s.log.Errorf("failed to generate token pair %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
s.log.Infof("user logged in successfully with email %v", email)
|
|
|
|
return &AuthResult{
|
|
AccessToken: tokenPair.AccessToken,
|
|
RefreshToken: tokenPair.RefreshToken,
|
|
}, nil
|
|
}
|
|
|
|
func (s *service) Register(ctx context.Context, email, passwordPlain string) (*AuthResult, error) {
|
|
_, err := s.repo.GetUserByEmail(ctx, email)
|
|
if err == nil {
|
|
s.log.Infof("registration failed: email already exists %v", email)
|
|
return nil, ErrInvalidCredentials
|
|
}
|
|
|
|
hash, err := password.HashPassword(passwordPlain)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
user, err := s.repo.CreateUser(ctx, usersdb.CreateUserParams{
|
|
Email: email,
|
|
Password: hash,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
tokenPair, err := jwt.GenerateTokenPair(user.ID.String(), s.cfg)
|
|
if err != nil {
|
|
s.log.Error("failed to generate token pair", "error", err)
|
|
return nil, err
|
|
}
|
|
|
|
s.log.Info("user registered successfully", "email", email)
|
|
|
|
return &AuthResult{
|
|
AccessToken: tokenPair.AccessToken,
|
|
RefreshToken: tokenPair.RefreshToken,
|
|
}, nil
|
|
}
|
|
|
|
func (s *service) GetUserByEmail(ctx context.Context, email string) (usersdb.User, error) {
|
|
return s.repo.GetUserByEmail(ctx, email)
|
|
}
|