import { ForbiddenException, type ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { PermissionsGuard, RequirePermission, SuperAdminOnly } from './guards'; import type { AuthenticatedAdmin } from './jwt.strategy'; import { SUPER_ADMIN_MOBILE, withSuperAdminRids } from './super-admin'; class Routes { @SuperAdminOnly() @RequirePermission('config.wallet') superOnly() {} @SuperAdminOnly({ allowBranch: true }) @RequirePermission('order.list') superOrBranch() {} @RequirePermission('order.list', 'order.omde', 'order.tamin') anyOf() {} open() {} } function admin(over: Partial = {}): AuthenticatedAdmin { return { id: 'a1', fullName: 'x', mobile: '09120000000', role: 'SUPER_ADMIN', userTypeId: 85, branchId: null, permissions: ['config.wallet', 'order.list', 'order.omde'], ...over, }; } function run(handler: keyof Routes, user: AuthenticatedAdmin) { const ctx = { getHandler: () => Routes.prototype[handler], getClass: () => Routes, switchToHttp: () => ({ getRequest: () => ({ user }) }), } as unknown as ExecutionContext; return new PermissionsGuard(new Reflector()).canActivate(ctx); } describe('PermissionsGuard — super-admin-only routes', () => { it('admits the super admin', () => { expect(run('superOnly', admin({ mobile: SUPER_ADMIN_MOBILE }))).toBe(true); }); it('refuses any other admin, even one holding the rid and the SUPER_ADMIN role', () => { expect(() => run('superOnly', admin())).toThrow(ForbiddenException); }); it('refuses a branch admin unless the route allows branches', () => { expect(() => run('superOnly', admin({ branchId: 'b1' }))).toThrow(ForbiddenException); expect(run('superOrBranch', admin({ branchId: 'b1' }))).toBe(true); expect(() => run('superOrBranch', admin())).toThrow(ForbiddenException); }); it('still requires the rid from a branch admin', () => { expect(() => run('superOrBranch', admin({ branchId: 'b1', permissions: [] }))).toThrow( ForbiddenException, ); }); it('leaves routes without the decorator alone', () => { expect(run('open', admin({ permissions: [] }))).toBe(true); }); }); describe('PermissionsGuard — several rids', () => { it('admits a holder of any one of them', () => { expect(run('anyOf', admin({ permissions: ['order.tamin'] }))).toBe(true); }); it('refuses a holder of none', () => { expect(() => run('anyOf', admin({ permissions: ['product.list'] }))).toThrow(ForbiddenException); }); }); describe('withSuperAdminRids', () => { it('adds the super-admin rids for the super admin only', () => { expect(withSuperAdminRids(SUPER_ADMIN_MOBILE, [])).toContain('config.wallet'); expect(withSuperAdminRids('09120000000', ['product.list'])).toEqual(['product.list']); }); });