根据需要向Guard注入服务

时间:2019-12-16 08:32:50

标签: nestjs

我有一个检查资源所有权的守卫。如果用户是所有者(创建该资源),那么他可以访问(更新,读取,删除)。

每个资源均由其自己的服务处理(注释由具有CommentsModule的{​​{1}}处理),依此类推。每个处理拥有所有权的资源的服务都实现一个名为CommentsService的功能,并且守护程序将调用该功能。

如果可能的话,我希望我的警卫根据调用它的控制器注入正确的服务。因此,如果hasOwnership正在呼叫警卫,那么它应该注入并使用CommentsController

我尝试使用动态模块在托管警卫队的CommentsService.hasOwnership的{​​{1}}上注入正确的模块/服务,但这似乎是行不通的,因为我无法正确处理循环依赖项。

由于循环依赖关系,将每项服务注入警卫并选择正确的服务将非常麻烦。

有更好的方法吗?这将是理想的行为。

imports

1 个答案:

答案 0 :(得分:1)

由于在运行时(而不是在编译时)需要其他服务,因此需要采用工厂方法。添加新资源时,维护起来有点麻烦,但这是您必须进行的权衡。

我要做的第一件事是创建一个工厂类,以根据ExecutionContext确定哪个服务是要使用的正确服务:

export interface IService {
  hasOwnership() : Promise<boolean>;
}

@Injectable()
export class ServiceFactory {

  //Make sure every service returned from this method implements the "IService" interface
  public getCorrectService(context: ExecutionContext) : IService {

    if(context...) {
      return new CommentsService();
    } else if(context...) {
      return new SomeOtherService();
    }
  }
}

现在,您可以将工厂注入您的警卫队以获取正确的服务:

@Injectable()
export default class ACGuard implements CanActivate {

  constructor(private serviceFactory: ServiceFactory) {}

  canActivate(context: ExecutionContext) {

    //Here's where the magic of this happens...
    const correctService: Iservice = this.serviceFactory.getCorrectService(context);

    return await correctService.hasOwnership();
  }
}