@nestbolt/permissions
Configuration
All configuration options for PermissionsModule.forRoot() and PermissionsModule.forRootAsync(), including cache, guard names, wildcards, and exception display.
The PermissionsModule supports both static and async configuration. In either case, the module registers as global -- you only need to import it once in your root AppModule, and all services, guards, and decorators will be available throughout your application.
Static Configuration (forRoot)
Use forRoot() when all configuration values are known at compile time:
import { Module } from "@nestjs/common";
import { PermissionsModule } from "@nestbolt/permissions";
import { TypeOrmPermissionUserRepository } from "./repositories/permission-user.repository";
@Module({
imports: [
PermissionsModule.forRoot({
userRepository: TypeOrmPermissionUserRepository,
defaultGuardName: "default",
enableWildcardPermissions: false,
cache: {
enabled: true,
ttl: 86400000,
},
displayPermissionInException: false,
displayRoleInException: false,
}),
],
})
export class AppModule {}Async Configuration (forRootAsync)
Use forRootAsync() when configuration values need to be resolved at runtime, for example from environment variables via ConfigService:
import { Module } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { PermissionsModule } from "@nestbolt/permissions";
import { TypeOrmPermissionUserRepository } from "./repositories/permission-user.repository";
@Module({
imports: [
ConfigModule.forRoot(),
PermissionsModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
userRepository: TypeOrmPermissionUserRepository,
defaultGuardName: config.get<string>("PERMISSIONS_GUARD_NAME", "default"),
enableWildcardPermissions: config.get<boolean>("ENABLE_WILDCARD_PERMISSIONS", false),
cache: {
enabled: config.get<boolean>("PERMISSIONS_CACHE_ENABLED", true),
ttl: config.get<number>("PERMISSIONS_CACHE_TTL", 86400000),
},
displayPermissionInException: config.get<boolean>("DISPLAY_PERMISSION_IN_EXCEPTION", false),
displayRoleInException: config.get<boolean>("DISPLAY_ROLE_IN_EXCEPTION", false),
}),
}),
],
})
export class AppModule {}PermissionsAsyncOptions Interface
interface PermissionsAsyncOptions {
imports?: any[];
inject?: any[];
useFactory: (
...args: any[]
) => Promise<PermissionsModuleOptions> | PermissionsModuleOptions;
}| Property | Type | Description |
|---|---|---|
imports | any[] | Modules to import so their providers can be injected into the factory. |
inject | any[] | Providers to inject into the useFactory function. |
useFactory | (...args) => PermissionsModuleOptions | Factory function that returns the configuration object. Can be async. |
Configuration Options Reference
PermissionsModuleOptions Interface
interface PermissionsModuleOptions {
userRepository: Type<PermissionUserRepository>;
defaultGuardName?: string;
enableWildcardPermissions?: boolean;
cache?: {
enabled?: boolean;
ttl?: number;
};
displayPermissionInException?: boolean;
displayRoleInException?: boolean;
}Option Details
userRepository
| Type | Type<PermissionUserRepository> |
| Required | Yes |
| Default | -- |
The class that implements the PermissionUserRepository interface. This is passed as a class reference (not an instance) -- the module will instantiate it via NestJS dependency injection. See the Quick Start guide for a full implementation example.
PermissionsModule.forRoot({
userRepository: TypeOrmPermissionUserRepository,
});defaultGuardName
| Type | string |
| Required | No |
| Default | "default" |
The default guard name used when creating or looking up roles and permissions without specifying a guard. Guard names allow you to scope roles and permissions to different authentication contexts.
For example, if your application has both a web interface and an API, you might use separate guards:
PermissionsModule.forRoot({
userRepository: TypeOrmPermissionUserRepository,
defaultGuardName: "api",
});Then when creating a permission without specifying a guard, it will use "api":
// This creates a permission with guardName = "api"
await permissionService.create("posts.create");
// You can override the guard for specific permissions
await permissionService.create("posts.create", "web");enableWildcardPermissions
| Type | boolean |
| Required | No |
| Default | false |
When enabled, permissions are matched using a wildcard algorithm. A permission name ending in .* matches any sub-permission, and a single * matches everything. See the Wildcard Permissions page for full details.
PermissionsModule.forRoot({
userRepository: TypeOrmPermissionUserRepository,
enableWildcardPermissions: true,
});cache.enabled
| Type | boolean |
| Required | No |
| Default | true |
Controls whether the in-memory permission cache is active. When enabled, permission data is cached to avoid repeated database queries during authorization checks. The cache is automatically flushed whenever roles or permissions are modified through the package's services.
PermissionsModule.forRoot({
userRepository: TypeOrmPermissionUserRepository,
cache: {
enabled: false, // Disable caching entirely
},
});cache.ttl
| Type | number (milliseconds) |
| Required | No |
| Default | 86400000 (24 hours) |
The time-to-live for cached permission data in milliseconds. After this period, the cached data is considered stale and will be refreshed from the database on the next access.
PermissionsModule.forRoot({
userRepository: TypeOrmPermissionUserRepository,
cache: {
enabled: true,
ttl: 3600000, // 1 hour
},
});Common TTL values:
| Duration | Milliseconds |
|---|---|
| 5 minutes | 300000 |
| 1 hour | 3600000 |
| 12 hours | 43200000 |
| 24 hours | 86400000 |
displayPermissionInException
| Type | boolean |
| Required | No |
| Default | false |
When set to true, the PermissionsGuard and RolesOrPermissionsGuard will include the names of the required permissions in the ForbiddenException error message. This can be helpful during development but may expose sensitive information in production.
When false (default):
User does not have the required permissions.When true:
User does not have the required permissions: [posts.create, posts.edit].displayRoleInException
| Type | boolean |
| Required | No |
| Default | false |
When set to true, the RolesGuard and RolesOrPermissionsGuard will include the names of the required roles in the ForbiddenException error message.
When false (default):
User does not have the required roles.When true:
User does not have the required roles: [admin, editor].Minimal Configuration
The only required option is userRepository. All other options have sensible defaults:
PermissionsModule.forRoot({
userRepository: TypeOrmPermissionUserRepository,
});This is equivalent to:
PermissionsModule.forRoot({
userRepository: TypeOrmPermissionUserRepository,
defaultGuardName: "default",
enableWildcardPermissions: false,
cache: { enabled: true, ttl: 86400000 },
displayPermissionInException: false,
displayRoleInException: false,
});Environment-Specific Configuration
A common pattern is to enable verbose error messages and disable caching in development while keeping defaults in production:
PermissionsModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
userRepository: TypeOrmPermissionUserRepository,
enableWildcardPermissions: true,
cache: {
enabled: config.get("NODE_ENV") === "production",
ttl: 86400000,
},
displayPermissionInException: config.get("NODE_ENV") !== "production",
displayRoleInException: config.get("NODE_ENV") !== "production",
}),
});