[英]Conditionally instantiate service class as a provider in NestJS
I have a controller called User
and two service classes: UserAdminService
and UserSuperAdminService
.我有一个名为
User
的控制器和两个服务类: UserAdminService
和UserSuperAdminService
。 When a user makes a request to any endpoint of the User
controller, I want to check if the user making the request is an Admin or a Super Admin (based on the roles in the token) and instantiate the correct service ( UserAdminService
or UserSuperAdminService
).当用户向
User
控制器的任何端点发出请求时,我想检查发出请求的用户是管理员还是超级管理员(基于令牌中的角色)并实例化正确的服务( UserAdminService
或UserSuperAdminService
) . Note that the two services implement the same UserService
interface (just the internals of the methods that change a bit).请注意,这两个服务实现了相同的
UserService
接口(只是方法的内部结构稍有变化)。 How can I make this with NestJS?我怎样才能用 NestJS 做到这一点?
What I tried:我尝试了什么:
user.module.ts用户.module.ts
providers: [
{
provide: "UserService",
inject: [REQUEST],
useFactory: (request: Request) => UserServiceFactory(request)
}
],
user-service.factory.ts用户服务.factory.ts
export function UserServiceFactory(request: Request) {
const { realm_access } = JwtService.parseJwt(
request.headers["authorization"].split(' ')[1]
);
if (realm_access["roles"].includes(RolesEnum.SuperAdmin))
return UserSuperAdminService;
else
return UserAdminService;
}
user.controller.ts用户.controller.ts
constructor(
@Inject("UserService") private readonly userService: UserServiceInterface
) {}
One of the reasons my code is not working is because I am returning the classes and not the instantiated objects from the factory, but I want NestJS to resolve the services dependencies.我的代码不工作的原因之一是因为我返回的是类而不是工厂中的实例化对象,但我希望 NestJS 解决服务依赖关系。 Any ideas?
有任何想法吗?
Rather than passing back the class to instantiate, which Nest doesn't handle, you could add the UserSuperAdminService
and UserAdminService
to the inject
array, and pass back the instance that Nest then would create per request.您可以将
UserSuperAdminService
和UserAdminService
添加到inject
数组,然后传回 Nest 然后根据请求创建的实例,而不是传回要实例化的类,Nest 不处理该类。
providers: [
{
provide: "UserService",
inject: [REQUEST, UserSuperAdminService, UserAdminService],
useFactory: (request: Request, superAdminService: UserSuperAdminService, adminService: UserAdminService) => UserServiceFactory(request, superAdminService, adminService)
}
...
]
export function UserServiceFactory(request: Request, superAdminService: UserSuperAdminService, adminService: UserAdminService) {
const { realm_access } = JwtService.parseJwt(
request.headers["authorization"].split(' ')[1]
);
if (realm_access["roles"].includes(RolesEnum.SuperAdmin))
return superAdminService;
else
return adminService;
}
Instead of trying to conditionally instantiate a service class you could create a global middleware to redirect the request to the appropriate controller eg您可以创建一个全局中间件来将请求重定向到适当的控制器,而不是尝试有条件地实例化服务类,例如
import { Injectable, NestMiddleware } from '@nestjs/common'; @Injectable() export class AdminUserMiddleware implements NestMiddleware { use(req: any, res: any, next: () => void) { const { realm_access } = JwtService.parseJwt( req.headers["authorization"].split(' ')[1] ); if (realm_access["roles"].includes(RolesEnum.SuperAdmin)) { req.url = req.url.replace(/^\/, '/super-admin/'); } next(); } }
Then you can apply it to all routes in your app.module.ts然后你可以将它应用到你的 app.module.ts 中的所有路由
@Module({ imports: [HttpModule], controllers: [UserAdminController, UserSuperAdminController] providers: [UserSuperAdminService, UserAdminService] }) export class AppModule implements NestModule { configure(consumer: MiddlewareConsumer) { consumer.apply(AdminUserMiddleware).forRoutes('/'); } }
and have the following controlers:并具有以下控制器:
@Controller('/') export class UserAdminController { private readonly logger: Logger = new Logger(UserAdminController.name); constructor(private readonly userAdminService: UserAdminService) {}
@Controller('/super-admin') export class UserSuperAdminController { private readonly logger: Logger = new Logger(UserSuperAdminController.name); constructor(private readonly userSuperAdminService: UserSuperAdminService) {} }
See the NestJS docs and this post for further details有关详细信息,请参阅 NestJS文档和这篇文章
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.