在 NestJS 上创建 OR Guard

问题描述 投票:0回答:1

我有一个带有路线的控制器,我想用 Guards 来保护该路线。 我有这三个守则:IsAuthentifiedGuard、HasRoleGuard 和 IsSafeGuard,我希望这两个条件至少其中之一有效:

  • IsAuthentifiedGuard 和 HasRoleGuard 都可以
  • IsSafeGuard 还可以

例如,如果用户经过身份验证并且具有足够的角色,则应该没问题,但如果没有,但调用是“安全的”,我也希望它没问题。

我的 OrGuard:

@Injectable()
export class OrGuard implements CanActivate {
  constructor(private readonly orGuards: CanActivate[][]) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const orGuardsPromises = await Promise.all(
      this.orGuards.map(async andGuards => {
        const andGuardPromises = await Promise.all(
          andGuards.map(async guard => {
            return guard.canActivate(context)
          }),
        )
        return andGuardPromises.every(canActivate => canActivate === true)
      }),
    )

    return orGuardsPromises.some(canActivate => canActivate === true)
  }
}

还有我的控制器:

@Controller('my_route')
export class MyController {
  @Post('/')
  @UseGuards(new OrGuard([[new IsAuthentifiedGuard(), new HasRoleGuard()], [new IsSafeGuard()]]))
  async myRoute() {}
}

但是我对需要依赖的守卫有疑问。 例如,如果 HasRoleGuard 在构造函数中需要 ConfigService,则这是行不通的。

另一种方法是使用 my 或guard,如下所示:

@UseGuards(OrGuard)
@SetMetadata('orGuards', [[IsAuthentifiedGuard, HasRoleGuard], [IsSafeGuard]])

但是在我的守卫中,我没有成功地从类名中实例化这些守卫以及它们所需的所有依赖项。

你有什么建议?

typescript dependency-injection nestjs
1个回答
0
投票

您想要做的事情可以通过

@nest-lab/or-guard
实现。您需要将您的守卫注册为提供程序(只需将它们添加到提供程序数组即可),并且您需要为
AndGuard
创建一个自定义提供程序,以便稍后可以由
OrGuard
引用它。像这样的事情应该对你有用:

@Module({
  providers: [
    IsAuthentifiedGuard,
    HasRoleGuard,
    IsSafeGuard,
    {
      provide: 'AndGuard',
      useClass: AndGuard([IsAuthenticatedGuard, HasRoleGuard]),
    },
    ...
  ]
})

然后你可以使用

@UseGuards(OrGuard(['AndGuard', IsSafeGuard]))
,它应该可以正常工作。如果您愿意,您可以查看测试以获得有关其工作原理的更多灵感

© www.soinside.com 2019 - 2024. All rights reserved.