[Feat] Add ForgetPassword API & Pages #15

This commit is contained in:
Harry-zklcdc
2025-02-24 18:05:38 +08:00
parent 801335ab5d
commit 35a55a9e03
11 changed files with 381 additions and 4 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ func modifyHandler(ctx iris.Context) {
}
if req.Email != nil {
if *req.Email != "" && utils.EmailFormat(*req.Email) {
if *req.Email != "" && !utils.EmailFormat(*req.Email) {
user.Email = *req.Email
}
}
+78
View File
@@ -0,0 +1,78 @@
package user
import (
"megrez/models"
"megrez/routers/api/v1/middleware"
"megrez/services/database"
"megrez/services/redis"
"github.com/kataras/iris/v12"
)
type forgerPasswordStruct struct {
Code string `json:"code"`
Password string `json:"password"`
RePassword string `json:"repassword"`
}
func forgetPasswordHandler(ctx iris.Context) {
l.SetFunction("forgetPasswordHandler")
var req forgerPasswordStruct
if err := ctx.ReadJSON(&req); err != nil {
middleware.Error(ctx, middleware.CodeBadRequest, iris.StatusBadRequest)
return
}
if req.Code == "" || req.Password == "" || req.RePassword == "" {
middleware.Error(ctx, middleware.CodeBadRequest, iris.StatusBadRequest)
return
}
if req.Password != req.RePassword {
middleware.Error(ctx, middleware.CodePasswordNotMatch, iris.StatusBadRequest)
return
}
rdb := redis.RawDB
v := rdb.Get(ctx, forgetPasswordRedisKeyPrefix+req.Code)
if v.Err() != nil {
middleware.Error(ctx, middleware.CodeUserVerifyInvalid, iris.StatusBadRequest)
return
}
r := rdb.Del(ctx, forgetPasswordRedisKeyPrefix+req.Code)
if r.Err() != nil {
middleware.Error(ctx, middleware.CodeServeBusy, iris.StatusInternalServerError)
l.Error("delete redis verify code error: %v", r.Err())
return
}
id, err := v.Int()
if err != nil {
middleware.Error(ctx, middleware.CodeUserVerifyInvalid, iris.StatusBadRequest)
return
}
user := models.Users{
ID: uint(id),
}
result := database.DB.First(&user)
if result.Error != nil {
l.Error("get user error: %v", result.Error)
middleware.Error(ctx, middleware.CodeUserVerifyInvalid, iris.StatusBadRequest)
return
}
user.Password = user.PasswordHash(req.Password)
result = database.DB.Model(&user).Update("password", user.Password)
if result.Error != nil {
middleware.Error(ctx, middleware.CodeServeBusy, iris.StatusInternalServerError)
l.Error("update user password Error: %v", result.Error)
return
}
middleware.Success(ctx)
}
+97
View File
@@ -0,0 +1,97 @@
package user
import (
"fmt"
"megrez/libs/crypto"
"megrez/models"
"megrez/routers/api/v1/middleware"
"megrez/services/config"
"megrez/services/database"
"megrez/services/redis"
"megrez/services/smtp"
"time"
"github.com/kataras/iris/v12"
)
type forgetSendStruct struct {
Email string `json:"email"`
}
const forgetPasswordRedisKeyPrefix = "forget:user:"
const forgetPasswordUrlPrefix = "/reset/"
const forgetPasswordTitle = "重置密码"
const forgetPasswordHTMLFormat = `
<div>
<table cellpadding="0" align="center" style="overflow:hidden;background:#fff;margin:0 auto;text-align:left;position:relative;font-size:14px; font-family:'lucida Grande',Verdana;line-height:1.5;box-shadow:0 0 3px #ccc;border:1px solid #ccc;border-radius:5px;border-collapse:collapse;">
<tbody>
<tr>
<th valign="middle" style="height:38px;color:#fff; font-size:14px;line-height:38px; font-weight:bold;text-align:left;padding:10px 24px 6px; border-bottom:1px solid #467ec3;background:#518bcb;border-radius:5px 5px 0 0;">
MEGREZ 天权算能聚联计算平台</th>
</tr>
<tr>
<td>
<div style="padding:20px 35px 40px;">
<h2 style="font-weight:bold;margin-bottom:5px;font-size:14px;">Hello, %s:</h2>
<p style="margin-top:20px">
请在15分钟内点击链接: <a href="%s">%s</a> &nbsp;进行密码重置操作,十五分钟后该链接将会失效.
</p>
<p style="margin-top:20px">
为了保护你的账户,请不要使用单一的密码来进行重置。
</p>
<p style="margin-top:20px">
如果您有任何问题,请联系系统管理员以获得更多信息与支持。
</p>
<p style="margin-left:2em;"></p>
<p style="text-indent:0;text-align:right;">MEGREZ 天权算能聚联计算平台</p>
</div>
</td>
</tr>
</tbody>
</table>
</div>
`
func forgetSendHandler(ctx iris.Context) {
var req forgetSendStruct
if err := ctx.ReadJSON(&req); err != nil {
middleware.Error(ctx, middleware.CodeBadRequest, iris.StatusBadRequest)
return
}
if req.Email == "" {
middleware.Error(ctx, middleware.CodeBadRequest, iris.StatusBadRequest)
return
}
user := models.Users{
Email: req.Email,
}
result := database.DB.Where(&user).First(&user)
if result.Error != nil {
l.Error("get user error: %v", result.Error)
middleware.Error(ctx, middleware.CodeUserNotExist, iris.StatusInternalServerError)
return
}
rdb := redis.RawDB
forgetUrl := crypto.Hex(32)
err := rdb.Set(ctx, forgetPasswordRedisKeyPrefix+forgetUrl, user.ID, 15*time.Minute).Err()
if err != nil {
middleware.Error(ctx, middleware.CodeServeBusy, iris.StatusInternalServerError)
l.Error("Set Redis error: %v", err)
return
}
forgetUrl = config.GetSystemBaseUrl() + forgetPasswordUrlPrefix + forgetUrl
err = smtp.Send(user.Email, forgetPasswordTitle, fmt.Sprintf(forgetPasswordHTMLFormat, user.Username, forgetUrl, forgetUrl))
if err != nil {
middleware.Error(ctx, middleware.CodeServeBusy, iris.StatusInternalServerError)
l.Error("Send SMTP Error: %v", err)
return
}
middleware.Success(ctx)
}
+2
View File
@@ -25,6 +25,8 @@ func InitUser(party router.Party) {
party.Post("/register", registerHandler)
party.Get("/profile", middleware.AuthCheck, profileHandler)
party.Post("/password", middleware.AuthCheck, resetPasswordHandler)
party.Post("/forget", forgetSendHandler)
party.Put("/password", forgetPasswordHandler)
party.Post("/email", middleware.AuthCheck, resetEmailHandler)
party.Get("/verify/{code:string}", verifyHandler)
party.Post("/verify", middleware.AuthCheck, verifySendHandler)
-1
View File
@@ -30,7 +30,6 @@ func verifyHandler(ctx iris.Context) {
}
email := v.Val()
l.Debug("verify email: %s", email)
user := models.Users{
Email: email,
}
+6 -1
View File
@@ -73,7 +73,12 @@ func verifySendHandler(ctx iris.Context) {
rdb := redis.RawDB
verifyUrl := crypto.Hex(32)
rdb.Set(ctx, verifyRedisKeyPrefix+verifyUrl, user.Email, 15*time.Minute)
err = rdb.Set(ctx, verifyRedisKeyPrefix+verifyUrl, user.Email, 15*time.Minute).Err()
if err != nil {
middleware.Error(ctx, middleware.CodeServeBusy, iris.StatusInternalServerError)
l.Error("Set Redis Error: %v", err)
return
}
verifyUrl = config.GetSystemBaseUrl() + verifyUrlPrefix + verifyUrl
err = smtp.Send(user.Email, verifyTitle, fmt.Sprintf(verifyHTMLFormat, user.Username, verifyUrl, verifyUrl))