From d0e95f9521744e74ea804d4a0069be9c40cf505f Mon Sep 17 00:00:00 2001 From: Harry-zklcdc Date: Mon, 24 Feb 2025 17:15:14 +0800 Subject: [PATCH] =?UTF-8?q?[Feat]=20=E2=9C=A8=20Reset=20Email=20API=20&=20?= =?UTF-8?q?Pages=20#15?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api.js | 3 ++ frontend/src/views/users/Settings.vue | 43 +++++++++++++++---- libs/utils/email.go | 14 +++++++ routers/api/v1/admin/users/modify.go | 8 ++++ routers/api/v1/middleware/code.go | 18 ++++---- routers/api/v1/user/register.go | 6 +++ routers/api/v1/user/resetEmail.go | 59 +++++++++++++++++++++++++++ routers/api/v1/user/routers.go | 1 + 8 files changed, 135 insertions(+), 17 deletions(-) create mode 100644 libs/utils/email.go create mode 100644 routers/api/v1/user/resetEmail.go diff --git a/frontend/src/api.js b/frontend/src/api.js index 131d44e..4689f42 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -38,6 +38,9 @@ export default { UserResetPassword(data) { return ajax('user/password', 'post', { data }) }, + UserResetEmail(data) { + return ajax('user/email', 'post', { data }) + }, UserVerifyRequest() { return ajax(`user/verify`, 'post', {}) }, diff --git a/frontend/src/views/users/Settings.vue b/frontend/src/views/users/Settings.vue index df10d5a..af14269 100644 --- a/frontend/src/views/users/Settings.vue +++ b/frontend/src/views/users/Settings.vue @@ -22,16 +22,17 @@
修改邮箱
- - + +
-
-
-
@@ -74,8 +75,11 @@ const userProfile = ref({}) const verifyRequesting = ref(false) -const emailModifyStatus = ref(false) -const emailModifyValue = ref('') +const resetEmailModifyStatus = ref(false) +const resetEmailRequesting = ref(false) +const resetEmailData = ref({ + email: '' +}) const resetPasswordRequesting = ref(false) const resetPasswordData = ref({ @@ -87,7 +91,7 @@ const resetPasswordData = ref({ const getProfile = () => { api.GetUserProfile().then((res) => { userProfile.value = res.data.data.result - emailModifyValue.value = userProfile.value.email + resetEmailData.value.email = userProfile.value.email console.log(userProfile.value) }).catch((err) => { toast.add({ severity: 'error', summary: '获取用户信息失败', detail: err.response.data.msg, life: 3000 }) @@ -144,6 +148,27 @@ const resetPassword = () => { }) } +const resetEmail = () => { + resetEmailRequesting.value = true + + if (resetEmailData.value.email == '') { + toast.add({ severity: 'error', summary: '邮箱不能为空', detail: '请重新输入', life: 3000 }) + resetEmailRequesting.value = false + return + } + + api.UserResetEmail(resetEmailData.value).then((res) => { + toast.add({ severity: 'success', summary: '修改成功', detail: '请重新登录', life: 3000 }) + resetEmailRequesting.value = false + resetEmailModifyStatus.value = false + getProfile() + }).catch((err) => { + toast.add({ severity: 'error', summary: '修改失败', detail: err.response.data.msg, life: 3000 }) + resetEmailRequesting.value = false + console.error(err) + }) +} + onMounted(() => { getProfile() }) diff --git a/libs/utils/email.go b/libs/utils/email.go new file mode 100644 index 0000000..4bdc9a6 --- /dev/null +++ b/libs/utils/email.go @@ -0,0 +1,14 @@ +package utils + +import ( + "regexp" +) + +func EmailFormat(email string) bool { + pattern := `^\w+(-+.\w+)*@\w+(-.\w+)*.\w+(-.\w+)*$` + match, err := regexp.MatchString(pattern, email) + if err != nil { + return false + } + return match +} diff --git a/routers/api/v1/admin/users/modify.go b/routers/api/v1/admin/users/modify.go index 8e4c955..4935e3b 100644 --- a/routers/api/v1/admin/users/modify.go +++ b/routers/api/v1/admin/users/modify.go @@ -1,6 +1,7 @@ package users import ( + "megrez/libs/utils" "megrez/models" "megrez/routers/api/v1/middleware" "megrez/services/database" @@ -9,6 +10,7 @@ import ( ) type modifyReqStruct struct { + Email *string `json:"email"` Password *string `json:"password"` Role *int `json:"role"` Verify *bool `json:"verify"` @@ -46,6 +48,12 @@ func modifyHandler(ctx iris.Context) { return } + if req.Email != nil { + if *req.Email != "" && utils.EmailFormat(*req.Email) { + user.Email = *req.Email + } + } + if req.Password != nil { if *req.Password != "" { user.Password = user.PasswordHash(*req.Password) diff --git a/routers/api/v1/middleware/code.go b/routers/api/v1/middleware/code.go index df74601..7f54802 100644 --- a/routers/api/v1/middleware/code.go +++ b/routers/api/v1/middleware/code.go @@ -14,6 +14,11 @@ const ( CodeUserNotExist ResCode = 1002 CodeRegisterRequestError ResCode = 1003 CodeRegisterError ResCode = 1004 + CodeEmailFormatError ResCode = 1005 + CodeUserAlreadyVerified ResCode = 1006 + CodeUserVerifyInvalid ResCode = 1007 + CodePasswordNotMatch ResCode = 1008 + CodeInternalCreateError ResCode = 1010 CodeInstanceDeleteError ResCode = 1011 CodeInstanceQueryError ResCode = 1012 @@ -42,10 +47,6 @@ const ( CodeAdminUserDeleteError ResCode = 2013 CodeAdminUserInstanceNoEmpty ResCode = 2014 CodeAdminUserModifyError ResCode = 2015 - - CodeUserAlreadyVerified ResCode = 3001 - CodeUserVerifyInvalid ResCode = 3002 - CodePasswordNotMatch ResCode = 3003 ) var codeMsgMap = map[ResCode]string{ @@ -60,6 +61,11 @@ var codeMsgMap = map[ResCode]string{ CodeUserNotExist: "user not exist", CodeRegisterRequestError: "register request error", CodeRegisterError: "username or email exist", + CodeEmailFormatError: "email format error", + CodeUserAlreadyVerified: "user already verified", + CodeUserVerifyInvalid: "email verify error", + CodePasswordNotMatch: "password not match", + CodeInternalCreateError: "create error", CodeInstanceDeleteError: "delete instance error", CodeInstanceStatusError: "instance status error", @@ -88,8 +94,4 @@ var codeMsgMap = map[ResCode]string{ CodeAdminUserDeleteError: "delete user error", CodeAdminUserModifyError: "modify user error", CodeAdminUserInstanceNoEmpty: "user instances not empty", - - CodeUserAlreadyVerified: "user already verified", - CodeUserVerifyInvalid: "email verify error", - CodePasswordNotMatch: "password not match", } diff --git a/routers/api/v1/user/register.go b/routers/api/v1/user/register.go index 6ca6334..503701d 100644 --- a/routers/api/v1/user/register.go +++ b/routers/api/v1/user/register.go @@ -1,6 +1,7 @@ package user import ( + "megrez/libs/utils" "megrez/models" "megrez/routers/api/v1/middleware" "megrez/services/config" @@ -29,6 +30,11 @@ func registerHandler(ctx iris.Context) { return } + if !utils.EmailFormat(userReq.Email) { + middleware.Error(ctx, middleware.CodeEmailFormatError, iris.StatusBadRequest) + return + } + user := models.Users{ Username: userReq.Username, Email: userReq.Email, diff --git a/routers/api/v1/user/resetEmail.go b/routers/api/v1/user/resetEmail.go new file mode 100644 index 0000000..f2f3a6a --- /dev/null +++ b/routers/api/v1/user/resetEmail.go @@ -0,0 +1,59 @@ +package user + +import ( + "megrez/libs/utils" + "megrez/models" + "megrez/routers/api/v1/middleware" + "megrez/services/database" + + "github.com/kataras/iris/v12" +) + +type resetEmailStruct struct { + Email string `json:"email"` +} + +func resetEmailHandler(ctx iris.Context) { + l.SetFunction("resetEmailHandler") + + userId, err := ctx.Values().GetInt("userId") + if err != nil { + middleware.Error(ctx, middleware.CodeBadRequest, iris.StatusBadRequest) + return + } + + var req resetEmailStruct + 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 + } + + if !utils.EmailFormat(req.Email) { + middleware.Error(ctx, middleware.CodeEmailFormatError, iris.StatusBadRequest) + return + } + + user := models.Users{ + ID: uint(userId), + } + result := database.DB.First(&user) + if result.Error != nil { + l.Error("get user error: %v", result.Error) + middleware.Error(ctx, middleware.CodeUserNotExist, iris.StatusInternalServerError) + return + } + + result = database.DB.Model(&user).Update("email", req.Email).Update("verify", false) + if result.Error != nil { + l.Error("save user error: %v", result.Error) + middleware.Error(ctx, middleware.CodeInternalPatchError, iris.StatusInternalServerError) + return + } + + middleware.Success(ctx) +} diff --git a/routers/api/v1/user/routers.go b/routers/api/v1/user/routers.go index 3e33087..0c01102 100644 --- a/routers/api/v1/user/routers.go +++ b/routers/api/v1/user/routers.go @@ -25,6 +25,7 @@ func InitUser(party router.Party) { party.Post("/register", registerHandler) party.Get("/profile", middleware.AuthCheck, profileHandler) party.Post("/password", middleware.AuthCheck, resetPasswordHandler) + party.Post("/email", middleware.AuthCheck, resetEmailHandler) party.Get("/verify/{code:string}", verifyHandler) party.Post("/verify", middleware.AuthCheck, verifySendHandler)