@nwire/rbac
v0.15.1
Published
Nwire — RBAC + permissions wrapped around CASL. defineAbility(user => ...) declares what each user can do; rbacPlugin enforces it on every dispatch.
Readme
@nwire/rbac
Declarative permissions powered by CASL —
defineAbility+ middleware +can()resolver.
What it does
Wraps CASL behind a small Nwire surface. defineAbility((user, { allow, deny }) => {...}) declares what each role can do; rbacPlugin auto-enforces tuple action.policy; can("update", "Post") gates resolvers declaratively; ctx.ability() works inside any handler for instance-level checks. Pairs with @nwire/auth so ctx.envelope.user is the input.
Install
pnpm add @nwire/rbac @nwire/authQuick start
import { defineAbility, rbacPlugin, can } from "@nwire/rbac";
import { identityPlugin } from "@nwire/auth";
import { createApp } from "@nwire/app";
import { defineAction } from "@nwire/forge";
import { post } from "@nwire/wires/http";
import { httpKoa } from "@nwire/koa";
export const buildAbility = defineAbility((user, { allow, deny }) => {
if (!user) return;
if (user.roles?.includes("admin")) {
allow("manage", "all");
return;
}
allow("read", "Post");
allow("create", "Post");
allow("update", "Post", { authorId: user.id });
allow("delete", "Post", { authorId: user.id });
});
const app = createApp({
appName: "my-app",
plugins: [identityPlugin({ adapter }), rbacPlugin({ buildAbility })],
});
app.wire(post("/posts/:id", { policy: ["update", "Post"] }), async (input, ctx) => {
/* ... */
});
// Boot under @nwire/koa — see its README for the endpoint+adopter shape.API surface
defineAbility(setup)— declare permissions per user.rbacPlugin({ buildAbility })— plug intocreateApp.can(action, subject)/cannot(action, subject)— handler middleware.abilityFromCtx(ctx)/subject(type, obj)— programmatic checks.conditionsFor(ability, action, type)— get Mongo-style conditions for query filters.
When to use
Any app that needs per-role authorization beyond action.policy strings. Pair with @nwire/auth so users come from a real IdP.
Within nwire-app
Register via createApp({ plugins: [rbacPlugin({...})] }) and pair with
@nwire/auth's identityPlugin so envelope.user is the policy input.
