diff --git a/frontend/src/api.js b/frontend/src/api.js
index 4689f42..d48bbf8 100644
--- a/frontend/src/api.js
+++ b/frontend/src/api.js
@@ -35,6 +35,12 @@ export default {
UserRegister(data) {
return ajax('user/register', 'post', { data })
},
+ UserForgetRequest(data) {
+ return ajax('user/forget', 'post', { data })
+ },
+ UserForgerPassword(data) {
+ return ajax('user/password', 'put', { data })
+ },
UserResetPassword(data) {
return ajax('user/password', 'post', { data })
},
diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js
index 3bf0b9a..9b47874 100644
--- a/frontend/src/router/index.js
+++ b/frontend/src/router/index.js
@@ -1,8 +1,10 @@
import AppLayout from '@/layout/AppLayout.vue';
import { createRouter, createWebHistory } from 'vue-router';
+import Forget from '@/views/Forget.vue';
import Login from '@/views/Login.vue';
import Register from '@/views/Register.vue';
+import Reset from '@/views/Reset.vue';
import Verify from '@/views/Verify.vue';
import InstanceCreate from '@/views/users/InstanceCreate.vue';
@@ -33,6 +35,16 @@ const router = createRouter({
name: 'register',
component: Register
},
+ {
+ path: '/forget',
+ name: 'forget',
+ component: Forget
+ },
+ {
+ path: '/reset/:code',
+ name: 'forget-reset',
+ component: Reset
+ },
{
path: '/verify/:code',
name: 'verify',
diff --git a/frontend/src/views/Forget.vue b/frontend/src/views/Forget.vue
new file mode 100644
index 0000000..c9bd384
--- /dev/null
+++ b/frontend/src/views/Forget.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
![]()
+
天权 算能聚联计算平台
+
忘记密码
+
+
+
+
+
+
+
+ 记起密码?立即登入
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/views/Login.vue b/frontend/src/views/Login.vue
index 3d24506..5c9dd86 100644
--- a/frontend/src/views/Login.vue
+++ b/frontend/src/views/Login.vue
@@ -25,7 +25,8 @@
没有账号?立即注册
- 忘记密码
+ 忘记密码
@@ -69,6 +70,10 @@ const handleSubmit = () => {
const handleRegister = () => {
router.push('/register')
}
+
+const handleForget = () => {
+ router.push('/forget')
+}
\ No newline at end of file
diff --git a/routers/api/v1/admin/users/modify.go b/routers/api/v1/admin/users/modify.go
index 4935e3b..992944f 100644
--- a/routers/api/v1/admin/users/modify.go
+++ b/routers/api/v1/admin/users/modify.go
@@ -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
}
}
diff --git a/routers/api/v1/user/forgerPassword.go b/routers/api/v1/user/forgerPassword.go
new file mode 100644
index 0000000..92e0b87
--- /dev/null
+++ b/routers/api/v1/user/forgerPassword.go
@@ -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)
+}
diff --git a/routers/api/v1/user/forgetSend.go b/routers/api/v1/user/forgetSend.go
new file mode 100644
index 0000000..2457a84
--- /dev/null
+++ b/routers/api/v1/user/forgetSend.go
@@ -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 = `
+
+
+
+
+ |
+ MEGREZ 天权算能聚联计算平台 |
+
+
+
+
+ Hello, %s:
+
+ 请在15分钟内点击链接: %s 进行密码重置操作,十五分钟后该链接将会失效.
+
+
+ 为了保护你的账户,请不要使用单一的密码来进行重置。
+
+
+ 如果您有任何问题,请联系系统管理员以获得更多信息与支持。
+
+
+ MEGREZ 天权算能聚联计算平台
+
+ |
+
+
+
+
+
+`
+
+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)
+}
diff --git a/routers/api/v1/user/routers.go b/routers/api/v1/user/routers.go
index 0c01102..17f0119 100644
--- a/routers/api/v1/user/routers.go
+++ b/routers/api/v1/user/routers.go
@@ -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)
diff --git a/routers/api/v1/user/verify.go b/routers/api/v1/user/verify.go
index 0115683..e7adf64 100644
--- a/routers/api/v1/user/verify.go
+++ b/routers/api/v1/user/verify.go
@@ -30,7 +30,6 @@ func verifyHandler(ctx iris.Context) {
}
email := v.Val()
- l.Debug("verify email: %s", email)
user := models.Users{
Email: email,
}
diff --git a/routers/api/v1/user/verifySend.go b/routers/api/v1/user/verifySend.go
index 63ebbab..9d3f1f9 100644
--- a/routers/api/v1/user/verifySend.go
+++ b/routers/api/v1/user/verifySend.go
@@ -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))