package controllers import ( "crypto/rand" "encoding/base64" "net/http" "github.com/gin-gonic/gin" "gitlab.com/pactual1/backend/database/user" "gitlab.com/pactual1/backend/models" "gitlab.com/pactual1/backend/services/messaging" "gitlab.com/pactual1/backend/shared" "golang.org/x/crypto/bcrypt" ) func ResetPassword(c *gin.Context) { var req models.ResetPasswordRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } dbUser, err := user.GetUserByEmail(req.Email) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "User not found"}) return } resetToken, err := GenerateResetToken() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } err = user.SaveResetTokenToDB(dbUser.ID, resetToken) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } subject := "Password Reset Request" body := "Here is your password reset link: https://pactualdev.com/setNewPassword?token=" + resetToken email := models.EmailNotification{Body: body, Subject: subject, Email: dbUser.Email} go func(email models.EmailNotification) { emailChannel := messaging.GetEmailChannel() emailChannel <- email }(email) c.JSON(http.StatusOK, gin.H{"message": "Reset email sent"}) } func GenerateResetToken() (string, error) { // Generate 32 random bytes (256 bits) randomBytes := make([]byte, 32) _, err := rand.Read(randomBytes) if err != nil { return "", err // return an error if there was one } // Encode the random bytes into a URL-safe base64 string resetToken := base64.URLEncoding.EncodeToString(randomBytes) return resetToken, nil } func UpdatePassword(c *gin.Context) { var req models.UpdatePasswordRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Find the PasswordTokens entry var passwordToken models.PasswordTokens if err := shared.GetDb().Where("token = ?", req.Token).First(&passwordToken).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Invalid token"}) return } // Find the associated User var user models.User if err := shared.GetDb().Where("id = ?", passwordToken.UserID).First(&user).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "User not found"}) return } // Hash the password before saving it hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // Update the user's password and set them as active user.Password = string(hashedPassword) user.IsActive = true if err := shared.GetDb().Save(&user).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // Delete the PasswordTokens entry if err := shared.GetDb().Delete(&passwordToken).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "Password updated successfully"}) }