feat(auth): add Casbin RBAC and user activity tracking
Integrate Casbin for role-based access control with admin routes for role management. Add user activity logging service to track login and refresh events. Refactor audit service to use AI-based content moderation.
This commit is contained in:
116
internal/service/role_service.go
Normal file
116
internal/service/role_service.go
Normal file
@@ -0,0 +1,116 @@
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user