/** * 权限管理器 * * 处理用户权限、角色管理、访问控制等功能 */ import { EventEmitter } from 'events'; import { NetworkValue } from '@esengine/ecs-framework-network-shared'; import { UserInfo } from './AuthenticationManager'; /** * 权限类型 */ export type Permission = string; /** * 角色定义 */ export interface Role { /** 角色ID */ id: string; /** 角色名称 */ name: string; /** 角色描述 */ description?: string; /** 权限列表 */ permissions: Permission[]; /** 父角色ID */ parentRoleId?: string; /** 是否系统角色 */ isSystemRole: boolean; /** 角色元数据 */ metadata: Record; /** 创建时间 */ createdAt: Date; } /** * 权限检查上下文 */ export interface PermissionContext { /** 用户ID */ userId: string; /** 用户角色 */ userRoles: string[]; /** 请求的权限 */ permission: Permission; /** 资源ID(可选) */ resourceId?: string; /** 附加上下文数据 */ context?: Record; } /** * 权限检查结果 */ export interface PermissionResult { /** 是否允许 */ granted: boolean; /** 原因 */ reason?: string; /** 匹配的角色 */ matchingRole?: string; /** 使用的权限 */ usedPermission?: Permission; } /** * 权限管理器配置 */ export interface AuthorizationConfig { /** 是否启用权限继承 */ enableInheritance?: boolean; /** 是否启用权限缓存 */ enableCache?: boolean; /** 缓存过期时间(毫秒) */ cacheExpirationTime?: number; /** 默认权限策略 */ defaultPolicy?: 'deny' | 'allow'; } /** * 权限管理器事件 */ export interface AuthorizationEvents { /** 权限被授予 */ 'permission-granted': (context: PermissionContext, result: PermissionResult) => void; /** 权限被拒绝 */ 'permission-denied': (context: PermissionContext, result: PermissionResult) => void; /** 角色创建 */ 'role-created': (role: Role) => void; /** 角色更新 */ 'role-updated': (roleId: string, updates: Partial) => void; /** 角色删除 */ 'role-deleted': (roleId: string) => void; /** 权限错误 */ 'authorization-error': (error: Error, context?: PermissionContext) => void; } /** * 权限缓存项 */ interface CacheItem { result: PermissionResult; expiresAt: Date; } /** * 预定义权限 */ export const Permissions = { // 系统权限 SYSTEM_ADMIN: 'system:admin', SYSTEM_CONFIG: 'system:config', // 用户管理权限 USER_CREATE: 'user:create', USER_READ: 'user:read', USER_UPDATE: 'user:update', USER_DELETE: 'user:delete', USER_MANAGE_ROLES: 'user:manage-roles', // 房间权限 ROOM_CREATE: 'room:create', ROOM_JOIN: 'room:join', ROOM_LEAVE: 'room:leave', ROOM_MANAGE: 'room:manage', ROOM_KICK_PLAYERS: 'room:kick-players', // 网络权限 NETWORK_SEND_RPC: 'network:send-rpc', NETWORK_SYNC_VARS: 'network:sync-vars', NETWORK_BROADCAST: 'network:broadcast', // 聊天权限 CHAT_SEND: 'chat:send', CHAT_MODERATE: 'chat:moderate', CHAT_PRIVATE: 'chat:private', // 文件权限 FILE_UPLOAD: 'file:upload', FILE_DOWNLOAD: 'file:download', FILE_DELETE: 'file:delete' } as const; /** * 预定义角色 */ export const SystemRoles = { ADMIN: 'admin', MODERATOR: 'moderator', USER: 'user', GUEST: 'guest' } as const; /** * 权限管理器 */ export class AuthorizationManager extends EventEmitter { private config: AuthorizationConfig; private roles = new Map(); private permissionCache = new Map(); private cleanupTimer: NodeJS.Timeout | null = null; constructor(config: AuthorizationConfig = {}) { super(); this.config = { enableInheritance: true, enableCache: true, cacheExpirationTime: 5 * 60 * 1000, // 5分钟 defaultPolicy: 'deny', ...config }; this.initialize(); } /** * 创建角色 */ async createRole(roleData: { id: string; name: string; description?: string; permissions: Permission[]; parentRoleId?: string; metadata?: Record; }): Promise { const { id, name, description, permissions, parentRoleId, metadata = {} } = roleData; if (this.roles.has(id)) { throw new Error(`Role with id "${id}" already exists`); } // 验证父角色是否存在 if (parentRoleId && !this.roles.has(parentRoleId)) { throw new Error(`Parent role "${parentRoleId}" not found`); } const role: Role = { id, name, description, permissions: [...permissions], parentRoleId, isSystemRole: false, metadata, createdAt: new Date() }; this.roles.set(id, role); this.clearPermissionCache(); // 清除缓存 console.log(`Role created: ${name} (${id})`); this.emit('role-created', role); return role; } /** * 获取角色 */ getRole(roleId: string): Role | undefined { return this.roles.get(roleId); } /** * 获取所有角色 */ getAllRoles(): Role[] { return Array.from(this.roles.values()); } /** * 更新角色 */ async updateRole(roleId: string, updates: Partial): Promise { const role = this.roles.get(roleId); if (!role) { return false; } // 系统角色不允许修改某些字段 if (role.isSystemRole) { const { permissions, parentRoleId, ...allowedUpdates } = updates; Object.assign(role, allowedUpdates); } else { // 不允许更新某些字段 const { id, createdAt, isSystemRole, ...allowedUpdates } = updates as any; Object.assign(role, allowedUpdates); } this.clearPermissionCache(); // 清除缓存 console.log(`Role updated: ${role.name} (${roleId})`); this.emit('role-updated', roleId, updates); return true; } /** * 删除角色 */ async deleteRole(roleId: string): Promise { const role = this.roles.get(roleId); if (!role) { return false; } if (role.isSystemRole) { throw new Error('Cannot delete system role'); } // 检查是否有子角色依赖此角色 const childRoles = Array.from(this.roles.values()) .filter(r => r.parentRoleId === roleId); if (childRoles.length > 0) { throw new Error(`Cannot delete role "${roleId}": ${childRoles.length} child roles depend on it`); } this.roles.delete(roleId); this.clearPermissionCache(); // 清除缓存 console.log(`Role deleted: ${role.name} (${roleId})`); this.emit('role-deleted', roleId); return true; } /** * 检查权限 */ async checkPermission(context: PermissionContext): Promise { try { // 检查缓存 const cacheKey = this.getCacheKey(context); if (this.config.enableCache) { const cached = this.permissionCache.get(cacheKey); if (cached && cached.expiresAt > new Date()) { return cached.result; } } const result = await this.performPermissionCheck(context); // 缓存结果 if (this.config.enableCache) { const expiresAt = new Date(Date.now() + this.config.cacheExpirationTime!); this.permissionCache.set(cacheKey, { result, expiresAt }); } // 触发事件 if (result.granted) { this.emit('permission-granted', context, result); } else { this.emit('permission-denied', context, result); } return result; } catch (error) { this.emit('authorization-error', error as Error, context); return { granted: this.config.defaultPolicy === 'allow', reason: `Authorization error: ${(error as Error).message}` }; } } /** * 检查用户是否有权限 */ async hasPermission(user: UserInfo, permission: Permission, resourceId?: string): Promise { const context: PermissionContext = { userId: user.id, userRoles: user.roles, permission, resourceId }; const result = await this.checkPermission(context); return result.granted; } /** * 获取用户的所有权限 */ async getUserPermissions(user: UserInfo): Promise { const permissions = new Set(); for (const roleId of user.roles) { const rolePermissions = await this.getRolePermissions(roleId); rolePermissions.forEach(p => permissions.add(p)); } return Array.from(permissions); } /** * 获取角色的所有权限(包括继承的权限) */ async getRolePermissions(roleId: string): Promise { const permissions = new Set(); const visited = new Set(); const collectPermissions = (currentRoleId: string) => { if (visited.has(currentRoleId)) { return; // 防止循环引用 } visited.add(currentRoleId); const role = this.roles.get(currentRoleId); if (!role) { return; } // 添加当前角色的权限 role.permissions.forEach(p => permissions.add(p)); // 递归添加父角色的权限 if (this.config.enableInheritance && role.parentRoleId) { collectPermissions(role.parentRoleId); } }; collectPermissions(roleId); return Array.from(permissions); } /** * 为角色添加权限 */ async addPermissionToRole(roleId: string, permission: Permission): Promise { const role = this.roles.get(roleId); if (!role) { return false; } if (!role.permissions.includes(permission)) { role.permissions.push(permission); this.clearPermissionCache(); console.log(`Permission "${permission}" added to role "${roleId}"`); } return true; } /** * 从角色移除权限 */ async removePermissionFromRole(roleId: string, permission: Permission): Promise { const role = this.roles.get(roleId); if (!role) { return false; } const index = role.permissions.indexOf(permission); if (index !== -1) { role.permissions.splice(index, 1); this.clearPermissionCache(); console.log(`Permission "${permission}" removed from role "${roleId}"`); } return true; } /** * 检查用户是否有指定角色 */ hasRole(user: UserInfo, roleId: string): boolean { return user.roles.includes(roleId); } /** * 为用户添加角色 */ async addRoleToUser(user: UserInfo, roleId: string): Promise { if (!this.roles.has(roleId)) { return false; } if (!user.roles.includes(roleId)) { user.roles.push(roleId); this.clearUserPermissionCache(user.id); console.log(`Role "${roleId}" added to user "${user.id}"`); } return true; } /** * 从用户移除角色 */ async removeRoleFromUser(user: UserInfo, roleId: string): Promise { const index = user.roles.indexOf(roleId); if (index !== -1) { user.roles.splice(index, 1); this.clearUserPermissionCache(user.id); console.log(`Role "${roleId}" removed from user "${user.id}"`); return true; } return false; } /** * 清除权限缓存 */ clearPermissionCache(): void { this.permissionCache.clear(); } /** * 清除指定用户的权限缓存 */ clearUserPermissionCache(userId: string): void { const keysToDelete: string[] = []; for (const [key] of this.permissionCache) { if (key.startsWith(`${userId}:`)) { keysToDelete.push(key); } } keysToDelete.forEach(key => this.permissionCache.delete(key)); } /** * 销毁权限管理器 */ destroy(): void { if (this.cleanupTimer) { clearInterval(this.cleanupTimer); this.cleanupTimer = null; } this.roles.clear(); this.permissionCache.clear(); this.removeAllListeners(); } /** * 初始化 */ private initialize(): void { // 创建系统角色 this.createSystemRoles(); // 启动缓存清理定时器(每30分钟清理一次) if (this.config.enableCache) { this.cleanupTimer = setInterval(() => { this.cleanupCache(); }, 30 * 60 * 1000); } } /** * 创建系统角色 */ private createSystemRoles(): void { // 管理员角色 const adminRole: Role = { id: SystemRoles.ADMIN, name: 'Administrator', description: 'Full system access', permissions: Object.values(Permissions), isSystemRole: true, metadata: {}, createdAt: new Date() }; // 版主角色 const moderatorRole: Role = { id: SystemRoles.MODERATOR, name: 'Moderator', description: 'Room and user management', permissions: [ Permissions.USER_READ, Permissions.ROOM_CREATE, Permissions.ROOM_JOIN, Permissions.ROOM_MANAGE, Permissions.ROOM_KICK_PLAYERS, Permissions.NETWORK_SEND_RPC, Permissions.NETWORK_SYNC_VARS, Permissions.CHAT_SEND, Permissions.CHAT_MODERATE, Permissions.CHAT_PRIVATE ], parentRoleId: SystemRoles.USER, isSystemRole: true, metadata: {}, createdAt: new Date() }; // 普通用户角色 const userRole: Role = { id: SystemRoles.USER, name: 'User', description: 'Basic user permissions', permissions: [ Permissions.ROOM_JOIN, Permissions.ROOM_LEAVE, Permissions.NETWORK_SEND_RPC, Permissions.NETWORK_SYNC_VARS, Permissions.CHAT_SEND, Permissions.FILE_DOWNLOAD ], parentRoleId: SystemRoles.GUEST, isSystemRole: true, metadata: {}, createdAt: new Date() }; // 访客角色 const guestRole: Role = { id: SystemRoles.GUEST, name: 'Guest', description: 'Limited access for guests', permissions: [ Permissions.ROOM_JOIN ], isSystemRole: true, metadata: {}, createdAt: new Date() }; this.roles.set(adminRole.id, adminRole); this.roles.set(moderatorRole.id, moderatorRole); this.roles.set(userRole.id, userRole); this.roles.set(guestRole.id, guestRole); console.log('System roles created'); } /** * 执行权限检查 */ private async performPermissionCheck(context: PermissionContext): Promise { // 获取用户的所有角色权限 const userPermissions = new Set(); for (const roleId of context.userRoles) { const rolePermissions = await this.getRolePermissions(roleId); rolePermissions.forEach(p => userPermissions.add(p)); } // 直接权限匹配 if (userPermissions.has(context.permission)) { return { granted: true, reason: 'Direct permission match', usedPermission: context.permission }; } // 通配符权限匹配 const wildcardPermissions = Array.from(userPermissions) .filter(p => p.endsWith('*')); for (const wildcardPerm of wildcardPermissions) { const prefix = wildcardPerm.slice(0, -1); if (context.permission.startsWith(prefix)) { return { granted: true, reason: 'Wildcard permission match', usedPermission: wildcardPerm }; } } // 如果没有匹配的权限 return { granted: this.config.defaultPolicy === 'allow', reason: this.config.defaultPolicy === 'allow' ? 'Default allow policy' : 'No matching permissions found' }; } /** * 获取缓存键 */ private getCacheKey(context: PermissionContext): string { const roleString = context.userRoles.sort().join(','); const resourcePart = context.resourceId ? `:${context.resourceId}` : ''; return `${context.userId}:${roleString}:${context.permission}${resourcePart}`; } /** * 清理过期缓存 */ private cleanupCache(): void { const now = new Date(); let cleanedCount = 0; for (const [key, item] of this.permissionCache.entries()) { if (item.expiresAt < now) { this.permissionCache.delete(key); cleanedCount++; } } if (cleanedCount > 0) { console.log(`Permission cache cleanup: ${cleanedCount} entries removed`); } } /** * 类型安全的事件监听 */ override on(event: K, listener: AuthorizationEvents[K]): this { return super.on(event, listener); } /** * 类型安全的事件触发 */ override emit(event: K, ...args: Parameters): boolean { return super.emit(event, ...args); } }