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 changed password", http.StatusConflict, errors.Responses.Fields.User, errors.Responses.Keys.PasswordAlreadyChanged) } else if err.Error() == "record not found" { utils.RespondWithError(c, err, "Couldn't find verification. This is most probably a outdated token.", http.StatusGone, errors.Responses.Fields.User, errors.Responses.Keys.NoAuthToken) } 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", }) }