From 398b8af489702590722fa3439544ca88accdc308 Mon Sep 17 00:00:00 2001 From: hucan <951870319@qq.com> Date: Fri, 18 Jul 2025 18:05:56 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=A2=9E=E5=8A=A0=E6=B3=A8=E5=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/apis/sys_user.go | 19 +++---- app/admin/router/sys_router.go | 2 + app/admin/service/dto/sys_user.go | 51 +++++++++++++++++-- app/admin/service/sys_user.go | 82 +++++++++++++++++++++++++++++-- common/statuscode/status_code.go | 26 ++++++++++ go.mod | 1 + utils/utility/email_helper.go | 8 +++ 7 files changed, 172 insertions(+), 17 deletions(-) create mode 100644 utils/utility/email_helper.go diff --git a/app/admin/apis/sys_user.go b/app/admin/apis/sys_user.go index d0b4338..913727e 100644 --- a/app/admin/apis/sys_user.go +++ b/app/admin/apis/sys_user.go @@ -133,7 +133,7 @@ func (e SysUser) Register(c *gin.Context) { s := service.SysUser{} err := e.MakeContext(c). MakeOrm(). - Bind(&req, binding.JSON). + Bind(&req). MakeService(&s.Service). Errors if err != nil { @@ -142,18 +142,19 @@ func (e SysUser) Register(c *gin.Context) { return } - code, err := s.Register(&req) - - if err != nil { - e.Logger.Error(err) - e.Error(500, nil, err.Error()) - return - } else if code != statuscode.Success { + if code := req.Validate(); code != statuscode.Success { e.Error(code, nil, statuscode.GetMsg(code, req.Lang)) return } - e.OK(nil, statuscode.GetMsg(code, req.Lang)) + result, code := s.Register(&req) + + if code != statuscode.Success { + e.Error(code, nil, statuscode.GetMsg(code, req.Lang)) + return + } + + e.OK(result, statuscode.GetMsg(code, req.Lang)) } // Update diff --git a/app/admin/router/sys_router.go b/app/admin/router/sys_router.go index b713e4b..a4b3258 100644 --- a/app/admin/router/sys_router.go +++ b/app/admin/router/sys_router.go @@ -60,6 +60,7 @@ func sysSwaggerRouter(r *gin.RouterGroup) { } func sysCheckRoleRouterInit(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { + api := apis.SysUser{} wss := r.Group("").Use(authMiddleware.MiddlewareFunc()) { wss.GET("/ws/:id/:channel", ws.WebsocketManager.WsClient) @@ -71,6 +72,7 @@ func sysCheckRoleRouterInit(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle v1.POST("/login", authMiddleware.LoginHandler) // Refresh time can be longer than token timeout v1.GET("/refresh_token", authMiddleware.RefreshHandler) + v1.POST("signup", api.Register) } registerBaseRouter(v1, authMiddleware) } diff --git a/app/admin/service/dto/sys_user.go b/app/admin/service/dto/sys_user.go index 35c7322..5cc315a 100644 --- a/app/admin/service/dto/sys_user.go +++ b/app/admin/service/dto/sys_user.go @@ -2,9 +2,14 @@ package dto import ( "go-admin/app/admin/models" + "go-admin/utils/utility" + "strings" "go-admin/common/dto" common "go-admin/common/models" + "go-admin/common/statuscode" + + "github.com/go-admin-team/go-admin-core/sdk/pkg/captcha" ) type SysUserGetPageReq struct { @@ -106,10 +111,43 @@ type SysUserInsertReq struct { } type RegisterReq struct { - Lang string `json:"lang" ` - Email string `json:"email" comment:"邮箱" vd:"len($)>0,email"` - PassWord string `json:"password" comment:"密码" vd:"len($)>0"` - ConfirmPassword string `json:"confirmPassword" comment:"确认密码" vd:"len($)>0"` + Lang string `json:"lang" form:"lang"` + Email string `json:"email" form:"email" comment:"邮箱"` + PassWord string `json:"pwd" form:"pwd" comment:"密码"` + ConfirmPassword string `json:"kwd" form:"kwd" comment:"确认密码"` + UUID string `json:"uuid" form:"uuid"` + Code string `json:"code" form:"code"` +} + +func (e *RegisterReq) Validate() int { + if e.Email == "" { + return statuscode.EmailEmpty + } + + if e.Email != "" && !utility.IsValidEmail(e.Email) { + return statuscode.EmailFormatError + } + + e.PassWord = strings.TrimSpace(e.PassWord) + e.ConfirmPassword = strings.TrimSpace(e.ConfirmPassword) + + if e.PassWord == "" { + return statuscode.PasswordEmpty + } + + if e.ConfirmPassword == "" { + return statuscode.ConfirmPasswordEmpty + } + + if e.PassWord != e.ConfirmPassword { + return statuscode.PassWordNotMatch + } + + if !captcha.Verify(e.UUID, e.Code, true) { + return statuscode.VerifyCodeError + } + + return statuscode.Success } func (s *SysUserInsertReq) Generate(model *models.SysUser) { @@ -194,3 +232,8 @@ type PassWord struct { NewPassword string `json:"newPassword" vd:"len($)>0"` OldPassword string `json:"oldPassword" vd:"len($)>0"` } + +type SysUserRegisterResp struct { + Token string `json:"token"` + Expire int `json:"expire"` +} diff --git a/app/admin/service/sys_user.go b/app/admin/service/sys_user.go index ac656f7..8ad4b9f 100644 --- a/app/admin/service/sys_user.go +++ b/app/admin/service/sys_user.go @@ -4,10 +4,13 @@ import ( "errors" "go-admin/app/admin/models" "go-admin/app/admin/service/dto" + "time" log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk/config" "github.com/go-admin-team/go-admin-core/sdk/pkg" "github.com/go-admin-team/go-admin-core/sdk/service" + "github.com/golang-jwt/jwt" "gorm.io/gorm" "go-admin/common/actions" @@ -20,23 +23,94 @@ type SysUser struct { } // 用户注册账号 -func (e SysUser) Register(req *dto.RegisterReq) (int, error) { +func (e SysUser) Register(req *dto.RegisterReq) (dto.SysUserRegisterResp, int) { + var role models.SysRole + result := dto.SysUserRegisterResp{} data := models.SysUser{ Username: req.Email, Email: req.Email, Password: req.PassWord, Status: "2", NickName: req.Email, - DeptId: 11, } data.Username = req.Email var count int64 if err := e.Orm.Model(data).Where("username = ?", req.Email).Count(&count).Error; err != nil { - return statuscode.AccountExisted, nil + return result, statuscode.AccountExisted } - return statuscode.Success, nil + if count > 0 { + return result, statuscode.AccountExisted + } + + if err := e.Orm.Model(&role).Where("role_key = ?", "normal_member").First(&role).Error; err != nil { + e.Log.Errorf("角色不存在") + return result, statuscode.ServerError + } + + data.RoleId = role.RoleId + + err := e.Orm.Transaction(func(tx *gorm.DB) error { + if err1 := tx.Create(&data).Error; err1 != nil { + e.Log.Errorf("创建用户失败 %v", err1) + return err1 + } + + token, expire, err1 := e.GenerateTokenForUser(&data, &role) + + if err1 != nil { + e.Log.Errorf("生成token 失败 %v", err1) + return err1 + } + + result.Token = token + result.Expire = int(expire.Unix()) + + return nil + }) + + if err != nil { + return result, statuscode.ServerError + } + + return result, statuscode.Success +} + +// 假设 mw 是 *GinJWTMiddleware 实例,user 是刚注册成功的用户对象 +func (e *SysUser) GenerateTokenForUser(user *models.SysUser, role *models.SysRole) (string, time.Time, error) { + // 1. 创建 token 对象 + token := jwt.New(jwt.GetSigningMethod("HS256")) + claims := token.Claims.(jwt.MapClaims) + claims["identity"] = user.UserId + claims["roleid"] = user.RoleId + claims["rolekey"] = role.RoleKey + claims["nice"] = user.Username + claims["datascope"] = role.DataScope + claims["rolename"] = role.RoleName + + timeout := time.Hour + if config.ApplicationConfig.Mode == "dev" { + timeout = time.Duration(876010) * time.Hour + } else { + if config.JwtConfig.Timeout != 0 { + timeout = time.Duration(config.JwtConfig.Timeout) * time.Second + } + } + + now := time.Now() + // 3. 设置过期时间 + expire := now.Add(timeout) + claims["exp"] = expire.Unix() + claims["orig_iat"] = now.Unix() + + // 4. 签名 token + tokenString, err := token.SignedString([]byte(config.JwtConfig.Secret)) //mw.signedString(token) + if err != nil { + return "", time.Time{}, err + } + + return tokenString, expire, nil } // GetPage 获取SysUser列表 diff --git a/common/statuscode/status_code.go b/common/statuscode/status_code.go index 5c77149..14e50bd 100644 --- a/common/statuscode/status_code.go +++ b/common/statuscode/status_code.go @@ -5,6 +5,12 @@ var StatusCodeZh = map[int]string{ AccountExisted: "账号已存在", AccountOrPasswordError: "账号或密码错误", PassWordNotMatch: "密码不一致", + ServerError: "服务端错误,请联系管理员", + EmailEmpty: "邮箱不能为空", + EmailFormatError: "邮箱格式不正确", + PasswordEmpty: "密码不能为空", + ConfirmPasswordEmpty: "确认密码不能为空", + VerifyCodeError: "验证码错误", } var StatusCodeEn = map[int]string{ @@ -12,6 +18,12 @@ var StatusCodeEn = map[int]string{ AccountExisted: "account already existed", AccountOrPasswordError: "account or password error", PassWordNotMatch: "password not match", + ServerError: "server error, please contact admin", + EmailEmpty: "email can not be empty", + EmailFormatError: "email format error", + PasswordEmpty: "password can not be empty", + ConfirmPasswordEmpty: "confirm password can not be empty", + VerifyCodeError: "verify code error", } func GetMsg(code int, lang string) string { @@ -33,4 +45,18 @@ const ( AccountOrPasswordError = 10003 //密码不一致 PassWordNotMatch = 10004 + + // + ServerError = 500 + + //邮箱不能为空 + EmailEmpty = 10005 + //邮箱格式不正确 + EmailFormatError = 10006 + //密码不能为空 + PasswordEmpty = 10007 + //确认密码不能为空 + ConfirmPasswordEmpty = 10008 + //验证码错误 + VerifyCodeError = 10009 ) diff --git a/go.mod b/go.mod index 8d03a50..329899e 100644 --- a/go.mod +++ b/go.mod @@ -77,6 +77,7 @@ require ( github.com/go-redis/redis/v7 v7.4.0 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 // indirect diff --git a/utils/utility/email_helper.go b/utils/utility/email_helper.go new file mode 100644 index 0000000..817c6c8 --- /dev/null +++ b/utils/utility/email_helper.go @@ -0,0 +1,8 @@ +package utility + +import "net/mail" + +func IsValidEmail(email string) bool { + _, err := mail.ParseAddress(email) + return err == nil +}