Type safe roles guard with the decorator for controller made easy. Just specify how to get role
from ExecutionContext
. nestjs-roles
will do the rest.
npm i nestjs-roles
First, let's define roles:
// role.enum.ts
export enum Role {
ADMIN = 'ADMIN',
USER = 'USER',
MODERATOR = 'MODERATOR',
}
Let's say you use nestjs-session and keep role
in session
property object of request
. So then create guard with getRole
callback:
// roles.guard.ts
import { ExecutionContext } from '@nestjs/common';
import { createRolesGuard } from 'nestjs-roles';
import { Role } from './role.enum';
function getRole(context: ExecutionContext) {
const { session } = context.switchToHttp().getRequest();
if (!session) return;
// you can use single role or array of roles
// if you provide array of roles, the guard will pass if one of roles is in required roles
return (session as { role?: Role | Role[] }).role;
}
export const Roles = createRolesGuard<Role>(getRole);
After that we can set Roles
guard globally (don't forget to pass Reflector
instance):
// bootstrap.ts
import { NestFactory, Reflector } from '@nestjs/core';
import { Roles } from './roles.guard';
const app = await NestFactory.create(AppModule);
const reflector = app.get<Reflector>(Reflector);
app.useGlobalGuards(new Roles(reflector));
All settings are done. Now you can set up access in your controllers:
// secrets.controller.ts
import { Roles } from './roles.guard';
@Controller('secrets')
@Roles.Params(true) // setup access on Controller for users with any existing role
export class SecretsController {
@Get('my')
async readMy() {
// ...
}
@Patch(':id')
@Roles.Params(Role.ADMIN) // override access on certain handler
async update() {
// ...
}
}