react-auth-gate 0.0.3 → 0.0.4

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.
Files changed (3) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +634 -653
  3. package/package.json +56 -56
package/README.md CHANGED
@@ -1,653 +1,634 @@
1
- # 🔐 react-auth-gate
2
-
3
- A production-grade React authorization framework that centralizes **RBAC**, **PBAC**, **ABAC**, feature flags, and async permission checks into a clean, declarative API.
4
-
5
- **Permission logic never lives inside components again.**
6
-
7
- [![npm version](https://img.shields.io/npm/v/react-auth-gate.svg)](https://www.npmjs.com/package/react-auth-gate)
8
- [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
9
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
10
-
11
- ---
12
-
13
- ## âœĻ Features
14
-
15
- - **ðŸŽŊ Declarative API** - Gate components with simple props
16
- - **🔄 RBAC + PBAC + ABAC** - Role, Permission, and Attribute-based access control
17
- - **⚡ Async Support** - Check permissions against APIs in real-time
18
- - **ðŸšĐ Feature Flags** - Built-in feature flag support
19
- - **ðŸŽĻ Framework Agnostic** - Works with any React app (Next.js, CRA, Vite, etc.)
20
- - **ðŸ“Ķ Tree-shakeable** - Zero runtime overhead for unused features
21
- - **🔍 TypeScript First** - Fully typed with excellent IntelliSense
22
- - **🛠ïļ Dev Tools Panel** - **Killer feature**: Automatic permission debugging panel in development
23
- - **ðŸŠķ Lightweight** - No heavy dependencies
24
-
25
- ---
26
-
27
- ## 🚀 Quick Start
28
-
29
- ### Installation
30
-
31
- ```bash
32
- npm install react-auth-gate
33
- ```
34
-
35
- ### Basic Usage
36
-
37
- ```tsx
38
- import { PermissionsRoot, PermissionsGate } from 'react-auth-gate';
39
-
40
- // 1. Define your permission rules
41
- const rules = {
42
- 'user.edit': ({ user, resource }) =>
43
- user.role === 'admin' || user.id === resource.id,
44
- 'post.delete': ({ user, resource }) =>
45
- user.id === resource.authorId,
46
- };
47
-
48
- // 2. Wrap your app
49
- function App() {
50
- return (
51
- <PermissionsRoot
52
- user={currentUser}
53
- roles={['editor']}
54
- permissions={['post.create', 'post.edit']}
55
- rules={rules}
56
- flags={{ newUI: true }}
57
- >
58
- <YourApp />
59
- </PermissionsRoot>
60
- );
61
- }
62
-
63
- // 3. Use permission gates anywhere
64
- function UserProfile({ user }) {
65
- return (
66
- <div>
67
- <h1>{user.name}</h1>
68
- <PermissionsGate allow="user.edit" resource={user}>
69
- <EditButton />
70
- </PermissionsGate>
71
- </div>
72
- );
73
- }
74
- ```
75
-
76
- **That's it!** Your permissions are centralized, testable, and declarative.
77
-
78
- ---
79
-
80
- ## 📚 Core Concepts
81
-
82
- ### Permission Rules
83
-
84
- Rules are functions that determine access. They receive a context object and return a boolean (or Promise<boolean>).
85
-
86
- ```tsx
87
- type PermissionRule = (ctx: {
88
- user: any; // Current user
89
- resource?: any; // Resource being accessed
90
- roles: string[]; // User's roles
91
- permissions: string[]; // User's permissions
92
- flags: Record<string, boolean>; // Feature flags
93
- }) => boolean | Promise<boolean>;
94
- ```
95
-
96
- ### Rule Types
97
-
98
- #### 1. **Role-Based (RBAC)**
99
- ```tsx
100
- const rules = {
101
- 'admin.access': ({ roles }) => roles.includes('admin'),
102
- };
103
- ```
104
-
105
- #### 2. **Permission-Based (PBAC)**
106
- ```tsx
107
- const rules = {
108
- 'post.create': ({ permissions }) => permissions.includes('post.create'),
109
- };
110
- ```
111
-
112
- #### 3. **Attribute-Based (ABAC)**
113
- ```tsx
114
- const rules = {
115
- 'user.edit': ({ user, resource }) =>
116
- user.role === 'admin' || user.id === resource.id,
117
- };
118
- ```
119
-
120
- #### 4. **Async Rules**
121
- ```tsx
122
- const rules = {
123
- 'subscription.premium': async ({ user }) => {
124
- const subscription = await checkSubscriptionAPI(user.id);
125
- return subscription.isPremium;
126
- },
127
- };
128
- ```
129
-
130
- ---
131
-
132
- ## ðŸŽŊ API Reference
133
-
134
- ### `<PermissionsRoot>`
135
-
136
- The root provider component. Use this to wrap your app with automatic dev tools integration.
137
-
138
- ```tsx
139
- <PermissionsRoot
140
- user={currentUser}
141
- roles={['admin', 'editor']}
142
- permissions={['post.edit', 'post.delete']}
143
- rules={rulesMap}
144
- flags={{ newUI: true }}
145
- enableDevTools={true} // default: auto-enabled in development
146
- >
147
- <App />
148
- </PermissionsRoot>
149
- ```
150
-
151
- **Props:**
152
- - `user` - Current authenticated user
153
- - `roles?` - Array of role strings
154
- - `permissions?` - Array of permission strings
155
- - `rules?` - Map of named permission rules
156
- - `flags?` - Feature flags object
157
- - `enableDevTools?` - Enable/disable dev panel (default: auto in dev mode)
158
-
159
- ---
160
-
161
- ### `<PermissionsGate>`
162
-
163
- Declarative permission boundary component.
164
-
165
- ```tsx
166
- <PermissionsGate
167
- allow="user.edit"
168
- resource={user}
169
- mode="hide"
170
- fallback={<div>Access Denied</div>}
171
- >
172
- <EditButton />
173
- </PermissionsGate>
174
- ```
175
-
176
- **Props:**
177
- - `allow?` - Permission check (string, array, or function)
178
- - `any?` - Array of permissions (OR logic)
179
- - `all?` - Array of permissions (AND logic)
180
- - `resource?` - Resource to check against
181
- - `mode?` - `"hide"` (default) or `"disable"`
182
- - `fallback?` - React node to show when denied
183
- - `children` - Protected content
184
-
185
- **Examples:**
186
-
187
- ```tsx
188
- // Single permission
189
- <PermissionsGate allow="admin.access">
190
- <AdminPanel />
191
- </PermissionsGate>
192
-
193
- // Multiple permissions (any)
194
- <PermissionsGate any={['admin', 'moderator']}>
195
- <ModPanel />
196
- </PermissionsGate>
197
-
198
- // Multiple permissions (all)
199
- <PermissionsGate all={['post.edit', 'post.publish']}>
200
- <PublishButton />
201
- </PermissionsGate>
202
-
203
- // Disable mode
204
- <PermissionsGate allow="post.delete" resource={post} mode="disable">
205
- <DeleteButton />
206
- </PermissionsGate>
207
-
208
- // Inline rule
209
- <PermissionsGate allow={({ user }) => user.verified}>
210
- <VerifiedBadge />
211
- </PermissionsGate>
212
-
213
- // With fallback
214
- <PermissionsGate allow="premium.feature" fallback={<UpgradePrompt />}>
215
- <PremiumContent />
216
- </PermissionsGate>
217
- ```
218
-
219
- ---
220
-
221
- ### `usePermission()`
222
-
223
- Hook for programmatic permission checks.
224
-
225
- ```tsx
226
- const { allowed, loading } = usePermission('user.edit', user);
227
-
228
- return (
229
- <button disabled={!allowed || loading}>
230
- {loading ? 'Checking...' : 'Edit'}
231
- </button>
232
- );
233
- ```
234
-
235
- **Returns:**
236
- - `allowed` - Boolean indicating if permission is granted
237
- - `loading` - Boolean indicating if check is in progress
238
-
239
- **Simpler version (no loading state):**
240
-
241
- ```tsx
242
- const canEdit = usePermissionValue('user.edit', user);
243
- ```
244
-
245
- ---
246
-
247
- ### `<Permissioned>`
248
-
249
- Render-prop version for maximum control.
250
-
251
- ```tsx
252
- <Permissioned allow="post.edit" resource={post}>
253
- {(allowed, loading) => (
254
- <button disabled={!allowed || loading}>
255
- {loading ? 'Checking...' : allowed ? 'Edit' : 'View Only'}
256
- </button>
257
- )}
258
- </Permissioned>
259
- ```
260
-
261
- ---
262
-
263
- ### `<ProtectedRoute>`
264
-
265
- Route protection component (framework-agnostic).
266
-
267
- ```tsx
268
- // React Router
269
- <Route
270
- path="/admin"
271
- element={
272
- <ProtectedRoute
273
- allow="admin.access"
274
- fallback={<Navigate to="/login" />}
275
- >
276
- <AdminDashboard />
277
- </ProtectedRoute>
278
- }
279
- />
280
-
281
- // Next.js
282
- function AdminPage() {
283
- const router = useRouter();
284
-
285
- return (
286
- <ProtectedRoute
287
- allow="admin"
288
- onAccessDenied={() => router.push('/login')}
289
- >
290
- <AdminPanel />
291
- </ProtectedRoute>
292
- );
293
- }
294
- ```
295
-
296
- **Props:**
297
- - `allow` - Permission check
298
- - `resource?` - Resource to check
299
- - `fallback?` - Content when denied (default: unauthorized message)
300
- - `onAccessDenied?` - Callback when access denied
301
- - `children` - Protected content
302
-
303
- ---
304
-
305
- ## 🛠ïļ Dev Tools Panel (The Killer Feature)
306
-
307
- In development mode, **react-auth-gate** automatically renders a floating permission debugger.
308
-
309
- ### Features
310
-
311
- ✅ **Live Permission Tracking** - See every permission check as it happens
312
- ✅ **Pass/Fail Details** - Understand why checks succeed or fail
313
- ✅ **Rule Inspection** - See which rules evaluated and their results
314
- ✅ **Context Override** - Test different roles, permissions, and flags
315
- ✅ **Real-time Simulation** - Toggle permissions without code changes
316
- ✅ **Zero Configuration** - Appears automatically when using `PermissionsRoot`
317
-
318
- ### How to Use
319
-
320
- 1. Use `PermissionsRoot` instead of `PermissionsProvider`
321
- 2. Run your app in development mode
322
- 3. Click the 🔐 icon in the bottom-right corner
323
-
324
- ### Panel Tabs
325
-
326
- **1. Evaluations**
327
- - Shows all permission checks in real-time
328
- - Pass/fail status with rule details
329
- - Timestamps and evaluation duration
330
- - Resource information
331
-
332
- **2. Overrides**
333
- - Toggle roles on/off
334
- - Add/remove permissions
335
- - Enable/disable feature flags
336
- - Test different scenarios instantly
337
-
338
- **3. Context**
339
- - View current user object
340
- - See active roles and permissions
341
- - Inspect feature flags
342
- - Debug context values
343
-
344
- ### Screenshot
345
-
346
- ```
347
- ┌─────────────────────────────────────────┐
348
- │ 🔐 Permissions Dev Panel [Clear] [✕] │
349
- ├─────────────────────────────────────────â”Ī
350
- │ Evaluations (12) │ Overrides │ Context │
351
- ├─────────────────────────────────────────â”Ī
352
- │ ✓ ALLOWED user.edit │
353
- │ user.edit: ✓ (2.34ms) │
354
- │ Resource: { id: "123", name: "..." } │
355
- │ 10:45:23 AM │
356
- │ │
357
- │ ✗ DENIED post.delete │
358
- │ post.delete: ✗ (1.12ms) │
359
- │ 10:45:25 AM │
360
- └─────────────────────────────────────────┘
361
- ```
362
-
363
- ---
364
-
365
- ## 🎓 Common Patterns
366
-
367
- ### Resource Ownership
368
-
369
- ```tsx
370
- const rules = {
371
- 'resource.edit': ({ user, resource }) =>
372
- user.role === 'admin' || user.id === resource.ownerId,
373
- };
374
- ```
375
-
376
- ### Time-Based Access
377
-
378
- ```tsx
379
- const rules = {
380
- 'event.register': ({ resource }) => {
381
- const now = Date.now();
382
- return now >= resource.registrationStart && now <= resource.registrationEnd;
383
- },
384
- };
385
- ```
386
-
387
- ### Hierarchical Permissions
388
-
389
- ```tsx
390
- const rules = {
391
- 'content.view': ({ permissions }) =>
392
- permissions.includes('content.view') ||
393
- permissions.includes('content.edit') ||
394
- permissions.includes('content.admin'),
395
- };
396
- ```
397
-
398
- ### Complex Business Logic
399
-
400
- ```tsx
401
- const rules = {
402
- 'order.cancel': ({ user, resource }) => {
403
- // Can't cancel shipped orders
404
- if (resource.status === 'shipped') return false;
405
-
406
- // Customer can cancel within 24h
407
- if (user.id === resource.customerId) {
408
- const hoursSinceOrder = (Date.now() - resource.createdAt) / (1000 * 60 * 60);
409
- return hoursSinceOrder < 24;
410
- }
411
-
412
- // Admin can always cancel
413
- return user.role === 'admin';
414
- },
415
- };
416
- ```
417
-
418
- ---
419
-
420
- ## 🧊 Testing
421
-
422
- Permission rules are pure functions, making them easy to test.
423
-
424
- ```tsx
425
- import { rules } from './permissions';
426
-
427
- describe('user.edit permission', () => {
428
- it('allows admin to edit any user', () => {
429
- const result = rules['user.edit']({
430
- user: { id: '1', role: 'admin' },
431
- resource: { id: '2' },
432
- roles: ['admin'],
433
- permissions: [],
434
- flags: {},
435
- });
436
-
437
- expect(result).toBe(true);
438
- });
439
-
440
- it('allows user to edit themselves', () => {
441
- const result = rules['user.edit']({
442
- user: { id: '1', role: 'user' },
443
- resource: { id: '1' },
444
- roles: ['user'],
445
- permissions: [],
446
- flags: {},
447
- });
448
-
449
- expect(result).toBe(true);
450
- });
451
-
452
- it('denies user from editing others', () => {
453
- const result = rules['user.edit']({
454
- user: { id: '1', role: 'user' },
455
- resource: { id: '2' },
456
- roles: ['user'],
457
- permissions: [],
458
- flags: {},
459
- });
460
-
461
- expect(result).toBe(false);
462
- });
463
- });
464
- ```
465
-
466
- ---
467
-
468
- ## ðŸ“Ķ Advanced Usage
469
-
470
- ### Custom Permission Provider
471
-
472
- If you need custom integration without dev tools:
473
-
474
- ```tsx
475
- import { PermissionsProvider } from 'react-auth-gate';
476
-
477
- <PermissionsProvider {...config}>
478
- <App />
479
- </PermissionsProvider>
480
- ```
481
-
482
- ### Manual Dev Tools Integration
483
-
484
- ```tsx
485
- import { PermissionsProvider, DevPanel, useDevRegister } from 'react-auth-gate';
486
-
487
- function Root() {
488
- const registerEvaluation = useDevRegister();
489
-
490
- return (
491
- <PermissionsProvider {...config} onEvaluationRegister={registerEvaluation}>
492
- <App />
493
- <DevPanel />
494
- </PermissionsProvider>
495
- );
496
- }
497
- ```
498
-
499
- ### Direct Rule Engine Access
500
-
501
- ```tsx
502
- import { evaluatePermission, createPermissionContext } from 'react-auth-gate';
503
-
504
- const context = createPermissionContext(user, resource, roles, permissions, flags);
505
- const result = await evaluatePermission(check, context, rulesMap);
506
- ```
507
-
508
- ---
509
-
510
- ## ðŸŽĻ TypeScript Support
511
-
512
- Fully typed with generics for your custom types:
513
-
514
- ```tsx
515
- interface User {
516
- id: string;
517
- role: 'admin' | 'user';
518
- }
519
-
520
- interface Post {
521
- id: string;
522
- authorId: string;
523
- }
524
-
525
- const rules: PermissionRulesMap<User, Post> = {
526
- 'post.edit': ({ user, resource }) => {
527
- // Full type safety!
528
- return user.role === 'admin' || user.id === resource?.authorId;
529
- },
530
- };
531
- ```
532
-
533
- ---
534
-
535
- ## 🔧 Framework Integration
536
-
537
- ### React Router
538
-
539
- ```tsx
540
- import { ProtectedRoute } from 'react-auth-gate';
541
- import { Navigate } from 'react-router-dom';
542
-
543
- <Route
544
- path="/admin"
545
- element={
546
- <ProtectedRoute allow="admin" fallback={<Navigate to="/" />}>
547
- <AdminPage />
548
- </ProtectedRoute>
549
- }
550
- />
551
- ```
552
-
553
- ### Next.js
554
-
555
- ```tsx
556
- // pages/admin.tsx
557
- import { ProtectedRoute } from 'react-auth-gate';
558
- import { useRouter } from 'next/router';
559
-
560
- export default function AdminPage() {
561
- const router = useRouter();
562
-
563
- return (
564
- <ProtectedRoute
565
- allow="admin"
566
- onAccessDenied={() => router.push('/login')}
567
- >
568
- <AdminDashboard />
569
- </ProtectedRoute>
570
- );
571
- }
572
- ```
573
-
574
- ### Remix
575
-
576
- ```tsx
577
- import { ProtectedRoute } from 'react-auth-gate';
578
- import { useNavigate } from '@remix-run/react';
579
-
580
- export default function Route() {
581
- const navigate = useNavigate();
582
-
583
- return (
584
- <ProtectedRoute
585
- allow="admin"
586
- onAccessDenied={() => navigate('/login')}
587
- >
588
- <Content />
589
- </ProtectedRoute>
590
- );
591
- }
592
- ```
593
-
594
- ---
595
-
596
- ## ðŸĪ” FAQ
597
-
598
- **Q: How is this different from checking permissions in components?**
599
- A: All permission logic is centralized in the rules map. Components don't contain authorization logic, making them easier to maintain and test.
600
-
601
- **Q: Can I use this with server-side auth?**
602
- A: Yes! This library handles UI-level authorization. Your server should still validate permissions. This prevents unnecessary API calls and provides better UX.
603
-
604
- **Q: Does this work with Next.js App Router?**
605
- A: Yes! Use `"use client"` for components using the library. Server Components can check permissions differently.
606
-
607
- **Q: What about bundle size?**
608
- A: ~5KB gzipped. Tree-shakeable, so you only pay for what you use.
609
-
610
- **Q: Can I use this without TypeScript?**
611
- A: Yes, but TypeScript is recommended for the best experience.
612
-
613
- **Q: How do I disable the dev panel in production?**
614
- A: It's automatically disabled when `process.env.NODE_ENV === 'production'`.
615
-
616
- ---
617
-
618
- ## ðŸŽŊ Best Practices
619
-
620
- 1. ✅ **Centralize rules** - Define all rules in one place
621
- 2. ✅ **Keep rules pure** - No side effects in rule functions
622
- 3. ✅ **Test rules independently** - Rules are just functions
623
- 4. ✅ **Use TypeScript** - Get type safety for users and resources
624
- 5. ✅ **Async sparingly** - Async rules add latency
625
- 6. ✅ **Server-side validation** - Never trust client-side checks alone
626
- 7. ✅ **Use the dev panel** - Debug permissions visually
627
- 8. ✅ **Resource-based when possible** - More secure than role-only checks
628
- 9. ✅ **Fallback content** - Provide good UX when access is denied
629
- 10. ✅ **Name rules clearly** - Use dot notation: `resource.action`
630
-
631
- ---
632
-
633
- ## 📄 License
634
-
635
- MIT ÂĐ 2024
636
-
637
- ---
638
-
639
- ## 🙌 Contributing
640
-
641
- Contributions are welcome! Please open an issue or PR.
642
-
643
- ---
644
-
645
- ## 🔗 Links
646
-
647
- - [GitHub Repository](https://github.com/klejdi94/react-auth-gate)
648
- - [npm Package](https://www.npmjs.com/package/react-auth-gate)
649
- - [Report Issues](https://github.com/klejdi94/react-auth-gate/issues)
650
-
651
- ---
652
-
653
- **Built with âĪïļ for developers who value clean, maintainable code.**
1
+ # 🔐 react-auth-gate
2
+
3
+ A production-grade React authorization framework that centralizes **RBAC**, **PBAC**, **ABAC**, feature flags, and async permission checks into a clean, declarative API.
4
+
5
+ **Permission logic never lives inside components again.**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/react-auth-gate.svg)](https://www.npmjs.com/package/react-auth-gate)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
10
+
11
+ 📚 **[Documentation](https://klejdi94.github.io/react-auth-gate/)** â€Ē ðŸŽŪ **[Live Demo](https://github.com/klejdi94/demo-react-auth-gate)**
12
+
13
+ ---
14
+
15
+ ## âœĻ Features
16
+
17
+ - **ðŸŽŊ Declarative API** - Gate components with simple props
18
+ - **🔄 RBAC + PBAC + ABAC** - Role, Permission, and Attribute-based access control
19
+ - **⚡ Async Support** - Check permissions against APIs in real-time
20
+ - **ðŸšĐ Feature Flags** - Built-in feature flag support
21
+ - **ðŸŽĻ Framework Agnostic** - Works with any React app (Next.js, CRA, Vite, etc.)
22
+ - **ðŸ“Ķ Tree-shakeable** - Zero runtime overhead for unused features
23
+ - **🔍 TypeScript First** - Fully typed with excellent IntelliSense
24
+ - **🛠ïļ Dev Tools Panel** - **Killer feature**: Automatic permission debugging panel in development
25
+ - **ðŸŠķ Lightweight** - No heavy dependencies
26
+
27
+ ---
28
+
29
+ ## 🚀 Quick Start
30
+
31
+ ### Installation
32
+
33
+ ```bash
34
+ npm install react-auth-gate
35
+ ```
36
+
37
+ ### Basic Usage
38
+
39
+ ```tsx
40
+ import { PermissionsRoot, PermissionsGate } from 'react-auth-gate';
41
+
42
+ // 1. Define your permission rules
43
+ const rules = {
44
+ 'user.edit': ({ user, resource }) =>
45
+ user.role === 'admin' || user.id === resource.id,
46
+ 'post.delete': ({ user, resource }) =>
47
+ user.id === resource.authorId,
48
+ };
49
+
50
+ // 2. Wrap your app
51
+ function App() {
52
+ return (
53
+ <PermissionsRoot
54
+ user={currentUser}
55
+ roles={['editor']}
56
+ permissions={['post.create', 'post.edit']}
57
+ rules={rules}
58
+ flags={{ newUI: true }}
59
+ >
60
+ <YourApp />
61
+ </PermissionsRoot>
62
+ );
63
+ }
64
+
65
+ // 3. Use permission gates anywhere
66
+ function UserProfile({ user }) {
67
+ return (
68
+ <div>
69
+ <h1>{user.name}</h1>
70
+ <PermissionsGate allow="user.edit" resource={user}>
71
+ <EditButton />
72
+ </PermissionsGate>
73
+ </div>
74
+ );
75
+ }
76
+ ```
77
+
78
+ **That's it!** Your permissions are centralized, testable, and declarative.
79
+
80
+ ---
81
+
82
+ ## 📚 Core Concepts
83
+
84
+ ### Permission Rules
85
+
86
+ Rules are functions that determine access. They receive a context object and return a boolean (or Promise<boolean>).
87
+
88
+ ```tsx
89
+ type PermissionRule = (ctx: {
90
+ user: any; // Current user
91
+ resource?: any; // Resource being accessed
92
+ roles: string[]; // User's roles
93
+ permissions: string[]; // User's permissions
94
+ flags: Record<string, boolean>; // Feature flags
95
+ }) => boolean | Promise<boolean>;
96
+ ```
97
+
98
+ ### Rule Types
99
+
100
+ #### 1. **Role-Based (RBAC)**
101
+ ```tsx
102
+ const rules = {
103
+ 'admin.access': ({ roles }) => roles.includes('admin'),
104
+ };
105
+ ```
106
+
107
+ #### 2. **Permission-Based (PBAC)**
108
+ ```tsx
109
+ const rules = {
110
+ 'post.create': ({ permissions }) => permissions.includes('post.create'),
111
+ };
112
+ ```
113
+
114
+ #### 3. **Attribute-Based (ABAC)**
115
+ ```tsx
116
+ const rules = {
117
+ 'user.edit': ({ user, resource }) =>
118
+ user.role === 'admin' || user.id === resource.id,
119
+ };
120
+ ```
121
+
122
+ #### 4. **Async Rules**
123
+ ```tsx
124
+ const rules = {
125
+ 'subscription.premium': async ({ user }) => {
126
+ const subscription = await checkSubscriptionAPI(user.id);
127
+ return subscription.isPremium;
128
+ },
129
+ };
130
+ ```
131
+
132
+ ---
133
+
134
+ ## ðŸŽŊ API Reference
135
+
136
+ ### `<PermissionsRoot>`
137
+
138
+ The root provider component. Use this to wrap your app with automatic dev tools integration.
139
+
140
+ ```tsx
141
+ <PermissionsRoot
142
+ user={currentUser}
143
+ roles={['admin', 'editor']}
144
+ permissions={['post.edit', 'post.delete']}
145
+ rules={rulesMap}
146
+ flags={{ newUI: true }}
147
+ enableDevTools={true} // default: auto-enabled in development
148
+ >
149
+ <App />
150
+ </PermissionsRoot>
151
+ ```
152
+
153
+ **Props:**
154
+ - `user` - Current authenticated user
155
+ - `roles?` - Array of role strings
156
+ - `permissions?` - Array of permission strings
157
+ - `rules?` - Map of named permission rules
158
+ - `flags?` - Feature flags object
159
+ - `enableDevTools?` - Enable/disable dev panel (default: auto in dev mode)
160
+
161
+ ---
162
+
163
+ ### `<PermissionsGate>`
164
+
165
+ Declarative permission boundary component.
166
+
167
+ ```tsx
168
+ <PermissionsGate
169
+ allow="user.edit"
170
+ resource={user}
171
+ mode="hide"
172
+ fallback={<div>Access Denied</div>}
173
+ >
174
+ <EditButton />
175
+ </PermissionsGate>
176
+ ```
177
+
178
+ **Props:**
179
+ - `allow?` - Permission check (string, array, or function)
180
+ - `any?` - Array of permissions (OR logic)
181
+ - `all?` - Array of permissions (AND logic)
182
+ - `resource?` - Resource to check against
183
+ - `mode?` - `"hide"` (default) or `"disable"`
184
+ - `fallback?` - React node to show when denied
185
+ - `children` - Protected content
186
+
187
+ **Examples:**
188
+
189
+ ```tsx
190
+ // Single permission
191
+ <PermissionsGate allow="admin.access">
192
+ <AdminPanel />
193
+ </PermissionsGate>
194
+
195
+ // Multiple permissions (any)
196
+ <PermissionsGate any={['admin', 'moderator']}>
197
+ <ModPanel />
198
+ </PermissionsGate>
199
+
200
+ // Multiple permissions (all)
201
+ <PermissionsGate all={['post.edit', 'post.publish']}>
202
+ <PublishButton />
203
+ </PermissionsGate>
204
+
205
+ // Disable mode
206
+ <PermissionsGate allow="post.delete" resource={post} mode="disable">
207
+ <DeleteButton />
208
+ </PermissionsGate>
209
+
210
+ // Inline rule
211
+ <PermissionsGate allow={({ user }) => user.verified}>
212
+ <VerifiedBadge />
213
+ </PermissionsGate>
214
+
215
+ // With fallback
216
+ <PermissionsGate allow="premium.feature" fallback={<UpgradePrompt />}>
217
+ <PremiumContent />
218
+ </PermissionsGate>
219
+ ```
220
+
221
+ ---
222
+
223
+ ### `usePermission()`
224
+
225
+ Hook for programmatic permission checks.
226
+
227
+ ```tsx
228
+ const { allowed, loading } = usePermission('user.edit', user);
229
+
230
+ return (
231
+ <button disabled={!allowed || loading}>
232
+ {loading ? 'Checking...' : 'Edit'}
233
+ </button>
234
+ );
235
+ ```
236
+
237
+ **Returns:**
238
+ - `allowed` - Boolean indicating if permission is granted
239
+ - `loading` - Boolean indicating if check is in progress
240
+
241
+ **Simpler version (no loading state):**
242
+
243
+ ```tsx
244
+ const canEdit = usePermissionValue('user.edit', user);
245
+ ```
246
+
247
+ ---
248
+
249
+ ### `<Permissioned>`
250
+
251
+ Render-prop version for maximum control.
252
+
253
+ ```tsx
254
+ <Permissioned allow="post.edit" resource={post}>
255
+ {(allowed, loading) => (
256
+ <button disabled={!allowed || loading}>
257
+ {loading ? 'Checking...' : allowed ? 'Edit' : 'View Only'}
258
+ </button>
259
+ )}
260
+ </Permissioned>
261
+ ```
262
+
263
+ ---
264
+
265
+ ### `<ProtectedRoute>`
266
+
267
+ Route protection component (framework-agnostic).
268
+
269
+ ```tsx
270
+ // React Router
271
+ <Route
272
+ path="/admin"
273
+ element={
274
+ <ProtectedRoute
275
+ allow="admin.access"
276
+ fallback={<Navigate to="/login" />}
277
+ >
278
+ <AdminDashboard />
279
+ </ProtectedRoute>
280
+ }
281
+ />
282
+
283
+ // Next.js
284
+ function AdminPage() {
285
+ const router = useRouter();
286
+
287
+ return (
288
+ <ProtectedRoute
289
+ allow="admin"
290
+ onAccessDenied={() => router.push('/login')}
291
+ >
292
+ <AdminPanel />
293
+ </ProtectedRoute>
294
+ );
295
+ }
296
+ ```
297
+
298
+ **Props:**
299
+ - `allow` - Permission check
300
+ - `resource?` - Resource to check
301
+ - `fallback?` - Content when denied (default: unauthorized message)
302
+ - `onAccessDenied?` - Callback when access denied
303
+ - `children` - Protected content
304
+
305
+ ---
306
+
307
+ ## 🛠ïļ Dev Tools Panel (The Killer Feature)
308
+
309
+ In development mode, **react-auth-gate** automatically renders a floating permission debugger.
310
+
311
+ ### Features
312
+
313
+ ✅ **Live Permission Tracking** - See every permission check as it happens
314
+ ✅ **Pass/Fail Details** - Understand why checks succeed or fail
315
+ ✅ **Rule Inspection** - See which rules evaluated and their results
316
+ ✅ **Context Override** - Test different roles, permissions, and flags
317
+ ✅ **Real-time Simulation** - Toggle permissions without code changes
318
+ ✅ **Zero Configuration** - Appears automatically when using `PermissionsRoot`
319
+
320
+ ### How to Use
321
+
322
+ 1. Use `PermissionsRoot` instead of `PermissionsProvider`
323
+ 2. Run your app in development mode
324
+ 3. Click the 🔐 icon in the bottom-right corner
325
+
326
+ ### Panel Tabs
327
+
328
+ **1. Evaluations**
329
+ - Shows all permission checks in real-time
330
+ - Pass/fail status with rule details
331
+ - Timestamps and evaluation duration
332
+ - Resource information
333
+
334
+ **2. Overrides**
335
+ - Toggle roles on/off
336
+ - Add/remove permissions
337
+ - Enable/disable feature flags
338
+ - Test different scenarios instantly
339
+
340
+ **3. Context**
341
+ - View current user object
342
+ - See active roles and permissions
343
+ - Inspect feature flags
344
+ - Debug context values
345
+
346
+
347
+
348
+ ## 🎓 Common Patterns
349
+
350
+ ### Resource Ownership
351
+
352
+ ```tsx
353
+ const rules = {
354
+ 'resource.edit': ({ user, resource }) =>
355
+ user.role === 'admin' || user.id === resource.ownerId,
356
+ };
357
+ ```
358
+
359
+ ### Time-Based Access
360
+
361
+ ```tsx
362
+ const rules = {
363
+ 'event.register': ({ resource }) => {
364
+ const now = Date.now();
365
+ return now >= resource.registrationStart && now <= resource.registrationEnd;
366
+ },
367
+ };
368
+ ```
369
+
370
+ ### Hierarchical Permissions
371
+
372
+ ```tsx
373
+ const rules = {
374
+ 'content.view': ({ permissions }) =>
375
+ permissions.includes('content.view') ||
376
+ permissions.includes('content.edit') ||
377
+ permissions.includes('content.admin'),
378
+ };
379
+ ```
380
+
381
+ ### Complex Business Logic
382
+
383
+ ```tsx
384
+ const rules = {
385
+ 'order.cancel': ({ user, resource }) => {
386
+ // Can't cancel shipped orders
387
+ if (resource.status === 'shipped') return false;
388
+
389
+ // Customer can cancel within 24h
390
+ if (user.id === resource.customerId) {
391
+ const hoursSinceOrder = (Date.now() - resource.createdAt) / (1000 * 60 * 60);
392
+ return hoursSinceOrder < 24;
393
+ }
394
+
395
+ // Admin can always cancel
396
+ return user.role === 'admin';
397
+ },
398
+ };
399
+ ```
400
+
401
+ ---
402
+
403
+ ## 🧊 Testing
404
+
405
+ Permission rules are pure functions, making them easy to test.
406
+
407
+ ```tsx
408
+ import { rules } from './permissions';
409
+
410
+ describe('user.edit permission', () => {
411
+ it('allows admin to edit any user', () => {
412
+ const result = rules['user.edit']({
413
+ user: { id: '1', role: 'admin' },
414
+ resource: { id: '2' },
415
+ roles: ['admin'],
416
+ permissions: [],
417
+ flags: {},
418
+ });
419
+
420
+ expect(result).toBe(true);
421
+ });
422
+
423
+ it('allows user to edit themselves', () => {
424
+ const result = rules['user.edit']({
425
+ user: { id: '1', role: 'user' },
426
+ resource: { id: '1' },
427
+ roles: ['user'],
428
+ permissions: [],
429
+ flags: {},
430
+ });
431
+
432
+ expect(result).toBe(true);
433
+ });
434
+
435
+ it('denies user from editing others', () => {
436
+ const result = rules['user.edit']({
437
+ user: { id: '1', role: 'user' },
438
+ resource: { id: '2' },
439
+ roles: ['user'],
440
+ permissions: [],
441
+ flags: {},
442
+ });
443
+
444
+ expect(result).toBe(false);
445
+ });
446
+ });
447
+ ```
448
+
449
+ ---
450
+
451
+ ## ðŸ“Ķ Advanced Usage
452
+
453
+ ### Custom Permission Provider
454
+
455
+ If you need custom integration without dev tools:
456
+
457
+ ```tsx
458
+ import { PermissionsProvider } from 'react-auth-gate';
459
+
460
+ <PermissionsProvider {...config}>
461
+ <App />
462
+ </PermissionsProvider>
463
+ ```
464
+
465
+ ### Manual Dev Tools Integration
466
+
467
+ ```tsx
468
+ import { PermissionsProvider, DevPanel, useDevRegister } from 'react-auth-gate';
469
+
470
+ function Root() {
471
+ const registerEvaluation = useDevRegister();
472
+
473
+ return (
474
+ <PermissionsProvider {...config} onEvaluationRegister={registerEvaluation}>
475
+ <App />
476
+ <DevPanel />
477
+ </PermissionsProvider>
478
+ );
479
+ }
480
+ ```
481
+
482
+ ### Direct Rule Engine Access
483
+
484
+ ```tsx
485
+ import { evaluatePermission, createPermissionContext } from 'react-auth-gate';
486
+
487
+ const context = createPermissionContext(user, resource, roles, permissions, flags);
488
+ const result = await evaluatePermission(check, context, rulesMap);
489
+ ```
490
+
491
+ ---
492
+
493
+ ## ðŸŽĻ TypeScript Support
494
+
495
+ Fully typed with generics for your custom types:
496
+
497
+ ```tsx
498
+ interface User {
499
+ id: string;
500
+ role: 'admin' | 'user';
501
+ }
502
+
503
+ interface Post {
504
+ id: string;
505
+ authorId: string;
506
+ }
507
+
508
+ const rules: PermissionRulesMap<User, Post> = {
509
+ 'post.edit': ({ user, resource }) => {
510
+ // Full type safety!
511
+ return user.role === 'admin' || user.id === resource?.authorId;
512
+ },
513
+ };
514
+ ```
515
+
516
+ ---
517
+
518
+ ## 🔧 Framework Integration
519
+
520
+ ### React Router
521
+
522
+ ```tsx
523
+ import { ProtectedRoute } from 'react-auth-gate';
524
+ import { Navigate } from 'react-router-dom';
525
+
526
+ <Route
527
+ path="/admin"
528
+ element={
529
+ <ProtectedRoute allow="admin" fallback={<Navigate to="/" />}>
530
+ <AdminPage />
531
+ </ProtectedRoute>
532
+ }
533
+ />
534
+ ```
535
+
536
+ ### Next.js
537
+
538
+ ```tsx
539
+ // pages/admin.tsx
540
+ import { ProtectedRoute } from 'react-auth-gate';
541
+ import { useRouter } from 'next/router';
542
+
543
+ export default function AdminPage() {
544
+ const router = useRouter();
545
+
546
+ return (
547
+ <ProtectedRoute
548
+ allow="admin"
549
+ onAccessDenied={() => router.push('/login')}
550
+ >
551
+ <AdminDashboard />
552
+ </ProtectedRoute>
553
+ );
554
+ }
555
+ ```
556
+
557
+ ### Remix
558
+
559
+ ```tsx
560
+ import { ProtectedRoute } from 'react-auth-gate';
561
+ import { useNavigate } from '@remix-run/react';
562
+
563
+ export default function Route() {
564
+ const navigate = useNavigate();
565
+
566
+ return (
567
+ <ProtectedRoute
568
+ allow="admin"
569
+ onAccessDenied={() => navigate('/login')}
570
+ >
571
+ <Content />
572
+ </ProtectedRoute>
573
+ );
574
+ }
575
+ ```
576
+
577
+ ---
578
+
579
+ ## ðŸĪ” FAQ
580
+
581
+ **Q: How is this different from checking permissions in components?**
582
+ A: All permission logic is centralized in the rules map. Components don't contain authorization logic, making them easier to maintain and test.
583
+
584
+ **Q: Can I use this with server-side auth?**
585
+ A: Yes! This library handles UI-level authorization. Your server should still validate permissions. This prevents unnecessary API calls and provides better UX.
586
+
587
+ **Q: Does this work with Next.js App Router?**
588
+ A: Yes! Use `"use client"` for components using the library. Server Components can check permissions differently.
589
+
590
+ **Q: What about bundle size?**
591
+ A: ~5KB gzipped. Tree-shakeable, so you only pay for what you use.
592
+
593
+ **Q: Can I use this without TypeScript?**
594
+ A: Yes, but TypeScript is recommended for the best experience.
595
+
596
+ **Q: How do I disable the dev panel in production?**
597
+ A: It's automatically disabled when `process.env.NODE_ENV === 'production'`.
598
+
599
+ ---
600
+
601
+ ## ðŸŽŊ Best Practices
602
+
603
+ 1. ✅ **Centralize rules** - Define all rules in one place
604
+ 2. ✅ **Keep rules pure** - No side effects in rule functions
605
+ 3. ✅ **Test rules independently** - Rules are just functions
606
+ 4. ✅ **Use TypeScript** - Get type safety for users and resources
607
+ 5. ✅ **Async sparingly** - Async rules add latency
608
+ 6. ✅ **Server-side validation** - Never trust client-side checks alone
609
+ 7. ✅ **Use the dev panel** - Debug permissions visually
610
+ 8. ✅ **Resource-based when possible** - More secure than role-only checks
611
+ 9. ✅ **Fallback content** - Provide good UX when access is denied
612
+ 10. ✅ **Name rules clearly** - Use dot notation: `resource.action`
613
+
614
+ ---
615
+
616
+ ## 📄 License
617
+
618
+ MIT ÂĐ 2024
619
+
620
+ ---
621
+
622
+ ## 🙌 Contributing
623
+
624
+ Contributions are welcome! Please open an issue or PR.
625
+
626
+ ---
627
+
628
+ ## 🔗 Links
629
+
630
+ - [GitHub Repository](https://github.com/klejdi94/react-auth-gate)
631
+ - [npm Package](https://www.npmjs.com/package/react-auth-gate)
632
+ - [Report Issues](https://github.com/klejdi94/react-auth-gate/issues)
633
+
634
+