Files
gridpilot.gg/apps/api/src/domain/auth/AuthorizationGuard.test.ts

89 lines
3.0 KiB
TypeScript

import { ForbiddenException, UnauthorizedException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { describe, expect, it, vi } from 'vitest';
import { AuthorizationGuard } from './AuthorizationGuard';
import { Public } from './Public';
import { RequireRoles } from './RequireRoles';
class DummyController {
@Public()
publicHandler(): void {}
protectedHandler(): void {}
@RequireRoles('admin')
adminHandler(): void {}
}
function createExecutionContext(options: { handler: Function; userId?: string }) {
const request = options.userId ? { user: { userId: options.userId } } : {};
return {
getHandler: () => options.handler,
getClass: () => DummyController,
switchToHttp: () => ({
getRequest: () => request,
}),
};
}
describe('AuthorizationGuard', () => {
it('allows public routes without a user session', () => {
const authorizationService = { getRolesForUser: vi.fn() };
const guard = new AuthorizationGuard(new Reflector(), authorizationService as any);
const ctx = createExecutionContext({
handler: DummyController.prototype.publicHandler,
});
expect(guard.canActivate(ctx as any)).toBe(true);
expect(authorizationService.getRolesForUser).not.toHaveBeenCalled();
});
it('denies non-public routes by default when not authenticated', () => {
const authorizationService = { getRolesForUser: vi.fn() };
const guard = new AuthorizationGuard(new Reflector(), authorizationService as any);
const ctx = createExecutionContext({
handler: DummyController.prototype.protectedHandler,
});
expect(() => guard.canActivate(ctx as any)).toThrow(UnauthorizedException);
});
it('allows non-public routes when authenticated', () => {
const authorizationService = { getRolesForUser: vi.fn().mockReturnValue([]) };
const guard = new AuthorizationGuard(new Reflector(), authorizationService as any);
const ctx = createExecutionContext({
handler: DummyController.prototype.protectedHandler,
userId: 'user-1',
});
expect(guard.canActivate(ctx as any)).toBe(true);
});
it('denies routes requiring roles when user does not have any required role', () => {
const authorizationService = { getRolesForUser: vi.fn().mockReturnValue(['user']) };
const guard = new AuthorizationGuard(new Reflector(), authorizationService as any);
const ctx = createExecutionContext({
handler: DummyController.prototype.adminHandler,
userId: 'user-1',
});
expect(() => guard.canActivate(ctx as any)).toThrow(ForbiddenException);
});
it('allows routes requiring roles when user has a required role', () => {
const authorizationService = { getRolesForUser: vi.fn().mockReturnValue(['admin']) };
const guard = new AuthorizationGuard(new Reflector(), authorizationService as any);
const ctx = createExecutionContext({
handler: DummyController.prototype.adminHandler,
userId: 'user-1',
});
expect(guard.canActivate(ctx as any)).toBe(true);
});
});