@rbac/rbac
Version:
Blazing Fast, Zero dependency, Hierarchical Role-Based Access Control for Node.js
132 lines (96 loc) • 3.82 kB
Markdown
This section shows how to configure RBAC, model permissions, and integrate the library into common application layers.
Create an instance by passing configuration and a role map. Configuration accepts a custom logger and a `enableLogger` flag to turn logging on or off.
```ts
import RBAC from '@rbac/rbac';
const rbac = RBAC({ enableLogger: true })({
guest: { can: ['products:find'] }
});
```
A role definition accepts:
- `can`: An array of strings or objects with a `name` and optional `when` guard. Strings match directly, and patterns can use glob wildcards or regular expressions.
- `inherits`: An optional array of roles to pull permissions from.
```ts
const rbac = RBAC()({
user: { can: ['products:find'] },
supervisor: {
can: [
{ name: 'products:edit', when: () => true },
{ name: 'products:*' } // wildcard
],
inherits: ['user']
}
});
```
`when` guards can be synchronous, async, a returned Promise, or a callback. They receive the `params` object passed to `can`.
```ts
const rbac = RBAC()({
auditor: {
can: [
{ name: 'products:audit:callback', when: (_params, done) => done(null, true) },
{ name: 'products:audit:async', when: async () => true },
{ name: 'products:audit:promise', when: Promise.resolve(true) }
]
}
});
```
The `can` helper resolves inheritance, matches exact operations, globs, or regexes, and evaluates conditional guards when present:
```ts
await rbac.can('supervisor', 'products:find');
await rbac.can('supervisor', 'products:create');
await rbac.can('auditor', /products:audit/);
await rbac.can('auditor', 'products:audit:async', { requestId: '42' });
```
Add or merge role definitions without rebuilding your application:
```ts
rbac.addRole('editor', { can: ['products:update'], inherits: ['user'] });
rbac.updateRoles({
user: { can: ['products:find', 'products:share'] }
});
```
Use the optional adapters to store roles in your database. Each adapter supports a customizable table/collection schema and an optional `tenantId` for multi-tenancy.
```ts
import { MongoRoleAdapter, MySQLRoleAdapter, PostgresRoleAdapter } from '@rbac/rbac/adapters';
const mongoAdapter = new MongoRoleAdapter({
uri: 'mongodb://localhost:27017',
dbName: 'mydb',
collection: 'roles'
});
const mysqlAdapter = new MySQLRoleAdapter({
uri: 'mysql://user:pass@localhost:3306/app',
table: 'roles'
});
const pgAdapter = new PostgresRoleAdapter({
connectionString: 'postgres://user:pass@localhost:5432/app',
table: 'roles'
});
```
Adapters expose `getRoles`, `addRole`, and `updateRoles` to manage definitions in storage.
Scope RBAC to a specific tenant by loading role definitions with a `tenantId`:
```ts
import { createTenantRBAC, MongoRoleAdapter } from '@rbac/rbac';
const adapter = new MongoRoleAdapter({
uri: 'mongodb://localhost:27017',
dbName: 'mydb',
collection: 'roles'
});
const rbacTenantA = await createTenantRBAC(adapter, 'tenant-a');
await rbacTenantA.can('user', 'products:find');
```
Guard routes using the built-in middleware factories for Express, NestJS, and Fastify. Each factory accepts optional callbacks to extract the role and params or to override the default denied response.
```ts
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);
```
Swap `createExpressMiddleware` for `createNestMiddleware` or `createFastifyMiddleware` to integrate with other frameworks.