@rbac/rbac v2.1.0
- ⏱ Lightweight
- 🔥 Blazing Fast
- ⚡️️ low dependency
Features
- Focused on operations
- Scalable
- Each role is given specific access rights for every operation
- High granularity in assigning rights
- Wildcard and regex support for operations
- Optional database adapters (MongoDB, MySQL, PostgreSQL)
- Express, NestJS and Fastify middlewares
- Roles can be updated at runtime
Thanks
This project now uses Vite to generate the bundled output
Thanks to Karl Düüna (DeadAlready) and his awesome post on medium
Getting Started
Install
yarn add @rbac/rbac or npm install @rbac/rbac
This library is written in TypeScript and the published package ships with its declaration files for a great developer experience.
RBAC is a curried function thats initially takes an object with configurations, then returns another function that takes an object with roles, finally returns an object that holds "can" property that is a function.
You can use it in many ways, below is one of them:
Setup RBAC config

| Property | Type | Params | Default | Description |
|---|---|---|---|---|
| logger | Function | role: Stringoperation: Stringresult: Boolean | defaultLogger | Function that logs operations to console |
| enableLogger | Boolean | true | Enable or disable logger |
Creating some roles

RBAC expects an object with roles as property names.
| Property | Type | Example | Description |
|---|---|---|---|
| can | Array | ['products:*'] | Array of strings, list of operations that user can do, it also supports glob patterns |
| when | Function, Async Function or Promise | (params , done ) => done (null , true ) | Optional Promise that should resolve in Truthy or Falsy, an async function that returns a boolean or Promise, or a Callback function that receives params and done as properties, should return done passing errors and result |
| inherits | Array | ['user'] | Optional Array of strings, list of roles inherited by this role |
IMPORTANT! "when" property can be a Callback function that receives params and done, an async function that returns a boolean or Promise, or a Promise that resolves in Truthy or Falsy values. Example:
import type { Roles } from '@rbac/rbac';
interface Params {
registered: boolean;
}
const roles: Roles<Params> = {
supervisor: {
can: [{ name: 'products:find', when: (params, done) => {
// done receives error as first argument and Truthy or Falsy value as second argument
done(null, params.registered);
}}]
},
admin: {
can: [{ name: 'products:*', when: async (params) => {
return params.registered;
} }]
}
};Check if user can do some operation

| Param | Type | Example | Description |
|---|---|---|---|
| First | String | 'admin' | Array of strings, list of operations that user can do |
| Second | String, Glob (Wildcard), Regex | 'products:find' | Operation to validate |
| Third | Any | {registered: true} | Optional Params that will flow to "when" callback Function |
Update roles at runtime
RBAC exposes two helpers to modify the role definition at runtime. addRole adds a new role and updateRoles merges new definitions with the existing ones.
import RBAC from '@rbac/rbac'
const base = RBAC({ enableLogger: false })({
user: { can: ['products:find'] }
})
base.addRole('editor', { can: ['products:update'], inherits: ['user'] })
await base.can('editor', 'products:update') // true
base.updateRoles({
user: { can: ['products:find', 'products:create'] }
})
await base.can('user', 'products:create') // trueDatabase adapters
RBAC exposes optional adapters to load and persist role definitions using
MongoDB, MySQL or PostgreSQL. Each adapter implements the RoleAdapter
interface with getRoles, addRole and updateRoles methods.
import RBAC from '@rbac/rbac'
import { MongoRoleAdapter } from '@rbac/rbac/adapters'
const adapter = new MongoRoleAdapter({
uri: 'mongodb://localhost:27017',
dbName: 'mydb',
collection: 'roles'
})
const roles = await adapter.getRoles()
const rbac = RBAC()(roles)Adapters available:
MongoRoleAdapterMySQLRoleAdapterPostgresRoleAdapter
Adapters also allow customizing the underlying table or collection column names
through a columns option when creating a new instance:
const adapter = new MySQLRoleAdapter({
table: 'roles',
columns: { name: 'rname', role: 'rdef', tenantId: 'tid' }
})Multi-tenant RBAC
Adapters can optionally receive a tenantId parameter to store and retrieve
roles for different tenants. When omitted, the adapter falls back to a default
tenant so existing single-tenant usage keeps working. Use createTenantRBAC to
instantiate an RBAC instance scoped to a tenant:
import { MongoRoleAdapter, createTenantRBAC } from '@rbac/rbac';
const adapter = new MongoRoleAdapter({ uri: 'mongodb://localhost:27017', dbName: 'mydb', collection: 'roles' });
await adapter.addRole('user', { can: ['products:find'] }, 'tenant-a');
const rbacTenantA = await createTenantRBAC(adapter, 'tenant-a');
await rbacTenantA.can('user', 'products:find'); // trueWant more? Check out the examples folder.
Middlewares
RBAC also provides helper middlewares for Express, NestJS and Fastify. They make it easy to guard routes using existing role definitions.
import RBAC, { createExpressMiddleware } from '@rbac/rbac';
const rbac = RBAC({ enableLogger: false })({
user: { can: ['products:find'] }
});
const canFindProducts = createExpressMiddleware(rbac)('products:find');
app.get('/products', canFindProducts, handler);For NestJS and Fastify you can use createNestMiddleware and createFastifyMiddleware
respectively with a similar API.
Roadmap
- Wildcard support
- Regex support
- Update roles in runtime
- Async
whencallbacks - Database adapters (MongoDB, MySQL, PostgreSQL)
- Middlewares for Express, NestJS and Fastify
v2.0.0
- Rewritten in TypeScript
- Internal refactor focused on readability and performance
- Added support to update roles at runtime
- Database adapters
- Middlewares for Express, NestJS and Fastify
Contributing
Contributions are welcome!
- Build RBAC
- Run
npm install(oryarn install) to get RBAC's dependencies - Run
npm run buildto compile the library and produce the minified bundle using Vite
- Development mode
- Having all the dependencies installed run
yarn dev. This command will generate a non-minified version of your library and will run a watcher so you get the compilation on file change.
- Running the tests
- Run
yarn test
- Scripts
npm run build- produces production version of your library under thelibfolder and generateslib/@rbac/rbac.min.jsvia Vitenpm run dev- produces development version of your library and runs a watchernpm test- well ... it runs the tests :)npm run test:watch- same as above but in a watch mode
License
This project is under MIT License https://opensource.org/licenses/MIT