package service import ( "context" "errors" "fmt" "go-server/internal/models" "go-server/internal/repository" "github.com/google/uuid" "golang.org/x/crypto/bcrypt" ) type UserService struct { repo *repository.UserRepository } type CreateUserInput struct { Email string Password string FirstName string LastName string } type UpdateUserInput struct { FirstName *string LastName *string } type ChangePasswordInput struct { Password string } func NewUserService(repo *repository.UserRepository) *UserService { return &UserService{repo: repo} } func (s *UserService) GetByID(ctx context.Context, id uuid.UUID) (*models.User, error) { return s.repo.GetByID(ctx, id) } func (s *UserService) GetAll(ctx context.Context) ([]*models.User, error) { return s.repo.GetAll(ctx) } func (s *UserService) Create(ctx context.Context, input CreateUserInput) (*models.User, error) { hashedPassword, err := hashPassword(input.Password) if err != nil { return nil, fmt.Errorf("password hashing failed: %w", err) } user := &models.User{ Email: input.Email, Password: hashedPassword, FirstName: input.FirstName, LastName: input.LastName, PlatformRole: models.PlatformRoleUser, } if err := s.repo.Create(ctx, user); err != nil { return nil, fmt.Errorf("failed to create user: %w", err) } return user, nil } func (s *UserService) Update(ctx context.Context, id uuid.UUID, input UpdateUserInput) (*models.User, error) { user, err := s.repo.GetByID(ctx, id) if err != nil { return nil, fmt.Errorf("failed to fetch user: %w", err) } if user == nil { return nil, errors.New("user not found") } if input.FirstName != nil { user.FirstName = *input.FirstName } if input.LastName != nil { user.LastName = *input.LastName } if err := s.repo.Update(ctx, user); err != nil { return nil, fmt.Errorf("failed to update user: %w", err) } return user, nil } func (s *UserService) UpdateLastLogin(ctx context.Context, id uuid.UUID) error { user, err := s.repo.GetByID(ctx, id) if err != nil { return fmt.Errorf("failed to fetch user: %w", err) } if user == nil { return errors.New("user not found") } if err := s.repo.Update(ctx, user); err != nil { return fmt.Errorf("failed to update last login: %w", err) } return nil } func (s *UserService) Delete(ctx context.Context, id uuid.UUID) error { return s.repo.Delete(ctx, id) } func (s *UserService) ChangePassword(ctx context.Context, id uuid.UUID, input ChangePasswordInput) error { hashedPassword, err := hashPassword(input.Password) if err != nil { return fmt.Errorf("password hashing failed: %w", err) } user, err := s.repo.GetByID(ctx, id) if err != nil { return fmt.Errorf("failed to fetch user: %w", err) } if user == nil { return errors.New("user not found") } user.Password = hashedPassword if err := s.repo.Update(ctx, user); err != nil { return fmt.Errorf("failed to update user: %w", err) } return nil } // hashPassword generates a bcrypt hash for a given password. func hashPassword(password string) (string, error) { hashed, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return "", err } return string(hashed), nil }