javascript - NestJS 的自訂路由裝飾器
我為我的路由創建了一些自訂的參數裝飾器,但我找不到任何有關如何為路由本身創建裝飾器的有用文檔。有一些描述是關於如何將現有的方法裝飾器打包在一起的,但對我沒有幫助。
我想要達成的是一些簡單的範圍驗證。範圍已經在請求上下文中設置好了。我目前使用的,僅基於 TypeScript 裝飾器,但實際上沒有任何進展:
控制器.ts
@RequiredScope(AuthScope.OWNER)
@Get('/some-route')
async get() {
...
}
required-scopes.ts
export function RequiredScope(...scopes: string[]) {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
console.log(`Validation of scopes '${scopes.join(',')}' for input '${RequestContext.getScopes().join(',')}'`)
if (!scopes.map(s => RequestContext.hasOneOfTheScopes(s)).find(valid => !valid)) {
throw new HttpException(`Missing at least one scope of '${scopes.join(',')}'`, HttpStatus.FORBIDDEN)
}
}
}
問題在於,我的請求上下文甚至不可用,因為設置上下文的中介軟體尚未啟動。請求立即失敗。
有人可以指引我正確的方向嗎?
答案#1
正如Khaled Mohamed友善建議的(謝謝!),用守衛來解決這個問題非常簡單,而且是一個更好的方法。
在 scopes.decorator.ts 中使用所需範圍作為參數創建一個裝飾器:
export const Scopes = (...scopes: string[]) => SetMetadata('scopes', scopes)
在 scopes.guard.ts 中設定一個守衛,它會檢查提供的 meta scopes,並檢查需求是否已滿足:
@Injectable()
export class ScopesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const scopes = this.reflector.get<string[]>('scopes', context.getHandler())
if (!scopes || scopes.length === 0) return true
if (!scopes.map(s => RequestContext.hasOneOfTheScopes(s)).find(valid => !valid)) {
throw new HttpException(`Missing at least one scope of '${scopes.join(',')}'`, HttpStatus.FORBIDDEN)
}
return true
}
}
在 app.module.ts 中全局啟用守衛:
@Module({
imports: [...],
controllers: [...],
providers: [
{
provide: APP_GUARD,
useClass: ScopesGuard,
}
],
})
在 controller.ts 中的路由上使用裝飾器:
@Scopes(AuthScope.OWNER)
@Get('/some-route')
async get() {
...
}
