Open anitricks opened 5 years ago
I think your inject token is incorrect? Try this
AccessControlModule.forRootAsync({
inject: [ROLE_REPO],
useFactory: (service: Role) => {
return new RolesBuilder([
...adminGrants // testing local file grants
]);
},
}),
Let me know how that goes. I think that should be right? Inject takes an array of provider tokens? Not Providers themselves? Think the required type (without looking at the documentation/type itself) it's string, Symbol, Function, Provider
Where Provider is Function, String, Symbol
?
@bashleigh i tried putting the token as the string but its throwing me error that it wants it this way: { provide, useClass }
I need to inject a TypeORM entity or a RoleService
to fetch the roles from the DB
can someone provide an example of injecting a database connection into forRootAsync method?
@anitricks Sorry been mega busy! Could you provide an example application?
How is this async? The useFactory doesn't accept an async promise of rolesbuilder so I don't see how this can be served from a database which will always need to wait for an async promise. in the forRootAsync, would it work to change it to be something like the following?
static forRootAsync(options: {
inject?: Provider[];
useFactory: (...args: any) => Promise<RolesBuilder> | RolesBuilder;
}): DynamicModule;
@thamera oh yea, that was stupid of me. Wanna make a PR for it with test? Really busy sorry.
Wish I could. I'm still learning a lot here and am not seeming to grasp some core elements here. I tried making the simple change directly in my local and it does work to be async but I still can't get this to load roles/grants from my db. I ended up moving my roles data calls into their own module (just a standard CRUD module using mongoose. I tried importing that module into my access control module where this loads with an import of my roles module. Trying to inject the roles service into the forrootasync but keep getting errors about resolving dependencies. I'm thinking the accesscontrolmodule loads too early in this setup to access the other module/service? Below is some of where I'm at if anyone has a suggestion:
Roles Module
@Module({
imports: [
MongooseModule.forFeature([{name: 'role', schema: RoleSchema}]),
RolesModule
],
controllers: [RolesController],
providers: [RolesService],
exports: [
RolesService,
MongooseModule.forFeature([{name: 'role', schema: RoleSchema}])
]
})
export class RolesModule {}
Roles Service:
@Injectable()
export class RolesService implements IRolesService {
constructor(@InjectModel('role') private readonly roleModel: Model<IRole> ) {}
async findAll(): Promise<IRole[]> {
return await this.roleModel.find().exec();
}
...
Access Control Module:
@Module({
imports: [
RolesModule,
AccessControlModule.forRootAsync({
inject: [RolesService],
useFactory: async (service: RolesService) => { //service: RolesService
const roles = await service.findAll();
let roleGrants = [];
... populate roleGrants array to roles/grants from db
return new RolesBuilder([
...roleGrants
]);
}
})
],
providers: [AccesscontrolService],
exports: [
//...AccesscontrolProviders
]
})
export class AccesscontrolModule {}
@thamera any updates over a solution or an exmaple?
I just needed something what works. I have realised that usually when you are using external module for db management it is worth of it to have also imports
option.
What about something like this https://github.com/creaux/nest-access-control/blob/2974fe2d0cdef35d031f64023cf3f6b403b0f72c/src/access-control.module.ts#L54
Ok so! Firstly! Sorry it's taken me nearly 2 years to reply. I've had an absolutely mental year and finally taken some time off to come back to reality. I did a quick test #49 and discovered that for some reason I added an import property to the forRootAsync method which I thought was weird. But turns out, that's what fixes your issue!
Not entirely sure why a provider specified as a provider is not found but an imported module, I think (trying to remember some research I did nearly 2 years ago) nestjs creates the imported modules before creating the providers you've specified so a theAccessControlModule.forRootAsync
static method would be called before your provider is created therefore, cannot find your specified provider! SO!
I'd added an import property, which I guess was added to get around this issue! I added my module with the provider I wanted to the imports
property and BOOM, it worked. This will solve your issue!
@Injectable()
class TestProvider {
}
@Module({
providers: [TestProvider],
exports: [TestProvider],
})
class TestModule {
}
@Module({
imports: [
AccessControlModule.forRootAsync({
imports: [TestModule],
inject: [TestProvider],
useFactory: (test: TestProvider): RolesBuilder => {
return new RolesBuilder();
},
}),
],
})
export class ExampleModule {}
So! Given this example and your provided snippet, it should work like this
@Module({
imports: [
AccessControlModule.forRootAsync({
imports: [RolesModule], // <=============== notice change here!
inject: [RolesService],
useFactory: async (service: RolesService) => { //service: RolesService
const roles = await service.findAll();
let roleGrants = [];
... populate roleGrants array to roles/grants from db
return new RolesBuilder([
...roleGrants
]);
}
})
],
providers: [AccesscontrolService],
exports: [
//...AccesscontrolProviders
]
})
export class AccesscontrolModule {}
This then ensures your RoleModule is created and exports your injectable provider BEFORE your factory is called.
Now to travel back in time and give this info to you 2 years ago!
Hi, all!
If I understand correctly at Nest.js we can't use providers in the forRootAsync
function?
Because when I try to import the provider that provides all my configs in forRootAsync. That provider can't be injected into the Module for usage. Maby somebody has a solution for this issue or any ideas on how to move around it?
Hi I'm not sure... One thing to look at is what version of nestjs you have. Since v8 this package is no more needed. Documentation describes how to implement castle, perhaps you want to have a look at it.
I am using the
forRootAsync
method to load roles dynamically from the database however I am getting an error. I am a newbie to Nestjs, so please let me know if I am doing something wrongI am trying to to import the
AccessControlModule
in the root module and I have aRolesService
to inject as a dependency in theforRootAsync
method. The code is below