Skip to content

为每个处理器设置角色

我们的 RolesGuard 现在在正常工作,但还不是很智能。我们仍然没有利用最重要的守卫的特征,即执行上下文。它还不知道角色,或者每个处理程序允许哪些角色。例如,CatsController 可以为不同的路由提供不同的权限方案。其中一些可能只对管理用户可用,而另一些则可以对所有人开放。我们如何以灵活和可重用的方式将角色与路由匹配起来?

这就是自定义元数据发挥作用的地方(从这里了解更多)。 Http-Typedi 提供了通过 @SetMetadata() 装饰器将定制元数据附加到路由处理程序的能力。这些元数据提供了我们所缺少的角色数据,而守卫需要这些数据来做出决策。让我们看看使用 @SetMetadata():

cats.controller.ts

ts
@PostMapping()
@SetMetadata('roles', ['admin'])
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}

TIP

@SetMetadata() 需要从 http-typedi 包导入。

通过上面的构建,我们将 roles 元数据(roles 是一个键,而 ['admin'] 是一个特定的值)附加到 create() 方法。虽然这样可以运行,但直接使用 @SetMetadata() 并不是一个好做法。相反,你应该创建你自己的装饰器

roles.decorator.ts

ts
import { SetMetadata } from 'http-typedi'

export const Roles = (...roles: string[]) => SetMetadata('roles', roles)

这种方法更简洁、更易读,而且是强类型的。现在我们有了一个自定义的 @Roles() 装饰器,我们可以使用它来装饰 create() 方法。

cats.controller.ts

ts
@PostMapping()
@Roles('admin')
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}