Maison >développement back-end >Golang >Fonction de réinitialisation du mot de passe : utilisation d'OTP pour réinitialiser le mot de passe
Passons à l'API suivante.
METTRE sur /api/reset-password, req -> otp, email, nouveau mot de passe, res -> pas de contenu
// controllers/passwordReset.go func ResetPassword(c *fiber.Ctx) error { type Input struct { OTP string `json:"otp"` Email string `json:"email"` NewPassword string `json:"new_password"` } var input Input err := c.BodyParser(&input) if err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "invalid data", }) } // no input field should be empty if input.OTP == "" || input.Email == "" || input.NewPassword == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "invalid data", }) } // TODO: check redis for otp and update password return c.SendStatus(fiber.StatusNoContent) }
Ajout d'un itinéraire pour cela
// routes/routes.go api.Put("/reset-password", controllers.ResetPassword)
Maintenant, j'ai besoin de deux fonctions :
// utils/passwordReset.go func VerifyOTP(otp string, email string, c context.Context) (error, bool) { key := otpKeyPrefix + email // get the value for the key value, err := config.RedisClient.Get(c, key).Result() if err != nil { // the following states that the key was not found if err == redis.Nil { return errors.New("otp expired / incorrect email"), false } // for other errors return err, true } // compare received otp's hash with value in redis err = bcrypt.CompareHashAndPassword([]byte(value), []byte(otp)) if err != nil { return errors.New("incorrect otp"), false } // delete redis key to prevent abuse of otp err = config.RedisClient.Del(c, key).Err() if err != nil { return err, true } return nil, false } func UpdatePassword(email string, password string, c context.Context) error { users := config.DB.Collection("users") // hash the password hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(password), 10) // update the password update := bson.M{ "$set": bson.M{ "password": hashedPassword, }, } _, err := users.UpdateByID(c, email, update) if err != nil { return err } return nil }
Maintenant, je dois les assembler tous les deux dans le contrôleur. J'utilise le booléen de la fonction VerifyOTP pour indiquer si l'erreur est une erreur interne ou si elle est due à l'entrée.
// controllers/passwordReset.go func ResetPassword(c *fiber.Ctx) error { type Input struct { OTP string `json:"otp"` Email string `json:"email"` NewPassword string `json:"new_password"` } var input Input err := c.BodyParser(&input) if err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "invalid data", }) } // no input field should be empty if input.OTP == "" || input.Email == "" || input.NewPassword == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "invalid data", }) } // check redis for otp err, isInternalErr := utils.VerifyOTP(input.OTP, input.Email, c.Context()) if err != nil { var code int if isInternalErr { code = fiber.StatusInternalServerError } else { code = fiber.StatusUnauthorized } return c.Status(code).JSON(fiber.Map{ "error": err.Error(), }) } err = utils.UpdatePassword(input.Email, input.NewPassword, c.Context()) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": err.Error(), }) } return c.SendStatus(fiber.StatusNoContent) }
L'API est maintenant construite et les tests peuvent être effectués à l'aide de la commande cURL suivante
curl --location --request PUT 'localhost:3000/api/reset-password' \ --header 'Content-Type: application/json' \ --data-raw '{ "email": "yashjaiswal.cse@gmail.com", "new_password": "tester123", "otp": "DM4RDNF07B" }'
Dans la prochaine partie, je commencerai par le frontend
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!