405 lines
12 KiB
Go
405 lines
12 KiB
Go
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_admin),false表示不存在(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
|
||
}
|