Files
core2026/app/gateway-api/src/adminCapabilities.ts
T

107 lines
3.9 KiB
TypeScript

export type AdminCapabilityRisk = 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
export type AdminCapabilityScope = 'GLOBAL' | 'PROFILE';
export interface AdminCapabilityDefinition {
permission: string;
label: string;
description: string;
risk: AdminCapabilityRisk;
scope: AdminCapabilityScope;
}
export const ADMIN_CAPABILITIES: readonly AdminCapabilityDefinition[] = [
{
permission: 'admin.notice.manage',
label: 'Gateway 공지 관리',
description: 'Gateway 전역 공지를 조회하고 변경합니다.',
risk: 'MEDIUM',
scope: 'GLOBAL',
},
{
permission: 'admin.users.create',
label: '로컬 계정 생성',
description: '환경에서 허용한 경우 로컬 계정을 생성합니다.',
risk: 'HIGH',
scope: 'GLOBAL',
},
{
permission: 'admin.users.manage',
label: '사용자·제재 관리',
description: '계정 복구, 제재, OAuth 유예와 예약 탈퇴를 관리합니다.',
risk: 'CRITICAL',
scope: 'GLOBAL',
},
{
permission: 'admin.audit.read',
label: '관리자 감사 조회',
description: 'Gateway 관리자 변경 이력과 실패 기록을 조회합니다.',
risk: 'HIGH',
scope: 'GLOBAL',
},
{
permission: 'admin.profiles.manage',
label: 'Profile 운영',
description: '지정 profile의 배포, 초기화와 runtime을 관리합니다.',
risk: 'CRITICAL',
scope: 'PROFILE',
},
{
permission: 'admin.reset.schedule',
label: 'Profile 초기화 예약',
description: '완료된 profile의 다음 초기화를 예약합니다.',
risk: 'CRITICAL',
scope: 'PROFILE',
},
{
permission: 'admin.resume.when-stopped',
label: '중지 Profile 재개',
description: '중지 또는 일시정지된 profile을 재개합니다.',
risk: 'HIGH',
scope: 'PROFILE',
},
{
permission: 'admin.survey.open',
label: '게임 설문 운영',
description: '지정 profile의 게임 내 설문 화면과 API를 운영합니다.',
risk: 'MEDIUM',
scope: 'PROFILE',
},
{
permission: 'admin.tournament',
label: '게임 대회 운영',
description: '지정 profile의 게임 내 토너먼트를 운영합니다.',
risk: 'HIGH',
scope: 'PROFILE',
},
{
permission: 'admin.releases.manage',
label: 'Gateway 릴리스',
description: 'Gateway control plane을 배포하거나 이전 release로 전환합니다.',
risk: 'CRITICAL',
scope: 'GLOBAL',
},
] as const;
const CAPABILITY_BY_PERMISSION = new Map(ADMIN_CAPABILITIES.map((entry) => [entry.permission, entry]));
export const getAdminCapability = (permission: string): AdminCapabilityDefinition | undefined =>
CAPABILITY_BY_PERMISSION.get(permission);
export const resolveAdminActionCapability = (path: string, rawInput?: unknown): string | undefined => {
if (path.endsWith('.users.createLocal')) return 'admin.users.create';
if (path.includes('.users.')) return 'admin.users.manage';
if (path.includes('.system.')) return 'admin.notice.manage';
if (path.includes('.releases.')) return 'admin.releases.manage';
if (path.endsWith('.profiles.requestAction') && rawInput && typeof rawInput === 'object') {
const action = (rawInput as { action?: unknown }).action;
if (action === 'RESET_SCHEDULED') return 'admin.reset.schedule';
if (action === 'RESUME') return 'admin.resume.when-stopped';
if (action === 'OPEN_SURVEY') return 'admin.survey.open';
}
if (path.includes('.operations.') || path.includes('.profiles.')) return 'admin.profiles.manage';
return undefined;
};
export const isProfileCapabilityPermission = (permission: string): boolean =>
getAdminCapability(permission)?.scope === 'PROFILE';