網站搜尋

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() {
    ...
}