package user import ( "errors" "fmt" "golang.org/x/crypto/bcrypt" ) type Repository interface { Create(in *CreateInput) (*User, error) GetByUsernameOrEmail(username string, email string) (*User, error) } type Service struct { repository Repository bcryptCost int } func New(r Repository) *Service { return &Service{repository: r, bcryptCost: bcrypt.DefaultCost} } func (s *Service) Register(in *RegisterInput) (*User, error) { if err := in.validate(); err != nil { return nil, fmt.Errorf("register: %w", err) } _, err := s.repository.GetByUsernameOrEmail(in.Username, in.Email) if err == nil { return nil, fmt.Errorf("register: %w", ErrUserExists) } if !errors.Is(err, ErrUserNotFound) { return nil, fmt.Errorf("register: %w", err) } pwHash, err := bcrypt.GenerateFromPassword([]byte(in.Password), s.bcryptCost) if err != nil { return nil, fmt.Errorf("register: %w", err) } ci := &CreateInput{ Username: in.Username, Email: in.Email, Phone: in.Phone, PwHash: string(pwHash), } user, err := s.repository.Create(ci) if err != nil { return nil, fmt.Errorf("register: %w", err) } return user, nil }