الانتقال إلى واجهة برمجة التطبيقات التالية.
ضع على /api/reset-password، req -> otp، البريد الإلكتروني، كلمة المرور الجديدة، res -> nocontent
// 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) }
إضافة مسار لها
// routes/routes.go api.Put("/reset-password", controllers.ResetPassword)
الآن أحتاج إلى وظيفتين:
// 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 }
الآن أنا بحاجة إلى تجميعهما معًا في وحدة التحكم. أنا أستخدم المنطقي من وظيفة VerifyOTP للإشارة إلى ما إذا كان الخطأ خطأ داخلي أم أنه بسبب الإدخال.
// 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) }
تم الآن إنشاء واجهة برمجة التطبيقات، ويمكن إجراء الاختبار باستخدام أمر cURL التالي
curl --location --request PUT 'localhost:3000/api/reset-password' \ --header 'Content-Type: application/json' \ --data-raw '{ "email": "[email protected]", "new_password": "tester123", "otp": "DM4RDNF07B" }'
في الجزء التالي، سأبدأ بالواجهة الأمامية
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3