为NestJS定制路由装饰器

5

我为我的路由创建了一些自定义参数装饰器,但是我没有找到有关如何为路由本身创建装饰器的有用文档。有一些描述如何捆绑现有方法装饰器的说明,但这对我没有帮助。

我想实现的是一些简单的作用域验证。作用域已经设置在请求上下文中。根据TypeScript装饰器,我目前拥有的东西实际上没有任何进展:

controller.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
你尝试过使用守卫而不是制作装饰器吗?https://docs.nestjs.com/guards - Khaled Mohamed
非常感谢您的建议。它非常有效,并且更适合这种情况的使用。 - tpschmidt
1个回答

5

Khaled Mohamed所好心提出的(感谢!),使用守卫(guards)来解决问题非常简单且更为有效。


scopes.decorator.ts中,通过将所需的作用域作为参数创建一个装饰器:

export const Scopes = (...scopes: string[]) => SetMetadata('scopes', scopes)

scopes.guard.ts 中设置一个守卫,用于检查提供的元 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() {
    ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接