feat: Implement Oauth2 login log service and repository

- Added Oauth2LogLoginService for managing user authorization logs.
- Implemented methods for inserting logs, cleaning logs, and exporting log data.
- Created a new file for Oauth2 login log service.

refactor: Remove unused open_api module

- Deleted the open_api.go file as it was not utilized in the project.

fix: Update error codes in SysProfileController

- Changed error codes for binding errors and user authentication errors to more descriptive values.

fix: Update cache handling in SysConfig and SysDictType services

- Modified Redis set operations to include expiration time for cached values.

refactor: Update middleware authorization checks

- Replaced PreAuthorize middleware with AuthorizeUser across multiple routes in system and tool modules for consistency.

chore: Clean up trace and ws modules

- Updated middleware authorization in trace and ws modules to use AuthorizeUser.
This commit is contained in:
TsMask
2025-04-27 11:07:34 +08:00
parent b29a36e7b5
commit 56991a0b49
72 changed files with 2334 additions and 873 deletions

View File

@@ -56,25 +56,25 @@ func (s *Account) ValidateCaptcha(code, uuid string) error {
}
// ByUsername 登录创建用户信息
func (s Account) ByUsername(username, password string) (token.TokenInfo, error) {
tokenInfo := token.TokenInfo{}
func (s Account) ByUsername(username, password string) (token.UserInfo, error) {
info := token.UserInfo{}
// 检查密码重试次数
retryKey, retryCount, lockTime, err := s.passwordRetryCount(username)
if err != nil {
return tokenInfo, err
return info, err
}
// 查询用户登录账号
sysUser := s.sysUserService.FindByUserName(username)
if sysUser.UserName != username {
return tokenInfo, fmt.Errorf("login.errNameOrPasswd")
return info, fmt.Errorf("login.errNameOrPasswd")
}
if sysUser.DelFlag == constants.STATUS_YES {
return tokenInfo, fmt.Errorf("login.errDelFlag")
return info, fmt.Errorf("login.errDelFlag")
}
if sysUser.StatusFlag == constants.STATUS_NO {
return tokenInfo, fmt.Errorf("login.errStatus")
return info, fmt.Errorf("login.errStatus")
}
// 检验用户密码
@@ -82,31 +82,61 @@ func (s Account) ByUsername(username, password string) (token.TokenInfo, error)
if compareBool {
s.CleanLoginRecordCache(sysUser.UserName) // 清除错误记录次数
} else {
_ = redis.SetByExpire("", retryKey, retryCount+1, lockTime)
return tokenInfo, fmt.Errorf("login.errNameOrPasswd")
_ = redis.Set("", retryKey, retryCount+1, lockTime)
return info, fmt.Errorf("login.errNameOrPasswd")
}
// 登录用户信息
tokenInfo.UserId = sysUser.UserId
tokenInfo.DeptId = sysUser.DeptId
tokenInfo.User = sysUser
info.UserId = sysUser.UserId
info.DeptId = sysUser.DeptId
info.User = sysUser
// 用户权限组标识
if config.IsSystemUser(sysUser.UserId) {
tokenInfo.Permissions = []string{constants.SYS_PERMISSION_SYSTEM}
info.Permissions = []string{constants.SYS_PERMISSION_SYSTEM}
} else {
perms := s.sysMenuService.FindPermsByUserId(sysUser.UserId)
tokenInfo.Permissions = parse.RemoveDuplicates(perms)
info.Permissions = parse.RemoveDuplicates(perms)
}
return tokenInfo, nil
return info, nil
}
// ByUserId 用户ID刷新令牌创建用户信息
func (s Account) ByUserId(userId int64) (token.UserInfo, error) {
info := token.UserInfo{}
// 查询用户登录账号
sysUser := s.sysUserService.FindById(userId)
if sysUser.UserId != userId {
return info, fmt.Errorf("user does not exist")
}
if sysUser.DelFlag == constants.STATUS_YES {
return info, fmt.Errorf("sorry, your account has been deleted. Sorry, your account has been deleted")
}
if sysUser.StatusFlag == constants.STATUS_NO {
return info, fmt.Errorf("sorry, your account has been disabled")
}
// 登录用户信息
info.UserId = sysUser.UserId
info.DeptId = sysUser.DeptId
info.User = sysUser
// 用户权限组标识
if config.IsSystemUser(sysUser.UserId) {
info.Permissions = []string{constants.SYS_PERMISSION_SYSTEM}
} else {
perms := s.sysMenuService.FindPermsByUserId(sysUser.UserId)
info.Permissions = parse.RemoveDuplicates(perms)
}
return info, nil
}
// UpdateLoginDateAndIP 更新登录时间和IP
func (s Account) UpdateLoginDateAndIP(tokenInfo token.TokenInfo) bool {
user := s.sysUserService.FindById(tokenInfo.UserId)
func (s Account) UpdateLoginDateAndIP(info token.UserInfo) bool {
user := s.sysUserService.FindById(info.UserId)
user.Password = "" // 密码不更新
user.LoginCount += 1
user.LoginIp = tokenInfo.LoginIp
user.LoginTime = tokenInfo.LoginTime
user.LoginIp = info.LoginIp
user.LoginTime = info.LoginTime
return s.sysUserService.Update(user) > 0
}

View File

@@ -1,13 +1,10 @@
package service
import (
"encoding/json"
"fmt"
"regexp"
"be.ems/src/framework/constants"
"be.ems/src/framework/database/redis"
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/parse"
systemModel "be.ems/src/modules/system/model"
systemService "be.ems/src/modules/system/service"
@@ -81,7 +78,7 @@ func (s Register) ByUserName(username, password string) (int64, error) {
if insertId > 0 {
return insertId, nil
}
return 0, fmt.Errorf("failed to register user [%s]. Please contact the system administrator", username)
return 0, fmt.Errorf("failed to register user [%s]. Please contact the GM", username)
}
// registerRoleInit 注册初始角色
@@ -93,45 +90,3 @@ func (s Register) registerRoleInit() []int64 {
func (s Register) registerPostInit() []int64 {
return []int64{}
}
// ValidatePasswordPolicy 判断密码策略强度
func (s Register) ValidatePasswordPolicy(password string, errLang string) (bool, string) {
passwordPolicyStr := s.sysConfigService.FindValueByKey("sys.user.passwordPolicy")
if passwordPolicyStr == "" {
// 未配置密码策略
return false, i18n.TKey(errLang, "config.sys.user.passwordPolicyNot")
}
var policy struct {
MinLength int `json:"minLength"`
SpecialChars int `json:"specialChars"`
Uppercase int `json:"uppercase"`
Lowercase int `json:"lowercase"`
}
err := json.Unmarshal([]byte(passwordPolicyStr), &policy)
if err != nil {
return false, err.Error()
}
errMsg := i18n.TTemplate(errLang, "sys.user.passwordPolicyError", map[string]any{
"minLength": policy.MinLength,
"specialChars": policy.SpecialChars,
"uppercase": policy.Uppercase,
"lowercase": policy.Lowercase,
})
specialChars := len(regexp.MustCompile(`[!@#$%^&*(),.?":{}|<>]`).FindAllString(password, -1))
if specialChars < policy.SpecialChars {
return false, errMsg
}
uppercase := len(regexp.MustCompile(`[A-Z]`).FindAllString(password, -1))
if uppercase < policy.Uppercase {
return false, errMsg
}
lowercase := len(regexp.MustCompile(`[a-z]`).FindAllString(password, -1))
if lowercase < policy.Lowercase {
return false, errMsg
}
return true, ""
}