package controller import ( "fmt" "be.ems/src/framework/i18n" "be.ems/src/framework/reqctx" "be.ems/src/framework/resp" "be.ems/src/framework/token" "be.ems/src/framework/utils/crypto" "be.ems/src/framework/utils/parse" "be.ems/src/framework/utils/regular" "be.ems/src/modules/system/service" "github.com/gin-gonic/gin" ) // 实例化控制层 SysProfileController 结构体 var NewSysProfile = &SysProfileController{ sysUserService: service.NewSysUser, sysRoleService: service.NewSysRole, sysPostService: service.NewSysPost, sysMenuService: service.NewSysMenu, } // 个人信息 // // PATH /system/user/profile type SysProfileController struct { sysUserService *service.SysUser // 用户服务 sysRoleService *service.SysRole // 角色服务 sysPostService *service.SysPost // 岗位服务 sysMenuService *service.SysMenu // 菜单服务 } // 个人信息 // // GET / // // @Tags system/user/profile // @Accept json // @Produce json // @Success 200 {object} object "Response Results" // @Security TokenAuth // @Summary Personal Information // @Description Personal Information // @Router /system/user/profile [get] func (s *SysProfileController) Info(c *gin.Context) { language := reqctx.AcceptLanguage(c) loginUser, err := reqctx.LoginUser(c) if err != nil { c.JSON(401, resp.CodeMsg(401, i18n.TKey(language, err.Error()))) return } // 查询用户所属角色组 roleGroup := []string{} roles := s.sysRoleService.FindByUserId(loginUser.User.UserId) for _, role := range roles { roleGroup = append(roleGroup, i18n.TKey(language, role.RoleName)) } // 查询用户所属岗位组 postGroup := []string{} posts := s.sysPostService.FindByUserId(loginUser.User.UserId) for _, post := range posts { postGroup = append(postGroup, i18n.TKey(language, post.PostName)) } loginUser.User.NickName = i18n.TKey(language, loginUser.User.NickName) loginUser.User.Remark = i18n.TKey(language, loginUser.User.Remark) loginUser.User.Dept.DeptName = i18n.TKey(language, loginUser.User.Dept.DeptName) for ri := range loginUser.User.Roles { loginUser.User.Roles[ri].RoleName = i18n.TKey(language, loginUser.User.Roles[ri].RoleName) } c.JSON(200, resp.OkData(map[string]any{ "user": loginUser.User, "roleGroup": parse.RemoveDuplicates(roleGroup), "postGroup": parse.RemoveDuplicates(postGroup), })) } // 个人信息修改 // // PUT / // // @Tags system/user/profile // @Accept json // @Produce json // @Param data body object true "Request Param" // @Success 200 {object} object "Response Results" // @Security TokenAuth // @Summary Personal Information Modification // @Description Personal Information Modification // @Router /system/user/profile [put] func (s *SysProfileController) UpdateProfile(c *gin.Context) { language := reqctx.AcceptLanguage(c) var body struct { NickName string `json:"nickName" binding:"required"` // 昵称 Sex string `json:"sex" binding:"required,oneof=0 1 2"` // 性别 Phone string `json:"phone"` // 手机号 Email string `json:"email"` // 邮箱 Avatar string `json:"avatar"` // 头像地址 } if err := c.ShouldBindBodyWithJSON(&body); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } // 登录用户信息 loginUser, err := reqctx.LoginUser(c) if err != nil { c.JSON(401, resp.CodeMsg(401, i18n.TKey(language, err.Error()))) return } userId := loginUser.UserId userName := loginUser.User.UserName // 检查手机号码格式并判断是否唯一 if body.Phone != "" { if regular.ValidMobile(body.Phone) { uniquePhone := s.sysUserService.CheckUniqueByPhone(body.Phone, userId) if !uniquePhone { // c.JSON(200, resp.CodeMsg(40018, "抱歉,手机号码已存在")) msg := i18n.TTemplate(language, "user.errPhoneExists", map[string]any{"name": userName}) c.JSON(200, resp.ErrMsg(msg)) return } } else { // c.JSON(200, resp.CodeMsg(40018, "抱歉,手机号码格式错误")) msg := i18n.TTemplate(language, "user.errPhoneFormat", map[string]any{"name": userName}) c.JSON(200, resp.ErrMsg(msg)) return } } // 检查邮箱格式并判断是否唯一 if body.Email != "" { if regular.ValidEmail(body.Email) { uniqueEmail := s.sysUserService.CheckUniqueByEmail(body.Email, userId) if !uniqueEmail { // c.JSON(200, resp.CodeMsg(40019, "抱歉,邮箱已存在")) msg := i18n.TTemplate(language, "user.errEmailExists", map[string]any{"name": userName}) c.JSON(200, resp.ErrMsg(msg)) return } } else { // c.JSON(200, resp.CodeMsg(40019, "抱歉,邮箱格式错误")) msg := i18n.TTemplate(language, "user.errEmailFormat", map[string]any{"name": userName}) c.JSON(200, resp.ErrMsg(msg)) return } } // 查询当前登录用户信息 userInfo := s.sysUserService.FindById(userId) if userInfo.UserId != userId { // c.JSON(200, resp.ErrMsg("没有权限访问用户数据!")) c.JSON(200, resp.ErrMsg(i18n.TKey(language, "user.noData"))) return } // 用户基本资料 userInfo.NickName = body.NickName userInfo.Phone = body.Phone userInfo.Email = body.Email userInfo.Sex = body.Sex userInfo.Avatar = body.Avatar userInfo.Password = "" // 密码不更新 userInfo.UpdateBy = userInfo.UserName rows := s.sysUserService.Update(userInfo) if rows > 0 { // 更新缓存用户信息 loginUser.User = userInfo // 刷新令牌信息 token.Cache(&loginUser) c.JSON(200, resp.Ok(nil)) return } c.JSON(200, resp.ErrMsg("Modification of personal information exception")) } // 个人重置密码 // // PUT /password // // @Tags system/user/profile // @Accept json // @Produce json // @Param data body object true "Request Param" // @Success 200 {object} object "Response Results" // @Security TokenAuth // @Summary Personal Reset Password // @Description Personal Reset Password // @Router /system/user/profile/password [put] func (s *SysProfileController) PasswordUpdate(c *gin.Context) { language := reqctx.AcceptLanguage(c) var body struct { OldPassword string `json:"oldPassword" binding:"required"` // 旧密码 NewPassword string `json:"newPassword" binding:"required"` // 新密码 } if err := c.ShouldBindBodyWithJSON(&body); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } // 登录用户信息 loginUser, err := reqctx.LoginUser(c) if err != nil { c.JSON(401, resp.CodeMsg(401, i18n.TKey(language, err.Error()))) return } userId := loginUser.UserId // 查询当前登录用户信息得到密码值 userInfo := s.sysUserService.FindById(userId) if userInfo.UserId != userId { // c.JSON(200, resp.ErrMsg("没有权限访问用户数据!")) c.JSON(200, resp.ErrMsg(i18n.TKey(language, "user.noData"))) return } // 检查匹配用户密码 oldCompare := crypto.BcryptCompare(body.OldPassword, userInfo.Password) if !oldCompare { // c.JSON(200, resp.ErrMsg("修改密码失败,旧密码错误")) c.JSON(200, resp.ErrMsg(i18n.TKey(language, "user.errPasswdOld"))) return } newCompare := crypto.BcryptCompare(body.NewPassword, userInfo.Password) if newCompare { // c.JSON(200, resp.ErrMsg("新密码不能与旧密码相同")) c.JSON(200, resp.ErrMsg(i18n.TKey(language, "user.errPasswdEqOld"))) return } // 检查密码是否与历史密码一致 err = s.sysUserService.ValidatePasswordNotAllowedHistory(userInfo.UserId, body.NewPassword) if err != nil { c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } // 修改新密码 userInfo.Password = body.NewPassword userInfo.UpdateBy = userInfo.UserName rows := s.sysUserService.Update(userInfo) if rows > 0 { c.JSON(200, resp.Ok(nil)) return } c.JSON(200, resp.Err(nil)) } // 强制重置密码 // // PUT /password-force func (s *SysProfileController) PasswordForce(c *gin.Context) { language := reqctx.AcceptLanguage(c) var body struct { Password string `json:"password" binding:"required"` } if err := c.ShouldBindBodyWithJSON(&body); err != nil { errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } // 检查用户密码策略强度 ok, errMsg := s.sysUserService.ValidatePasswordPolicy(body.Password, language) if !ok { c.JSON(200, resp.ErrMsg(errMsg)) return } // 登录用户信息 loginUser, err := reqctx.LoginUser(c) if err != nil { c.JSON(401, resp.CodeMsg(401, i18n.TKey(language, err.Error()))) return } // 检查是否存在 userInfo := s.sysUserService.FindById(loginUser.UserId) if userInfo.UserId != loginUser.UserId { // c.JSON(200, resp.ErrMsg("没有权限访问用户数据!")) c.JSON(200, resp.ErrMsg(i18n.TKey(language, "user.noData"))) return } // 首次登录 forcePasswdChange := userInfo.LoginCount <= 2 // 非首次登录,判断密码是否过期 if !forcePasswdChange { alert, _ := s.sysUserService.ValidatePasswordExpireTime(userInfo.PasswordUpdateTime) forcePasswdChange = alert } if !forcePasswdChange { c.JSON(403, resp.ErrMsg("not matching the amendment")) return } // 检查密码是否与历史密码一致 err = s.sysUserService.ValidatePasswordNotAllowedHistory(userInfo.UserId, body.Password) if err != nil { c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } userInfo.Password = body.Password userInfo.UpdateBy = reqctx.LoginUserToUserName(c) rows := s.sysUserService.Update(userInfo) if rows > 0 { // 更新缓存用户信息 userInfo.Password = "" // 移除令牌信息 token.Remove(reqctx.Authorization(c)) c.JSON(200, resp.Ok(nil)) return } c.JSON(200, resp.Err(nil)) }