@mostajs/rbac 2.0.3 → 2.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.
- package/README.md +38 -653
- package/dist/lib/repos-factory.d.ts +1 -1
- package/dist/lib/repos-factory.d.ts.map +1 -1
- package/dist/lib/repos-factory.js +9 -104
- package/dist/lib/repos-factory.js.map +1 -1
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -1,694 +1,79 @@
|
|
|
1
1
|
# @mostajs/rbac
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> User, Role, Permission, PermissionCategory — schemas, repositories, seed, admin creation.
|
|
4
|
+
> Author: Dr Hamid MADANI drmdh@msn.com
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
[](LICENSE)
|
|
7
|
-
|
|
8
|
-
Part of the [@mosta suite](https://mostajs.dev). Fournit des composants React complets et des factories API pour gerer les utilisateurs, roles, permissions et matrice RBAC.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Table des matieres
|
|
13
|
-
|
|
14
|
-
1. [Installation](#installation)
|
|
15
|
-
2. [Quick Start](#quick-start)
|
|
16
|
-
3. [Integration complete dans une nouvelle app](#integration-complete)
|
|
17
|
-
4. [Composants React](#composants-react)
|
|
18
|
-
5. [API Route Factories (serveur)](#api-route-factories)
|
|
19
|
-
6. [Definitions RBAC (seed)](#definitions-rbac)
|
|
20
|
-
7. [Internationalisation (i18n)](#internationalisation)
|
|
21
|
-
8. [API Reference](#api-reference)
|
|
22
|
-
9. [Architecture](#architecture)
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## Installation
|
|
6
|
+
## Install
|
|
27
7
|
|
|
28
8
|
```bash
|
|
29
|
-
npm install @mostajs/rbac @mostajs/
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Peer dependencies a installer :
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
npm install @tanstack/react-query lucide-react sonner
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
> `@mostajs/audit` est optionnel — si installe, les actions CRUD seront journalisees automatiquement.
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## Quick Start
|
|
43
|
-
|
|
44
|
-
### 1. Page d'administration RBAC (frontend)
|
|
45
|
-
|
|
46
|
-
```tsx
|
|
47
|
-
// src/app/dashboard/roles/page.tsx
|
|
48
|
-
'use client'
|
|
49
|
-
import { RBACManager } from '@mostajs/rbac'
|
|
50
|
-
|
|
51
|
-
export default function RolesPage() {
|
|
52
|
-
return <RBACManager apiBasePath="/api" />
|
|
53
|
-
}
|
|
9
|
+
npm install @mostajs/rbac @mostajs/orm
|
|
54
10
|
```
|
|
55
11
|
|
|
56
|
-
|
|
12
|
+
## How to Use
|
|
57
13
|
|
|
58
|
-
###
|
|
14
|
+
### 1. Schemas (client-safe)
|
|
59
15
|
|
|
60
16
|
```typescript
|
|
61
|
-
|
|
62
|
-
import { createRolesHandler } from '@mostajs/rbac/server'
|
|
63
|
-
import { checkPermission } from '@/lib/auth'
|
|
64
|
-
|
|
65
|
-
export const { GET, POST } = createRolesHandler({
|
|
66
|
-
checkPermission,
|
|
67
|
-
adminPermission: 'roles:manage',
|
|
68
|
-
})
|
|
17
|
+
import { UserSchema, RoleSchema, PermissionSchema, PermissionCategorySchema } from '@mostajs/rbac'
|
|
69
18
|
```
|
|
70
19
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
## Integration complete
|
|
74
|
-
|
|
75
|
-
Guide pas-a-pas pour integrer `@mostajs/rbac` dans une nouvelle application Next.js.
|
|
76
|
-
|
|
77
|
-
### Etape 1 — Installer les packages
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
npm install @mostajs/rbac @mostajs/auth @mostajs/orm
|
|
81
|
-
npm install @tanstack/react-query lucide-react sonner
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Etape 2 — Definir vos permissions et roles
|
|
85
|
-
|
|
86
|
-
Creez un fichier de definitions RBAC propre a votre app :
|
|
20
|
+
### 2. Repositories (server-side)
|
|
87
21
|
|
|
88
22
|
```typescript
|
|
89
|
-
|
|
90
|
-
import type { PermissionDefinition, RoleDefinition, CategoryDefinition } from '@mostajs/rbac'
|
|
91
|
-
|
|
92
|
-
// Categories de permissions
|
|
93
|
-
export const CATEGORIES: CategoryDefinition[] = [
|
|
94
|
-
{ name: 'users', label: 'Utilisateurs', description: 'Gestion des utilisateurs', icon: 'Users', order: 1, system: true },
|
|
95
|
-
{ name: 'products', label: 'Produits', description: 'Gestion des produits', icon: 'Package', order: 2, system: false },
|
|
96
|
-
{ name: 'orders', label: 'Commandes', description: 'Gestion des commandes', icon: 'Receipt', order: 3, system: false },
|
|
97
|
-
{ name: 'reports', label: 'Rapports', description: 'Consultation des rapports', icon: 'BarChart', order: 4, system: false },
|
|
98
|
-
]
|
|
99
|
-
|
|
100
|
-
// Permissions
|
|
101
|
-
export const PERMISSIONS_DEFS: PermissionDefinition[] = [
|
|
102
|
-
{ code: 'users:view', name: 'users:view', description: 'Voir les utilisateurs', category: 'users' },
|
|
103
|
-
{ code: 'users:create', name: 'users:create', description: 'Creer un utilisateur', category: 'users' },
|
|
104
|
-
{ code: 'users:edit', name: 'users:edit', description: 'Modifier un utilisateur', category: 'users' },
|
|
105
|
-
{ code: 'users:delete', name: 'users:delete', description: 'Supprimer un utilisateur', category: 'users' },
|
|
106
|
-
{ code: 'products:view', name: 'products:view', description: 'Voir les produits', category: 'products' },
|
|
107
|
-
{ code: 'products:edit', name: 'products:edit', description: 'Modifier les produits', category: 'products' },
|
|
108
|
-
{ code: 'orders:view', name: 'orders:view', description: 'Voir les commandes', category: 'orders' },
|
|
109
|
-
{ code: 'orders:manage', name: 'orders:manage', description: 'Gerer les commandes', category: 'orders' },
|
|
110
|
-
{ code: 'reports:view', name: 'reports:view', description: 'Consulter les rapports', category: 'reports' },
|
|
111
|
-
]
|
|
112
|
-
|
|
113
|
-
// Roles par defaut
|
|
114
|
-
export const DEFAULT_ROLES: Record<string, RoleDefinition> = {
|
|
115
|
-
admin: {
|
|
116
|
-
name: 'admin',
|
|
117
|
-
description: 'Administrateur — acces complet',
|
|
118
|
-
system: true,
|
|
119
|
-
permissions: PERMISSIONS_DEFS.map(p => p.code),
|
|
120
|
-
},
|
|
121
|
-
manager: {
|
|
122
|
-
name: 'manager',
|
|
123
|
-
description: 'Manager — gestion produits et commandes',
|
|
124
|
-
system: false,
|
|
125
|
-
permissions: ['users:view', 'products:view', 'products:edit', 'orders:view', 'orders:manage', 'reports:view'],
|
|
126
|
-
},
|
|
127
|
-
viewer: {
|
|
128
|
-
name: 'viewer',
|
|
129
|
-
description: 'Consultation seule',
|
|
130
|
-
system: false,
|
|
131
|
-
permissions: ['products:view', 'orders:view', 'reports:view'],
|
|
132
|
-
},
|
|
133
|
-
}
|
|
23
|
+
import { UserRepository, RoleRepository } from '@mostajs/rbac/server'
|
|
134
24
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
)
|
|
25
|
+
const dialect = await getDialect()
|
|
26
|
+
const userRepo = new UserRepository(dialect)
|
|
27
|
+
const user = await userRepo.findByEmail('admin@test.com')
|
|
28
|
+
await userRepo.findByIdWithRoles(user.id)
|
|
29
|
+
await userRepo.addRole(user.id, roleId)
|
|
139
30
|
```
|
|
140
31
|
|
|
141
|
-
###
|
|
142
|
-
|
|
143
|
-
Chaque entite RBAC a besoin de deux routes : collection et item par ID.
|
|
32
|
+
### 3. Seed RBAC (from setup.json data)
|
|
144
33
|
|
|
145
34
|
```typescript
|
|
146
|
-
|
|
147
|
-
import { createRolesHandler } from '@mostajs/rbac/server'
|
|
148
|
-
import { checkPermission } from '@/lib/auth'
|
|
149
|
-
import { logAudit, getAuditUser } from '@mostajs/audit/lib/audit' // optionnel
|
|
35
|
+
import { seedRBAC } from '@mostajs/rbac/server'
|
|
150
36
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
getAuditUser, // optionnel
|
|
37
|
+
await seedRBAC({
|
|
38
|
+
categories: [{ name: 'admin', label: 'Administration', icon: 'Settings', order: 0, system: true }],
|
|
39
|
+
permissions: [{ code: 'admin:access', name: 'admin:access', description: 'Admin access', category: 'admin' }],
|
|
40
|
+
roles: { admin: { name: 'admin', description: 'Administrator', permissions: ['*'] } },
|
|
156
41
|
})
|
|
157
42
|
```
|
|
158
43
|
|
|
159
|
-
|
|
160
|
-
// src/app/api/admin/roles/[id]/route.ts
|
|
161
|
-
import { createRolesIdHandler } from '@mostajs/rbac/server'
|
|
162
|
-
import { checkPermission } from '@/lib/auth'
|
|
163
|
-
|
|
164
|
-
export const { GET, PUT, DELETE } = createRolesIdHandler({
|
|
165
|
-
checkPermission,
|
|
166
|
-
adminPermission: 'roles:manage',
|
|
167
|
-
})
|
|
168
|
-
```
|
|
44
|
+
### 4. Create Admin
|
|
169
45
|
|
|
170
46
|
```typescript
|
|
171
|
-
|
|
172
|
-
import { createPermissionsHandler } from '@mostajs/rbac/server'
|
|
173
|
-
import { checkPermission } from '@/lib/auth'
|
|
174
|
-
import { PERMISSIONS_DEFS } from '@/lib/rbac-definitions'
|
|
175
|
-
|
|
176
|
-
export const { GET, POST } = createPermissionsHandler({
|
|
177
|
-
checkPermission,
|
|
178
|
-
adminPermission: 'permissions:manage',
|
|
179
|
-
permissionDefinitions: PERMISSIONS_DEFS,
|
|
180
|
-
})
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
// src/app/api/admin/permissions/[id]/route.ts
|
|
185
|
-
import { createPermissionsIdHandler } from '@mostajs/rbac/server'
|
|
186
|
-
import { checkPermission } from '@/lib/auth'
|
|
187
|
-
|
|
188
|
-
export const { PUT, DELETE } = createPermissionsIdHandler({
|
|
189
|
-
checkPermission,
|
|
190
|
-
adminPermission: 'permissions:manage',
|
|
191
|
-
})
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
// src/app/api/admin/permissions/matrix/route.ts
|
|
196
|
-
import { createMatrixHandler } from '@mostajs/rbac/server'
|
|
197
|
-
import { checkPermission } from '@/lib/auth'
|
|
198
|
-
|
|
199
|
-
export const { GET, POST } = createMatrixHandler({
|
|
200
|
-
checkPermission,
|
|
201
|
-
adminPermission: 'permissions:manage',
|
|
202
|
-
})
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
```typescript
|
|
206
|
-
// src/app/api/admin/categories/route.ts
|
|
207
|
-
import { createCategoriesHandler } from '@mostajs/rbac/server'
|
|
208
|
-
import { checkPermission } from '@/lib/auth'
|
|
209
|
-
import { CATEGORIES } from '@/lib/rbac-definitions'
|
|
210
|
-
|
|
211
|
-
export const { GET, POST } = createCategoriesHandler({
|
|
212
|
-
checkPermission,
|
|
213
|
-
adminPermission: 'categories:manage',
|
|
214
|
-
categoryDefinitions: CATEGORIES,
|
|
215
|
-
})
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
```typescript
|
|
219
|
-
// src/app/api/admin/categories/[id]/route.ts
|
|
220
|
-
import { createCategoriesIdHandler } from '@mostajs/rbac/server'
|
|
221
|
-
import { checkPermission } from '@/lib/auth'
|
|
222
|
-
|
|
223
|
-
export const { PUT, DELETE } = createCategoriesIdHandler({
|
|
224
|
-
checkPermission,
|
|
225
|
-
adminPermission: 'categories:manage',
|
|
226
|
-
})
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
```typescript
|
|
230
|
-
// src/app/api/admin/permissions/seed/route.ts
|
|
231
|
-
import { createSeedHandler } from '@mostajs/rbac/server'
|
|
232
|
-
import { checkPermission } from '@/lib/auth'
|
|
233
|
-
import { PERMISSIONS_DEFS, DEFAULT_ROLES, CATEGORIES } from '@/lib/rbac-definitions'
|
|
234
|
-
|
|
235
|
-
export const { POST } = createSeedHandler({
|
|
236
|
-
checkPermission,
|
|
237
|
-
adminPermission: 'admin',
|
|
238
|
-
permissionDefinitions: PERMISSIONS_DEFS,
|
|
239
|
-
defaultRoles: DEFAULT_ROLES,
|
|
240
|
-
categoryDefinitions: CATEGORIES,
|
|
241
|
-
})
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
```typescript
|
|
245
|
-
// src/app/api/users/route.ts
|
|
246
|
-
import { createUsersHandler } from '@mostajs/rbac/server'
|
|
247
|
-
import { checkPermission } from '@/lib/auth'
|
|
248
|
-
|
|
249
|
-
export const { GET, POST } = createUsersHandler({
|
|
250
|
-
checkPermission,
|
|
251
|
-
adminPermission: 'users:manage',
|
|
252
|
-
knownRoles: ['admin', 'manager', 'viewer'],
|
|
253
|
-
})
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
```typescript
|
|
257
|
-
// src/app/api/users/[id]/route.ts
|
|
258
|
-
import { createUsersIdHandler } from '@mostajs/rbac/server'
|
|
259
|
-
import { checkPermission } from '@/lib/auth'
|
|
260
|
-
|
|
261
|
-
export const { GET, PUT, DELETE } = createUsersIdHandler({
|
|
262
|
-
checkPermission,
|
|
263
|
-
adminPermission: 'users:manage',
|
|
264
|
-
})
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### Etape 4 — Provider TanStack Query
|
|
268
|
-
|
|
269
|
-
Les composants RBAC utilisent `@tanstack/react-query`. Ajoutez le provider :
|
|
270
|
-
|
|
271
|
-
```tsx
|
|
272
|
-
// src/app/providers.tsx
|
|
273
|
-
'use client'
|
|
274
|
-
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
275
|
-
import { useState } from 'react'
|
|
276
|
-
|
|
277
|
-
export function Providers({ children }: { children: React.ReactNode }) {
|
|
278
|
-
const [queryClient] = useState(() => new QueryClient())
|
|
279
|
-
return (
|
|
280
|
-
<QueryClientProvider client={queryClient}>
|
|
281
|
-
{children}
|
|
282
|
-
</QueryClientProvider>
|
|
283
|
-
)
|
|
284
|
-
}
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
```tsx
|
|
288
|
-
// src/app/layout.tsx
|
|
289
|
-
import { Providers } from './providers'
|
|
290
|
-
|
|
291
|
-
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
292
|
-
return (
|
|
293
|
-
<html>
|
|
294
|
-
<body>
|
|
295
|
-
<Providers>{children}</Providers>
|
|
296
|
-
</body>
|
|
297
|
-
</html>
|
|
298
|
-
)
|
|
299
|
-
}
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
### Etape 5 — Pages d'administration
|
|
303
|
-
|
|
304
|
-
```tsx
|
|
305
|
-
// src/app/dashboard/roles/page.tsx
|
|
306
|
-
'use client'
|
|
307
|
-
import { RBACManager } from '@mostajs/rbac'
|
|
308
|
-
|
|
309
|
-
export default function RolesPage() {
|
|
310
|
-
return (
|
|
311
|
-
<RBACManager
|
|
312
|
-
apiBasePath="/api"
|
|
313
|
-
systemRoles={['admin']}
|
|
314
|
-
roleColors={{ admin: 'bg-red-100 text-red-800', manager: 'bg-blue-100 text-blue-800' }}
|
|
315
|
-
/>
|
|
316
|
-
)
|
|
317
|
-
}
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
```tsx
|
|
321
|
-
// src/app/dashboard/users/page.tsx
|
|
322
|
-
'use client'
|
|
323
|
-
import { UsersManager } from '@mostajs/rbac'
|
|
324
|
-
|
|
325
|
-
export default function UsersPage() {
|
|
326
|
-
return (
|
|
327
|
-
<UsersManager
|
|
328
|
-
apiBasePath="/api"
|
|
329
|
-
roleColors={{ admin: 'bg-red-100 text-red-800', manager: 'bg-blue-100 text-blue-800' }}
|
|
330
|
-
statusColors={{ active: 'bg-green-100 text-green-800', inactive: 'bg-gray-100 text-gray-800' }}
|
|
331
|
-
/>
|
|
332
|
-
)
|
|
333
|
-
}
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
### Etape 6 — Initialiser les donnees (seed)
|
|
337
|
-
|
|
338
|
-
Au premier lancement, initialisez les permissions, roles et categories :
|
|
339
|
-
|
|
340
|
-
```bash
|
|
341
|
-
# Via l'UI : cliquer "Initialiser" dans l'onglet Matrice
|
|
342
|
-
|
|
343
|
-
# Ou via curl :
|
|
344
|
-
curl -X POST http://localhost:3000/api/admin/permissions/seed \
|
|
345
|
-
-H 'Cookie: next-auth.session-token=...'
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
Reponse :
|
|
349
|
-
|
|
350
|
-
```json
|
|
351
|
-
{
|
|
352
|
-
"data": {
|
|
353
|
-
"categories": 4,
|
|
354
|
-
"permissions": 9,
|
|
355
|
-
"roles": 3,
|
|
356
|
-
"message": "4 categories, 9 permissions et 3 roles initialises"
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
### Etape 7 — Verification
|
|
362
|
-
|
|
363
|
-
```bash
|
|
364
|
-
npm run dev
|
|
365
|
-
|
|
366
|
-
# Ouvrir http://localhost:3000/dashboard/roles
|
|
367
|
-
# → 4 onglets : Matrice, Roles, Permissions, Categories
|
|
368
|
-
# → Cliquer "Initialiser" pour seed
|
|
369
|
-
|
|
370
|
-
# Ouvrir http://localhost:3000/dashboard/users
|
|
371
|
-
# → Liste des utilisateurs avec CRUD
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
---
|
|
375
|
-
|
|
376
|
-
## Composants React
|
|
47
|
+
import { createAdmin } from '@mostajs/rbac/lib/create-admin'
|
|
377
48
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
### RBACManager
|
|
381
|
-
|
|
382
|
-
Orchestrateur principal avec 4 onglets (Matrice, Roles, Permissions, Categories).
|
|
383
|
-
|
|
384
|
-
```tsx
|
|
385
|
-
import { RBACManager } from '@mostajs/rbac'
|
|
386
|
-
|
|
387
|
-
<RBACManager
|
|
388
|
-
apiBasePath="/api" // Prefixe des routes API (defaut: '/api')
|
|
389
|
-
t={traductionFunction} // Fonction i18n (optionnel)
|
|
390
|
-
systemRoles={['admin']} // Roles proteges (lecture seule)
|
|
391
|
-
roleColors={{ // Couleurs badges roles (optionnel)
|
|
392
|
-
admin: 'bg-red-100 text-red-800',
|
|
393
|
-
manager: 'bg-blue-100 text-blue-800',
|
|
394
|
-
}}
|
|
395
|
-
/>
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
### UsersManager
|
|
399
|
-
|
|
400
|
-
Gestion des utilisateurs : liste, creation, edition, suppression.
|
|
401
|
-
|
|
402
|
-
```tsx
|
|
403
|
-
import { UsersManager } from '@mostajs/rbac'
|
|
404
|
-
|
|
405
|
-
<UsersManager
|
|
406
|
-
apiBasePath="/api"
|
|
407
|
-
roleColors={{ admin: 'bg-red-100 text-red-800' }}
|
|
408
|
-
statusColors={{ active: 'bg-green-100 text-green-800' }}
|
|
409
|
-
/>
|
|
49
|
+
await createAdmin({ email: 'admin@test.com', password: 'Admin123!', firstName: 'Admin', lastName: 'Test' })
|
|
50
|
+
// Handles: bcrypt hash + find admin role + create user + link role
|
|
410
51
|
```
|
|
411
52
|
|
|
412
|
-
###
|
|
413
|
-
|
|
414
|
-
CRUD roles avec protection des roles systeme.
|
|
415
|
-
|
|
416
|
-
```tsx
|
|
417
|
-
import { RolesManager } from '@mostajs/rbac'
|
|
418
|
-
|
|
419
|
-
<RolesManager apiBasePath="/api" systemRoles={['admin']} />
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
### PermissionsManager
|
|
423
|
-
|
|
424
|
-
CRUD permissions groupees par categorie.
|
|
425
|
-
|
|
426
|
-
```tsx
|
|
427
|
-
import { PermissionsManager } from '@mostajs/rbac'
|
|
428
|
-
|
|
429
|
-
<PermissionsManager apiBasePath="/api" />
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
### CategoriesManager
|
|
433
|
-
|
|
434
|
-
CRUD categories avec ordonnancement et protection systeme.
|
|
435
|
-
|
|
436
|
-
```tsx
|
|
437
|
-
import { CategoriesManager } from '@mostajs/rbac'
|
|
438
|
-
|
|
439
|
-
<CategoriesManager apiBasePath="/api" />
|
|
440
|
-
```
|
|
441
|
-
|
|
442
|
-
### PermissionMatrix
|
|
443
|
-
|
|
444
|
-
Matrice roles/permissions avec checkboxes, groupement par categorie, et boutons Sauvegarder/Initialiser.
|
|
445
|
-
|
|
446
|
-
```tsx
|
|
447
|
-
import { PermissionMatrix } from '@mostajs/rbac'
|
|
448
|
-
|
|
449
|
-
<PermissionMatrix apiBasePath="/api" />
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
---
|
|
453
|
-
|
|
454
|
-
## API Route Factories
|
|
455
|
-
|
|
456
|
-
Toutes les factories s'importent depuis `@mostajs/rbac/server`. Chaque factory retourne des handlers HTTP (GET, POST, PUT, DELETE).
|
|
457
|
-
|
|
458
|
-
### Pattern commun
|
|
459
|
-
|
|
460
|
-
Toutes les factories prennent un `checkPermission` injectable :
|
|
53
|
+
### 5. Module Info (for @mostajs/setup)
|
|
461
54
|
|
|
462
55
|
```typescript
|
|
463
|
-
|
|
464
|
-
checkPermission: (perm: string) => Promise<{
|
|
465
|
-
error: NextResponse | null // null = autorise
|
|
466
|
-
session: any // session utilisateur
|
|
467
|
-
}>
|
|
468
|
-
adminPermission: string // permission requise (ex: 'roles:manage')
|
|
469
|
-
logAudit?: (entry) => void // optionnel, journalisation
|
|
470
|
-
getAuditUser?: (session) => {} // optionnel, extraction user
|
|
471
|
-
}
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
### Factories disponibles
|
|
56
|
+
import { getSchemas, moduleInfo } from '@mostajs/rbac/lib/module-info'
|
|
475
57
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
| `createUsersIdHandler` | `@mostajs/rbac/server` | `/api/users/[id]` | GET, PUT, DELETE |
|
|
480
|
-
| `createRolesHandler` | `@mostajs/rbac/server` | `/api/admin/roles` | GET, POST |
|
|
481
|
-
| `createRolesIdHandler` | `@mostajs/rbac/server` | `/api/admin/roles/[id]` | GET, PUT, DELETE |
|
|
482
|
-
| `createPermissionsHandler` | `@mostajs/rbac/server` | `/api/admin/permissions` | GET, POST |
|
|
483
|
-
| `createPermissionsIdHandler` | `@mostajs/rbac/server` | `/api/admin/permissions/[id]` | PUT, DELETE |
|
|
484
|
-
| `createMatrixHandler` | `@mostajs/rbac/server` | `/api/admin/permissions/matrix` | GET, POST |
|
|
485
|
-
| `createCategoriesHandler` | `@mostajs/rbac/server` | `/api/admin/categories` | GET, POST |
|
|
486
|
-
| `createCategoriesIdHandler` | `@mostajs/rbac/server` | `/api/admin/categories/[id]` | PUT, DELETE |
|
|
487
|
-
| `createSeedHandler` | `@mostajs/rbac/server` | `/api/admin/permissions/seed` | POST |
|
|
488
|
-
|
|
489
|
-
### Client-side API helpers
|
|
490
|
-
|
|
491
|
-
Pour appeler les routes depuis le frontend (utilises en interne par les composants) :
|
|
492
|
-
|
|
493
|
-
```typescript
|
|
494
|
-
import { createUsersApi, createRolesApi, createPermissionsApi, createMatrixApi, createCategoriesApi } from '@mostajs/rbac'
|
|
495
|
-
|
|
496
|
-
const usersApi = createUsersApi('/api')
|
|
497
|
-
const users = await usersApi.fetchUsers()
|
|
498
|
-
await usersApi.createUser({ email: 'a@b.com', password: '123456', firstName: 'A', lastName: 'B', role: 'viewer' })
|
|
499
|
-
|
|
500
|
-
const rolesApi = createRolesApi('/api')
|
|
501
|
-
const roles = await rolesApi.fetchRoles()
|
|
502
|
-
|
|
503
|
-
const matrixApi = createMatrixApi('/api')
|
|
504
|
-
const matrix = await matrixApi.fetchMatrix()
|
|
505
|
-
await matrixApi.seedRbac()
|
|
58
|
+
const schemas = getSchemas() // [UserSchema, RoleSchema, PermissionSchema, PermissionCategorySchema]
|
|
59
|
+
await moduleInfo.seed(setupJson.rbac)
|
|
60
|
+
await moduleInfo.createAdmin({ email, password, firstName, lastName })
|
|
506
61
|
```
|
|
507
62
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
## Definitions RBAC
|
|
511
|
-
|
|
512
|
-
Le systeme de seed permet d'initialiser les categories, permissions et roles depuis des definitions TypeScript.
|
|
513
|
-
|
|
514
|
-
### PermissionDefinition
|
|
63
|
+
### 6. Dual ORM/NET Mode
|
|
515
64
|
|
|
516
65
|
```typescript
|
|
517
|
-
|
|
518
|
-
code: string // Identifiant unique (ex: 'users:view')
|
|
519
|
-
name: string // Nom en DB (generalement = code)
|
|
520
|
-
description: string
|
|
521
|
-
category: string // Nom de la categorie parente
|
|
522
|
-
}
|
|
523
|
-
```
|
|
524
|
-
|
|
525
|
-
### RoleDefinition
|
|
66
|
+
import { getRbacRepos } from '@mostajs/rbac/lib/repos-factory'
|
|
526
67
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
system: boolean // true = protege (ne peut pas etre supprime)
|
|
532
|
-
permissions: string[] // Liste des codes permission
|
|
533
|
-
}
|
|
68
|
+
const { users, roles, permissions, categories } = await getRbacRepos()
|
|
69
|
+
// In ORM mode: BaseRepository + dialect
|
|
70
|
+
// In NET mode: NetClient-backed repositories
|
|
71
|
+
// Controlled by MOSTA_DATA=orm|net
|
|
534
72
|
```
|
|
535
73
|
|
|
536
|
-
###
|
|
74
|
+
### 7. API Handlers (Next.js)
|
|
537
75
|
|
|
538
76
|
```typescript
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
label: string // Label affiche
|
|
542
|
-
description: string
|
|
543
|
-
icon: string // Nom d'icone Lucide
|
|
544
|
-
order: number // Ordre d'affichage
|
|
545
|
-
system: boolean // true = ne peut pas etre supprime
|
|
546
|
-
}
|
|
547
|
-
```
|
|
548
|
-
|
|
549
|
-
---
|
|
550
|
-
|
|
551
|
-
## Internationalisation
|
|
552
|
-
|
|
553
|
-
Tous les composants acceptent une fonction `t(key)` pour l'i18n :
|
|
554
|
-
|
|
555
|
-
```tsx
|
|
556
|
-
const t = (key: string) => translations[key] || key
|
|
557
|
-
|
|
558
|
-
<RBACManager apiBasePath="/api" t={t} />
|
|
559
|
-
```
|
|
560
|
-
|
|
561
|
-
Cles utilisees :
|
|
562
|
-
|
|
563
|
-
| Cle | Defaut |
|
|
564
|
-
|-----|--------|
|
|
565
|
-
| `roles.title` | Titre de la page |
|
|
566
|
-
| `roles.tabs.matrix` | Onglet Matrice |
|
|
567
|
-
| `roles.tabs.roles` | Onglet Roles |
|
|
568
|
-
| `roles.tabs.permissions` | Onglet Permissions |
|
|
569
|
-
| `roles.tabs.categories` | Onglet Categories |
|
|
570
|
-
|
|
571
|
-
---
|
|
572
|
-
|
|
573
|
-
## API Reference
|
|
574
|
-
|
|
575
|
-
### Exports client (`@mostajs/rbac`)
|
|
576
|
-
|
|
577
|
-
| Export | Type | Description |
|
|
578
|
-
|--------|------|-------------|
|
|
579
|
-
| `RBACManager` | Component | Orchestrateur 4 onglets |
|
|
580
|
-
| `UsersManager` | Component | CRUD utilisateurs |
|
|
581
|
-
| `RolesManager` | Component | CRUD roles |
|
|
582
|
-
| `PermissionsManager` | Component | CRUD permissions |
|
|
583
|
-
| `CategoriesManager` | Component | CRUD categories |
|
|
584
|
-
| `PermissionMatrix` | Component | Matrice roles/permissions |
|
|
585
|
-
| `createUsersApi(basePath)` | Function | Helpers fetch users |
|
|
586
|
-
| `createRolesApi(basePath)` | Function | Helpers fetch roles |
|
|
587
|
-
| `createPermissionsApi(basePath)` | Function | Helpers fetch permissions |
|
|
588
|
-
| `createMatrixApi(basePath)` | Function | Helpers fetch matrix + seed |
|
|
589
|
-
| `createCategoriesApi(basePath)` | Function | Helpers fetch categories |
|
|
590
|
-
|
|
591
|
-
### Exports serveur (`@mostajs/rbac/server`)
|
|
592
|
-
|
|
593
|
-
| Export | Type | Description |
|
|
594
|
-
|--------|------|-------------|
|
|
595
|
-
| `createUsersHandler(config)` | Factory | GET/POST users |
|
|
596
|
-
| `createUsersIdHandler(config)` | Factory | GET/PUT/DELETE user by ID |
|
|
597
|
-
| `createRolesHandler(config)` | Factory | GET/POST roles |
|
|
598
|
-
| `createRolesIdHandler(config)` | Factory | GET/PUT/DELETE role by ID |
|
|
599
|
-
| `createPermissionsHandler(config)` | Factory | GET/POST permissions |
|
|
600
|
-
| `createPermissionsIdHandler(config)` | Factory | PUT/DELETE permission by ID |
|
|
601
|
-
| `createMatrixHandler(config)` | Factory | GET/POST matrice |
|
|
602
|
-
| `createCategoriesHandler(config)` | Factory | GET/POST categories |
|
|
603
|
-
| `createCategoriesIdHandler(config)` | Factory | PUT/DELETE category by ID |
|
|
604
|
-
| `createSeedHandler(config)` | Factory | POST seed RBAC |
|
|
605
|
-
|
|
606
|
-
### Types
|
|
607
|
-
|
|
608
|
-
| Type | Description |
|
|
609
|
-
|------|-------------|
|
|
610
|
-
| `User` | Utilisateur (id, email, firstName, lastName, role, status) |
|
|
611
|
-
| `RoleData` | Role (id, name, description, permissions[], userCount) |
|
|
612
|
-
| `PermissionData` | Permission (id, name, description, category, roleCount) |
|
|
613
|
-
| `CategoryData` | Categorie (id, name, label, icon, order, system) |
|
|
614
|
-
| `MatrixData` | Matrice (roles, categories, categoryLabels, matrix) |
|
|
615
|
-
| `RBACConfig` | Config composants (apiBasePath, t, systemRoles, colors) |
|
|
616
|
-
| `PermissionDefinition` | Definition permission pour seed |
|
|
617
|
-
| `RoleDefinition` | Definition role pour seed |
|
|
618
|
-
| `CategoryDefinition` | Definition categorie pour seed |
|
|
619
|
-
|
|
620
|
-
---
|
|
621
|
-
|
|
622
|
-
## Architecture
|
|
623
|
-
|
|
624
|
-
```
|
|
625
|
-
@mostajs/rbac
|
|
626
|
-
├── components/ # React 'use client'
|
|
627
|
-
│ ├── RBACManager.tsx # Orchestrateur 4 onglets
|
|
628
|
-
│ ├── UsersManager.tsx # CRUD utilisateurs
|
|
629
|
-
│ ├── RolesManager.tsx # CRUD roles
|
|
630
|
-
│ ├── PermissionsManager.tsx # CRUD permissions
|
|
631
|
-
│ ├── CategoriesManager.tsx # CRUD categories
|
|
632
|
-
│ ├── PermissionMatrix.tsx # Matrice interactive
|
|
633
|
-
│ └── ui/ # Shadcn/ui embarques
|
|
634
|
-
├── api/ # Factories serveur
|
|
635
|
-
│ ├── users.ts # createUsersHandler
|
|
636
|
-
│ ├── users-id.ts # createUsersIdHandler
|
|
637
|
-
│ ├── roles.ts # createRolesHandler
|
|
638
|
-
│ ├── roles-id.ts # createRolesIdHandler
|
|
639
|
-
│ ├── permissions.ts # createPermissionsHandler
|
|
640
|
-
│ ├── permissions-id.ts # createPermissionsIdHandler
|
|
641
|
-
│ ├── matrix.ts # createMatrixHandler
|
|
642
|
-
│ ├── categories.ts # createCategoriesHandler
|
|
643
|
-
│ ├── categories-id.ts # createCategoriesIdHandler
|
|
644
|
-
│ └── seed.ts # createSeedHandler
|
|
645
|
-
├── lib/
|
|
646
|
-
│ ├── rbac-api.ts # Helpers fetch client
|
|
647
|
-
│ └── utils.ts # cn() (Tailwind merge)
|
|
648
|
-
├── types/
|
|
649
|
-
│ └── index.ts # Toutes les interfaces
|
|
650
|
-
├── index.ts # Exports client
|
|
651
|
-
└── server.ts # Exports serveur
|
|
77
|
+
import { createUsersHandler } from '@mostajs/rbac/api/users'
|
|
78
|
+
export const { GET, POST } = createUsersHandler({ checkPermission, adminPermission: 'admin:access' })
|
|
652
79
|
```
|
|
653
|
-
|
|
654
|
-
### Dependances
|
|
655
|
-
|
|
656
|
-
```
|
|
657
|
-
@mostajs/rbac
|
|
658
|
-
├── @mostajs/auth (required) # UserRepository, RoleRepository, hashPassword
|
|
659
|
-
├── @mostajs/orm (required) # getDialect(), abstraction DB
|
|
660
|
-
├── @mostajs/audit (optional) # logAudit() pour journalisation
|
|
661
|
-
├── zod # Validation schemas
|
|
662
|
-
├── @tanstack/react-query # Cache & mutations
|
|
663
|
-
├── lucide-react # Icones
|
|
664
|
-
├── sonner # Toasts
|
|
665
|
-
└── radix-ui # Primitives UI (Dialog, Tabs, etc.)
|
|
666
|
-
```
|
|
667
|
-
|
|
668
|
-
### Pattern d'injection
|
|
669
|
-
|
|
670
|
-
```
|
|
671
|
-
┌─────────────────────┐ inject config ┌──────────────────────┐
|
|
672
|
-
│ @mostajs/rbac │ ◄───────────────────────── │ Votre app │
|
|
673
|
-
│ │ │ │
|
|
674
|
-
│ createRolesHandler({│ │ checkPermission, │
|
|
675
|
-
│ checkPermission, │ │ 'roles:manage', │
|
|
676
|
-
│ adminPermission, │ │ logAudit, │
|
|
677
|
-
│ logAudit?, │ │ getAuditUser │
|
|
678
|
-
│ }) │ │ │
|
|
679
|
-
└─────────────────────┘ └──────────────────────┘
|
|
680
|
-
|
|
681
|
-
┌─────────────────────┐ props ┌──────────────────────┐
|
|
682
|
-
│ <RBACManager │ ◄───────────────────────── │ Votre page │
|
|
683
|
-
│ apiBasePath="/api"│ │ │
|
|
684
|
-
│ t={i18nFunction} │ │ dashboard/roles/ │
|
|
685
|
-
│ systemRoles={[..]}│ │ page.tsx │
|
|
686
|
-
│ /> │ │ │
|
|
687
|
-
└─────────────────────┘ └──────────────────────┘
|
|
688
|
-
```
|
|
689
|
-
|
|
690
|
-
---
|
|
691
|
-
|
|
692
|
-
## License
|
|
693
|
-
|
|
694
|
-
MIT — Dr Hamid MADANI <drmdh@msn.com>
|
|
@@ -59,7 +59,7 @@ export interface RbacRepos {
|
|
|
59
59
|
permissions: IPermissionRepository;
|
|
60
60
|
categories: IPermissionCategoryRepository;
|
|
61
61
|
}
|
|
62
|
-
/** Get RBAC repositories
|
|
62
|
+
/** Get RBAC repositories — dialect resolved by octoswitcher (ORM or NET) */
|
|
63
63
|
export declare function getRbacRepos(): Promise<RbacRepos>;
|
|
64
64
|
/** Reset cache (for tests) */
|
|
65
65
|
export declare function resetRbacRepos(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repos-factory.d.ts","sourceRoot":"","sources":["../../lib/repos-factory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"repos-factory.d.ts","sourceRoot":"","sources":["../../lib/repos-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,28 +1,13 @@
|
|
|
1
|
-
// repos-factory.ts — Centralized repository factory
|
|
2
|
-
//
|
|
3
|
-
// In NET mode: returns NetClient-backed repositories with the same API
|
|
1
|
+
// repos-factory.ts — Centralized repository factory
|
|
2
|
+
// Uses @mostajs/octoswitcher to get the right dialect (ORM or NET)
|
|
4
3
|
// Author: Dr Hamid MADANI drmdh@msn.com
|
|
5
|
-
import { isNetMode } from './data-mode.js';
|
|
6
4
|
let _cached = null;
|
|
7
|
-
/** Get RBAC repositories
|
|
5
|
+
/** Get RBAC repositories — dialect resolved by octoswitcher (ORM or NET) */
|
|
8
6
|
export async function getRbacRepos() {
|
|
9
7
|
if (_cached)
|
|
10
8
|
return _cached;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
else {
|
|
15
|
-
_cached = await createOrmRepos();
|
|
16
|
-
}
|
|
17
|
-
return _cached;
|
|
18
|
-
}
|
|
19
|
-
/** Reset cache (for tests) */
|
|
20
|
-
export function resetRbacRepos() { _cached = null; }
|
|
21
|
-
// ============================================================
|
|
22
|
-
// ORM mode — original repositories
|
|
23
|
-
// ============================================================
|
|
24
|
-
async function createOrmRepos() {
|
|
25
|
-
const { getDialect, registerSchemas } = await import('@mostajs/orm');
|
|
9
|
+
const { getDialect } = await import('@mostajs/octoswitcher');
|
|
10
|
+
const { registerSchemas } = await import('@mostajs/orm');
|
|
26
11
|
const { UserSchema } = await import('../schemas/user.schema.js');
|
|
27
12
|
const { RoleSchema } = await import('../schemas/role.schema.js');
|
|
28
13
|
const { PermissionSchema } = await import('../schemas/permission.schema.js');
|
|
@@ -33,94 +18,14 @@ async function createOrmRepos() {
|
|
|
33
18
|
const { PermissionCategoryRepository } = await import('../repositories/permission-category.repository.js');
|
|
34
19
|
registerSchemas([UserSchema, RoleSchema, PermissionSchema, PermissionCategorySchema]);
|
|
35
20
|
const dialect = await getDialect();
|
|
36
|
-
|
|
21
|
+
_cached = {
|
|
37
22
|
users: new UserRepository(dialect),
|
|
38
23
|
roles: new RoleRepository(dialect),
|
|
39
24
|
permissions: new PermissionRepository(dialect),
|
|
40
25
|
categories: new PermissionCategoryRepository(dialect),
|
|
41
26
|
};
|
|
27
|
+
return _cached;
|
|
42
28
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// ============================================================
|
|
46
|
-
async function createNetRepos() {
|
|
47
|
-
const { NetClient } = await import('@mostajs/net/client');
|
|
48
|
-
const client = new NetClient({ url: process.env.MOSTA_NET_URL });
|
|
49
|
-
return {
|
|
50
|
-
users: createNetUserRepo(client),
|
|
51
|
-
roles: createNetRoleRepo(client),
|
|
52
|
-
permissions: createNetPermissionRepo(client),
|
|
53
|
-
categories: createNetCategoryRepo(client),
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
function createNetUserRepo(c) {
|
|
57
|
-
return {
|
|
58
|
-
findAllSafe: (filter = {}, options) => c.findAll('users', filter, Object.assign(Object.assign({}, options), { exclude: ['password'] })),
|
|
59
|
-
findByIdSafe: (id) => c.findById('users', id), // NET-side can add exclude later
|
|
60
|
-
findByEmail: (email) => c.findOne('users', { email: email.toLowerCase() }),
|
|
61
|
-
updateLastLogin: async (id) => { await c.update('users', id, { lastLoginAt: new Date().toISOString() }); },
|
|
62
|
-
findByIdWithRoles: (id) => c.findByIdWithRelations('users', id, ['roles']),
|
|
63
|
-
findAllWithRoles: (filter = {}, options) => c.findWithRelations('users', filter, ['roles'], options),
|
|
64
|
-
countByRole: (roleId) => c.count('users', { roles: roleId }),
|
|
65
|
-
addRole: (userId, roleId) => c.addToSet('users', userId, 'roles', roleId),
|
|
66
|
-
removeRole: (userId, roleId) => c.pull('users', userId, 'roles', roleId),
|
|
67
|
-
create: (data) => c.create('users', data),
|
|
68
|
-
update: (id, data) => c.update('users', id, data),
|
|
69
|
-
delete: (id) => c.delete('users', id),
|
|
70
|
-
findById: (id) => c.findById('users', id),
|
|
71
|
-
findOne: (filter) => c.findOne('users', filter),
|
|
72
|
-
findAll: (filter = {}, options) => c.findAll('users', filter, options),
|
|
73
|
-
count: (filter) => c.count('users', filter),
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
function createNetRoleRepo(c) {
|
|
77
|
-
return {
|
|
78
|
-
findAll: (filter = {}, options) => c.findAll('roles', filter, options),
|
|
79
|
-
findByName: (name) => c.findOne('roles', { name }),
|
|
80
|
-
findAllWithPermissions: () => c.findWithRelations('roles', {}, ['permissions']),
|
|
81
|
-
findByIdWithPermissions: (id) => c.findByIdWithRelations('roles', id, ['permissions']),
|
|
82
|
-
addPermission: (roleId, permId) => c.addToSet('roles', roleId, 'permissions', permId),
|
|
83
|
-
removePermission: (roleId, permId) => c.pull('roles', roleId, 'permissions', permId),
|
|
84
|
-
removePermissionFromAll: async (permId) => {
|
|
85
|
-
var _a;
|
|
86
|
-
const roles = await c.findAll('roles');
|
|
87
|
-
for (const role of roles) {
|
|
88
|
-
if ((_a = role.permissions) === null || _a === void 0 ? void 0 : _a.includes(permId)) {
|
|
89
|
-
await c.pull('roles', role.id, 'permissions', permId);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
create: (data) => c.create('roles', data),
|
|
94
|
-
update: (id, data) => c.update('roles', id, data),
|
|
95
|
-
delete: (id) => c.delete('roles', id),
|
|
96
|
-
findById: (id) => c.findById('roles', id),
|
|
97
|
-
count: (filter) => c.count('roles', filter),
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
function createNetPermissionRepo(c) {
|
|
101
|
-
return {
|
|
102
|
-
findAllSorted: () => c.findAll('permissions', {}, { sort: { category: 1, name: 1 } }),
|
|
103
|
-
findByName: (name) => c.findOne('permissions', { name }),
|
|
104
|
-
countByCategory: (catId) => c.count('permissions', { category: catId }),
|
|
105
|
-
create: (data) => c.create('permissions', data),
|
|
106
|
-
update: (id, data) => c.update('permissions', id, data),
|
|
107
|
-
delete: (id) => c.delete('permissions', id),
|
|
108
|
-
findAll: (filter = {}, options) => c.findAll('permissions', filter, options),
|
|
109
|
-
findById: (id) => c.findById('permissions', id),
|
|
110
|
-
count: (filter) => c.count('permissions', filter),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
function createNetCategoryRepo(c) {
|
|
114
|
-
return {
|
|
115
|
-
findAllOrdered: () => c.findAll('permission_categories', {}, { sort: { order: 1, name: 1 } }),
|
|
116
|
-
findByName: (name) => c.findOne('permission_categories', { name }),
|
|
117
|
-
create: (data) => c.create('permission_categories', data),
|
|
118
|
-
update: (id, data) => c.update('permission_categories', id, data),
|
|
119
|
-
delete: (id) => c.delete('permission_categories', id),
|
|
120
|
-
findAll: (filter = {}, options) => c.findAll('permission_categories', filter, options),
|
|
121
|
-
findById: (id) => c.findById('permission_categories', id),
|
|
122
|
-
count: (filter) => c.count('permission_categories', filter),
|
|
123
|
-
upsert: (filter, data) => c.upsert('permission_categories', filter, data),
|
|
124
|
-
};
|
|
125
|
-
}
|
|
29
|
+
/** Reset cache (for tests) */
|
|
30
|
+
export function resetRbacRepos() { _cached = null; }
|
|
126
31
|
//# sourceMappingURL=repos-factory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repos-factory.js","sourceRoot":"","sources":["../../lib/repos-factory.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"repos-factory.js","sourceRoot":"","sources":["../../lib/repos-factory.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,mEAAmE;AACnE,wCAAwC;AA6ExC,IAAI,OAAO,GAAqB,IAAI,CAAC;AAErC,4EAA4E;AAC5E,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;IAC7D,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IACzD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;IACjE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;IACjE,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,iCAAiC,CAAC,CAAC;IAC7E,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,MAAM,CAAC,0CAA0C,CAAC,CAAC;IAC9F,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,oCAAoC,CAAC,CAAC;IAC9E,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,oCAAoC,CAAC,CAAC;IAC9E,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,0CAA0C,CAAC,CAAC;IAC1F,MAAM,EAAE,4BAA4B,EAAE,GAAG,MAAM,MAAM,CAAC,mDAAmD,CAAC,CAAC;IAE3G,eAAe,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,wBAAwB,CAAC,CAAC,CAAC;IACtF,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;IAEnC,OAAO,GAAG;QACR,KAAK,EAAE,IAAI,cAAc,CAAC,OAAc,CAAoB;QAC5D,KAAK,EAAE,IAAI,cAAc,CAAC,OAAc,CAAoB;QAC5D,WAAW,EAAE,IAAI,oBAAoB,CAAC,OAAc,CAA0B;QAC9E,UAAU,EAAE,IAAI,4BAA4B,CAAC,OAAc,CAAkC;KAC9F,CAAC;IACF,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,8BAA8B;AAC9B,MAAM,UAAU,cAAc,KAAW,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/rbac",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "RBAC — User/Role/Permission schemas, repos, management UI, API handlers",
|
|
5
5
|
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -186,6 +186,7 @@
|
|
|
186
186
|
"prepublishOnly": "npm run build"
|
|
187
187
|
},
|
|
188
188
|
"dependencies": {
|
|
189
|
+
"@mostajs/octoswitcher": "^1.0.0",
|
|
189
190
|
"@mostajs/orm": "^1.0.0",
|
|
190
191
|
"bcryptjs": "^3.0.3",
|
|
191
192
|
"class-variance-authority": "^0.7.0",
|
|
@@ -210,11 +211,15 @@
|
|
|
210
211
|
"@mostajs/auth": "^1.0.2",
|
|
211
212
|
"@mostajs/menu": "^1.0.3",
|
|
212
213
|
"@mostajs/socle": "^2.0.0",
|
|
214
|
+
"@tanstack/react-query": "^5.96.2",
|
|
213
215
|
"@types/bcryptjs": "^2.4.0",
|
|
214
216
|
"@types/node": "^25.3.3",
|
|
215
217
|
"@types/react": "^19.0.0",
|
|
218
|
+
"lucide-react": "^1.7.0",
|
|
216
219
|
"next": "^16.1.6",
|
|
220
|
+
"radix-ui": "^1.4.3",
|
|
217
221
|
"react": "^19.0.0",
|
|
222
|
+
"sonner": "^2.0.7",
|
|
218
223
|
"typescript": "^5.6.0"
|
|
219
224
|
},
|
|
220
225
|
"peerDependenciesMeta": {
|