rbac-shield 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,126 +2,81 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/rbac-shield.svg)](https://www.npmjs.com/package/rbac-shield)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
- [![Status](https://img.shields.io/badge/Status-Beta-orange.svg)]()
6
5
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
7
6
 
8
- > [!WARNING] > **Public Beta**: ensuring strict type safety and performance. API is stable but minor breaking changes might occur before v1.0.
9
-
10
7
  **The production-ready, type-safe Role-Based Access Control (RBAC) system for Next.js applications.**
11
8
 
12
- Built for modern web development with **React 19**, **TypeScript 5**, and **Next.js App Router** compatibility. RBAC Shield provides a seamless, multi-tenant permission system that just works.
13
-
14
- ---
15
-
16
- ## 📑 Table of Contents
17
-
18
- - [Features](#-features)
19
- - [Quick Setup (CLI)](#-quick-setup-recommended)
20
- - [Manual Installation](#-manual-installation)
21
- - [Quick Start](#-quick-start)
22
- - [Guides & Patterns](#-guides--patterns)
23
- - [Roles as Permissions](#roles-as-permissions)
24
- - [Complex Logic (AND/OR)](#complex-logic-andor)
25
- - [Customizing UX](#customizing-ux-loading--redirects)
26
- - [SSR & Hydration](#ssr--hydration-eliminate-loading-states)
27
- - [Logic Switching (Dynamic APIs)](#logic-switching-dynamic-apis)
28
- - [Server Action Guards](#server-action-guards)
29
- - [API Reference](#-api-reference)
30
- - [Security & Best Practices](#-security--best-practices)
31
- - [Troubleshooting](#-troubleshooting)
9
+ Built for modern web development with **React 19**, **TypeScript 5**, and **Next.js App Router** compatibility. RBAC Shield provides a seamless, multi-tenant permission system that supports both **Role-based** and **Permission-based** strategies.
32
10
 
33
11
  ---
34
12
 
35
13
  ## ✨ Features
36
14
 
37
- - 🎯 **Type-Safe Permissions**: Typescript "Prettify" helpers ensure tooltips show exact prop shapes, amazing IntelliSense.
38
- - 🚀 **High Performance**: Optimized with React Context and memoization. Permission checks are < 1ms.
39
- - 🏢 **Multi-Tenant Native**: Switch between multiple organizations/roles instantly without page reloads.
40
- - **Zero Loading States**: Support for `initialData` prop allows instant hydration from server-side data.
41
- - 🛡️ **Route Protection**: Declarative client-side guards with automatic handling of loading states and redirects.
42
- - 🌍 **Universal Support**: Works seamlessly in **Client Components**, **Server Components**, and **Middleware**.
43
- - 📦 **Zero Dependencies**: Lightweight (~35KB) and built entirely on standard React APIs.
15
+ - 🎯 **Type-Safe Permissions**: Typescript "Prettify" helpers ensure tooltips show exact prop shapes.
16
+ - 👑 **First-Class Role Support**: Check for **Roles**, **Permissions**, or **Both**.
17
+ - 🚀 **High Performance**: Optimized with React Context and memoization.
18
+ - 🏢 **Multi-Tenant Native**: Switch between organizations/roles instantly.
19
+ - **Zero Loading States**: Instant hydration via server-side data injection.
20
+ - 🛡️ **Route Protection**: Declarative guards with auto-redirects.
21
+ - 🌍 **Universal**: Works in Client Components, Server Components, and Middleware.
44
22
 
45
23
  ---
46
24
 
47
- ## 🚀 Quick Setup (Recommended)
25
+ ## 📦 Installation
48
26
 
49
- The fastest way to integrate RBAC Shield is with our interactive CLI. It initializes your configuration and handles all boilerplate.
27
+ ### Option 1: Interactive CLI (Recommended)
28
+
29
+ This will set up your types and configuration file automatically.
50
30
 
51
31
  ```bash
52
32
  npx rbac-shield init
53
33
  ```
54
34
 
55
- The CLI will:
56
-
57
- 1. Detect your project type (Next.js/React, TS/JS)
58
- 2. Help you define your resources (e.g., `projects`) and actions (e.g., `create`)
59
- 3. Generate a clean, type-safe `lib/rbac.ts` file configured for your app
60
-
61
- ---
62
-
63
- ## 📦 Manual Installation
64
-
65
- If you prefer to set things up yourself:
35
+ ### Option 2: Manual Install
66
36
 
67
37
  ```bash
68
38
  npm install rbac-shield
69
39
  # or
70
40
  yarn add rbac-shield
71
- # or
72
- pnpm add rbac-shield
73
- # or
74
- bun add rbac-shield
75
41
  ```
76
42
 
77
- **Peer Dependencies:**
78
- Ensure you have peer dependencies installed (standard in Next.js apps):
79
- `react >= 18.0.0`, `react-dom >= 18.0.0`, `next >= 13.0.0`
80
-
81
43
  ---
82
44
 
83
45
  ## 🚀 Quick Start
84
46
 
85
- ### 1. Define Your Schema
47
+ ### 1. Define Schema
86
48
 
87
- Create a single source of truth for your permissions in `lib/rbac.ts` (or `config/rbac.ts`).
49
+ Create `lib/rbac.ts` to define your types and export your instances.
88
50
 
89
51
  ```typescript
90
52
  // lib/rbac.ts
91
53
  "use client";
92
54
  import { createRBAC } from "rbac-shield";
93
55
 
94
- // 1. Define resources (things you secure)
95
- export type Resources = "projects" | "billing" | "users" | "marketing";
56
+ export type Resources = "projects" | "billing" | "users";
57
+ export type Actions = "view" | "create" | "edit" | "delete";
96
58
 
97
- // 2. Define actions (what users can do)
98
- export type Actions = "view" | "create" | "edit" | "delete" | "export";
99
-
100
- // 3. Create your instances
101
59
  export const {
102
60
  RBACProvider,
103
- useRBAC, // Renamed from useRBAC (alias available)
61
+ useRBAC,
62
+ useHasRole,
104
63
  useHasPermission,
105
- useMatch,
64
+ useAccess, // Advanced checks
106
65
  Can,
107
66
  ProtectedRoute,
108
67
  guard,
109
68
  } = createRBAC<Resources, Actions>();
110
69
  ```
111
70
 
112
- ### 2. Wrap Your App
71
+ ### 2. Wrap App
113
72
 
114
- Add the provider to your root layout to enable state management.
73
+ Wrap your root layout with the provider.
115
74
 
116
75
  ```tsx
117
76
  // app/layout.tsx
118
77
  import { RBACProvider } from "@/lib/rbac";
119
78
 
120
- export default function RootLayout({
121
- children,
122
- }: {
123
- children: React.ReactNode;
124
- }) {
79
+ export default function RootLayout({ children }) {
125
80
  return (
126
81
  <html lang="en">
127
82
  <body>
@@ -134,63 +89,63 @@ export default function RootLayout({
134
89
 
135
90
  ### 3. Load Permissions
136
91
 
137
- Initialize the system with data from your backend (e.g., after login).
92
+ Initialize permissions. For async user data, **wait for the user to load** before setting auth.
138
93
 
139
94
  ```tsx
140
- // components/AuthProvider.tsx
95
+ // components/PermissionLoader.tsx
141
96
  "use client";
142
97
  import { useEffect } from "react";
143
- import { useRBAC, useMatch } from "@/lib/rbac"; // Use the hook directly
144
-
145
- export function AuthProvider({
146
- user,
147
- children,
148
- }: {
149
- user: any;
150
- children: React.ReactNode;
151
- }) {
98
+ import { useRBAC } from "@/lib/rbac";
99
+ import { useUser } from "@/hooks/useUser";
100
+
101
+ export function PermissionLoader({ children }) {
152
102
  const { setAuth, switchTenant } = useRBAC();
103
+ const { user, isLoading } = useUser();
153
104
 
154
105
  useEffect(() => {
155
- if (user) {
156
- // Load permissions into RBAC Shield
157
- setAuth([
158
- {
159
- tenantId: "team-123",
160
- permissions: ["projects:view", "projects:edit"],
161
- },
162
- ]);
163
- // Activate the context
164
- switchTenant("team-123");
165
- }
166
- }, [user, setAuth, switchTenant]);
106
+ if (isLoading || !user) return;
107
+
108
+ // Load Roles + Permissions
109
+ setAuth([
110
+ {
111
+ tenantId: user.id || "default",
112
+ roles: [user.role], // e.g. ["admin"]
113
+ permissions: user.permissions, // e.g. ["projects:view"]
114
+ },
115
+ ]);
167
116
 
117
+ switchTenant(user.id || "default");
118
+ }, [user, isLoading]);
119
+
120
+ if (isLoading || !user) return null; // Prevent render until authed
168
121
  return <>{children}</>;
169
122
  }
170
123
  ```
171
124
 
172
- ### 4. Secure Your App
125
+ ### 4. Protect Routes
173
126
 
174
- Use the generated hooks and components anywhere.
127
+ Use the components to guard access.
175
128
 
176
129
  ```tsx
177
- import { ProtectedRoute, Can, useHasPermission } from "@/lib/rbac";
130
+ import { ProtectedRoute, Can, useHasRole, useAccess } from "@/lib/rbac";
131
+
132
+ export default function AdminDashboard() {
133
+ const isSuperAdmin = useHasRole("super_admin");
178
134
 
179
- export default function ProjectSettings() {
180
- const canDelete = useHasPermission("projects:delete");
135
+ // Advanced: Check if user is Admin OR has special permission
136
+ const canManage = useAccess({
137
+ roles: ["admin"],
138
+ permissions: ["system:manage"],
139
+ });
181
140
 
182
141
  return (
183
- // 1. Protect Example: Redirects to / if missing permission
184
- <ProtectedRoute requiredPermission="projects:edit" fallbackPath="/">
185
- <h1>Project Settings</h1>
142
+ <ProtectedRoute role={["admin", "super_admin"]} fallbackPath="/login">
143
+ <h1>Admin Dashboard</h1>
186
144
 
187
- {/* 2. Conditional Render Example */}
188
- <Can permission="billing:view" fallback={<p>Upgrade to see billing</p>}>
145
+ {/* Conditional Rendering */}
146
+ <Can permission="billing:view">
189
147
  <BillingWidget />
190
148
  </Can>
191
-
192
- {/* 3. Hook Logic Example */}
193
- <button disabled={!canDelete}>Delete Project</button>
194
149
  </ProtectedRoute>
195
150
  );
196
151
  }
@@ -198,284 +153,84 @@ export default function ProjectSettings() {
198
153
 
199
154
  ---
200
155
 
201
- ## 📖 Guides & Patterns
202
-
203
- ### Roles as Permissions
156
+ ## 👑 Role Management & Logic
204
157
 
205
- Avoid hardcoding role checks like `if (role === 'admin')`. Instead, treat roles as permissions!
206
- Assign a "identity permission" to your roles, e.g., `role:admin`, `role:manager`.
158
+ RBAC Shield uses a **Unified Access Logic** across all components.
207
159
 
208
- ```tsx
209
- // ❌ Bad: Brittle
210
- if (user.role === 'admin') <AdminText />
211
-
212
- // ✅ Good: Flexible
213
- // User permissions: ['post:read', 'role:admin']
214
- <Can permission="role:admin" fallback="Welcome User">
215
- Welcome Admin
216
- </Can>
217
- ```
160
+ ### Logic Matrix
218
161
 
219
- ### Complex Logic (AND/OR)
162
+ | Props Provided | Logic Applied | Example |
163
+ | :------------------ | :--------------------------------------------------- | :------------------------------------- |
164
+ | **Role Only** | User has `role` | `<Can role="admin">` |
165
+ | **Permission Only** | User has `permission` | `<Can permission="edit">` |
166
+ | **Both** | **STRICT AND**: User has `role` **AND** `permission` | `<Can role="admin" permission="edit">` |
220
167
 
221
- Sometimes you need a user to have a specific permission **AND** a specific role.
222
- Use the array format with `requireAll`.
168
+ ### Wildcards (`*`)
223
169
 
224
- ```tsx
225
- // User must be 'admin' AND have 'post:delete' permission
226
- <Can permission={["role:admin", "post:delete"]} requireAll>
227
- <DeleteEverythingButton />
228
- </Can>
229
- ```
170
+ - **Roles**: If user has role `*`, they pass ALL role checks.
171
+ - **Permissions**: If user has permission `*`, they pass ALL permission checks.
230
172
 
231
- ### Customizing UX (Loading & Redirects)
173
+ ### Arrays (OR Logic)
232
174
 
233
- You have full control over the loading and fallback states. Pass `null` to hide them completely.
175
+ Providing an array means "User must match **ANY** of these".
234
176
 
235
177
  ```tsx
236
- // 1. Silent Loading (No Spinner)
237
- <ProtectedRoute permission="admin:view" loadingComponent={null} >
238
- <Dashboard />
239
- </ProtectedRoute>
240
-
241
- // 2. Instant Redirect (No "Access Denied" screen)
242
- <ProtectedRoute permission="admin:view" fallback={null} fallbackPath="/login" >
243
- <Dashboard />
244
- </ProtectedRoute>
245
-
246
- // 3. No Redirect (Show Custom 403 Page)
247
- <ProtectedRoute permission="admin:view" redirect={false} fallback={<AccessDeniedPage />} >
248
- <Dashboard />
249
- </ProtectedRoute>
250
- ```
251
-
252
- ### SSR & Hydration (Eliminate Loading States)
253
-
254
- Prevent the "flicker" of loading states by passing server-side permissions directly to the provider.
255
-
256
- ```tsx
257
- // app/layout.tsx (Server Component)
258
- import { RBACProvider } from "@/lib/rbac";
259
- import { getSession } from "@/lib/auth"; // Your auth logic
260
-
261
- export default async function RootLayout({ children }) {
262
- const session = await getSession();
263
-
264
- // Prepare valid initial data matches TenantAuthInput[]
265
- const initialData = session
266
- ? [
267
- {
268
- tenantId: session.orgId,
269
- permissions: session.permissions, // string[] from DB is fine!
270
- },
271
- ]
272
- : [];
273
-
274
- return (
275
- <html>
276
- <body>
277
- <RBACProvider initialData={initialData}>{children}</RBACProvider>
278
- </body>
279
- </html>
280
- );
281
- }
282
- ```
283
-
284
- ### Logic Switching (Dynamic APIs)
285
-
286
- Need to call different APIs or execute different logic based on permissions? You have two options:
287
-
288
- #### Option 1: Top-Level Hook (Recommended)
289
-
290
- Use this when you want to resolve the handler _during render_ but call it later (e.g., on click).
291
-
292
- ```tsx
293
- import { useRBAC, useMatch } from "@/lib/rbac";
294
-
295
- export default function Dashboard() {
296
- // 1. Resolve the handler at the top level
297
- // Note: We return a FUNCTION () => ... so it doesn't run immediately!
298
- const getData = useMatch({
299
- "admin:view": () => () => api.getAdminStats(),
300
- "manager:view": () => () => api.getManagerStats(),
301
- default: () => () => api.getUserStats(),
302
- });
303
-
304
- const handleRefresh = () => {
305
- // 2. Call the resolved function
306
- if (getData) getData();
307
- };
308
-
309
- return <button onClick={handleRefresh}>Refresh Data</button>;
310
- }
311
- ```
312
-
313
- #### Option 2: Event Handler Utility
314
-
315
- Use the `match` utility (not the hook) if you want to keep all logic inside the event handler.
316
-
317
- ```tsx
318
- import { usePermissions, match } from "@/lib/rbac";
319
-
320
- export default function Dashboard() {
321
- const permissions = usePermissions(); // Hooks must be top-level
322
-
323
- const handleRefresh = () => {
324
- // 'match' is a plain function, safe to use here!
325
- match(permissions, {
326
- "admin:view": () => api.getAdminStats(),
327
- "manager:view": () => api.getManagerStats(),
328
- default: () => api.getUserStats(),
329
- });
330
- };
331
- }
332
- ```
333
-
334
- ### Server Action Guards
335
-
336
- Protect arbitrary functions (like Server Actions) using the `guard` wrapper.
337
-
338
- ```typescript
339
- // actions/project.ts (Server Action)
340
- import { guard } from "rbac-shield";
341
- import { getSession } from "@/lib/auth";
342
-
343
- export async function deleteProject(id: string) {
344
- const session = await getSession();
345
-
346
- // Wrap your delicate logic
347
- const safeAction = guard(
348
- session.permissions, // User's permissions
349
- "project:delete", // Required permission
350
- async () => {
351
- await db.project.delete(id);
352
- return "Deleted!";
353
- }
354
- );
355
-
356
- return safeAction(); // Throws Error if unauthorized
357
- }
178
+ // Allow if user is 'admin' OR 'manager'
179
+ <ProtectedRoute role={["admin", "manager"]}>
358
180
  ```
359
181
 
360
182
  ---
361
183
 
362
- ## 📚 API Reference
184
+ ## API Reference
363
185
 
364
186
  ### Components
365
187
 
366
- #### `<RBACProvider>`
367
-
368
- Top-level provider component.
369
-
370
- - **initialData**: (Optional) `TenantAuthInput[]`. Hydrate state immediately.
371
- - **debug**: (Optional) `boolean`. Log permission checks to console.
372
-
373
188
  #### `<ProtectedRoute>`
374
189
 
375
- A wrapper component that guards an entire route or section.
190
+ Guards an entire route. Redirects if access denied.
376
191
 
377
- - **permission**: Single permission string OR array (`[]`).
378
- - **requireAll**: `boolean` (Default: `false`).
379
- - **redirect**: `boolean` (Default: `true`).
380
- - **fallbackPath**: URL to redirect to if unauthorized.
381
- - **fallback**: UI to show while redirecting.
382
- - **loadingComponent**: Custom UI to show during initial check.
192
+ - **role**: `string | string[]`
193
+ - **permission**: `string | string[]`
194
+ - **requireAll**: `boolean` (Default: `false` - generally used for checking multiple permissions)
195
+ - **redirect**: `boolean` (Default: `true`)
196
+ - **fallbackPath**: `string` (Default: `/`)
197
+ - **fallback**: `ReactNode` (Shown while redirecting)
383
198
 
384
199
  #### `<Can>`
385
200
 
386
- Structural component for conditional rendering.
201
+ Conditionally renders children.
387
202
 
388
- - **permission**: Single string OR array.
389
- - **requireAll**: `boolean`.
390
- - **fallback**: UI to show when permission is denied.
203
+ - **role**: `string | string[]`
204
+ - **permission**: `string | string[]`
205
+ - **fallback**: `ReactNode` (Shown if denied)
391
206
 
392
207
  ### Hooks
393
208
 
394
- #### `useRBAC()`
395
-
396
- Access raw state and actions.
209
+ #### `useAccess({ roles?, permissions? })`
397
210
 
398
- - `setAuth(authData)`: Accepts simple `string[]`.
399
- - `switchTenant(id)`: Change active context.
400
- - `isLoading`: `boolean`.
401
- - `activeTenantId`: `string | null`.
211
+ Returns `boolean`. Checks if user matches ANY of the roles OR ANY of the permissions.
402
212
 
403
- #### `useMatch(handlers)`
213
+ #### `useHasRole(role)`
404
214
 
405
- Executes logic based on the first matching permission.
406
-
407
- - **handlers**: Object `{ [permission]: () => T }`.
408
- - **default**: Fallback function.
215
+ Returns `boolean`. Checks for specific role (or wildcard).
409
216
 
410
217
  #### `useHasPermission(permission)`
411
218
 
412
- Returns `boolean`. Checks for exact permission match or wildcard `*`.
413
-
414
- #### `useHasAnyPermission(permissions[])`
415
-
416
- Returns `boolean`. True if user has **at least one** permission.
219
+ Returns `boolean`. Checks for specific permission (or wildcard).
417
220
 
418
- #### `useHasAllPermissions(permissions[])`
419
-
420
- Returns `boolean`. True only if user has **every single** permission.
421
-
422
- ### Utilities
423
-
424
- #### `guard(userPerms, requiredPerm, function)`
425
-
426
- Higher-order function that wraps and protects a function execution.
427
-
428
- #### `checkPermission(userPerms, requiredPerm)`
429
-
430
- Universal helper for checking permissions (works on Server/Client/Edge).
431
-
432
- ---
433
-
434
- ## 🛡️ Security & Best Practices
435
-
436
- > [!IMPORTANT] > **Client-side checks are for User Experience (UX) only.**
437
-
438
- RBAC Shield controls what the user _sees_ in the browser, but it cannot stop a determined attacker from crafting API requests manually.
439
-
440
- ### 1. Server-Side Verification (Universal)
441
-
442
- Use the universal `checkPermission` helper in Middleware, Server Actions, or API Routes:
443
-
444
- ```tsx
445
- import { checkPermission } from "rbac-shield";
446
- // 1. Middleware Example
447
- export function middleware(req) {
448
- const permissions = getPermissionsFromCookie(req);
449
- if (!checkPermission(permissions, "admin:access")) {
450
- return NextResponse.redirect(new URL("/403", req.url));
451
- }
452
- }
453
- ```
454
-
455
- ### 2. Debug Mode
456
-
457
- Enable debug mode to see permission logs in the console:
221
+ #### `useRBAC()`
458
222
 
459
- ```tsx
460
- <RBACProvider debug={true}>{children}</RBACProvider>
461
- ```
223
+ Access raw state (`isLoading`, `activeTenantId`, etc.) and actions (`setAuth`).
462
224
 
463
225
  ---
464
226
 
465
- ## 🐛 Troubleshooting
227
+ ## 🛡️ Best Practices
466
228
 
467
- | Issue | Solution |
468
- | ---------------------- | -------------------------------------------------------------------------------------------------------------- |
469
- | **Infinite Loading** | Ensure `RBACProvider` wraps your app and `setAuth` is called with valid data. |
470
- | **Type Errors** | Verify your `Resources` and `Actions` types in `lib/rbac.ts` are exported. |
471
- | **Hydration Mismatch** | `ProtectedRoute` and `Can` are client components; ensure they are used in client contexts or wrapped properly. |
229
+ 1. **Server-Side Verification**: Always verify permissions on the server (API Routes, Server Actions) using the `checkPermission` utility or `guard` wrapper. Client-side checks are for UX only.
230
+ 2. **Combine Checks**: Use Roles for high-level page access, and Permissions for specific button visibility.
472
231
 
473
232
  ---
474
233
 
475
- ## 🤝 Contributing
476
-
477
- We welcome contributions! Please open an issue or submit a PR on our [GitHub repository](https://github.com/your-repo/rbac-shield).
478
-
479
234
  ## 📄 License
480
235
 
481
236
  MIT © [Arif Hossain Roman](https://github.com/devnuckles)
package/bin/templates.js CHANGED
@@ -33,7 +33,9 @@ export type Actions = ${actionsType};
33
33
  export const {
34
34
  RBACProvider,
35
35
  useRBAC,
36
- useHasPermission,
36
+ useHasRole,
37
+ useHasPermission,
38
+ useAccess,
37
39
  useHasAnyPermission,
38
40
  useHasAllPermissions,
39
41
  usePermissions,
@@ -53,7 +55,9 @@ import { createRBAC } from 'rbac-shield';
53
55
  export const {
54
56
  RBACProvider,
55
57
  useRBAC,
56
- useHasPermission,
58
+ useHasRole,
59
+ useHasPermission,
60
+ useAccess,
57
61
  useHasAnyPermission,
58
62
  useHasAllPermissions,
59
63
  usePermissions,
@@ -5,7 +5,9 @@ type Prettify<T> = {
5
5
  } & {};
6
6
  export interface CanProps<R extends string, A extends string> {
7
7
  /** Single permission or array of permissions to check */
8
- permission: PermissionString<R, A> | PermissionString<R, A>[];
8
+ permission?: PermissionString<R, A> | PermissionString<R, A>[];
9
+ /** Single role or array of roles to check */
10
+ role?: string | string[];
9
11
  children: React.ReactNode;
10
12
  /** Content to render if permission is denied */
11
13
  fallback?: React.ReactNode;
@@ -15,7 +17,9 @@ export interface CanProps<R extends string, A extends string> {
15
17
  export interface ProtectedRouteProps<R extends string, A extends string> {
16
18
  children: React.ReactNode;
17
19
  /** Single permission or array of permissions to check */
18
- permission: PermissionString<R, A> | PermissionString<R, A>[];
20
+ permission?: PermissionString<R, A> | PermissionString<R, A>[];
21
+ /** Single role or array of roles to check */
22
+ role?: string | string[];
19
23
  /** Path to redirect to if access denied (if redirect is true) */
20
24
  fallbackPath?: string;
21
25
  /** Content to render if access denied (or while redirecting) */
@@ -40,7 +44,12 @@ export interface RBACFactory<R extends string, A extends string> {
40
44
  switchTenant: (tenantId: string) => void;
41
45
  reset: () => void;
42
46
  };
47
+ useHasRole: (role: string) => boolean;
43
48
  useHasPermission: (permission: PermissionString<R, A>) => boolean;
49
+ useAccess: (requirements: {
50
+ roles?: string[];
51
+ permissions?: string[];
52
+ }) => boolean;
44
53
  useHasAnyPermission: (permissions: PermissionString<R, A>[]) => boolean;
45
54
  useHasAllPermissions: (permissions: PermissionString<R, A>[]) => boolean;
46
55
  usePermissions: () => PermissionString<R, A>[];
package/dist/factory.d.ts CHANGED
@@ -5,7 +5,9 @@ type Prettify<T> = {
5
5
  } & {};
6
6
  export interface CanProps<R extends string, A extends string> {
7
7
  /** Single permission or array of permissions to check */
8
- permission: PermissionString<R, A> | PermissionString<R, A>[];
8
+ permission?: PermissionString<R, A> | PermissionString<R, A>[];
9
+ /** Single role or array of roles to check */
10
+ role?: string | string[];
9
11
  children: React.ReactNode;
10
12
  /** Content to render if permission is denied */
11
13
  fallback?: React.ReactNode;
@@ -15,7 +17,9 @@ export interface CanProps<R extends string, A extends string> {
15
17
  export interface ProtectedRouteProps<R extends string, A extends string> {
16
18
  children: React.ReactNode;
17
19
  /** Single permission or array of permissions to check */
18
- permission: PermissionString<R, A> | PermissionString<R, A>[];
20
+ permission?: PermissionString<R, A> | PermissionString<R, A>[];
21
+ /** Single role or array of roles to check */
22
+ role?: string | string[];
19
23
  /** Path to redirect to if access denied (if redirect is true) */
20
24
  fallbackPath?: string;
21
25
  /** Content to render if access denied (or while redirecting) */
@@ -40,7 +44,12 @@ export interface RBACFactory<R extends string, A extends string> {
40
44
  switchTenant: (tenantId: string) => void;
41
45
  reset: () => void;
42
46
  };
47
+ useHasRole: (role: string) => boolean;
43
48
  useHasPermission: (permission: PermissionString<R, A>) => boolean;
49
+ useAccess: (requirements: {
50
+ roles?: string[];
51
+ permissions?: string[];
52
+ }) => boolean;
44
53
  useHasAnyPermission: (permissions: PermissionString<R, A>[]) => boolean;
45
54
  useHasAllPermissions: (permissions: PermissionString<R, A>[]) => boolean;
46
55
  usePermissions: () => PermissionString<R, A>[];