chore: import DH V2 D5.6.4 production baseline
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
ExecutionContext,
|
||||
ForbiddenException,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import { RequirePermissions } from '../../src/authorization/decorators/require-permissions.decorator';
|
||||
import { PermissionsGuard } from '../../src/authorization/guards/permissions.guard';
|
||||
import { Public } from '../../src/auth/decorators/public.decorator';
|
||||
import type { AuthPrincipal } from '../../src/common/http/request-context';
|
||||
|
||||
@RequirePermissions('dashboard.read')
|
||||
class ProtectedController {
|
||||
@RequirePermissions('users.create')
|
||||
createUser() {}
|
||||
|
||||
openToAuthenticatedUsers() {}
|
||||
}
|
||||
|
||||
class UndecoratedController {
|
||||
handle() {}
|
||||
}
|
||||
|
||||
@RequirePermissions('dashboard.read')
|
||||
class PublicController {
|
||||
@Public()
|
||||
handle() {}
|
||||
}
|
||||
|
||||
function principal(permissions: string[]): AuthPrincipal {
|
||||
return {
|
||||
userId: 'b6f6b10e-434a-4d72-9ec9-3520212dd290',
|
||||
username: 'admin',
|
||||
sessionId: '1bab61ac-65d1-40e6-816b-63d90131a795',
|
||||
firstName: 'Admin',
|
||||
lastName: 'DH',
|
||||
email: null,
|
||||
mustChangePassword: false,
|
||||
roles: ['admin'],
|
||||
permissions,
|
||||
transport: 'cookie',
|
||||
};
|
||||
}
|
||||
|
||||
function context(
|
||||
controller: new () => object,
|
||||
handlerName: string,
|
||||
auth?: AuthPrincipal,
|
||||
): ExecutionContext {
|
||||
const handler = controller.prototype[
|
||||
handlerName as keyof typeof controller.prototype
|
||||
];
|
||||
|
||||
return {
|
||||
getHandler: () => handler,
|
||||
getClass: () => controller,
|
||||
switchToHttp: () => ({
|
||||
getRequest: () => ({ auth }),
|
||||
}),
|
||||
} as unknown as ExecutionContext;
|
||||
}
|
||||
|
||||
const guard = new PermissionsGuard(new Reflector());
|
||||
|
||||
test('PermissionsGuard leaves handlers without requirements available', () => {
|
||||
assert.equal(
|
||||
guard.canActivate(context(UndecoratedController, 'handle')),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('PermissionsGuard gives explicit public metadata priority', () => {
|
||||
assert.equal(guard.canActivate(context(PublicController, 'handle')), true);
|
||||
});
|
||||
|
||||
test('PermissionsGuard returns 401 when required permissions have no principal', () => {
|
||||
assert.throws(
|
||||
() => guard.canActivate(context(ProtectedController, 'createUser')),
|
||||
(error: unknown) =>
|
||||
error instanceof UnauthorizedException && error.getStatus() === 401,
|
||||
);
|
||||
});
|
||||
|
||||
test('PermissionsGuard returns 403 when any required permission is missing', () => {
|
||||
assert.throws(
|
||||
() =>
|
||||
guard.canActivate(
|
||||
context(
|
||||
ProtectedController,
|
||||
'createUser',
|
||||
principal(['dashboard.read']),
|
||||
),
|
||||
),
|
||||
(error: unknown) =>
|
||||
error instanceof ForbiddenException && error.getStatus() === 403,
|
||||
);
|
||||
});
|
||||
|
||||
test('PermissionsGuard requires changing a temporary password first', () => {
|
||||
const auth = principal(['dashboard.read', 'users.create']);
|
||||
auth.mustChangePassword = true;
|
||||
|
||||
assert.throws(
|
||||
() =>
|
||||
guard.canActivate(context(ProtectedController, 'createUser', auth)),
|
||||
(error: unknown) =>
|
||||
error instanceof ForbiddenException &&
|
||||
error.getStatus() === 403 &&
|
||||
(error.getResponse() as { code?: string }).code ===
|
||||
'PASSWORD_CHANGE_REQUIRED',
|
||||
);
|
||||
});
|
||||
|
||||
test('PermissionsGuard authorizes when class and handler permissions are granted', () => {
|
||||
assert.equal(
|
||||
guard.canActivate(
|
||||
context(
|
||||
ProtectedController,
|
||||
'createUser',
|
||||
principal(['dashboard.read', 'users.create']),
|
||||
),
|
||||
),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('PermissionsGuard applies class requirements to every handler', () => {
|
||||
assert.equal(
|
||||
guard.canActivate(
|
||||
context(
|
||||
ProtectedController,
|
||||
'openToAuthenticatedUsers',
|
||||
principal(['dashboard.read']),
|
||||
),
|
||||
),
|
||||
true,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user