import { ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { PermissionsGuard } from '../../domains/identity/guards'; import { isAuditListUnrestricted } from '../../domains/operations/audit/audit-list-scope'; import { PERMISSIONS_KEY } from '../../shared/common/decorators'; /** Mirrors run-seed.ts role permission assignments (SEC010–SEC012). */ const ROLE_PERMISSIONS: Record = { SUPER_ADMIN: ['*'], MATCH_ADMIN: [ 'matches.manage', 'settlement.confirm', 'content.manage', 'bets.view', 'reports.view', 'audit.view', ], FINANCE_ADMIN: [ 'wallet.deposit', 'wallet.withdraw', 'cashback.confirm', 'agents.view', 'agents.credit', 'users.view', 'users.create', 'deposit.manage', 'deposit.review', 'reports.view', 'bets.view', 'audit.view', ], SUPPORT: ['users.view', 'users.reset_password', 'bets.view', 'reports.view', 'audit.view'], }; function mockContext(user: Record): ExecutionContext { return { switchToHttp: () => ({ getRequest: () => ({ user }), }), getHandler: () => ({}), getClass: () => ({}), } as ExecutionContext; } function guardAllows(user: Record, ...required: string[]): boolean { const reflector = { getAllAndOverride: (key: string) => (key === PERMISSIONS_KEY ? required : undefined), } as unknown as Reflector; const guard = new PermissionsGuard(reflector); try { return guard.canActivate(mockContext(user)); } catch { return false; } } function userWithRole(role: string) { return { userType: 'ADMIN', role, permissions: ROLE_PERMISSIONS[role] ?? [], }; } describe('Admin RBAC (SEC010–SEC012)', () => { it('SEC010: SUPPORT cannot perform wallet deposit', () => { const user = userWithRole('SUPPORT'); expect(guardAllows(user, 'wallet.deposit')).toBe(false); expect(guardAllows(user, 'users.view')).toBe(true); expect(guardAllows(user, 'users.reset_password')).toBe(true); }); it('SEC011: FINANCE_ADMIN cannot manage matches', () => { const user = userWithRole('FINANCE_ADMIN'); expect(guardAllows(user, 'matches.manage')).toBe(false); expect(guardAllows(user, 'wallet.deposit')).toBe(true); expect(guardAllows(user, 'agents.credit')).toBe(true); }); it('SEC012: MATCH_ADMIN cannot perform wallet deposit', () => { const user = userWithRole('MATCH_ADMIN'); expect(guardAllows(user, 'wallet.deposit')).toBe(false); expect(guardAllows(user, 'settlement.confirm')).toBe(true); expect(guardAllows(user, 'content.manage')).toBe(true); expect(guardAllows(user, 'settlement.resettle')).toBe(false); }); it('SUPER_ADMIN bypasses permission checks', () => { const user = userWithRole('SUPER_ADMIN'); expect(guardAllows(user, 'wallet.deposit')).toBe(true); expect(guardAllows(user, 'matches.manage')).toBe(true); expect(guardAllows(user, 'settings.manage')).toBe(true); }); it('audit list scope: only SUPER_ADMIN is unrestricted', () => { expect(isAuditListUnrestricted('SUPER_ADMIN')).toBe(true); expect(isAuditListUnrestricted('FINANCE_ADMIN')).toBe(false); expect(isAuditListUnrestricted('MATCH_ADMIN')).toBe(false); }); });