by Wenli

node-casbin is a production-ready Node.js library for enforcing authorization via ACL, RBAC, and ABAC models. Supports runtime policy management and multiple storage adapters.
This block provides node-casbin, a policy-based access control library for Node.js. It supports ACL, RBAC, ABAC, and other authorization models through a unified enforcer API backed by pluggable adapters and role managers. The typical buyer is a backend TypeScript/Node.js team adding fine-grained permission enforcement to an existing Express, Fastify, or NestJS service.
effect/ - Effector interfaces and default implementations that aggregate per-rule enforcement results into a final allow/deny decisionlog/ - Logger interface, default logger, and log utility functionsmodel/ - Model loading, assertion parsing, and function map for policy evaluation expressionspersist/ - Adapter interfaces and implementations: file, string, filtered, batch, updatable, watcherrbac/ - Role manager interface and default implementation for RBAC hierarchy resolutionutil/ - Built-in operator functions, IP helpers, and general utilitiescachedEnforcer.ts - CachedEnforcer: enforcer with result caching layerconfig.ts - Config: INI-style configuration file parserconstants.ts - Shared constantscoreEnforcer.ts - CoreEnforcer: base class wiring model, adapter, and effectorenforceContext.ts - EnforceContext: per-request context type overridesenforcer.ts - Enforcer / newEnforcer: primary public entrypointfrontend.ts - Browser-compatible frontend helpersglobal.d.ts - Ambient type declarationsindex.ts - Root barrel re-exporting all public symbolsinternalEnforcer.ts - InternalEnforcer: internal policy mutation methodsmanagementEnforcer.ts - ManagementEnforcer: management API (add/remove policies)syncedEnforcer.ts - SyncedEnforcer: thread-safe enforcer with mutexnpm install user@example.com
npm install @casbin/expression-eval await-lock buffer csv-parse minimatch
No native modules, pod installs, or Android linking steps are required. All dependencies are pure JavaScript/TypeScript.
Spin up an isolated sandbox and run it server-side — no local setup.
Tetrees AI Review of this version
This Express backend / api completed archive review. Structure, dependency manifests, documentation, functional source, and common risk patterns were checked by the Tetrees verification pipeline; runtime phases are stated separately.
Deterministic AVCP artifact review
Pipeline avcp-2026-08-04.1 · SHA-256 20fe0be7965a5472…
This version-scoped review deterministically inspects the submitted archive for structure, dependencies, documentation, functional source, and common malicious or high-risk signals. Build and test phases are reported as passed only after an isolated sandbox audition. It is not a guarantee of perfect security.
Reviewed Aug 4, 2026
Push this product straight into your AI IDE, web builder or cloud IDE.
Connect Tetrees to a compatible AI IDE, list products you own, and request the verified ZIP without exposing seller upload controls.
No reviews yet.
Sign in to join the discussion
Loading discussion…
Copy the source/ directory into your project, e.g. as src/casbin/.
In tsconfig.json, ensure these compiler options are set:
{
"compilerOptions": {
"target": "ES2019",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true,
"resolveJsonModule": true
}
}
import { newEnforcer, Enforcer } from './casbin/index';
Prepare a model file (e.g. model.conf) and a policy file (e.g. policy.csv) on disk, or use the string/array adapters to avoid filesystem dependencies in tests.
No environment variables are required by the library itself. If you use a database adapter (separate package), configure its connection string in your own env.
async function newEnforcer(
model: string | Model,
adapter?: string | Adapter
): Promise<Enforcer>
Top-level factory that loads a model and an adapter, returning a ready-to-use Enforcer. Pass file paths for both arguments during development. Pass a constructed Model and Adapter instance in production to avoid filesystem access at runtime.
class Enforcer extends ManagementEnforcer {
enforce(...rvals: unknown[]): Promise<boolean>
enforceSync(...rvals: unknown[]): boolean
enforceEx(...rvals: unknown[]): Promise<[boolean, string[]]>
addPolicy(...params: string[]): Promise<boolean>
removePolicy(...params: string[]): Promise<boolean>
addRoleForUser(user: string, role: string, domain?: string): Promise<boolean>
getRolesForUser(name: string, domain?: string): Promise<string[]>
}
The primary class for all authorization checks and policy management. Use enforce for async permission checks and the management methods to mutate policy at runtime without restarting the process.
class SyncedEnforcer extends Enforcer {
startAutoLoadPolicy(interval: number): void
stopAutoLoadPolicy(): void
}
A mutex-wrapped enforcer safe for concurrent use. Use this when multiple async request handlers share a single enforcer instance and you also have a watcher or auto-reload requirement. Call startAutoLoadPolicy(intervalMs) to periodically refresh policy from the adapter.
class StringAdapter implements Adapter {
constructor(policy: string)
}
Loads policy rules from a raw CSV string instead of a file. Useful in tests, serverless environments, or when policy is stored in a database and retrieved as text.
class DefaultRoleManager implements RoleManager {
constructor(maxHierarchyLevel: number)
addLink(name1: string, name2: string, ...domain: string[]): Promise<void>
hasLink(name1: string, name2: string, ...domain: string[]): Promise<boolean>
}
Default in-memory RBAC role graph. Use directly when you need to pre-populate role hierarchies programmatically before handing the role manager to an enforcer.
Create an enforcer from files and guard a route. The enforce call returns true if the subject has the given action on the object.
import { newEnforcer, Enforcer } from './casbin/index';
import express, { Request, Response, NextFunction } from 'express';
let enforcer: Enforcer;
async function initCasbin() {
enforcer = await newEnforcer(
'config/model.conf',
'config/policy.csv'
);
}
async function authzMiddleware(req: Request, res: Response, next: NextFunction) {
const user = (req as any).user?.id ?? 'anonymous';
const allowed = await enforcer.enforce(user, req.path, req.method.toLowerCase());
if (!allowed) {
return res.status(403).json({ error: 'Forbidden' });
}
next();
}
const app = express();
initCasbin().then(() => {
app.use(authzMiddleware);
app.get('/data', (_req, res) => res.json({ data: 'ok' }));
app.listen(3000);
});
Avoid filesystem dependencies in tests by building the policy from a string.
import { newEnforcer, StringAdapter } from './casbin/index';
import { newModel } from './casbin/index';
const modelText = `
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
`;
const policyText = `
p, alice, /data, read
p, bob, /data, write
`;
async function runTest() {
const m = newModel();
m.loadModelFromText(modelText);
const adapter = new StringAdapter(policyText);
const enforcer = await newEnforcer(m, adapter);
console.log(await enforcer.enforce('alice', '/data', 'read')); // true
console.log(await enforcer.enforce('alice', '/data', 'write')); // false
console.log(await enforcer.enforce('bob', '/data', 'write')); // true
}
runTest();
Use the management API to add roles and verify access without reloading policy files.
import { newEnforcer, StringAdapter } from './casbin/index';
import { newModel } from './casbin/index';
const rbacModel = `
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
`;
async function main() {
const m = newModel();
m.loadModelFromText(rbacModel);
const enforcer = await newEnforcer(m, new StringAdapter('p, admin, /admin, read'));
await enforcer.addRoleForUser('alice', 'admin');
console.log(await enforcer.enforce('alice', '/admin', 'read')); // true
const roles = await enforcer.getRolesForUser('alice');
console.log(roles); // ['admin']
await enforcer.deleteRoleForUser('alice', 'admin');
console.log(await enforcer.enforce('alice', '/admin', 'read')); // false
}
main();
index.ts - Root barrel; re-exports everything from all sub-modules. Import from here.enforcer.ts - Defines Enforcer and the newEnforcer factory; the primary integration surface.managementEnforcer.ts - Adds policy CRUD methods (addPolicy, removePolicy, role management) on top of InternalEnforcer.internalEnforcer.ts - Implements low-level policy load/save coordination and enforcer initialization.coreEnforcer.ts - Base class that wires together model, adapter, effector, and logger; contains enforce logic.syncedEnforcer.ts - Wraps enforcer operations in a mutex (await-lock) for concurrent safety and adds auto-reload.cachedEnforcer.ts - Extends Enforcer with an in-memory result cache keyed on request values.enforceContext.ts - EnforceContext lets you override which model section names (r, p, e, m) are used per call.config.ts - Parses INI/conf model files; used internally by Model.constants.ts - Library-wide string constants (section names, default values).frontend.ts - Exports helpers for browser/edge use cases without Node.js fs dependency.global.d.ts - Ambient declarations enabling TypeScript to resolve certain imports.effect/ - Effector interface + DefaultEffector; controls how multiple matched rules combine into a boolean.log/ - Logger interface, DefaultLogger, and logPrint helper used throughout enforcement.model/ - Model class, Assertion, and FunctionMap (built-in functions available in matchers).persist/ - All adapter interfaces and file/string/filtered/batch implementations plus Watcher.rbac/ - RoleManager interface and DefaultRoleManager (in-memory graph with hierarchy depth limit).util/ - builtinOperators (glob, regex, IP range matchers), IP utilities, and general string helpers.casbin ships CJS; if your project uses "type": "module", set "moduleResolution": "node16" and use .js extensions in imports, or transpile with ts-node --esm carefully. Easiest fix: keep "module": "commonjs" in tsconfig.json.fs not found in browser/edge builds: FileAdapter uses Node.js fs; use StringAdapter or a custom adapter instead. Do not import from ./casbin/persist/fileAdapter in browser bundles.csv-parse version conflict: user@example.com requires csv-parse@^5; if another dependency pins csv-parse@4, dedupe with npm dedupe or pin csv-parse@5 in overrides.loadModelFromText is sensitive to section headers. Each [section] line must start at column 0 with no leading spaces; missing sections produce cryptic "section not found" errors.addPolicy and enforce concurrently on a plain Enforcer is not safe. Swap to SyncedEnforcer or serialize mutations behind your own lock.Watcher only signals; you must call enforcer.loadPolicy() inside setUpdateCallback. Forgetting the callback means policy changes in the adapter are never picked up at runtime.I have the node-casbin source (casbin@5.43.0) located in `src/casbin/` of my project.
I also have a USAGE.md at the root of that block explaining the full API and exports.
My project is a TypeScript/Express backend service.
Please help me integrate casbin access control step by step:
1. Read USAGE.md and the source entry point at src/casbin/index.ts.
2. Create a singleton enforcer module at src/authz/enforcer.ts that:
- Loads model from src/authz/model.conf
- Loads policy using StringAdapter (policy defined inline for now)
- Exports the enforcer instance
3. Create an Express middleware at src/authz/middleware.ts that:
- Reads the authenticated user from req.user.id
- Calls enforcer.enforce(user, req.path, req.method.toLowerCase())
- Returns 403 if denied
4. Add a management route POST /admin/policy that calls enforcer.addPolicy(sub, obj, act).
5. Show me the RBAC model.conf for role-based access.
6. Add a unit test using StringAdapter with no file I/O.
Only use exports visible in src/casbin/index.ts. Do not invent APIs.
Use async/await throughout. Show full file contents for each new file.
The upstream library is licensed under the Apache License 2.0. See source/ file headers for the full copyright notice. Upstream repository: apache/casbin-node-casbin. NPM package: casbin.
This product’s unique contribution is clean room implementation of valuable code block into AVCP compatible standard.
The full install guide and integration prompts unlock after purchase.
Automation, Utilities & Developer Tools
Free