Access Control List (ACL) module for NestJS with guards and database storage
npm install nestjs-access-control-listA production-ready Access Control List (ACL) module for NestJS applications, providing role-based and permission-based authorization with a fully auth-agnostic design.
- π Auth-Agnostic β Works with any authentication system
- π― Role + Permission Based β Flexible access control
- π£οΈ Path & Method Based ACL β Supports glob patterns
- π¨ Decorators β @Public() and @AccessTo()
- π¦ TypeORM Integration β Built-in or custom entities
- π Management APIs β Complete CRUD operations
---
``bash`
npm install nestjs-access-control-list
---
β οΈ Run the SQL script once to create ACL tables:
``
node_modules/nestjs-access-control-list/dist/access-control-list/migrations/create-acl-tables.sql
Tables created: users, roles, user_role_map, acl_module, acl_permission, acl_module_permission_map, acl_role_module_permission_map, acl_module_permission_api_map
---
`typescript
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { APP_GUARD } from '@nestjs/core';
import {
AclNestModule,
AccessControlListModule,
AclGuard,
ACL_ENTITIES,
} from 'nestjs-access-control-list';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'password',
database: 'myapp',
entities: [...ACL_ENTITIES],
synchronize: false,
}),
AclNestModule.register(ACL_ENTITIES),
AccessControlListModule.register(ACL_ENTITIES),
],
providers: [
{
provide: APP_GUARD,
useClass: AclGuard, // Global guard
},
],
})
export class AppModule {}
`
`typescript
import { Users } from './entities/users.entity';
import { Roles } from './entities/roles.entity';
// ... import other custom entities
const CUSTOM_ENTITIES = {
USER: Users,
ROLE: Roles,
USER_ROLE_MAP: UserRoleMap,
MODULE: AclModule,
PERMISSION: AclPermission,
MODULE_PERMISSION_MAP: AclModulePermission,
ROLE_MODULE_PERMISSION_MAP: AclRoleModulePermission,
MODULE_PERMISSION_API_MAP: AclModulePermissionApi,
};
@Module({
imports: [
TypeOrmModule.forRoot({
entities: [Users, Roles, / ... other entities /],
}),
AclNestModule.register(CUSTOM_ENTITIES),
AccessControlListModule.register(CUSTOM_ENTITIES),
],
providers: [
{
provide: APP_GUARD,
useClass: AclGuard, // Global guard
},
],
})
export class AppModule {}
`
`typescript
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AclGuard } from 'nestjs-access-control-list';
@Controller('admin')
@UseGuards(AclGuard) // Apply to specific controller
export class AdminController {
@Get('dashboard')
dashboard() {
return 'Admin dashboard';
}
}
`
Or per route:
`typescript`
@Get('dashboard')
@UseGuards(AclGuard) // Apply to specific route
dashboard() {
return 'Admin dashboard';
}
---
`typescript
import { Public } from 'nestjs-access-control-list';
@Public()
@Get('health')
health() {
return { status: 'ok' };
}
`
`typescript
import { AccessTo } from 'nestjs-access-control-list';
@AccessTo('admin', 'super_admin')
@Get('dashboard')
dashboard() {
return 'Admin dashboard';
}
`
No decorator neededβautomatically checked via database:
`typescript`
@Get('profile')
getProfile() {
// ACL Guard checks: GET /users/profile
}
---
The ACL module needs to know where to find the authenticated user in your requests.
`typescript`
AclNestModule.register(ACL_ENTITIES);
// Reads: req.user and user.id
Works with most Passport strategies (JWT, Local, OAuth) that attach user to req.user.
`typescript`
AclNestModule.register(ACL_ENTITIES, {
getUser: (req) => req.userDetails, // Custom user location
getUserId: (user) => user.user_id, // Custom ID field
bypassPaths: ['/auth/**', '/health'], // Skip ACL for these routes
});
Use when your auth middleware attaches user to a different property or uses different ID field names.
`typescript`
AclNestModule.register(ACL_ENTITIES, {
getUser: (req) => req.auth, // JWT payload location
getUserId: (payload) => payload.sub, // Standard JWT subject claim
});
Common when using JWT tokens where the payload is stored in req.auth or similar.
---
Base path: /access-control-list
β List all modules (optional: ?isParent=true/false)
- POST /modules β Create a module (auto-generates moduleKey from name)
- GET /modules/:id β Get module by ID
- PUT /modules/:id β Update a module
- DELETE /modules/:id β Delete a module (recursively deletes children)$3
- GET /permissions β List all permissions
- POST /permissions β Create a permission (auto-generates permissionKey from name)
- GET /permissions/:id β Get permission by ID
- PUT /permissions/:id β Update a permission
- DELETE /permissions/:id β Delete a permission (soft delete with cascading)$3
- GET /module-permission-map β List all mappings
- POST /module-permission-map β Create a mapping
- GET /module-permission-map/:id β Get mapping by ID
- DELETE /module-permission-map/:id β Soft delete a mapping$3
- GET /role-module-permission-map β List all mappings
- POST /role-module-permission-map β Create/replace all permissions for a role
- GET /role-module-permission-map/:id β Get mapping by ID
- GET /role-module-permission-map/by-role/:roleId β Get formatted role permissions
- PUT /role-module-permission-map/:id β Update a mapping
- DELETE /role-module-permission-map/:id β Soft delete a mapping$3
- GET /roles β List all active roles
- GET /roles/:id β Get role by ID
- GET /roles/:roleId/users β Get users assigned to role
- GET /roles/:roleId/permissions β Get role permissions
- DELETE /roles/:roleId/permissions β Remove all permissions from role$3
- GET /users/:id β Get user by ID
- GET /users/:userId/roles β Get user with their assigned roles$3
- GET /api-module-permission-map β List all API mappings
- POST /api-module-permission-map β Create API mapping (maps apiPath + httpMethod to permission)
- GET /api-module-permission-map/:id β Get mapping by ID
- PUT /api-module-permission-map/:id β Update a mapping
- DELETE /api-module-permission-map/:id β Soft delete a mapping
- GET /api-module-permission-map/by-module-permission/:modulePermissionId β Get all API endpoints for a permission$3
- GET /modules-with-permissions β Get all modules grouped with their permissions
- GET /roles/:roleId/assigned-permissions β Get currently assigned permissions for role
- GET /roles/:roleId/modules-with-permissions β Get modules with permissions showing assignment status
- GET /roles/:roleId/api-permissions β Get all API endpoints accessible by role
- GET /roles/:roleId/modules-with-permissions-and-apis β Complete view with modules, permissions, and APIs
- POST /roles/assign-permissions β Replace all permissions for a role (soft deletes old, creates new)---
π¦ Exports
`typescript
import {
AclNestModule,
AccessControlListModule,
AclGuard,
AclService,
AccessControlListService,
ACL_ENTITIES,
AclConfig,
Public,
AccessTo,
} from 'nestjs-access-control-list';
`---
π License
MIT
Keywords:
nestjs, acl, authorization, rbac, permissions, guard, decorator, typeorm, access-control`