refactor: migrate from raw pgx to GORM, unify ErrNoRows, cleanup auth
This commit is contained in:
+41
-23
@@ -11,30 +11,33 @@ import (
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"gitea.d3m0k1d.ru/HellreigN/Control-plane/internal/db"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrEmailExists = errors.New("email already registered")
|
||||
ErrInvalidCreds = errors.New("invalid email or password")
|
||||
ErrUserNotFound = errors.New("user not found")
|
||||
ErrInvalidUserID = errors.New("invalid user ID")
|
||||
ErrInvalidRefresh = errors.New("invalid refresh token")
|
||||
ErrRefreshExpired = errors.New("refresh token expired")
|
||||
ErrLogoutInvalid = errors.New("refresh token not found or already used")
|
||||
ErrWrongPassword = errors.New("current password is incorrect")
|
||||
ErrWeakPassword = errors.New("password must be at least 8 characters with uppercase, lowercase, and digit")
|
||||
ErrSamePassword = errors.New("new password must differ from current password")
|
||||
ErrEmailExists = errors.New("email already registered")
|
||||
ErrInvalidCreds = errors.New("invalid email or password")
|
||||
ErrUserNotFound = errors.New("user not found")
|
||||
ErrInvalidUserID = errors.New("invalid user ID")
|
||||
ErrInvalidRefresh = errors.New("invalid refresh token")
|
||||
ErrRefreshExpired = errors.New("refresh token expired")
|
||||
ErrLogoutInvalid = errors.New("refresh token not found or already used")
|
||||
ErrWrongPassword = errors.New("current password is incorrect")
|
||||
ErrWeakPassword = errors.New(
|
||||
"password must be at least 8 characters with uppercase, lowercase, and digit",
|
||||
)
|
||||
ErrSamePassword = errors.New("new password must differ from current password")
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
repo *Repository
|
||||
repo UserRepository
|
||||
jwtSecret []byte
|
||||
jwtExp time.Duration
|
||||
refreshExp time.Duration
|
||||
}
|
||||
|
||||
func NewService(repo *Repository, jwtSecret string, jwtExp, refreshExp time.Duration) *Service {
|
||||
func NewService(repo UserRepository, jwtSecret string, jwtExp, refreshExp time.Duration) *Service {
|
||||
return &Service{
|
||||
repo: repo,
|
||||
jwtSecret: []byte(jwtSecret),
|
||||
@@ -113,7 +116,7 @@ func (s *Service) Register(ctx context.Context, req RegisterRequest) (*AuthRespo
|
||||
req.Email = strings.ToLower(req.Email)
|
||||
|
||||
existing, err := s.repo.FindByEmail(ctx, req.Email)
|
||||
if err != nil && !errors.Is(err, ErrNoRows) {
|
||||
if err != nil && !errors.Is(err, db.ErrNoRows) {
|
||||
return nil, fmt.Errorf("failed to check existing user: %w", err)
|
||||
}
|
||||
if existing != nil {
|
||||
@@ -145,13 +148,16 @@ func (s *Service) Login(ctx context.Context, req LoginRequest) (*AuthResponse, e
|
||||
req.Email = strings.ToLower(req.Email)
|
||||
user, err := s.repo.FindByEmail(ctx, req.Email)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrNoRows) {
|
||||
if errors.Is(err, db.ErrNoRows) {
|
||||
return nil, ErrInvalidCreds
|
||||
}
|
||||
return nil, fmt.Errorf("failed to find user: %w", err)
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password)); err != nil {
|
||||
if err := bcrypt.CompareHashAndPassword(
|
||||
[]byte(user.PasswordHash),
|
||||
[]byte(req.Password),
|
||||
); err != nil {
|
||||
return nil, ErrInvalidCreds
|
||||
}
|
||||
|
||||
@@ -163,7 +169,7 @@ func (s *Service) Refresh(ctx context.Context, rawRefresh string) (*AuthResponse
|
||||
|
||||
doc, err := s.repo.FindRefreshTokenByHash(ctx, hash)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrNoRows) {
|
||||
if errors.Is(err, db.ErrNoRows) {
|
||||
return nil, ErrInvalidRefresh
|
||||
}
|
||||
return nil, fmt.Errorf("failed to find refresh token: %w", err)
|
||||
@@ -202,7 +208,7 @@ func (s *Service) GetUserByID(ctx context.Context, userID string) (*UserPublic,
|
||||
|
||||
user, err := s.repo.FindByID(ctx, userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrNoRows) {
|
||||
if errors.Is(err, db.ErrNoRows) {
|
||||
return nil, ErrUserNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("failed to find user: %w", err)
|
||||
@@ -212,20 +218,27 @@ func (s *Service) GetUserByID(ctx context.Context, userID string) (*UserPublic,
|
||||
return &public, nil
|
||||
}
|
||||
|
||||
func (s *Service) ChangePassword(ctx context.Context, userID string, req PasswordChangeRequest) error {
|
||||
func (s *Service) ChangePassword(
|
||||
ctx context.Context,
|
||||
userID string,
|
||||
req PasswordChangeRequest,
|
||||
) error {
|
||||
if userID == "" {
|
||||
return ErrInvalidUserID
|
||||
}
|
||||
|
||||
user, err := s.repo.FindByID(ctx, userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrNoRows) {
|
||||
if errors.Is(err, db.ErrNoRows) {
|
||||
return ErrUserNotFound
|
||||
}
|
||||
return fmt.Errorf("failed to find user: %w", err)
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.OldPassword)); err != nil {
|
||||
if err := bcrypt.CompareHashAndPassword(
|
||||
[]byte(user.PasswordHash),
|
||||
[]byte(req.OldPassword),
|
||||
); err != nil {
|
||||
return ErrWrongPassword
|
||||
}
|
||||
|
||||
@@ -249,14 +262,18 @@ func (s *Service) ChangePassword(ctx context.Context, userID string, req Passwor
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdateProfile(ctx context.Context, userID string, req UpdateProfileRequest) (*UserPublic, error) {
|
||||
func (s *Service) UpdateProfile(
|
||||
ctx context.Context,
|
||||
userID string,
|
||||
req UpdateProfileRequest,
|
||||
) (*UserPublic, error) {
|
||||
if userID == "" {
|
||||
return nil, ErrInvalidUserID
|
||||
}
|
||||
|
||||
user, err := s.repo.FindByID(ctx, userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrNoRows) {
|
||||
if errors.Is(err, db.ErrNoRows) {
|
||||
return nil, ErrUserNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("failed to find user: %w", err)
|
||||
@@ -272,5 +289,6 @@ func (s *Service) UpdateProfile(ctx context.Context, userID string, req UpdatePr
|
||||
}
|
||||
|
||||
func isPGUniqueViolation(err error) bool {
|
||||
return err != nil && (strings.Contains(err.Error(), "unique") || strings.Contains(err.Error(), "23505"))
|
||||
return err != nil &&
|
||||
(strings.Contains(err.Error(), "unique") || strings.Contains(err.Error(), "23505"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user