114 lines
2.6 KiB
Go
114 lines
2.6 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
|
|
"go-backend/internal/auth"
|
|
"go-backend/internal/database/sqlc"
|
|
)
|
|
|
|
type UserService struct {
|
|
db *sql.DB
|
|
queries *sqlc.Queries
|
|
}
|
|
|
|
func NewUserService(db *sql.DB, queries *sqlc.Queries) *UserService {
|
|
return &UserService{
|
|
db: db,
|
|
queries: queries,
|
|
}
|
|
}
|
|
|
|
func (s *UserService) FindByID(ctx context.Context, id string) (*sqlc.UserAuth, error) {
|
|
user, err := s.queries.SelectUserById(ctx, id)
|
|
|
|
if err != nil {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return &user, nil
|
|
}
|
|
|
|
func (s *UserService) FindByUsername(ctx context.Context, username string) (*sqlc.UserAuth, error) {
|
|
user, err := s.queries.SelectUserByUsername(ctx, username)
|
|
|
|
if err != nil {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return &user, nil
|
|
}
|
|
|
|
func (s *UserService) CreateUser(ctx context.Context, userInput sqlc.InsertUserParams) (*sqlc.UserAuth, error) {
|
|
user, err := s.queries.InsertUser(ctx, userInput)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &user, nil
|
|
}
|
|
|
|
var (
|
|
ErrCurrentPasswordRequired = errors.New("current password is required to set a new password")
|
|
ErrInvalidCurrentPassword = errors.New("current password is incorrect")
|
|
)
|
|
|
|
// PatchUserInput carries a partial update: a nil field means "leave this
|
|
// field alone", distinguishing "not provided" from a provided zero value,
|
|
// since Go has no nullish type to express that on its own.
|
|
type PatchUserInput struct {
|
|
Username *string
|
|
Email *string
|
|
CurrentPassword *string
|
|
NewPassword *string
|
|
}
|
|
|
|
func (s *UserService) PatchUser(ctx context.Context, id string, patchUserInput PatchUserInput) (*sqlc.UserAuth, error) {
|
|
params := sqlc.PatchUserParams{ID: id}
|
|
|
|
if patchUserInput.Username != nil {
|
|
params.Username = sql.NullString{String: *patchUserInput.Username, Valid: true}
|
|
}
|
|
|
|
if patchUserInput.Email != nil {
|
|
params.Email = sql.NullString{String: *patchUserInput.Email, Valid: true}
|
|
}
|
|
|
|
if patchUserInput.NewPassword != nil {
|
|
if patchUserInput.CurrentPassword == nil {
|
|
return nil, ErrCurrentPasswordRequired
|
|
}
|
|
|
|
user, err := s.queries.SelectUserById(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !auth.VerifyPassword(user.PasswordHash, *patchUserInput.CurrentPassword) {
|
|
return nil, ErrInvalidCurrentPassword
|
|
}
|
|
|
|
newHash, err := auth.HashPassword(*patchUserInput.NewPassword)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
params.PasswordHash = sql.NullString{String: newHash, Valid: true}
|
|
}
|
|
|
|
user, err := s.queries.PatchUser(ctx, params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &user, nil
|
|
}
|