2026-03-14 02:09:38 +08:00
|
|
|
|
package service
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"context"
|
|
|
|
|
|
|
|
|
|
|
|
apperrors "carrot_bbs/internal/errors"
|
|
|
|
|
|
"carrot_bbs/internal/model"
|
|
|
|
|
|
"carrot_bbs/internal/repository"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// RoleService 角色管理服务接口
|
|
|
|
|
|
type RoleService interface {
|
|
|
|
|
|
// GetUserRoles 获取用户的所有角色
|
|
|
|
|
|
GetUserRoles(ctx context.Context, userID string) ([]model.Role, error)
|
|
|
|
|
|
|
|
|
|
|
|
// AssignRole 为用户分配角色
|
|
|
|
|
|
AssignRole(ctx context.Context, operatorID, targetUserID, role string) error
|
|
|
|
|
|
|
|
|
|
|
|
// RemoveRole 移除用户的角色
|
|
|
|
|
|
RemoveRole(ctx context.Context, operatorID, targetUserID, role string) error
|
|
|
|
|
|
|
|
|
|
|
|
// GetAllRoles 获取所有角色定义
|
|
|
|
|
|
GetAllRoles(ctx context.Context) ([]model.Role, error)
|
|
|
|
|
|
|
|
|
|
|
|
// GetRole 获取角色详情
|
|
|
|
|
|
GetRole(ctx context.Context, name string) (*model.Role, error)
|
2026-03-14 18:01:55 +08:00
|
|
|
|
|
|
|
|
|
|
// GetRoleDetail 获取角色详情(包含用户数量和权限)
|
|
|
|
|
|
GetRoleDetail(ctx context.Context, name string) (*RoleDetail, error)
|
|
|
|
|
|
|
|
|
|
|
|
// GetRolePermissions 获取角色的权限列表
|
|
|
|
|
|
GetRolePermissions(ctx context.Context, name string) ([]Permission, error)
|
|
|
|
|
|
|
|
|
|
|
|
// GetAllPermissions 获取系统中所有权限定义
|
|
|
|
|
|
GetAllPermissions(ctx context.Context) ([]Permission, error)
|
|
|
|
|
|
|
|
|
|
|
|
// UpdateRolePermissions 更新角色权限
|
|
|
|
|
|
UpdateRolePermissions(ctx context.Context, roleName string, permissions []Permission) error
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Permission 权限定义
|
|
|
|
|
|
type Permission struct {
|
|
|
|
|
|
Resource string `json:"resource"`
|
|
|
|
|
|
Action string `json:"action"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// RoleDetail 角色详情
|
|
|
|
|
|
type RoleDetail struct {
|
|
|
|
|
|
Name string `json:"name"`
|
|
|
|
|
|
DisplayName string `json:"display_name"`
|
|
|
|
|
|
Description string `json:"description"`
|
|
|
|
|
|
ParentRole *string `json:"parent_role"`
|
|
|
|
|
|
Priority int `json:"priority"`
|
|
|
|
|
|
UserCount int64 `json:"user_count"`
|
|
|
|
|
|
Permissions []Permission `json:"permissions"`
|
|
|
|
|
|
CreatedAt string `json:"created_at"`
|
|
|
|
|
|
UpdatedAt string `json:"updated_at"`
|
2026-03-14 02:09:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type roleService struct {
|
|
|
|
|
|
roleRepo repository.RoleRepository
|
|
|
|
|
|
casbinSvc CasbinService
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NewRoleService 创建角色管理服务
|
|
|
|
|
|
func NewRoleService(
|
|
|
|
|
|
roleRepo repository.RoleRepository,
|
|
|
|
|
|
casbinSvc CasbinService,
|
|
|
|
|
|
) RoleService {
|
|
|
|
|
|
return &roleService{
|
|
|
|
|
|
roleRepo: roleRepo,
|
|
|
|
|
|
casbinSvc: casbinSvc,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *roleService) GetUserRoles(ctx context.Context, userID string) ([]model.Role, error) {
|
|
|
|
|
|
roleNames, err := s.casbinSvc.GetRolesForUser(ctx, userID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var roles []model.Role
|
|
|
|
|
|
for _, name := range roleNames {
|
|
|
|
|
|
role, err := s.roleRepo.GetRole(ctx, name)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
continue // 忽略找不到的角色
|
|
|
|
|
|
}
|
|
|
|
|
|
roles = append(roles, *role)
|
|
|
|
|
|
}
|
|
|
|
|
|
return roles, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *roleService) AssignRole(ctx context.Context, operatorID, targetUserID, role string) error {
|
|
|
|
|
|
// 不能修改自己的角色
|
|
|
|
|
|
if operatorID == targetUserID {
|
|
|
|
|
|
return apperrors.ErrCannotModifyOwnRole
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查目标用户是否已有该角色
|
|
|
|
|
|
hasRole, err := s.casbinSvc.HasRoleForUser(ctx, targetUserID, role)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
if hasRole {
|
|
|
|
|
|
return apperrors.ErrRoleAlreadyAssigned
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查角色是否存在
|
|
|
|
|
|
_, err = s.roleRepo.GetRole(ctx, role)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return apperrors.ErrRoleNotFound
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 添加角色
|
|
|
|
|
|
return s.casbinSvc.AddRoleForUser(ctx, targetUserID, role)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *roleService) RemoveRole(ctx context.Context, operatorID, targetUserID, role string) error {
|
|
|
|
|
|
// 不能修改自己的角色
|
|
|
|
|
|
if operatorID == targetUserID {
|
|
|
|
|
|
return apperrors.ErrCannotModifyOwnRole
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 不能修改超级管理员角色
|
|
|
|
|
|
if role == model.RoleSuperAdmin {
|
|
|
|
|
|
return apperrors.ErrCannotModifySuperAdmin
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查用户是否有该角色
|
|
|
|
|
|
hasRole, err := s.casbinSvc.HasRoleForUser(ctx, targetUserID, role)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
if !hasRole {
|
|
|
|
|
|
return apperrors.ErrRoleNotAssigned
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return s.casbinSvc.DeleteRoleForUser(ctx, targetUserID, role)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *roleService) GetAllRoles(ctx context.Context) ([]model.Role, error) {
|
|
|
|
|
|
return s.roleRepo.GetAllRoles(ctx)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *roleService) GetRole(ctx context.Context, name string) (*model.Role, error) {
|
|
|
|
|
|
return s.roleRepo.GetRole(ctx, name)
|
|
|
|
|
|
}
|
2026-03-14 18:01:55 +08:00
|
|
|
|
|
|
|
|
|
|
func (s *roleService) GetRoleDetail(ctx context.Context, name string) (*RoleDetail, error) {
|
|
|
|
|
|
role, err := s.roleRepo.GetRole(ctx, name)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, apperrors.ErrRoleNotFound
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取用户数量
|
|
|
|
|
|
userCount, err := s.roleRepo.GetRoleUserCount(ctx, name)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
userCount = 0
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取权限
|
|
|
|
|
|
permissions, err := s.casbinSvc.GetPermissionsForRole(ctx, name)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
perms := make([]Permission, 0)
|
|
|
|
|
|
for _, p := range permissions {
|
|
|
|
|
|
if len(p) >= 2 {
|
|
|
|
|
|
perms = append(perms, Permission{
|
|
|
|
|
|
Resource: p[0],
|
|
|
|
|
|
Action: p[1],
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return &RoleDetail{
|
|
|
|
|
|
Name: role.Name,
|
|
|
|
|
|
DisplayName: role.DisplayName,
|
|
|
|
|
|
Description: role.Description,
|
|
|
|
|
|
ParentRole: role.ParentRole,
|
|
|
|
|
|
Priority: role.Priority,
|
|
|
|
|
|
UserCount: userCount,
|
|
|
|
|
|
Permissions: perms,
|
|
|
|
|
|
CreatedAt: role.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
|
|
|
|
|
UpdatedAt: role.UpdatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
|
|
|
|
|
}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *roleService) GetRolePermissions(ctx context.Context, name string) ([]Permission, error) {
|
|
|
|
|
|
// 检查角色是否存在
|
|
|
|
|
|
_, err := s.roleRepo.GetRole(ctx, name)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, apperrors.ErrRoleNotFound
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
permissions, err := s.casbinSvc.GetPermissionsForRole(ctx, name)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化为空数组,避免 JSON 序列化为 null
|
|
|
|
|
|
perms := make([]Permission, 0)
|
|
|
|
|
|
for _, p := range permissions {
|
|
|
|
|
|
if len(p) >= 2 {
|
|
|
|
|
|
perms = append(perms, Permission{
|
|
|
|
|
|
Resource: p[0],
|
|
|
|
|
|
Action: p[1],
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return perms, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *roleService) GetAllPermissions(ctx context.Context) ([]Permission, error) {
|
|
|
|
|
|
permissions := s.casbinSvc.GetAllPermissions(ctx)
|
|
|
|
|
|
|
|
|
|
|
|
perms := make([]Permission, 0)
|
|
|
|
|
|
for _, p := range permissions {
|
|
|
|
|
|
if len(p) >= 3 {
|
|
|
|
|
|
// p[0] 是角色名,p[1] 是资源,p[2] 是操作
|
|
|
|
|
|
perms = append(perms, Permission{
|
|
|
|
|
|
Resource: p[1],
|
|
|
|
|
|
Action: p[2],
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return perms, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *roleService) UpdateRolePermissions(ctx context.Context, roleName string, permissions []Permission) error {
|
|
|
|
|
|
// 检查角色是否存在
|
|
|
|
|
|
_, err := s.roleRepo.GetRole(ctx, roleName)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return apperrors.ErrRoleNotFound
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 不能修改超级管理员权限
|
|
|
|
|
|
if roleName == model.RoleSuperAdmin {
|
|
|
|
|
|
return apperrors.ErrCannotModifySuperAdmin
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换权限格式
|
|
|
|
|
|
var perms [][]string
|
|
|
|
|
|
for _, p := range permissions {
|
|
|
|
|
|
perms = append(perms, []string{p.Resource, p.Action})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return s.casbinSvc.UpdatePermissionsForRole(ctx, roleName, perms)
|
|
|
|
|
|
}
|