Files

405 lines
12 KiB
Go
Raw Permalink 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 (
"context"
"errors"
"fmt"
"goalfymax-admin/internal/models"
"goalfymax-admin/internal/storage"
"goalfymax-admin/pkg/utils"
"go.uber.org/zap"
)
// UserService 用户服务接口
type UserService interface {
Login(req *models.LoginRequest) (*models.LoginResponse, error)
Create(req *models.UserCreateRequest) (*models.User, error)
GetByID(id uint) (*models.User, error)
Update(id uint, req *models.UserUpdateRequest) (*models.User, error)
Delete(id uint) error
List(req *models.UserListRequest) ([]models.User, int64, error)
ListWithRoles(req *models.UserListRequest) ([]models.UserWithRoles, int64, error)
UpdateStatus(id uint, status int) error
UpdateRole(id uint, roleID uint) error
CheckUserSystemRole(userID int) (bool, error)
ChangeUserSystemRole(userID int, systemRole string) error
}
type userService struct {
userStorage storage.UserStorage
rbacStorage storage.RBACStorage
goalfyMaxUserStorage storage.GoalfyMaxUserStorage
jwtManager *utils.JWTManager
logger *utils.Logger
ssoAdminService SSOAdminService
}
// NewUserService 创建用户服务实例
func NewUserService(userStorage storage.UserStorage, rbacStorage storage.RBACStorage, goalfyMaxUserStorage storage.GoalfyMaxUserStorage, jwtManager *utils.JWTManager, logger *utils.Logger, ssoAdminService SSOAdminService) UserService {
return &userService{
userStorage: userStorage,
rbacStorage: rbacStorage,
goalfyMaxUserStorage: goalfyMaxUserStorage,
jwtManager: jwtManager,
logger: logger,
ssoAdminService: ssoAdminService,
}
}
// Login 用户登录
func (s *userService) Login(req *models.LoginRequest) (*models.LoginResponse, error) {
// 获取用户信息
user, err := s.userStorage.GetByUsername(req.Username)
if err != nil {
s.logger.Error("用户不存在", zap.String("username", req.Username))
return nil, errors.New("用户名或密码错误")
}
// 检查用户状态
if user.Status != 1 {
s.logger.Error("用户已被禁用", zap.String("username", req.Username))
return nil, errors.New("用户已被禁用")
}
// SSO用户不需要密码验证直接通过
// 生成JWT token
token, err := s.jwtManager.GenerateToken(user.ID, user.Username)
if err != nil {
s.logger.Error("生成token失败", zap.Error(err))
return nil, errors.New("登录失败")
}
// 记录登录日志
// 这里应该调用日志存储服务记录登录日志
s.logger.Info("用户登录成功", zap.String("username", user.Username))
return &models.LoginResponse{
Token: token,
User: *user,
ExpireAt: 0, // 实际应该计算过期时间
}, nil
}
// Create 创建用户
func (s *userService) Create(req *models.UserCreateRequest) (*models.User, error) {
// 验证用户名是否已存在
_, err := s.userStorage.GetByUsername(req.Username)
if err == nil {
return nil, errors.New("用户名已存在")
}
// 验证邮箱是否已存在
_, err = s.userStorage.GetByEmail(req.Email)
if err == nil {
return nil, errors.New("邮箱已存在")
}
// 1. 先调用SSO创建用户
ctx := context.Background()
ssoReq := &SSOAdminUserCreateRequest{
Username: req.Username,
Email: req.Email,
Phone: "", // 默认空手机号
Password: req.Password,
}
ssoUser, err := s.ssoAdminService.CreateUser(ctx, ssoReq)
if err != nil {
return nil, fmt.Errorf("SSO创建用户失败: %w", err)
}
// 2. 设置系统角色为sys_admin
if err := s.ssoAdminService.SetSystemRole(ctx, ssoUser.ID, "sys_admin"); err != nil {
// 如果设置失败,记录错误但不阻止用户创建
fmt.Printf("警告: 设置系统角色失败: %v\n", err)
}
// 设置角色ID如果没有指定则使用默认角色
roleID := req.RoleID
if roleID == 0 {
defaultRoleID, err := s.getDefaultRole()
if err != nil {
s.logger.Error("获取默认角色失败", zap.Error(err))
return nil, errors.New("获取默认角色失败")
}
roleID = defaultRoleID
}
// 创建用户
user := &models.User{
Username: req.Username,
Email: req.Email,
Nickname: req.Nickname,
Status: 1,
SSOProvider: req.SSOProvider,
RoleID: roleID,
}
err = s.userStorage.Create(user)
if err != nil {
s.logger.Error("创建用户失败", zap.Error(err))
return nil, errors.New("创建用户失败")
}
s.logger.Info("用户创建成功", zap.String("username", user.Username), zap.Uint("role_id", roleID))
return user, nil
}
// GetByID 根据ID获取用户
func (s *userService) GetByID(id uint) (*models.User, error) {
return s.userStorage.GetByID(id)
}
// Update 更新用户
func (s *userService) Update(id uint, req *models.UserUpdateRequest) (*models.User, error) {
// 获取用户信息
user, err := s.userStorage.GetByID(id)
if err != nil {
return nil, errors.New("用户不存在")
}
// 更新用户信息
if req.Nickname != "" {
user.Nickname = req.Nickname
}
if req.Email != "" {
// 检查邮箱是否已被其他用户使用
existingUser, err := s.userStorage.GetByEmail(req.Email)
if err == nil && existingUser.ID != id {
return nil, errors.New("邮箱已被其他用户使用")
}
user.Email = req.Email
}
if req.Avatar != "" {
user.Avatar = req.Avatar
}
if req.Status != nil {
user.Status = *req.Status
}
if req.RoleID != nil {
user.RoleID = *req.RoleID
}
if req.SSOProvider != "" {
user.SSOProvider = req.SSOProvider
}
err = s.userStorage.Update(user)
if err != nil {
s.logger.Error("更新用户失败", zap.Error(err))
return nil, errors.New("更新用户失败")
}
s.logger.Info("用户更新成功", zap.Uint("user_id", id))
return user, nil
}
// Delete 删除用户
func (s *userService) Delete(id uint) error {
// 检查用户是否存在
_, err := s.userStorage.GetByID(id)
if err != nil {
return errors.New("用户不存在")
}
err = s.userStorage.Delete(id)
if err != nil {
s.logger.Error("删除用户失败", zap.Error(err))
return errors.New("删除用户失败")
}
s.logger.Info("用户删除成功", zap.Uint("user_id", id))
return nil
}
// List 获取用户列表
func (s *userService) List(req *models.UserListRequest) ([]models.User, int64, error) {
return s.userStorage.List(req)
}
// UpdateStatus 更新用户状态
func (s *userService) UpdateStatus(id uint, status int) error {
// 检查用户是否存在
_, err := s.userStorage.GetByID(id)
if err != nil {
return errors.New("用户不存在")
}
err = s.userStorage.UpdateStatus(id, status)
if err != nil {
s.logger.Error("更新用户状态失败", zap.Error(err))
return errors.New("更新用户状态失败")
}
s.logger.Info("用户状态更新成功", zap.Uint("user_id", id), zap.Int("status", status))
return nil
}
// ListWithRoles 获取用户列表(包含角色信息)
func (s *userService) ListWithRoles(req *models.UserListRequest) ([]models.UserWithRoles, int64, error) {
// 获取用户列表
users, total, err := s.userStorage.List(req)
if err != nil {
return nil, 0, err
}
// 为每个用户查询角色信息
usersWithRoles := make([]models.UserWithRoles, len(users))
for i, user := range users {
if user.RoleID == 0 {
// role_id 为 0 表示未分配角色,直接返回空角色
s.logger.Debug("用户未分配角色", zap.Uint("userID", user.ID))
usersWithRoles[i] = models.UserWithRoles{User: user, Role: nil}
continue
}
// 查询用户角色
role, err := s.rbacStorage.GetRoleByID(user.RoleID)
if err != nil {
s.logger.Warn("获取用户角色失败", zap.Uint("userID", user.ID), zap.Uint("roleID", user.RoleID), zap.Error(err))
// 如果获取角色失败,仍然返回用户信息,但角色为空
usersWithRoles[i] = models.UserWithRoles{
User: user,
Role: nil,
}
} else {
usersWithRoles[i] = models.UserWithRoles{
User: user,
Role: role,
}
}
}
return usersWithRoles, total, nil
}
// getDefaultRole 获取默认角色L5全员
func (s *userService) getDefaultRole() (uint, error) {
// 查询默认角色ID
var roleID uint
err := s.rbacStorage.GetDefaultRoleID(&roleID)
if err != nil {
s.logger.Error("获取默认角色失败", zap.Error(err))
return 0, errors.New("获取默认角色失败")
}
return roleID, nil
}
// UpdateRole 更新用户角色
func (s *userService) UpdateRole(id uint, roleID uint) error {
// 检查用户是否存在
user, err := s.userStorage.GetByID(id)
if err != nil {
s.logger.Error("获取用户信息失败", zap.Uint("user_id", id), zap.Error(err))
return errors.New("用户不存在")
}
// 更新用户角色
user.RoleID = roleID
err = s.userStorage.Update(user)
if err != nil {
s.logger.Error("更新用户角色失败", zap.Uint("user_id", id), zap.Uint("role_id", roleID), zap.Error(err))
return errors.New("更新用户角色失败")
}
s.logger.Info("用户角色更新成功", zap.Uint("user_id", id), zap.Uint("role_id", roleID))
return nil
}
// CheckUserSystemRole 检查用户在系统用户管理表中的角色
// 返回: true表示存在sys_adminfalse表示不存在custom
func (s *userService) CheckUserSystemRole(userID int) (bool, error) {
// admin_users表的id字段就是SSO用户ID
// 所以通过userID查询admin_users表如果存在则说明是系统管理员
_, err := s.userStorage.GetByID(uint(userID))
if err != nil {
// 如果查询失败用户不存在返回false
return false, nil
}
// 用户存在返回true
return true, nil
}
// ChangeUserSystemRole 变更用户在SSO中的系统角色
// 同时需要在admin_users表中添加或删除记录
func (s *userService) ChangeUserSystemRole(userID int, systemRole string) error {
ctx := context.Background()
// 1. 先调用SSO接口变更角色
err := s.ssoAdminService.SetSystemRole(ctx, userID, systemRole)
if err != nil {
s.logger.Error("调用SSO接口变更角色失败", zap.Int("user_id", userID), zap.String("system_role", systemRole), zap.Error(err))
return fmt.Errorf("调用SSO接口变更角色失败: %w", err)
}
// 2. 根据角色变更更新admin_users表
if systemRole == "sys_admin" {
// 设置为系统管理员需要确保admin_users表中存在该用户
_, err := s.userStorage.GetByID(uint(userID))
if err != nil {
// 用户不存在,需要创建
// 从GoalfyMax用户表获取用户信息
goalfyUser, err := s.goalfyMaxUserStorage.GetByUserID(userID)
if err != nil {
s.logger.Error("获取GoalfyMax用户信息失败", zap.Int("user_id", userID), zap.Error(err))
return fmt.Errorf("获取GoalfyMax用户信息失败: %w", err)
}
// 获取默认角色ID系统管理员角色
defaultRoleID, err := s.getDefaultRole()
if err != nil {
s.logger.Error("获取默认角色失败", zap.Error(err))
// 如果获取默认角色失败使用角色ID 5系统管理员
defaultRoleID = 5
}
// 创建admin_users记录
// 注意admin_users表的id字段对应SSO用户ID
user := &models.User{
BaseModel: models.BaseModel{
ID: uint(userID), // 使用SSO用户ID作为主键
},
Username: goalfyUser.Username,
Email: goalfyUser.Email,
Nickname: goalfyUser.Nickname,
Status: 1,
SSOProvider: "default",
RoleID: defaultRoleID,
}
// 使用storage的Create方法它应该能处理指定ID的情况
err = s.userStorage.Create(user)
if err != nil {
s.logger.Error("创建admin_users记录失败", zap.Int("user_id", userID), zap.Error(err))
return fmt.Errorf("创建admin_users记录失败: %w", err)
}
s.logger.Info("创建系统管理员用户成功", zap.Int("user_id", userID))
} else {
// 用户已存在,更新状态为正常(如果需要)
s.logger.Info("用户已是系统管理员", zap.Int("user_id", userID))
}
} else if systemRole == "custom" {
// 设置为普通用户需要删除admin_users表中的记录软删除
_, err := s.userStorage.GetByID(uint(userID))
if err == nil {
// 用户存在,删除记录
err = s.userStorage.Delete(uint(userID))
if err != nil {
s.logger.Error("删除admin_users记录失败", zap.Int("user_id", userID), zap.Error(err))
return fmt.Errorf("删除admin_users记录失败: %w", err)
}
s.logger.Info("删除系统管理员用户成功", zap.Int("user_id", userID))
} else {
s.logger.Info("用户不是系统管理员,无需删除", zap.Int("user_id", userID))
}
} else {
return fmt.Errorf("无效的系统角色: %s", systemRole)
}
s.logger.Info("用户系统角色变更成功", zap.Int("user_id", userID), zap.String("system_role", systemRole))
return nil
}