package auth import ( "context" "errors" "time" sqlc "github.com/chedius/delivery-tracker/internal/db/sqlc" "github.com/google/uuid" "github.com/jackc/pgx/v5" "golang.org/x/crypto/bcrypt" ) type Service struct { queries *sqlc.Queries secret []byte expiry time.Duration } type User struct { ID string Username string // Password string } func New(queries *sqlc.Queries, secret []byte, expiry time.Duration) *Service { return &Service{queries, secret, expiry} } func (s *Service) Register(ctx context.Context, username, password string) (User, string, error) { if username == "" || password == "" { return User{}, "", ErrCredentialsEmpty } if _, err := s.queries.GetUserByUsername(ctx, username); err == nil { return User{}, "", ErrUserExists } if len(password) < 6 { return User{}, "", ErrPasswordTooShort } hashedPassword, err := s.HashPassword(password) if err != nil { return User{}, "", err } user, err := s.queries.CreateUser(ctx, sqlc.CreateUserParams{ Username: username, PasswordHash: hashedPassword, }) if err != nil { return User{}, "", err } token, err := GenerateToken(uuid.UUID(user.ID.Bytes), s.secret, s.expiry) if err != nil { return User{}, "", err } return User{ ID: user.ID.String(), Username: user.Username, }, token, nil } func (s *Service) Login(ctx context.Context, username, password string) (string, error) { // returns JWT user, err := s.queries.GetUserByUsername(ctx, username) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return "", ErrUserNotFound } return "", err } if !s.VerifyPassword(user.PasswordHash, password) { return "", ErrInvalidCredentials } token, err := GenerateToken(uuid.UUID(user.ID.Bytes), s.secret, s.expiry) if err != nil { return "", err } return token, nil } func (s *Service) HashPassword(password string) (string, error) { hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return "", err } return string(hash), nil } func (s *Service) VerifyPassword(hash, password string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) return err == nil }