@flusys/nestjs-iam
v5.3.0
Published
Identity and Access Management (IAM) module for NestJS applications
Maintainers
Readme
@flusys/nestjs-iam
Identity and Access Management for NestJS — RBAC, DIRECT, and FULL permission modes with caching and multi-tenant support.
Installation
npm install @flusys/nestjs-iam @flusys/nestjs-shared @flusys/nestjs-core1. Register the Module
Synchronous
Mode 1: Single Database
import { IAMModule } from '@flusys/nestjs-iam';
@Module({
imports: [
IAMModule.forRoot({
global: true,
includeController: true,
bootstrapAppConfig: {
databaseMode: 'single',
enableCompanyFeature: false,
permissionMode: 'RBAC', // 'RBAC' | 'DIRECT' | 'FULL' (default: 'FULL')
},
config: {
defaultDatabaseConfig: {
type: 'mysql',
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT ?? 3306),
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
},
},
}),
],
})
export class AppModule {}Mode 2: Multi-Tenant
IAMModule.forRoot({
global: true,
includeController: true,
bootstrapAppConfig: {
databaseMode: 'multi-tenant',
enableCompanyFeature: true,
permissionMode: 'FULL',
},
config: {
tenantDefaultDatabaseConfig: {
type: 'mysql',
host: process.env.TENANT_DB_HOST,
port: Number(process.env.TENANT_DB_PORT ?? 3306),
username: process.env.TENANT_DB_USER,
password: process.env.TENANT_DB_PASSWORD,
database: process.env.TENANT_DB_NAME,
},
tenants: [
{ id: 'tenant-a', database: 'tenant_a_db', permissionMode: 'FULL' },
{ id: 'tenant-b', database: 'tenant_b_db', permissionMode: 'RBAC' },
],
},
});Asynchronous (with ConfigService)
import { ConfigModule, ConfigService } from '@nestjs/config';
import { IAMModule, ITenantDatabaseConfig } from '@flusys/nestjs-iam';
// Single database
IAMModule.forRootAsync({
global: true,
includeController: true,
bootstrapAppConfig: {
databaseMode: 'single',
enableCompanyFeature: true,
permissionMode: 'FULL',
},
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
defaultDatabaseConfig: {
type: 'mysql',
host: configService.get('DB_HOST'),
port: configService.get<number>('DB_PORT'),
username: configService.get('DB_USER'),
password: configService.get('DB_PASSWORD'),
database: configService.get('DB_NAME'),
},
}),
inject: [ConfigService],
});
// Multi-tenant
IAMModule.forRootAsync({
global: true,
includeController: true,
bootstrapAppConfig: {
databaseMode: 'multi-tenant',
enableCompanyFeature: true,
permissionMode: 'FULL',
},
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
tenantDefaultDatabaseConfig: {
type: 'mysql',
host: configService.get('TENANT_DB_HOST'),
port: configService.get<number>('TENANT_DB_PORT'),
username: configService.get('TENANT_DB_USER'),
password: configService.get('TENANT_DB_PASSWORD'),
database: configService.get('TENANT_DB_NAME'),
},
tenants: configService.get<ITenantDatabaseConfig[]>('TENANTS'),
}),
inject: [ConfigService],
});2. Register Entities in TypeORM
Use getIAMEntitiesByConfig() — arguments must match bootstrapAppConfig:
import { getIAMEntitiesByConfig } from '@flusys/nestjs-iam/entities';
TypeOrmModule.forRoot({
entities: [
...getIAMEntitiesByConfig(
true, // enableCompanyFeature
'FULL', // permissionMode: 'FULL' | 'RBAC' | 'DIRECT'
),
],
});3. Protect Endpoints
All FLUSYS endpoints use POST. Apply JwtAuthGuard and @RequirePermission from nestjs-shared:
import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
import { RequirePermission, CurrentUser } from '@flusys/nestjs-shared/decorators';
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
@UseGuards(JwtAuthGuard)
@Controller('products')
export class ProductController {
@Post('insert')
@RequirePermission('product.create')
async create(@CurrentUser() user: ILoggedUserInfo) {
/* ... */
}
@Post('get-all')
@RequirePermission('product.read')
async getAll(@CurrentUser() user: ILoggedUserInfo) {
/* ... */
}
}Wildcard matching is supported: @RequirePermission('product.*') matches any action whose code starts with product..
5. Programmatic Permission Check
Inject PermissionService (use @Inject() — required for bundled code):
import { PermissionService } from '@flusys/nestjs-iam';
@Injectable()
export class ProductService {
constructor(@Inject(PermissionService) private readonly permissionService: PermissionService) {}
async canCreate(userId: string, companyId?: string): Promise<boolean> {
return this.permissionService.hasPermission(userId, 'product.create', companyId);
}
}Exported Services
| Service | Scope | Description |
| ------------------- | ------- | -------------------------------------------------------------- |
| PermissionService | REQUEST | hasPermission(), getUserPermissions(), getRolesForUser() |
| |
All constructor injections need explicit @Inject() — TypeScript metadata is lost during esbuild bundling.
License
MIT © FLUSYS
