From 55bb11115d8f1278b8170c6bf6beae55ea063c3a Mon Sep 17 00:00:00 2001 From: bkawk Date: Sun, 5 Feb 2023 21:22:50 +0000 Subject: [PATCH] reset password --- api/handlers/forgotPassword.go | 2 +- api/handlers/resetPassword.go | 62 +++++++++++++++++++++++++--------- api/models/user.go | 6 ++-- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/api/handlers/forgotPassword.go b/api/handlers/forgotPassword.go index ca6c011..53c4cb5 100644 --- a/api/handlers/forgotPassword.go +++ b/api/handlers/forgotPassword.go @@ -50,7 +50,7 @@ func ForgotPasswordPost(c echo.Context) error { return fmt.Errorf("environment variable not set: VERIFY_URL") } // Send welcome email - emailError := emails.SendResetPasswordEmail(u.Email, resetEmailUrl+"?verificationCode="+u.VerificationCode) + emailError := emails.SendResetPasswordEmail(u.Email, resetEmailUrl+"?verificationCode="+u.PasswordResetToken) if emailError != nil { fmt.Println(emailError) return c.JSON(http.StatusInternalServerError, echo.Map{"error": emailError}) diff --git a/api/handlers/resetPassword.go b/api/handlers/resetPassword.go index 788a860..1ccb906 100644 --- a/api/handlers/resetPassword.go +++ b/api/handlers/resetPassword.go @@ -1,34 +1,64 @@ package handlers import ( + "context" "net/http" + "time" "bkawk/go-echo/api/models" "github.com/labstack/echo/v4" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "golang.org/x/crypto/bcrypt" ) // RegisterEndpoint handles user registration requests func ResetPasswordPost(c echo.Context) error { - // bind the incoming request body to a User struct - u := new(models.User) - if err := c.Bind(u); err != nil { - return err + var err error + passwordResetToken := c.FormValue("passwordResetToken") + newPassword := c.FormValue("newPassword") + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost) + if err != nil { + return c.String(http.StatusBadRequest, "Failed to hash password") } - // validate user input - if u.Username == "" || u.Password == "" || u.Email == "" { - return c.JSON(http.StatusBadRequest, map[string]string{ - "error": "invalid request body", - }) + // Get database connection from context + db := c.Get("db").(*mongo.Database) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + collection := db.Collection("users") + + // Find the user document with the password reset token + var user models.User + err = collection.FindOne(ctx, bson.M{"passwordResetToken": passwordResetToken}).Decode(&user) + if err != nil { + if err == mongo.ErrNoDocuments { + return c.String(http.StatusBadRequest, "Invalid password reset token") + } + return c.String(http.StatusInternalServerError, "Error while finding user") + } + + // Check if the password reset was requested within the past 24 hours + forgotPassword := user.ForgotPassword + delta := time.Now().Unix() - forgotPassword + if delta > 24*60*60 { + return c.String(http.StatusBadRequest, "Password reset token expired "+time.Duration(delta).String()) } - // add the new user to the database - // (this is a dummy implementation and would be replaced in a real application) - // ... + // Update the user document with the new password + filter := bson.M{"passwordResetToken": passwordResetToken} + var update bson.M + if time.Now().Unix()-forgotPassword > 5*60 { + update = bson.M{"$set": bson.M{"password": hashedPassword}, "$unset": bson.M{"passwordResetToken": ""}} + } else { + update = bson.M{"$set": bson.M{"password": hashedPassword}} + } + _, err = collection.UpdateOne(ctx, filter, update) + if err != nil { + return c.String(http.StatusInternalServerError, "Error while updating user") + } - // return a success response - return c.JSON(http.StatusOK, map[string]string{ - "message": "user registered successfully", - }) + return c.String(http.StatusOK, "Password successfully reset") } diff --git a/api/models/user.go b/api/models/user.go index 343938b..e3f38be 100644 --- a/api/models/user.go +++ b/api/models/user.go @@ -7,9 +7,9 @@ type User struct { Password string `json:"password" bson:"password" validate:"max=64,min=8"` RefreshToken string `json:"refreshToken,omitempty" bson:"refreshToken,omitempty"` CreatedAt int64 `json:"createdAt" bson:"createdAt"` - VerificationCode string `json:"verificationCode,omitempty" bson:"verificationCode,omitempty"` - PasswordResetToken string `json:"passwordResetToken,omitempty" bson:"passwordResetToken,omitempty"` + VerificationCode string `json:"verificationCode,omitempty" bson:"verificationCode,omitempty"` // Verification code for email verification + PasswordResetToken string `json:"passwordResetToken,omitempty" bson:"passwordResetToken,omitempty"` // Verification code for password reset LastSeen int64 `json:"lastSeen,omitempty" bson:"lastSeen,omitempty"` IsVerified bool `bson:"isVerified"` - ForgotPassword int64 `json:"forgotPassword,omitempty" bson:"forgotPassword,omitempty"` + ForgotPassword int64 `json:"forgotPassword,omitempty" bson:"forgotPassword,omitempty"` // Timestamp for forgot password }