Prompt Detail:
To implement the forgot password functionality, you can use the following steps:
- Generate a random token for the user when they request a password reset.
- Save the token and its expiry time in the database.
- Send the token via email to the user with a password reset link.
- Create a route to handle the password reset request using the token.
Note that this example does not include the email sending part. You can use a package like github.com/sendgrid/sendgrid-go
to send emails.
First, update the models/user.go
file to add the password reset token and its expiry time:
gopackage models
import (
"time"
// ... other imports ...
)
type User struct {
ID uint `gorm:"primaryKey;autoIncrement"`
Email string `gorm:"unique;not null"`
Password string `gorm:"not null"`
PasswordResetToken string `gorm:""`
PasswordResetTokenExpiry time.Time `gorm:""`
// ... other fields ...
}
// ... other functions ...
Next, update the main.go
file to add the forgot password and reset password routes and handlers:
gopackage main
import (
// ... other imports ...
"math/rand"
"time"
)
func main() {
// ... existing code ...
r.POST("/forgot-password", forgotPassword)
r.POST("/reset-password", resetPassword)
r.Run(":8080")
}
func forgotPassword(c *gin.Context) {
var user models.User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
var foundUser models.User
if err := db.Where("email = ?", user.Email).First(&foundUser).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
return
}
token := generateRandomToken()
foundUser.PasswordResetToken = token
foundUser.PasswordResetTokenExpiry = time.Now().Add(1 * time.Hour) // Token valid for 1 hour
db.Save(&foundUser)
// TODO: Send an email to the user with the token and a link to reset their password
c.JSON(http.StatusOK, gin.H{"message": "Password reset email sent"})
}
func resetPassword(c *gin.Context) {
var resetData struct {
Token string `json:"token" binding:"required"`
Password string `json:"password" binding:"required"`
}
if err := c.ShouldBindJSON(&resetData); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
var user models.User
if err := db.Where("password_reset_token = ? AND password_reset_token_expiry > ?", resetData.Token, time.Now()).First(&user).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid or expired token"})
return
}
user.Password = resetData.Password
user.PasswordResetToken = ""
user.PasswordResetTokenExpiry = time.Time{}
db.Save(&user)
c.JSON(http.StatusOK,
Add a comment