gpt4 book ai didi

javascript - 使用模块功能的提供程序创建作用域模块

转载 作者:搜寻专家 更新时间:2023-10-30 21:34:02 25 4
gpt4 key购买 nike

当我多次使用导入 PolicyModule.forFeature 时,下一次导入 PolicyModule 会覆盖 PolicyStorage 中的门。
当我尝试通过调用 PolicyProvider

CandidateModuleCandidateEducationService 中使用 PolicyProvider
await this.policy.denyAccessUnlessGranted('canDelete', education);

我收到异常未找到实体“CandidateEducationEntity”门

我在 CandidateEducationService 中输出 PolicyStorage 并使用 JobPolicy 获得数组门

PolicyStorage {
gates:
[ { policy: [Function: JobPolicy], entity: [Function: JobEntity] } ]
}

但我很期待

PolicyStorage {
gates:
[ { policy: [Function: CandidateEducationPolicy], entity: [Function: CandidateEducationEntity] } ]
}

我创建了一个动态模块 PolicyModule

@Module({})
export class PolicyModule {
public static forFeature(gates: PolicyGate[]): DynamicModule {
const providers: Provider[] = [
...gates.map(gate => gate.policy),
{
provide: PolicyStorage,
useValue: new PolicyStorage(gates),
},
PolicyProvider,
];

return {
module: PolicyModule,
imports: [
CommonModule,
],
providers,
exports: providers,
};
}
}

策略存储

@Injectable()
export class PolicyStorage {
constructor(private gates: PolicyGate[]) {
console.log(this.gates);
}

public find(name: string): PolicyGate | null {
return this.gates.find(policy => policy.entity.name === name);
}
}

PolicyProvider

@Injectable()
export class PolicyProvider<E, P> {
constructor(
private readonly moduleRef: ModuleRef,
private readonly gateStorage: PolicyStorage,
private readonly appContext: AppContextService,
) {
}

public async denyAccessUnlessGranted(methodNames: MethodKeys<P>, entity: E, customData?: any) {
if (await this.denies(methodNames, entity, customData)) {
throw new ForbiddenException();
}
}

public async allowAccessIfGranted(methodNames: MethodKeys<P>, entity: E, customData?: any) {
const allowed = await this.allows(methodNames, entity, customData);
if (!allowed) {
throw new ForbiddenException();
}
}

private async allows(methodNames: MethodKeys<P>, entity: E, customData?: any): Promise<boolean> {
const results = await this.getPolicyResults(methodNames, entity, customData);

return results.every(res => res === true);
}

private async denies(methodNames: MethodKeys<P>, entity: E, customData?: any): Promise<boolean> {
const results = await this.getPolicyResults(methodNames, entity, customData);

return results.every(res => res === false);
}

private async getPolicyResults(methodNames: MethodKeys<P>, entity: E, customData?: any): Promise<boolean[]> {
const methodNamesArray = Array.isArray(methodNames) ? methodNames : [methodNames];
const gate = this.findByClassName(entity.constructor.name);
const user = this.appContext.get('user');
const policy = await this.moduleRef.get<P>(gate.policy, {strict: false});
const results = [];

for (const methodName of methodNamesArray) {
results.push(!!await policy[methodName as string](entity, user, customData));
}

return results;
}

private findByClassName(name: string) {
const gate = this.gateStorage.find(name);

if (!gate) {
throw new RuntimeException(`Gate by entity '${name}' not found`);
}

return gate;
}
}

在其他模块中使用模块。示例:
工作模块

@Module({
imports: [
TypeOrmModule.forFeature(
[
JobEntity,
],
),
PolicyModule.forFeature([
{
policy: JobPolicy,
entity: JobEntity,
},
]),
],
controllers: [
ManagerJobsController,
],
providers: [
ManagerJobsService,
],
})
export class JobsModule {
}

候选模块

@Module({
imports: [
TypeOrmModule.forFeature(
[
CandidateEducationEntity,
],
),
PolicyModule.forFeature([
{
policy: CandidateEducationPolicy,
entity: CandidateEducationEntity,
},
]),
],
controllers: [
CandidateEducationController,
],
providers: [
CandidateEducationService,
],
})
export class CandidateModule {
}

最佳答案

更新:

Nest v6 引入了请求范围的提供程序,请参阅 this answer .


所有模块及其提供者都是单例。如果您在同一个模块中使用同一个 token 注册一个提供者两次,它将被覆盖。

如果您查看 TypeOrmModule,您会发现它 registers its repository providers在一个独特的custom token下对于每个实体:

export function getRepositoryToken(entity: Function) {
if (
entity.prototype instanceof Repository ||
entity.prototype instanceof AbstractRepository
) {
return getCustomRepositoryToken(entity);
}
return `${entity.name}Repository`;
}

因此在您的情况下,您可以使用函数 getPolicyProviderTokengetPolicyStorageToken 并在这些 token 下注册和注入(inject)您的提供商,这些 token 对于每个导入模块都是唯一的。

关于javascript - 使用模块功能的提供程序创建作用域模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54610471/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com