@khoadue/react-rbac
v0.1.0
Published
React RBAC library with permission hooks, guard components, and REST/Supabase adapters
Maintainers
Readme
@khoadue/react-rbac
React RBAC library for permission-driven UI. Backend remains the source of truth; this package fetches, caches, and gates rendering only.
Install
npm install @khoadue/react-rbacOptional peers:
npm install @supabase/supabase-js # Supabase adapter
npm install react-router-dom # React Router RouteGuard helperQuick start (REST)
import { RBACProvider, CanAccess, RouteGuard } from '@khoadue/react-rbac';
import { createRestAdapter } from '@khoadue/react-rbac/rest';
const adapter = createRestAdapter({
baseUrl: import.meta.env.VITE_API_URL + '/api',
getToken: () => localStorage.getItem('access_token'),
});
export function App() {
return (
<RBACProvider adapter={adapter} fallback={<div>Loading permissions…</div>}>
<CanAccess permission="orders.create">
<button type="button">New Order</button>
</CanAccess>
<RouteGuard permission="orders.view" navigate={(to) => window.location.assign(to)}>
<OrdersPage />
</RouteGuard>
</RBACProvider>
);
}Expected backend endpoint: GET /permissions/me → { permissions: string[]; roles: string[] }.
Quick start (Supabase)
import { RBACProvider } from '@khoadue/react-rbac';
import { createSupabaseAdapter } from '@khoadue/react-rbac/supabase';
import { supabase } from './supabase-client';
const adapter = createSupabaseAdapter({
supabase,
rpcName: 'get_my_permissions',
});
export function App() {
return (
<RBACProvider adapter={adapter}>
<AppRoutes />
</RBACProvider>
);
}Your Supabase project should expose an RPC like get_my_permissions() returning { permissions, roles }.
API
Core exports
| Export | Purpose |
|--------|---------|
| RBACProvider | Loads permissions via adapter, caches with TTL |
| useRBAC() | Full context: can, canAll, canAny, hasRole, refresh |
| usePermission(key) | Boolean for one permission |
| usePermissions(keys[]) | { hasAll, hasAny, check } |
| useModule(moduleKey) | { canView, canCreate, canEdit, canDelete, can } |
| CanAccess | Declarative show/hide wrapper |
| RouteGuard | Page-level gate with navigate callback |
| createReactRouterGuard(Navigate) | Optional React Router integration |
| withPermission | HOC for class components |
| defineManifest | Helper for host-app permission manifests |
Adapters
createRestAdapter({
baseUrl: '/api',
getToken: () => token,
permissionsPath: '/permissions/me', // optional
});
createSupabaseAdapter({
supabase,
rpcName: 'get_my_permissions', // optional
});Manifest in host apps
Keep your permission registry in the host project:
import { defineManifest } from '@khoadue/react-rbac';
export const rbacManifest = defineManifest({
appVersion: '1.0.0',
modules: [
{
key: 'orders',
name: 'Orders',
permissions: [
{ key: 'orders.view', action: 'view', name: 'View orders' },
{ key: 'orders.create', action: 'create', name: 'Create order' },
],
},
],
});Sync that manifest to your backend via CI/CD (see rbac-fullstack-mastery skill references).
Security note
Frontend RBAC is visual only. It hides buttons and routes — it does not enforce access. Every API endpoint must independently verify permissions on the backend. Never trust can() from the client for mutations.
Wildcard * is resolved in the UI for convenience; the backend must also resolve super-admin access.
Local development
From repo root:
npm install
npm run build
npm run testInstall in another project during development:
npm install file:../path/to/e2e-encrypt/packages/react-rbac