175 lines
5.8 KiB
Go
175 lines
5.8 KiB
Go
package service
|
||
|
||
import (
|
||
"fmt"
|
||
"time"
|
||
|
||
"be.ems/src/framework/config"
|
||
"be.ems/src/framework/constants"
|
||
"be.ems/src/framework/database/redis"
|
||
"be.ems/src/framework/token"
|
||
"be.ems/src/framework/utils/crypto"
|
||
"be.ems/src/framework/utils/parse"
|
||
systemModelVO "be.ems/src/modules/system/model/vo"
|
||
systemService "be.ems/src/modules/system/service"
|
||
)
|
||
|
||
// 实例化服务层 Account 结构体
|
||
var NewAccount = &Account{
|
||
sysUserService: systemService.NewSysUser,
|
||
sysConfigService: systemService.NewSysConfig,
|
||
sysRoleService: systemService.NewSysRole,
|
||
sysMenuService: systemService.NewSysMenu,
|
||
}
|
||
|
||
// 账号身份操作服务 服务层处理
|
||
type Account struct {
|
||
sysUserService *systemService.SysUser // 用户信息服务
|
||
sysConfigService *systemService.SysConfig // 参数配置服务
|
||
sysRoleService *systemService.SysRole // 角色服务
|
||
sysMenuService *systemService.SysMenu // 菜单服务
|
||
}
|
||
|
||
// ValidateCaptcha 校验验证码
|
||
func (s *Account) ValidateCaptcha(code, uuid string) error {
|
||
// 验证码检查,从数据库配置获取验证码开关 true开启,false关闭
|
||
captchaEnabledStr := s.sysConfigService.FindValueByKey("sys.account.captchaEnabled")
|
||
if !parse.Boolean(captchaEnabledStr) {
|
||
return nil
|
||
}
|
||
if code == "" || uuid == "" {
|
||
// 验证码信息错误
|
||
return fmt.Errorf("captcha.err")
|
||
}
|
||
verifyKey := constants.CACHE_CAPTCHA_CODE + ":" + uuid
|
||
captcha, _ := redis.Get("", verifyKey)
|
||
if captcha == "" {
|
||
// 验证码已失效
|
||
return fmt.Errorf("captcha.errValid")
|
||
}
|
||
_ = redis.Del("", verifyKey)
|
||
if captcha != code {
|
||
// 验证码错误
|
||
return fmt.Errorf("captcha.err")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// ByUsername 登录创建用户信息
|
||
func (s Account) ByUsername(username, password string) (token.TokenInfo, error) {
|
||
tokenInfo := token.TokenInfo{}
|
||
|
||
// 检查密码重试次数
|
||
retryKey, retryCount, lockTime, err := s.passwordRetryCount(username)
|
||
if err != nil {
|
||
return tokenInfo, err
|
||
}
|
||
|
||
// 查询用户登录账号
|
||
sysUser := s.sysUserService.FindByUserName(username)
|
||
if sysUser.UserName != username {
|
||
return tokenInfo, fmt.Errorf("login.errNameOrPasswd")
|
||
}
|
||
if sysUser.DelFlag == constants.STATUS_YES {
|
||
return tokenInfo, fmt.Errorf("login.errDelFlag")
|
||
}
|
||
if sysUser.StatusFlag == constants.STATUS_NO {
|
||
return tokenInfo, fmt.Errorf("login.errStatus")
|
||
}
|
||
|
||
// 检验用户密码
|
||
compareBool := crypto.BcryptCompare(password, sysUser.Password)
|
||
if compareBool {
|
||
s.CleanLoginRecordCache(sysUser.UserName) // 清除错误记录次数
|
||
} else {
|
||
_ = redis.SetByExpire("", retryKey, retryCount+1, lockTime)
|
||
return tokenInfo, fmt.Errorf("login.errNameOrPasswd")
|
||
}
|
||
|
||
// 登录用户信息
|
||
tokenInfo.UserId = sysUser.UserId
|
||
tokenInfo.DeptId = sysUser.DeptId
|
||
tokenInfo.User = sysUser
|
||
// 用户权限组标识
|
||
if config.IsSystemUser(sysUser.UserId) {
|
||
tokenInfo.Permissions = []string{constants.SYS_PERMISSION_SYSTEM}
|
||
} else {
|
||
perms := s.sysMenuService.FindPermsByUserId(sysUser.UserId)
|
||
tokenInfo.Permissions = parse.RemoveDuplicates(perms)
|
||
}
|
||
return tokenInfo, nil
|
||
}
|
||
|
||
// UpdateLoginDateAndIP 更新登录时间和IP
|
||
func (s Account) UpdateLoginDateAndIP(tokenInfo token.TokenInfo) bool {
|
||
user := s.sysUserService.FindById(tokenInfo.UserId)
|
||
user.Password = "" // 密码不更新
|
||
user.LoginIp = tokenInfo.LoginIp
|
||
user.LoginTime = tokenInfo.LoginTime
|
||
return s.sysUserService.Update(user) > 0
|
||
}
|
||
|
||
// CleanLoginRecordCache 清除错误记录次数
|
||
func (s Account) CleanLoginRecordCache(userName string) bool {
|
||
cacheKey := fmt.Sprintf("%s:%s", constants.CACHE_PWD_ERR_COUNT, userName)
|
||
hasKey, err := redis.Has("", cacheKey)
|
||
if hasKey > 0 && err == nil {
|
||
return redis.Del("", cacheKey) == nil
|
||
}
|
||
return false
|
||
}
|
||
|
||
// passwordRetryCount 密码重试次数
|
||
func (s Account) passwordRetryCount(userName string) (string, int64, time.Duration, error) {
|
||
// 从数据库配置获取登录次数和错误锁定时间
|
||
maxRetryCountStr := s.sysConfigService.FindValueByKey("sys.user.maxRetryCount")
|
||
lockTimeStr := s.sysConfigService.FindValueByKey("sys.user.lockTime")
|
||
// 验证登录次数和错误锁定时间
|
||
maxRetryCount := parse.Number(maxRetryCountStr)
|
||
lockTime := parse.Number(lockTimeStr)
|
||
|
||
// 验证缓存记录次数
|
||
retryKey := fmt.Sprintf("%s:%s", constants.CACHE_PWD_ERR_COUNT, userName)
|
||
retryCount, err := redis.Get("", retryKey)
|
||
if retryCount == "" || err != nil {
|
||
retryCount = "0"
|
||
}
|
||
// 是否超过错误值
|
||
retryCountInt64 := parse.Number(retryCount)
|
||
if retryCountInt64 >= int64(maxRetryCount) {
|
||
// msg := fmt.Sprintf("密码输入错误 %d 次,帐户锁定 %d 分钟", maxRetryCount, lockTime)
|
||
msg := fmt.Errorf("login.errRetryPasswd") // 密码输入错误多次,帐户已被锁定
|
||
return retryKey, retryCountInt64, time.Duration(lockTime) * time.Minute, fmt.Errorf("%s", msg)
|
||
}
|
||
return retryKey, retryCountInt64, time.Duration(lockTime) * time.Minute, nil
|
||
}
|
||
|
||
// RoleAndMenuPerms 角色和菜单数据权限
|
||
func (s Account) RoleAndMenuPerms(userId int64, isSystemUser bool) ([]string, []string) {
|
||
if isSystemUser {
|
||
return []string{constants.SYS_ROLE_SYSTEM_KEY}, []string{constants.SYS_PERMISSION_SYSTEM}
|
||
}
|
||
// 角色key
|
||
var roleGroup []string
|
||
roles := s.sysRoleService.FindByUserId(userId)
|
||
for _, role := range roles {
|
||
roleGroup = append(roleGroup, role.RoleKey)
|
||
}
|
||
// 菜单权限key
|
||
perms := s.sysMenuService.FindPermsByUserId(userId)
|
||
return parse.RemoveDuplicates(roleGroup), parse.RemoveDuplicates(perms)
|
||
}
|
||
|
||
// RouteMenus 前端路由所需要的菜单
|
||
func (s Account) RouteMenus(userId int64, isSystemUser bool) []systemModelVO.Router {
|
||
var buildMenus []systemModelVO.Router
|
||
if isSystemUser {
|
||
menus := s.sysMenuService.BuildTreeMenusByUserId(0)
|
||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
||
} else {
|
||
menus := s.sysMenuService.BuildTreeMenusByUserId(userId)
|
||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
||
}
|
||
return buildMenus
|
||
}
|