package services import ( "net/http" "strings" "GoMembership/internal/constants" "GoMembership/internal/models" "GoMembership/internal/repositories" "GoMembership/internal/utils" "GoMembership/pkg/logger" "github.com/alexedwards/argon2id" "github.com/go-playground/validator/v10" "time" ) type UserServiceInterface interface { RegisterUser(user *models.User) (int64, string, error) GetUserByEmail(email string) (*models.User, error) GetUserByID(id int64) (*models.User, error) GetUsers(where map[string]interface{}) (*[]models.User, error) VerifyUser(token *string) (*models.User, error) } type UserService struct { Repo repositories.UserRepositoryInterface } func (service *UserService) RegisterUser(user *models.User) (int64, string, error) { if err := validateRegistrationData(user); err != nil { return http.StatusNotAcceptable, "", err } setPassword(user.Password, user) user.Status = constants.UnverifiedStatus user.CreatedAt = time.Now() user.UpdatedAt = time.Now() id, err := service.Repo.CreateUser(user) if err != nil && strings.Contains(err.Error(), "UNIQUE constraint failed") { return http.StatusConflict, "", err } else if err != nil { return http.StatusInternalServerError, "", err } user.ID = id token, err := utils.GenerateVerificationToken() if err != nil { return http.StatusInternalServerError, "", err } logger.Info.Printf("TOKEN: %v", token) _, err = service.Repo.SetVerificationToken(user, &token) if err != nil { return http.StatusInternalServerError, "", err } return id, token, nil } func (service *UserService) Update(user *models.User) (int64, string, error) { if err := validateRegistrationData(user); err != nil { return http.StatusNotAcceptable, "", err } setPassword(user.Password, user) user.Status = constants.UnverifiedStatus user.CreatedAt = time.Now() user.UpdatedAt = time.Now() id, err := service.Repo.CreateUser(user) if err != nil && strings.Contains(err.Error(), "UNIQUE constraint failed") { return http.StatusConflict, "", err } else if err != nil { return http.StatusInternalServerError, "", err } user.ID = id token, err := utils.GenerateVerificationToken() if err != nil { return http.StatusInternalServerError, "", err } logger.Info.Printf("TOKEN: %v", token) _, err = service.Repo.SetVerificationToken(user, &token) if err != nil { return http.StatusInternalServerError, "", err } return id, token, nil } func (service *UserService) GetUserByID(id int64) (*models.User, error) { return service.Repo.GetUserByID(id) } func (service *UserService) GetUserByEmail(email string) (*models.User, error) { return service.Repo.GetUserByEmail(email) } func (service *UserService) GetUsers(where map[string]interface{}) (*[]models.User, error) { return service.Repo.GetUsers(where) } func (service *UserService) VerifyUser(token *string) (*models.User, error) { user, err := service.Repo.VerifyUserOfToken(token) if err != nil { return nil, err } return user, nil } func validateRegistrationData(user *models.User) error { validate := validator.New() validate.RegisterValidation("age", utils.AgeValidator) validate.RegisterValidation("bic", utils.BICValidator) validate.RegisterValidation("iban", utils.IBANValidator) validate.RegisterValidation("subscriptionModel", utils.SubscriptionModelValidator) validate.RegisterValidation("membershipField", utils.ValidateRequiredMembershipField) return validate.Struct(user) } func setPassword(plaintextPassword string, u *models.User) error { hash, err := argon2id.CreateHash(plaintextPassword, argon2id.DefaultParams) if err != nil { return err } u.Password = hash return nil }