diff --git a/internal/constants/constants.go b/internal/constants/constants.go index e1e4f54..3d52fa6 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -2,17 +2,18 @@ package constants const ( UnverifiedStatus = iota + 1 + DisabledStatus VerifiedStatus ActiveStatus PassiveStatus - DisabledStatus DelayedPaymentStatus SettledPaymentStatus AwaitingPaymentStatus - MailVerificationSubject = "Nur noch ein kleiner Schritt!" - MailRegistrationSubject = "Neues Mitglied hat sich registriert" - MailWelcomeSubject = "Willkommen beim Dörpsmobil Hasloh e.V." - MailContactSubject = "Jemand hat das Kontaktformular gefunden" + MailVerificationSubject = "Nur noch ein kleiner Schritt!" + MailChangePasswordSubject = "Passwort Änderung angefordert" + MailRegistrationSubject = "Neues Mitglied hat sich registriert" + MailWelcomeSubject = "Willkommen beim Dörpsmobil Hasloh e.V." + MailContactSubject = "Jemand hat das Kontaktformular gefunden" ) var Roles = struct { @@ -63,6 +64,14 @@ var Licences = struct { T: "T", } +var VerificationTypes = struct { + Email string + Password string +}{ + Email: "email", + Password: "password", +} + var Priviliges = struct { View int8 Create int8 @@ -75,11 +84,6 @@ var Priviliges = struct { Delete: 30, } -const PRIV_VIEW = 1 -const PRIV_ADD = 2 -const PRIV_EDIT = 4 -const PRIV_DELETE = 8 - var MemberUpdateFields = map[string]bool{ "Email": true, "Phone": true, diff --git a/internal/controllers/user_Password.go b/internal/controllers/user_Password.go new file mode 100644 index 0000000..3f7b743 --- /dev/null +++ b/internal/controllers/user_Password.go @@ -0,0 +1,103 @@ +package controllers + +import ( + "GoMembership/internal/constants" + "GoMembership/internal/utils" + "GoMembership/pkg/errors" + "net/http" + "strconv" + + "github.com/gin-gonic/gin" +) + +func (uc *UserController) RequestPasswordChangeHandler(c *gin.Context) { + + // Expected data from the user + var input struct { + Email string `json:"email" binding:"required,email"` + } + + if err := c.ShouldBindJSON(&input); err != nil { + utils.HandleValidationError(c, err) + return + } + // find user + db_user, err := uc.Service.GetUserByEmail(input.Email) + if err != nil { + utils.RespondWithError(c, err, "couldn't get user by email", http.StatusNotFound, "user.user", "user.email") + return + } + + // check if user may change the password + if db_user.Status <= constants.DisabledStatus { + utils.RespondWithError(c, errors.ErrNotAuthorized, "User password change request denied, user is disabled", http.StatusForbidden, errors.Responses.Fields.Login, errors.Responses.Keys.UserDisabled) + return + } + + // create token + token, err := uc.Service.HandlePasswordChangeRequest(db_user) + if err != nil { + utils.RespondWithError(c, err, "couldn't handle password change request", http.StatusInternalServerError, errors.Responses.Fields.General, errors.Responses.Keys.InternalServerError) + return + } + + // send email + if err := uc.EmailService.SendChangePasswordEmail(db_user, &token); err != nil { + utils.RespondWithError(c, err, "Couldn't send change password email", http.StatusInternalServerError, errors.Responses.Fields.General, errors.Responses.Keys.InternalServerError) + return + } + + c.JSON(http.StatusAccepted, gin.H{ + "message": "password_change_requested", + }) +} + +func (uc *UserController) ChangePassword(c *gin.Context) { + // Expected data from the user + var input struct { + Password string `json:"password" binding:"required"` + Token string `json:"token" binding:"required"` + } + userIDint, err := strconv.Atoi(c.Param("id")) + if err != nil { + utils.RespondWithError(c, err, "Invalid user ID", http.StatusBadRequest, errors.Responses.Fields.User, errors.Responses.Keys.InvalidUserID) + return + } + + if err := c.ShouldBindJSON(&input); err != nil { + utils.HandleValidationError(c, err) + return + } + + verification, err := uc.Service.VerifyUser(&input.Token, &constants.VerificationTypes.Password) + if err != nil || uint(userIDint) != verification.UserID { + if err == errors.ErrAlreadyVerified { + utils.RespondWithError(c, err, "User already verified", http.StatusConflict, errors.Responses.Fields.User, errors.Responses.Keys.PasswordAlreadyChanged) + } else { + utils.RespondWithError(c, err, "Couldn't verify user", http.StatusInternalServerError, errors.Responses.Fields.General, errors.Responses.Keys.InternalServerError) + } + + return + } + + user, err := uc.Service.GetUserByID(verification.UserID) + if err != nil { + utils.RespondWithError(c, err, "Couldn't find user", http.StatusNotFound, errors.Responses.Fields.User, errors.Responses.Keys.UserNotFoundWrongPassword) + return + } + + user.Status = constants.ActiveStatus + user.Verification = *verification + user.ID = verification.UserID + user.Password = input.Password + + _, err = uc.Service.UpdateUser(user) + if err != nil { + utils.RespondWithError(c, err, "Couldn't update user", http.StatusInternalServerError, errors.Responses.Fields.User, errors.Responses.Keys.InternalServerError) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "password_changed", + }) +} diff --git a/internal/controllers/user_controller.go b/internal/controllers/user_controller.go index 77da7ca..2822c81 100644 --- a/internal/controllers/user_controller.go +++ b/internal/controllers/user_controller.go @@ -204,7 +204,7 @@ func (uc *UserController) LoginHandler(c *gin.Context) { } if err := c.ShouldBindJSON(&input); err != nil { - utils.RespondWithError(c, err, "Error in LoginHandler", http.StatusBadRequest, "general", "server.validation.invalid_json") + utils.RespondWithError(c, err, "Invalid JSON or malformed request", http.StatusBadRequest, errors.Responses.Fields.General, errors.Responses.Keys.Invalid) return } @@ -216,9 +216,18 @@ func (uc *UserController) LoginHandler(c *gin.Context) { return } + if user.Status <= constants.DisabledStatus { + utils.RespondWithError(c, fmt.Errorf("User banned from login %v %v", user.FirstName, user.LastName), + "Login Error; user is disabled", + http.StatusNotAcceptable, + errors.Responses.Fields.Login, + errors.Responses.Keys.UserDisabled) + return + } + ok, err := user.PasswordMatches(input.Password) if err != nil { - utils.RespondWithError(c, err, "Login Error; password comparisson failed", http.StatusInternalServerError, errors.Responses.Fields.General, errors.Responses.Keys.InternalServerError) + utils.RespondWithError(c, err, "Login Error; password comparisson failed", http.StatusInternalServerError, errors.Responses.Fields.Login, errors.Responses.Keys.InternalServerError) return } if !ok { @@ -233,7 +242,7 @@ func (uc *UserController) LoginHandler(c *gin.Context) { logger.Error.Printf("jwtsecret: %v", config.Auth.JWTSecret) token, err := middlewares.GenerateToken(config.Auth.JWTSecret, user, "") if err != nil { - utils.RespondWithError(c, err, "Error generating token in LoginHandler", http.StatusInternalServerError, errors.Responses.Fields.General, errors.Responses.Keys.JwtGenerationFailed) + utils.RespondWithError(c, err, "Error generating token in LoginHandler", http.StatusInternalServerError, errors.Responses.Fields.Login, errors.Responses.Keys.JwtGenerationFailed) return } @@ -331,15 +340,26 @@ func (uc *UserController) VerifyMailHandler(c *gin.Context) { return } - user, err := uc.Service.VerifyUser(&token) + verification, err := uc.Service.VerifyUser(&token, &constants.VerificationTypes.Email) if err != nil { logger.Error.Printf("Cannot verify user: %v", err) c.HTML(http.StatusUnauthorized, "verification_error.html", gin.H{"ErrorMessage": "Emailadresse wurde schon bestätigt. Sollte dies nicht der Fall sein, wende Dich bitte an info@carsharing-hasloh.de."}) return } - logger.Info.Printf("VerificationMailHandler User: %#v", user.Email) + + user, err := uc.Service.GetUserByID(verification.UserID) + if err != nil { + utils.RespondWithError(c, err, "Couldn't find user", http.StatusNotFound, errors.Responses.Fields.User, errors.Responses.Keys.UserNotFoundWrongPassword) + return + } + + user.Status = constants.ActiveStatus + user.Verification = *verification + user.ID = verification.UserID + + uc.Service.UpdateUser(user) + logger.Info.Printf("Verified User: %#v", user.Email) uc.EmailService.SendWelcomeEmail(user) c.HTML(http.StatusOK, "verification_success.html", gin.H{"FirstName": user.FirstName}) - } diff --git a/internal/middlewares/cors.go b/internal/middlewares/cors.go index 3f31eac..1516792 100644 --- a/internal/middlewares/cors.go +++ b/internal/middlewares/cors.go @@ -13,7 +13,7 @@ func CORSMiddleware() gin.HandlerFunc { logger.Info.Print("Applying CORS") return cors.New(cors.Config{ AllowOrigins: strings.Split(config.Site.AllowOrigins, ","), - AllowMethods: []string{"GET", "POST", "PATCH", "OPTIONS"}, // "PUT", "PATCH", "DELETE", "OPTIONS"}, + AllowMethods: []string{"GET", "POST", "PATCH", "PUT"}, AllowHeaders: []string{"Origin", "Content-Type", "Accept", "Authorization", "X-Requested-With", "X-CSRF-Token"}, ExposeHeaders: []string{"Content-Length"}, AllowCredentials: true, diff --git a/internal/repositories/user_permissions.go b/internal/repositories/user_permissions.go new file mode 100644 index 0000000..9a1f5c4 --- /dev/null +++ b/internal/repositories/user_permissions.go @@ -0,0 +1,10 @@ +package repositories + +import ( + "GoMembership/internal/database" + "GoMembership/internal/models" +) + +func (r *UserRepository) SetUserStatus(id uint, status uint) error { + return database.DB.Model(&models.User{}).Where("id = ?", id).Update("status", status).Error +} diff --git a/internal/repositories/user_repository.go b/internal/repositories/user_repository.go index 45ac2a0..7864719 100644 --- a/internal/repositories/user_repository.go +++ b/internal/repositories/user_repository.go @@ -3,7 +3,6 @@ package repositories import ( "gorm.io/gorm" - "GoMembership/internal/constants" "GoMembership/internal/database" "gorm.io/gorm/clause" @@ -18,10 +17,12 @@ type UserRepositoryInterface interface { UpdateUser(user *models.User) (*models.User, error) GetUsers(where map[string]interface{}) (*[]models.User, error) GetUserByEmail(email string) (*models.User, error) - SetVerificationToken(verification *models.Verification) (uint, error) IsVerified(userID *uint) (bool, error) - GetVerificationOfToken(token *string) (*models.Verification, error) + GetVerificationOfToken(token *string, verificationType *string) (*models.Verification, error) + SetVerificationToken(verification *models.Verification) (token string, err error) + DeleteVerification(id uint, verificationType string) error DeleteUser(id uint) error + SetUserStatus(id uint, status uint) error } type UserRepository struct{} @@ -156,42 +157,3 @@ func (ur *UserRepository) GetUserByEmail(email string) (*models.User, error) { } return &user, nil } - -func (ur *UserRepository) IsVerified(userID *uint) (bool, error) { - var user models.User - result := database.DB.Select("status").First(&user, userID) - if result.Error != nil { - if result.Error == gorm.ErrRecordNotFound { - return false, gorm.ErrRecordNotFound - } - return false, result.Error - } - return user.Status != constants.UnverifiedStatus, nil -} - -func (ur *UserRepository) GetVerificationOfToken(token *string) (*models.Verification, error) { - - var emailVerification models.Verification - result := database.DB.Where("verification_token = ?", token).First(&emailVerification) - if result.Error != nil { - if result.Error == gorm.ErrRecordNotFound { - return nil, gorm.ErrRecordNotFound - } - return nil, result.Error - } - return &emailVerification, nil -} - -func (ur *UserRepository) SetVerificationToken(verification *models.Verification) (uint, error) { - // Use GORM to insert or update the Verification record - result := database.DB.Clauses(clause.OnConflict{ - Columns: []clause.Column{{Name: "user_id"}}, - DoUpdates: clause.AssignmentColumns([]string{"verification_token", "created_at"}), - }).Create(&verification) - - if result.Error != nil { - return 0, result.Error - } - - return verification.ID, nil -} diff --git a/internal/repositories/user_verification.go b/internal/repositories/user_verification.go new file mode 100644 index 0000000..24bcb96 --- /dev/null +++ b/internal/repositories/user_verification.go @@ -0,0 +1,57 @@ +package repositories + +import ( + "GoMembership/internal/constants" + "GoMembership/internal/database" + "GoMembership/internal/models" + + "gorm.io/gorm" + "gorm.io/gorm/clause" +) + +func (ur *UserRepository) IsVerified(userID *uint) (bool, error) { + var user models.User + result := database.DB.Select("status").First(&user, userID) + if result.Error != nil { + if result.Error == gorm.ErrRecordNotFound { + return false, gorm.ErrRecordNotFound + } + return false, result.Error + } + return user.Status > constants.DisabledStatus, nil +} + +func (ur *UserRepository) GetVerificationOfToken(token *string, verificationType *string) (*models.Verification, error) { + + var emailVerification models.Verification + result := database.DB.Where("verification_token = ? AND type = ?", token, verificationType).First(&emailVerification) + if result.Error != nil { + if result.Error == gorm.ErrRecordNotFound { + return nil, gorm.ErrRecordNotFound + } + return nil, result.Error + } + return &emailVerification, nil +} + +func (ur *UserRepository) SetVerificationToken(verification *models.Verification) (token string, err error) { + + result := database.DB.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "user_id"}}, + DoUpdates: clause.AssignmentColumns([]string{"verification_token", "created_at", "type"}), + }).Create(&verification) + + if result.Error != nil { + return "", result.Error + } + + return verification.VerificationToken, nil +} + +func (ur *UserRepository) DeleteVerification(id uint, verificationType string) error { + result := database.DB.Where("user_id = ? AND type = ?", id, verificationType).Delete(&models.Verification{}) + if result.Error != nil { + return result.Error + } + return nil +} diff --git a/internal/services/email_service.go b/internal/services/email_service.go index 51b14e7..91ac4f0 100644 --- a/internal/services/email_service.go +++ b/internal/services/email_service.go @@ -3,6 +3,7 @@ package services import ( "bytes" "html/template" + "os" "gopkg.in/gomail.v2" @@ -21,7 +22,7 @@ func NewEmailService(host string, port int, username string, password string) *E return &EmailService{dialer: dialer} } -func (s *EmailService) SendEmail(to string, subject string, body string, replyTo string) error { +func (s *EmailService) SendEmail(to string, subject string, body string, bodyTXT string, replyTo string) error { msg := gomail.NewMessage() msg.SetHeader("From", s.dialer.Username) msg.SetHeader("To", to) @@ -29,7 +30,12 @@ func (s *EmailService) SendEmail(to string, subject string, body string, replyTo if replyTo != "" { msg.SetHeader("REPLY_TO", replyTo) } - msg.SetBody("text/html", body) + if bodyTXT != "" { + msg.SetBody("text/plain", bodyTXT) + } + + msg.AddAlternative("text/html", body) + msg.WriteTo(os.Stdout) if err := s.dialer.DialAndSend(msg); err != nil { logger.Error.Printf("Could not send email to %s: %v", to, err) @@ -79,7 +85,10 @@ func (s *EmailService) SendVerificationEmail(user *models.User, token *string) e logger.Error.Print("Couldn't send verification mail") return err } - return s.SendEmail(user.Email, subject, body, "") + return s.SendEmail(user.Email, subject, body, "", "") + +} + func (s *EmailService) SendChangePasswordEmail(user *models.User, token *string) error { // Prepare data to be injected into the template data := struct { @@ -136,12 +145,17 @@ func (s *EmailService) SendWelcomeEmail(user *models.User) error { } subject := constants.MailWelcomeSubject - body, err := ParseTemplate("mail_welcome.tmpl", data) + htmlBody, err := ParseTemplate("mail_welcome.tmpl", data) if err != nil { logger.Error.Print("Couldn't send welcome mail") return err } - return s.SendEmail(user.Email, subject, body, "") + plainBody, err := ParseTemplate("mail_welcome.txt.tmpl", data) + if err != nil { + logger.Error.Print("Couldn't parse password mail") + return err + } + return s.SendEmail(user.Email, subject, htmlBody, plainBody, "") } func (s *EmailService) SendRegistrationNotification(user *models.User) error { @@ -185,12 +199,17 @@ func (s *EmailService) SendRegistrationNotification(user *models.User) error { } subject := constants.MailRegistrationSubject - body, err := ParseTemplate("mail_registration.tmpl", data) + htmlBody, err := ParseTemplate("mail_registration.tmpl", data) if err != nil { logger.Error.Print("Couldn't send admin notification mail") return err } - return s.SendEmail(config.Recipients.UserRegistration, subject, body, "") + plainBody, err := ParseTemplate("mail_registration.txt.tmpl", data) + if err != nil { + logger.Error.Print("Couldn't parse password mail") + return err + } + return s.SendEmail(user.Email, subject, htmlBody, plainBody, "") } func (s *EmailService) RelayContactFormMessage(sender string, name string, message string) error { @@ -208,10 +227,15 @@ func (s *EmailService) RelayContactFormMessage(sender string, name string, messa WebsiteTitle: config.Site.WebsiteTitle, } subject := constants.MailContactSubject - body, err := ParseTemplate("mail_contact_form.tmpl", data) + htmlBody, err := ParseTemplate("mail_contact_form.tmpl", data) if err != nil { logger.Error.Print("Couldn't send contact form message mail") return err } - return s.SendEmail(config.Recipients.ContactForm, subject, body, sender) + plainBody, err := ParseTemplate("mail_contact_form.txt.tmpl", data) + if err != nil { + logger.Error.Print("Couldn't parse password mail") + return err + } + return s.SendEmail(config.Recipients.ContactForm, subject, htmlBody, plainBody, sender) } diff --git a/internal/services/user_password.go b/internal/services/user_password.go new file mode 100644 index 0000000..adaf46b --- /dev/null +++ b/internal/services/user_password.go @@ -0,0 +1,21 @@ +package services + +import ( + "GoMembership/internal/constants" + "GoMembership/internal/models" +) + +func (s *UserService) HandlePasswordChangeRequest(user *models.User) (token string, err error) { + // Deactivate user and reset Verification + if err := s.SetUserStatus(user.ID, constants.DisabledStatus); err != nil { + return "", err + } + + if err := s.RevokeVerification(&user.ID, constants.VerificationTypes.Password); err != nil { + return "", err + } + + // Generate a token + return s.SetVerificationToken(&user.ID, &constants.VerificationTypes.Password) + +} diff --git a/internal/services/user_permissions.go b/internal/services/user_permissions.go new file mode 100644 index 0000000..89f9799 --- /dev/null +++ b/internal/services/user_permissions.go @@ -0,0 +1,5 @@ +package services + +func (s *UserService) SetUserStatus(id uint, status uint) error { + return s.Repo.SetUserStatus(id, status) +} diff --git a/internal/services/user_service.go b/internal/services/user_service.go index 53e9a30..fdf60df 100644 --- a/internal/services/user_service.go +++ b/internal/services/user_service.go @@ -1,15 +1,12 @@ package services import ( - "net/http" "strings" "GoMembership/internal/constants" "GoMembership/internal/models" "GoMembership/internal/repositories" - "GoMembership/internal/utils" "GoMembership/pkg/errors" - "GoMembership/pkg/logger" "github.com/alexedwards/argon2id" "gorm.io/gorm" @@ -18,13 +15,17 @@ import ( ) type UserServiceInterface interface { - RegisterUser(user *models.User) (uint, string, error) + RegisterUser(user *models.User) (id uint, token string, err error) GetUserByEmail(email string) (*models.User, error) GetUserByID(id uint) (*models.User, error) GetUsers(where map[string]interface{}) (*[]models.User, error) - VerifyUser(token *string) (*models.User, error) UpdateUser(user *models.User) (*models.User, error) DeleteUser(lastname string, id uint) error + SetUserStatus(id uint, status uint) error + VerifyUser(token *string, verificationType *string) (*models.Verification, error) + SetVerificationToken(id *uint, verificationType *string) (string, error) + RevokeVerification(id *uint, verificationType string) error + HandlePasswordChangeRequest(user *models.User) (token string, err error) } type UserService struct { @@ -81,7 +82,7 @@ func (service *UserService) UpdateUser(user *models.User) (*models.User, error) return updatedUser, nil } -func (service *UserService) RegisterUser(user *models.User) (uint, string, error) { +func (service *UserService) RegisterUser(user *models.User) (id uint, token string, err error) { setPassword(user.Password, user) @@ -89,49 +90,20 @@ func (service *UserService) RegisterUser(user *models.User) (uint, string, error user.CreatedAt = time.Now() user.UpdatedAt = time.Now() user.PaymentStatus = constants.AwaitingPaymentStatus - // if user.Licence == nil { - // user.Licence = &models.Licence{Status: constants.UnverifiedStatus} - // } user.BankAccount.MandateDateSigned = time.Now() - id, err := service.Repo.CreateUser(user) - + id, err = service.Repo.CreateUser(user) if err != nil { return 0, "", err } - user.ID = id - - token, err := utils.GenerateVerificationToken() + token, err = service.SetVerificationToken(&id, &constants.VerificationTypes.Email) if err != nil { return 0, "", err } - - logger.Info.Printf("TOKEN: %v", token) - - // Check if user is already verified - verified, err := service.Repo.IsVerified(&user.ID) - if err != nil { - return 0, "", err - } - if verified { - return 0, "", errors.ErrAlreadyVerified - } - - // Prepare the Verification record - verification := models.Verification{ - UserID: user.ID, - VerificationToken: token, - } - - if _, err = service.Repo.SetVerificationToken(&verification); err != nil { - return http.StatusInternalServerError, "", err - } - return id, token, nil } func (service *UserService) GetUserByID(id uint) (*models.User, error) { - return repositories.GetUserByID(&id) } @@ -146,35 +118,6 @@ func (service *UserService) GetUsers(where map[string]interface{}) (*[]models.Us return service.Repo.GetUsers(where) } -func (service *UserService) VerifyUser(token *string) (*models.User, error) { - verification, err := service.Repo.GetVerificationOfToken(token) - if err != nil { - return nil, err - } - // Check if the user is already verified - verified, err := service.Repo.IsVerified(&verification.UserID) - if err != nil { - return nil, err - } - user, err := repositories.GetUserByID(&verification.UserID) - if err != nil { - return nil, err - } - if verified { - return user, errors.ErrAlreadyVerified - } - // Update user status to active - t := time.Now() - verification.EmailVerifiedAt = &t - - user.Status = constants.VerifiedStatus - user.Verification = *verification - user.ID = verification.UserID - service.Repo.UpdateUser(user) - - return user, nil -} - func setPassword(plaintextPassword string, u *models.User) error { hash, err := argon2id.CreateHash(plaintextPassword, argon2id.DefaultParams) if err != nil { diff --git a/internal/services/user_verification.go b/internal/services/user_verification.go new file mode 100644 index 0000000..39b2bdc --- /dev/null +++ b/internal/services/user_verification.go @@ -0,0 +1,60 @@ +package services + +import ( + "GoMembership/internal/models" + "GoMembership/internal/utils" + "GoMembership/pkg/errors" + "time" +) + +func (s *UserService) SetVerificationToken(id *uint, verificationType *string) (string, error) { + + token, err := utils.GenerateVerificationToken() + if err != nil { + return "", err + } + + // Check if user is already verified + verified, err := s.Repo.IsVerified(id) + if err != nil { + return "", err + } + if verified { + return "", errors.ErrAlreadyVerified + } + + // Prepare the Verification record + verification := models.Verification{ + UserID: *id, + VerificationToken: token, + Type: *verificationType, + } + + return s.Repo.SetVerificationToken(&verification) +} + +func (s *UserService) RevokeVerification(id *uint, verificationType string) error { + return s.Repo.DeleteVerification(*id, verificationType) + +} + +func (service *UserService) VerifyUser(token *string, verificationType *string) (*models.Verification, error) { + verification, err := service.Repo.GetVerificationOfToken(token, verificationType) + if err != nil { + return nil, err + } + + // Check if the user is already verified + verified, err := service.Repo.IsVerified(&verification.UserID) + if err != nil { + return nil, err + } + if verified { + return nil, errors.ErrAlreadyVerified + } + t := time.Now() + verification.VerifiedAt = &t + + // Update user status to active + return verification, nil +} diff --git a/internal/utils/priviliges.go b/internal/utils/priviliges.go index b463dfd..747799f 100644 --- a/internal/utils/priviliges.go +++ b/internal/utils/priviliges.go @@ -81,21 +81,6 @@ func FilterAllowedStructFields(input interface{}, existing interface{}, allowedF } else { originField.Set(fieldValue) } - - // If the slice contains structs, recursively filter each element - // if fieldValue.Type().Elem().Kind() == reflect.Struct { - // for j := 0; j < fieldValue.Len(); j++ { - // err := FilterAllowedStructFields( - // fieldValue.Index(j).Addr().Interface(), - // originField.Index(j).Addr().Interface(), - // allowedFields, - // fullKey, - // ) - // if err != nil { - // return err - // } - // } - // } continue } diff --git a/pkg/errors/errors.go b/pkg/errors/errors.go index dc1f584..75989fb 100644 --- a/pkg/errors/errors.go +++ b/pkg/errors/errors.go @@ -12,13 +12,14 @@ type ValidationKeys struct { JwtGenerationFailed string Duplicate string InvalidUserID string + PasswordAlreadyChanged string + UserDisabled string } type ValidationFields struct { General string ParentMemberShipID string SubscriptionModel string - UserID string Login string Email string User string @@ -60,14 +61,15 @@ var Responses = struct { UserNotFoundWrongPassword: "server.validation.user_not_found_or_wrong_password", JwtGenerationFailed: "server.error.jwt_generation_failed", Duplicate: "server.validation.duplicate", + UserDisabled: "server.validation.user_disabled", + PasswordAlreadyChanged: "server.validation.password_already_changed", }, Fields: ValidationFields{ General: "general", ParentMemberShipID: "parent_membership_id", SubscriptionModel: "subscription_model", - UserID: "user_id", - Login: "login", - Email: "email", - User: "user", + Login: "user.login", + Email: "user.email", + User: "user.user", }, }