feat():learning后台管理项目初始化
This commit is contained in:
404
internal/services/user_service.go
Normal file
404
internal/services/user_service.go
Normal file
@@ -0,0 +1,404 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user