#nestjs #nestjs-passport
#nestjs #nestjs-паспорт
Вопрос:
Я определяю защиту ролей следующим образом:
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { User } from './user.entity';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(
private reflector: Reflector,
) { }
async matchRoles(roles: string[], userRole: User["roles"]) {
let match = false;
if (roles.indexOf(userRole) > -1) {
match = true;
}
return match
}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const roles = this.reflector.get<string[]>('roles', context.getClass());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user: User = request.user;
return this.matchRoles(roles, user.roles)
}
}
в этом примере ролей это работает только на уровне контроллера, подобном этому:
@Controller('games')
@hasRoles('user')
@UseGuards(AuthGuard(), JwtGuard, RolesGuard)
export class GamesController {
...
Но я хочу, чтобы он работал динамически как с контроллером, так и с обработчиком.
таким образом, я могу применить @hasRoles('user')
для каждого маршрута в контроллере и @hasRoles('admin')
для некоторых маршрутов в этом контроллере.
Итак, для этого мне нужно изменить метод reflector с getClass
на getHandler
динамически.
Ответ №1:
У Nest Reflector
есть встроенный метод для объединения набора метаданных на контроллерах и обработчиках маршрутов, с getAllAndMerge
которым будут объединены метаданные из класса и метода. Чтобы использовать его, вы должны сделать что-то вроде
const roles = this.reflector.getAllAndMerge(
'roles',
[
context.getHandler(),
context.getClass()
]
);
Если вы хотите получить только один набор метаданных и иметь запасной вариант (скажем, если вам нужны только метаданные обработчика, если они существуют, и если нет, получите метаданные класса), вы можете использовать getAllAndOverride
аналогичным образом
const roles = this.reflector.getAllAndOverride(
'roles',
[
context.getHandler(),
context.getClass()
]
);