first commit

This commit is contained in:
何昌清
2026-03-26 22:13:03 +08:00
parent bbe1faa363
commit a2685f7f1e
51 changed files with 11244 additions and 0 deletions

294
services/user_service.go Normal file
View File

@@ -0,0 +1,294 @@
package services
import (
"Quincy_admin/repositories"
"Quincy_admin/schemas"
"Quincy_admin/utils"
"fmt"
"net"
"time"
"golang.org/x/crypto/bcrypt"
)
type UserService struct {
repo *repositories.UserRepository
}
func NewUserService(repo *repositories.UserRepository) (*UserService, error) {
service := &UserService{repo: repo}
return service, nil
}
// CreateUser 创建用户
func (s *UserService) CreateUser(userReq *schemas.CreateUser) error {
// 只有当密码不为空时才进行加密处理
if userReq.Password != "" {
hashedPassword, err := s.HashPassword(userReq.Password)
if err != nil {
return fmt.Errorf("密码加密失败: %v", err)
}
userReq.Password = hashedPassword
} else {
return fmt.Errorf("密码不能为空")
}
//添加默认值
userReq.RoleCode = 0
userReq.Status = schemas.UserStatusDisabled
// 如果 UserCode 为空,生成一个唯一的 UserCode确保与数据库中已有的不重复
foundUniqueCode := false
for i := 0; i < 5; i++ { // 最多尝试5次
userReq.SessionCode = utils.GenerateUserCode("S10", 7)
// 检查数据库是否已存在该 sessioncode
count, err := s.repo.IsUserCodeExists(userReq.SessionCode)
if err != nil {
return err
}
if count == 0 {
foundUniqueCode = true
break
}
}
// 如果5次尝试后仍未找到唯一code返回错误
if !foundUniqueCode {
return fmt.Errorf("无法生成唯一的用户编码已尝试5次")
}
// 生成唯一的 Username确保与数据库中已有的不重复
foundUniqueName := false
for i := 0; i < 5; i++ {
userReq.Username, _ = utils.GenerateUsername(8)
// 检查数据库是否已存在该 Username
count, err := s.repo.IsUsernameExists(userReq.Username)
if err != nil {
return err
}
if count == 0 {
foundUniqueName = true
break
}
}
// 如果5次尝试后仍未找到唯一username返回错误
if !foundUniqueName {
return fmt.Errorf("无法生成唯一的用户名已尝试5次")
}
return s.repo.Create(userReq)
}
// IsEmailExists 检查邮箱是否已存在
func (s *UserService) IsEmailExists(email string) (int, error) {
return s.repo.IsEmailExists(email)
}
// GetUserByID 通过用户ID查找用户
func (s *UserService) GetUserByID(scode string) (*schemas.UserInfo, error) {
return s.repo.FindByID(scode)
}
// GetUserByUsername 通过用户名查找用户
func (s *UserService) GetUserByUsername(username string) (*schemas.UserInfo, error) {
return s.repo.FindByUsername(username)
}
// GetUserLocation 获取用户地理位置信息
func (s *UserService) GetUserLocation(ipAddress string) (map[string]string, error) {
geoDB := utils.GetGeoIP()
if geoDB == nil {
return nil, fmt.Errorf("GeoIP database not initialized")
}
// 解析 IP 地址
ip := net.ParseIP(ipAddress)
if ip == nil {
return nil, fmt.Errorf("invalid IP address: %s", ipAddress)
}
// 查询地理位置
record, err := geoDB.City(ip)
if err != nil {
return nil, fmt.Errorf("failed to query GeoIP database: %v", err)
}
// 构造返回结果
location := map[string]string{
"ip": ipAddress,
"country": record.Country.Names["zh-CN"],
"country_code": record.Country.IsoCode,
"province": "",
"city": "",
"latitude": fmt.Sprintf("%f", record.Location.Latitude),
"longitude": fmt.Sprintf("%f", record.Location.Longitude),
}
// 获取省份/州信息
if len(record.Subdivisions) > 0 {
location["province"] = record.Subdivisions[0].Names["zh-CN"]
}
// 获取城市信息
if record.City.Names["zh-CN"] != "" {
location["city"] = record.City.Names["zh-CN"]
}
//fmt.Println("location:", location)
return location, nil
}
// StoreLoginSession 存储登录会话
//func (s *UserService) StoreLoginSession(sessionKey string, userInfo *schemas.UserInfo, expireTime time.Duration) error {
// InitRedis := utils.GetRedis()
// ctx := utils.GetContext()
//
// // 将用户信息序列化后存储到Redis
// userInfoBytes, err := json.Marshal(userInfo)
// if err != nil {
// return err
// }
//
// err = InitRedis.Set(ctx, sessionKey, userInfoBytes, expireTime).Err()
// if err != nil {
// return err
// }
//
// return nil
//}
// RecordLoginLog 记录登录日志
func (s *UserService) RecordLoginLog(userID int, username string, ipAddress string, userAgent string, status int, failureReason string) error {
// 获取地理位置信息
locationInfo, err := s.GetUserLocation("60.255.157.229")
var locationStr string
if err == nil {
locationStr = fmt.Sprintf("%s%s%s",
locationInfo["country"],
locationInfo["province"],
locationInfo["city"])
} else {
locationStr = "未知位置"
}
// 创建登录日志记录
now := time.Now()
loginLog := &schemas.LoginLog{
UserID: userID,
Username: username,
IPAddress: ipAddress,
Location: locationStr,
UserAgent: userAgent,
LoginTime: schemas.NewCustomTime(&now),
Status: status,
FailureReason: failureReason,
CreateTime: schemas.NewCustomTime(&now),
}
// 插入数据库
return s.repo.RecordLoginLog(loginLog)
}
// UpdateUser 更新用户信息
func (s *UserService) UpdateUser(user *schemas.UpdateUser) (int, error) {
// 检查是否尝试修改超级管理员账户ID=1
if user.ID == 1 {
return 0, fmt.Errorf("无法修改超级管理员账户信息")
}
// 只有当密码不为空时才进行加密处理
if user.Password != "" {
hashedPassword, err := s.HashPassword(user.Password)
if err != nil {
return 0, fmt.Errorf("密码加密失败: %v", err)
}
user.Password = hashedPassword
} else {
// 如果密码为空,则不更新密码字段
user.Password = ""
}
return s.repo.Update(user)
}
// UpdateLastLoginTime 更新用户最后登录时间
func (s *UserService) UpdateLastLoginTime(scode string) error {
return s.repo.UpdateLastLoginTime(scode, time.Now())
}
// UpdateStatus 删除用户
func (s *UserService) UpdateStatus(id int, enable int) error {
// 防止修改超级管理员账户ID=1
if id == 1 {
return fmt.Errorf("无权限修改超级管理员账户")
}
return s.repo.UpdateStatus(id, enable)
}
// HashPassword 对密码进行加密
func (s *UserService) HashPassword(password string) (string, error) {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(hashedPassword), nil
}
// VerifyPassword 验证密码
func (s *UserService) VerifyPassword(plainPassword, hashedPassword string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(plainPassword))
return err == nil
}
// GetUserList 获取用户列表
func (s *UserService) GetUserList(req *schemas.UserListRequest) ([]*schemas.UserInfo, int64, error) {
return s.repo.GetUserList(req)
}
// GetRoleList 获取角色列表
func (s *UserService) GetRoleList(req *schemas.RoleListRequest) ([]*schemas.RoleResponseList, int64, error) {
return s.repo.GetRoleList(req)
}
// GetLoginLogList 获取登录日志列表
func (s *UserService) GetLoginLogList(req *schemas.LoginLogListRequest) ([]*schemas.LoginLog, int64, error) {
return s.repo.GetLoginLogList(req)
}
// AssignRole 分配角色
func (s *UserService) AssignRole(userIdValue, roleIdValue int) error {
// 检查用户是否已分配角色
exists, err := s.repo.AssignRoleExists(userIdValue)
if err != nil {
return err
}
if !exists {
// 用户未分配角色,执行插入操作
return s.repo.AssignRole(userIdValue, roleIdValue)
} else {
// 用户已分配角色,执行更新操作
return s.repo.UpdateAssignRole(userIdValue, roleIdValue)
}
}
// UpdateRoleStatus 删除用户
func (s *UserService) UpdateRoleStatus(id int, enable int) error {
// 防止修改超级管理员账户ID=1
if id == 1 {
return fmt.Errorf("无权限修改超级管理员账户")
}
return s.repo.UpdateRoleStatus(id, enable)
}
// CreateRole 创建角色
func (s *UserService) CreateRole(req *schemas.CreateRole) error {
return s.repo.CreateRole(req)
}
// UpdateRole 更新角色
func (s *UserService) UpdateRole(req *schemas.CreateRole) error {
return s.repo.UpdateRole(req)
}