Files
Quincy_admin/services/user_service.go
2026-03-26 22:13:03 +08:00

295 lines
8.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}