nestjs-access-control-list
v1.0.0
Published
Access Control List (ACL) module for NestJS with guards and database storage
Maintainers
Readme
nestjs-access-control-list
A production-ready Access Control List (ACL) module for NestJS applications, providing role-based and permission-based authorization with a fully auth-agnostic design.
✨ Features
- 🔐 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
📦 Installation
npm install nestjs-access-control-list🗄️ Database Setup
⚠️ Run the SQL script once to create ACL tables:
node_modules/nestjs-access-control-list/dist/access-control-list/migrations/create-acl-tables.sqlTables created: users, roles, user_role_map, acl_module, acl_permission, acl_module_permission_map, acl_role_module_permission_map, acl_module_permission_api_map
⚡ Quick Setup
Option A: Using Built-in Entities
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 {}Option B: Using Custom Entities
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 {}Using Guard Per Controller (Non-Global)
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:
@Get('dashboard')
@UseGuards(AclGuard) // Apply to specific route
dashboard() {
return 'Admin dashboard';
}🛡️ Protecting Routes
Public Routes
import { Public } from 'nestjs-access-control-list';
@Public()
@Get('health')
health() {
return { status: 'ok' };
}Role-Based Access
import { AccessTo } from 'nestjs-access-control-list';
@AccessTo('admin', 'super_admin')
@Get('dashboard')
dashboard() {
return 'Admin dashboard';
}Permission-Based Access
No decorator needed—automatically checked via database:
@Get('profile')
getProfile() {
// ACL Guard checks: GET /users/profile
}⚙️ Auth Configuration
The ACL module needs to know where to find the authenticated user in your requests.
Default (req.user)
AclNestModule.register(ACL_ENTITIES);
// Reads: req.user and user.idWorks with most Passport strategies (JWT, Local, OAuth) that attach user to req.user.
Custom Auth
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.
JWT Example
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.
🔁 Management APIs
Base path: /access-control-list
Modules
GET /modules– List all modules (optional:?isParent=true/false)POST /modules– Create a module (auto-generatesmoduleKeyfrom name)GET /modules/:id– Get module by IDPUT /modules/:id– Update a moduleDELETE /modules/:id– Delete a module (recursively deletes children)
Permissions
GET /permissions– List all permissionsPOST /permissions– Create a permission (auto-generatespermissionKeyfrom name)GET /permissions/:id– Get permission by IDPUT /permissions/:id– Update a permissionDELETE /permissions/:id– Delete a permission (soft delete with cascading)
Module-Permission Mapping
GET /module-permission-map– List all mappingsPOST /module-permission-map– Create a mappingGET /module-permission-map/:id– Get mapping by IDDELETE /module-permission-map/:id– Soft delete a mapping
Role-Module-Permission Mapping
GET /role-module-permission-map– List all mappingsPOST /role-module-permission-map– Create/replace all permissions for a roleGET /role-module-permission-map/:id– Get mapping by IDGET /role-module-permission-map/by-role/:roleId– Get formatted role permissionsPUT /role-module-permission-map/:id– Update a mappingDELETE /role-module-permission-map/:id– Soft delete a mapping
Roles
GET /roles– List all active rolesGET /roles/:id– Get role by IDGET /roles/:roleId/users– Get users assigned to roleGET /roles/:roleId/permissions– Get role permissionsDELETE /roles/:roleId/permissions– Remove all permissions from role
Users
GET /users/:id– Get user by IDGET /users/:userId/roles– Get user with their assigned roles
API-Module-Permission Mapping
GET /api-module-permission-map– List all API mappingsPOST /api-module-permission-map– Create API mapping (mapsapiPath+httpMethodto permission)GET /api-module-permission-map/:id– Get mapping by IDPUT /api-module-permission-map/:id– Update a mappingDELETE /api-module-permission-map/:id– Soft delete a mappingGET /api-module-permission-map/by-module-permission/:modulePermissionId– Get all API endpoints for a permission
UI-Friendly Endpoints
GET /modules-with-permissions– Get all modules grouped with their permissionsGET /roles/:roleId/assigned-permissions– Get currently assigned permissions for roleGET /roles/:roleId/modules-with-permissions– Get modules with permissions showing assignment statusGET /roles/:roleId/api-permissions– Get all API endpoints accessible by roleGET /roles/:roleId/modules-with-permissions-and-apis– Complete view with modules, permissions, and APIsPOST /roles/assign-permissions– Replace all permissions for a role (soft deletes old, creates new)
📦 Exports
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
