Reputation: 111
I pointed out the decorator in one place, but it didn't work at all. Then, I connected the guardian to the module as shown in the documentation. Now, the guardian is processing any request.
export const Permissions = (...permissions: PermissionEnum[]) =>
SetMetadata('permissions', permissions);
@Injectable()
export class PermissionGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const requirePermissions = this.reflector.getAllAndOverride<
PermissionEnum[]
>('permissions', [context.getHandler(), context.getClass()]);
console.log(requirePermissions, 'requirePermissions');
if (!requirePermissions) {
throw new HttpException(
lang.ru.http_exceptions.forbidden,
HttpStatus.FORBIDDEN,
);
}
const user = context.switchToHttp().getRequest();
//console.log(context.switchToHttp(), 'switchToHttp');
//console.log(context.switchToHttp().getRequest(), 'getRequest');
return false;
}
}
@HttpCode(201)
@UseGuards(JwtAuthGuard)
@Permissions(PermissionEnum.USER_VIEW)
@Get('/users')
getAll(@Query() query: AdminUserQueryDto) {
return this.adminService.getUsers(query);
}
@Module({
...
providers: [RoleService, { provide: APP_GUARD, useClass: PermissionGuard }],
...
})
export class RoleModule {}
Is this how it should be?
Can you tell me how I can make the guard work only on those routes where the decorator is present?
Upvotes: 0
Views: 51
Reputation: 954
You are injecting your guard to the module, so it will apply for every controller and every route handler of that module. Instead you can use the @UseGuards
decorator for each route handler.
@HttpCode(201)
@UseGuards(JwtAuthGuard)
@Permissions(PermissionEnum.USER_VIEW)
@UseGuards(PermissionGuard)
@Get('/users')
getAll(@Query() query: AdminUserQueryDto) {
return this.adminService.getUsers(query);
}
If you don't want to use both @Permissions
and @UseGuards
decorators, you can use the decorator composition option. Using that feature you can combine both decorator and create a new one.
import { applyDecorators } from '@nestjs/common';
export function PermissionsWithGuard(...permissions: PermissionEnum[]) {
return applyDecorators(
Permissions(permissions),
UseGuards(PermissionGuard),
);
}
Then in your controller
@HttpCode(201)
@UseGuards(JwtAuthGuard)
@PermissionsWithGuard(PermissionEnum.USER_VIEW)
@Get('/users')
getAll(@Query() query: AdminUserQueryDto) {
return this.adminService.getUsers(query);
}
Or else you can directly modify your Permission decorator to apply the guard too.
import { applyDecorators } from '@nestjs/common';
export function PermissionsWithGuard(...permissions: PermissionEnum[]) {
return applyDecorators(
SetMetadata('permissions', permissions),
UseGuards(PermissionGuard),
);
}
Upvotes: 0