@flusys/nestjs-iam 0.1.0-beta.1 → 0.1.0-beta.2

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 (118) hide show
  1. package/README.md +665 -0
  2. package/cjs/config/iam.constants.js +11 -0
  3. package/cjs/config/index.js +18 -0
  4. package/cjs/controllers/action.controller.js +117 -0
  5. package/cjs/controllers/company-action-permission.controller.js +110 -0
  6. package/cjs/controllers/index.js +23 -0
  7. package/cjs/controllers/my-permission.controller.js +90 -0
  8. package/cjs/controllers/role-permission.controller.js +160 -0
  9. package/cjs/controllers/role.controller.js +58 -0
  10. package/cjs/controllers/user-action-permission.controller.js +110 -0
  11. package/cjs/docs/iam-swagger.config.js +202 -0
  12. package/cjs/docs/index.js +18 -0
  13. package/cjs/dtos/action.dto.js +347 -0
  14. package/cjs/dtos/index.js +21 -0
  15. package/cjs/dtos/permission.dto.js +554 -0
  16. package/cjs/dtos/role.dto.js +238 -0
  17. package/cjs/entities/action-base.entity.js +135 -0
  18. package/cjs/entities/action.entity.js +28 -0
  19. package/cjs/entities/index.js +81 -0
  20. package/cjs/entities/permission-base.entity.js +156 -0
  21. package/cjs/entities/permission-with-company.entity.js +99 -0
  22. package/cjs/entities/role-base.entity.js +86 -0
  23. package/cjs/entities/role-with-company.entity.js +55 -0
  24. package/cjs/entities/role.entity.js +25 -0
  25. package/cjs/entities/user-iam-permission.entity.js +57 -0
  26. package/cjs/enums/action-type.enum.js +22 -0
  27. package/cjs/enums/index.js +19 -0
  28. package/cjs/enums/permission-type.enum.js +16 -0
  29. package/cjs/helpers/index.js +19 -0
  30. package/cjs/helpers/permission-evaluator.helper.js +175 -0
  31. package/cjs/helpers/permission-mode.helper.js +49 -0
  32. package/cjs/index.js +28 -79
  33. package/cjs/interfaces/action.interface.js +4 -0
  34. package/cjs/interfaces/iam-module-async-options.interface.js +4 -0
  35. package/cjs/interfaces/iam-module-options.interface.js +18 -0
  36. package/cjs/interfaces/index.js +21 -0
  37. package/cjs/interfaces/role.interface.js +7 -0
  38. package/cjs/modules/iam.module.js +237 -0
  39. package/cjs/modules/index.js +18 -0
  40. package/cjs/services/action.service.js +253 -0
  41. package/cjs/services/iam-config.service.js +107 -0
  42. package/cjs/services/iam-datasource.provider.js +205 -0
  43. package/cjs/services/index.js +23 -0
  44. package/cjs/services/permission-cache.service.js +308 -0
  45. package/cjs/services/permission.service.js +1020 -0
  46. package/cjs/services/role.service.js +181 -0
  47. package/cjs/types/index.js +18 -0
  48. package/cjs/types/logic-node.type.js +54 -0
  49. package/fesm/config/iam.constants.js +1 -0
  50. package/fesm/config/index.js +1 -0
  51. package/fesm/controllers/action.controller.js +107 -0
  52. package/fesm/controllers/company-action-permission.controller.js +100 -0
  53. package/fesm/controllers/index.js +7 -0
  54. package/fesm/controllers/my-permission.controller.js +80 -0
  55. package/fesm/controllers/role-permission.controller.js +150 -0
  56. package/fesm/controllers/role.controller.js +48 -0
  57. package/fesm/controllers/user-action-permission.controller.js +100 -0
  58. package/fesm/docs/iam-swagger.config.js +192 -0
  59. package/fesm/docs/index.js +1 -0
  60. package/fesm/dtos/action.dto.js +317 -0
  61. package/fesm/dtos/index.js +4 -0
  62. package/fesm/dtos/permission.dto.js +490 -0
  63. package/fesm/dtos/role.dto.js +214 -0
  64. package/fesm/entities/action-base.entity.js +128 -0
  65. package/fesm/entities/action.entity.js +18 -0
  66. package/fesm/entities/index.js +56 -0
  67. package/fesm/entities/permission-base.entity.js +138 -0
  68. package/fesm/entities/permission-with-company.entity.js +89 -0
  69. package/fesm/entities/role-base.entity.js +79 -0
  70. package/fesm/entities/role-with-company.entity.js +45 -0
  71. package/fesm/entities/role.entity.js +15 -0
  72. package/fesm/entities/user-iam-permission.entity.js +38 -0
  73. package/fesm/enums/action-type.enum.js +12 -0
  74. package/fesm/enums/index.js +2 -0
  75. package/fesm/enums/permission-type.enum.js +6 -0
  76. package/fesm/helpers/index.js +2 -0
  77. package/fesm/helpers/permission-evaluator.helper.js +165 -0
  78. package/fesm/helpers/permission-mode.helper.js +49 -0
  79. package/fesm/index.js +11 -79
  80. package/fesm/interfaces/action.interface.js +3 -0
  81. package/fesm/interfaces/iam-module-async-options.interface.js +3 -0
  82. package/fesm/interfaces/iam-module-options.interface.js +1 -0
  83. package/fesm/interfaces/index.js +4 -0
  84. package/fesm/interfaces/role.interface.js +4 -0
  85. package/fesm/modules/iam.module.js +227 -0
  86. package/fesm/modules/index.js +1 -0
  87. package/fesm/services/action.service.js +243 -0
  88. package/fesm/services/iam-config.service.js +97 -0
  89. package/fesm/services/iam-datasource.provider.js +154 -0
  90. package/fesm/services/index.js +6 -0
  91. package/fesm/services/permission-cache.service.js +298 -0
  92. package/fesm/services/permission.service.js +1010 -0
  93. package/fesm/services/role.service.js +171 -0
  94. package/fesm/types/index.js +1 -0
  95. package/fesm/types/logic-node.type.js +36 -0
  96. package/package.json +25 -25
  97. package/cjs/config-index.js +0 -1
  98. package/cjs/controllers-index.js +0 -1
  99. package/cjs/docs-index.js +0 -79
  100. package/cjs/dtos-index.js +0 -1
  101. package/cjs/entities-index.js +0 -1
  102. package/cjs/enums-index.js +0 -1
  103. package/cjs/helpers-index.js +0 -1
  104. package/cjs/interfaces-index.js +0 -1
  105. package/cjs/modules-index.js +0 -1
  106. package/cjs/services-index.js +0 -1
  107. package/cjs/types-index.js +0 -1
  108. package/fesm/config-index.js +0 -1
  109. package/fesm/controllers-index.js +0 -1
  110. package/fesm/docs-index.js +0 -79
  111. package/fesm/dtos-index.js +0 -1
  112. package/fesm/entities-index.js +0 -1
  113. package/fesm/enums-index.js +0 -1
  114. package/fesm/helpers-index.js +0 -1
  115. package/fesm/interfaces-index.js +0 -0
  116. package/fesm/modules-index.js +0 -1
  117. package/fesm/services-index.js +0 -1
  118. package/fesm/types-index.js +0 -1
package/README.md ADDED
@@ -0,0 +1,665 @@
1
+ # IAM Package Guide
2
+
3
+ > **Package:** `@flusys/nestjs-iam`
4
+ > **Purpose:** Identity and Access Management with RBAC, ABAC, and permission logic
5
+ > **Version:** 4.4.0 | **Updated:** 2026-01-24
6
+
7
+ ## Table of Contents
8
+
9
+ - [Overview](#overview)
10
+ - [Installation](#installation)
11
+ - [Module Configuration](#module-configuration)
12
+ - [Core Concepts](#core-concepts)
13
+ - [Entities](#entities)
14
+ - [Permission Modes](#permission-modes)
15
+ - [Permission Logic](#permission-logic)
16
+ - [Services](#services)
17
+ - [REST API Endpoints](#rest-api-endpoints)
18
+ - [Multi-Tenant Support](#multi-tenant-support)
19
+ - [Permission Guard Integration](#permission-guard-integration)
20
+ - [Best Practices](#best-practices)
21
+ - [API Reference](#api-reference)
22
+ - [Package Architecture](#package-architecture)
23
+
24
+ ---
25
+
26
+ ## Overview
27
+
28
+ `@flusys/nestjs-iam` provides a comprehensive Identity and Access Management system:
29
+
30
+ - **Hierarchical Actions** - Organize permissions in tree structures
31
+ - **Action Types** - BACKEND (cached for guards), FRONTEND (returned to UI), BOTH
32
+ - **RBAC** - Role-Based Access Control
33
+ - **ABAC/DIRECT** - Direct user-to-action assignments
34
+ - **Permission Logic** - Complex AND/OR rules
35
+ - **Company/Branch Scoping** - Multi-tenant permissions with three-level granularity
36
+ - **Centralized Caching** - Automatic cache invalidation for security
37
+
38
+ ### Package Hierarchy
39
+
40
+ ```
41
+ @flusys/nestjs-core <- Foundation
42
+ |
43
+ @flusys/nestjs-shared <- Shared utilities
44
+ |
45
+ @flusys/nestjs-auth <- User/Company management
46
+ |
47
+ @flusys/nestjs-iam <- Permission management (THIS PACKAGE)
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Installation
53
+
54
+ ```bash
55
+ npm install @flusys/nestjs-iam @flusys/nestjs-shared @flusys/nestjs-core
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Module Configuration
61
+
62
+ ### With Auth Module (Recommended)
63
+
64
+ ```typescript
65
+ import { AuthModule } from '@flusys/nestjs-auth';
66
+ import { IAMModule } from '@flusys/nestjs-iam';
67
+
68
+ @Module({
69
+ imports: [
70
+ AuthModule.forRoot({
71
+ includeIAM: true, // Required for single-tenant mode
72
+ bootstrapAppConfig: {
73
+ databaseMode: 'single',
74
+ enableCompanyFeature: true,
75
+ },
76
+ config: { /* auth config */ },
77
+ }),
78
+
79
+ IAMModule.forRoot({
80
+ global: true,
81
+ includeController: true,
82
+ bootstrapAppConfig: {
83
+ databaseMode: 'single',
84
+ enableCompanyFeature: true,
85
+ permissionMode: 'FULL', // 'FULL' | 'RBAC' | 'DIRECT'
86
+ },
87
+ }),
88
+ ],
89
+ })
90
+ export class AppModule {}
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Core Concepts
96
+
97
+ ### Actions
98
+
99
+ Actions represent permissions in the system:
100
+
101
+ | Field | Description |
102
+ |-------|-------------|
103
+ | `name` | Human-readable name |
104
+ | `code` | Unique identifier (e.g., `user.create`) |
105
+ | `actionType` | Category: `backend`, `frontend`, or `both` |
106
+ | `metadata` | Additional data (icon, routerLink for frontend) |
107
+ | `parentId` | Parent action for hierarchy |
108
+ | `serial` | Display order |
109
+
110
+ ### Action Types
111
+
112
+ ```typescript
113
+ enum ActionType {
114
+ BACKEND = 'backend', // API endpoint permissions (cached for PermissionGuard)
115
+ FRONTEND = 'frontend', // UI features (returned in my-permissions API)
116
+ BOTH = 'both', // Both backend and frontend
117
+ }
118
+ ```
119
+
120
+ ### Roles
121
+
122
+ Roles are collections of actions:
123
+
124
+ | Field | Description |
125
+ |-------|-------------|
126
+ | `name` | Human-readable name |
127
+ | `description` | Role description |
128
+ | `companyId` | Company scope (when company feature enabled) |
129
+ | `isActive` | Active status |
130
+
131
+ ### Permission Types
132
+
133
+ ```typescript
134
+ enum IamPermissionType {
135
+ USER_ROLE = 'user_role', // User assigned to role
136
+ ROLE_ACTION = 'role_action', // Role has action
137
+ USER_ACTION = 'user_action', // User has action directly
138
+ COMPANY_ACTION = 'company_action', // Company action whitelist
139
+ }
140
+ ```
141
+
142
+ ### Permission Resolution Order
143
+
144
+ 1. **Company-Action Whitelist** - Filter by company (if enabled)
145
+ 2. **UserAction (DENY)** - Explicit denials take precedence
146
+ 3. **UserAction (GRANT)** - Explicit grants
147
+ 4. **UserRole -> RoleAction** - Inherited from roles
148
+ 5. **Action Permission Logic** - Complex AND/OR rules
149
+
150
+ ---
151
+
152
+ ## Entities
153
+
154
+ ### ActionBase
155
+
156
+ Core action fields in `action-base.entity.ts`:
157
+
158
+ | Column | Type | Description |
159
+ |--------|------|-------------|
160
+ | `readOnly` | boolean | System-protected action |
161
+ | `name` | varchar(255) | Action name |
162
+ | `code` | varchar(255) | Unique code |
163
+ | `description` | varchar(500) | Description |
164
+ | `actionType` | enum | BACKEND, FRONTEND, BOTH |
165
+ | `permissionLogic` | json | AND/OR rules |
166
+ | `parentId` | uuid | Parent action ID |
167
+ | `serial` | int | Display order |
168
+ | `isActive` | boolean | Active status |
169
+ | `metadata` | json | Additional data |
170
+
171
+ ### RoleBase
172
+
173
+ Core role fields in `role-base.entity.ts`:
174
+
175
+ | Column | Type | Description |
176
+ |--------|------|-------------|
177
+ | `readOnly` | boolean | System-protected role |
178
+ | `name` | varchar(255) | Role name |
179
+ | `description` | varchar(500) | Description |
180
+ | `isActive` | boolean | Active status |
181
+ | `serial` | int | Display order |
182
+ | `metadata` | json | Additional data |
183
+
184
+ ### RoleWithCompany
185
+
186
+ Extends RoleBase with:
187
+ - `companyId` (uuid) - Company scope
188
+
189
+ ### PermissionBase
190
+
191
+ Core permission fields in `permission-base.entity.ts`:
192
+
193
+ | Column | Type | Description |
194
+ |--------|------|-------------|
195
+ | `permissionType` | enum | USER_ROLE, ROLE_ACTION, etc. |
196
+ | `sourceType` | enum | USER, ROLE, COMPANY |
197
+ | `sourceId` | uuid | Source entity ID |
198
+ | `targetType` | enum | ROLE, ACTION |
199
+ | `targetId` | uuid | Target entity ID |
200
+ | `userId` | uuid | User ID (nullable) |
201
+ | `validFrom` | timestamp | Permission valid from |
202
+ | `validUntil` | timestamp | Permission valid until |
203
+ | `reason` | text | Reason for permission |
204
+ | `metadata` | json | Additional data |
205
+
206
+ ### UserIamPermissionWithCompany
207
+
208
+ Extends PermissionBase with:
209
+ - `companyId` (uuid) - Company scope
210
+ - `branchId` (uuid) - Branch scope
211
+
212
+ **Permission Granularity:**
213
+
214
+ | Level | companyId | branchId | Use Case |
215
+ |-------|-----------|----------|----------|
216
+ | Global | null | null | Super admin across all companies |
217
+ | Company-wide | set | null | Manager for ALL branches in company |
218
+ | Branch-specific | set | set | Manager for specific branch only |
219
+
220
+ ---
221
+
222
+ ## Permission Modes
223
+
224
+ Set in `bootstrapAppConfig.permissionMode`:
225
+
226
+ ### RBAC Mode (Role-Based)
227
+
228
+ ```
229
+ User -> Role -> Action
230
+ ```
231
+
232
+ Only role-based permissions. Users get permissions through assigned roles.
233
+
234
+ ### DIRECT Mode (Action-Based)
235
+
236
+ ```
237
+ User -> Action
238
+ ```
239
+
240
+ Only direct permissions. Users get actions assigned directly.
241
+
242
+ ### FULL Mode (Combined)
243
+
244
+ ```
245
+ User -> Role -> Action
246
+ User -> Action
247
+ ```
248
+
249
+ Both RBAC and direct permissions. Default mode.
250
+
251
+ ### PermissionModeHelper
252
+
253
+ ```typescript
254
+ import { PermissionModeHelper } from '@flusys/nestjs-iam/helpers';
255
+
256
+ const mode = PermissionModeHelper.fromString('RBAC');
257
+ // Returns: IAMPermissionMode.RBAC
258
+ ```
259
+
260
+ ---
261
+
262
+ ## Permission Logic
263
+
264
+ Complex rules using AND/OR operators:
265
+
266
+ ```typescript
267
+ interface LogicNode {
268
+ id: string;
269
+ type: 'group' | 'action';
270
+ operator?: 'AND' | 'OR'; // Only for type: 'group'
271
+ children?: LogicNode[]; // Only for type: 'group'
272
+ actionId?: string; // Only for type: 'action'
273
+ }
274
+ ```
275
+
276
+ ### Example: Nested Logic
277
+
278
+ ```typescript
279
+ const logic: LogicNode = {
280
+ id: 'root',
281
+ type: 'group',
282
+ operator: 'AND',
283
+ children: [
284
+ { id: '1', type: 'action', actionId: 'employee-action-id' },
285
+ {
286
+ id: '2',
287
+ type: 'group',
288
+ operator: 'OR',
289
+ children: [
290
+ { id: '2-1', type: 'action', actionId: 'department-head' },
291
+ { id: '2-2', type: 'action', actionId: 'hr-clearance' },
292
+ ],
293
+ },
294
+ ],
295
+ };
296
+ // User must have employee AND (department-head OR hr-clearance)
297
+ ```
298
+
299
+ ---
300
+
301
+ ## Services
302
+
303
+ ### ActionService
304
+
305
+ ```typescript
306
+ import { ActionService } from '@flusys/nestjs-iam';
307
+
308
+ // Create action
309
+ await actionService.insert({
310
+ name: 'View Users',
311
+ code: 'user.view',
312
+ actionType: ActionType.BACKEND,
313
+ parentId: parentAction.id,
314
+ });
315
+
316
+ // Get hierarchical tree
317
+ const tree = await actionService.getActionTree(user, 'search', true, false);
318
+
319
+ // Get actions for permission (company-filtered)
320
+ const actions = await actionService.getActionsForPermission(user);
321
+ ```
322
+
323
+ ### RoleService
324
+
325
+ ```typescript
326
+ import { RoleService } from '@flusys/nestjs-iam';
327
+
328
+ // Create role
329
+ await roleService.insert({
330
+ name: 'Administrator',
331
+ description: 'Full system access',
332
+ companyId: 'company-id',
333
+ });
334
+ ```
335
+
336
+ ### PermissionService
337
+
338
+ ```typescript
339
+ import { PermissionService } from '@flusys/nestjs-iam';
340
+
341
+ // Assign roles to user
342
+ await permissionService.assignUserRoles({
343
+ userId: 'user-id',
344
+ companyId: 'company-id',
345
+ branchId: null, // null = ALL branches
346
+ items: [{ id: 'role-id', action: PermissionAction.ADD }],
347
+ });
348
+
349
+ // Assign actions directly
350
+ await permissionService.assignUserActions({
351
+ userId: 'user-id',
352
+ companyId: 'company-id',
353
+ branchId: 'branch-id',
354
+ items: [{ id: 'action-id', action: PermissionAction.ADD }],
355
+ });
356
+
357
+ // Assign actions to role
358
+ await permissionService.assignRoleActions({
359
+ roleId: 'role-id',
360
+ items: [{ id: 'action-id', action: PermissionAction.ADD }],
361
+ });
362
+
363
+ // Get user's permissions
364
+ const permissions = await permissionService.getMyPermissions(
365
+ userId, branchId, companyId, parentCodes
366
+ );
367
+ ```
368
+
369
+ ### PermissionCacheService
370
+
371
+ ```typescript
372
+ import { PermissionCacheService } from '@flusys/nestjs-iam';
373
+
374
+ // Set permissions
375
+ await cacheService.setPermissions(
376
+ { userId, companyId, branchId, enableCompanyFeature: true },
377
+ ['users.read', 'users.write']
378
+ );
379
+
380
+ // Invalidate user cache
381
+ await cacheService.invalidateUser('user-id', 'company-id', ['branch-id']);
382
+
383
+ // Invalidate role members
384
+ await cacheService.invalidateRole('role-id', userIds, 'company-id');
385
+ ```
386
+
387
+ **Cache Key Format:**
388
+ ```
389
+ permissions:user:{userId} // Without company
390
+ permissions:company:{companyId}:branch:{branchId}:user:{userId} // With company
391
+ ```
392
+
393
+ ---
394
+
395
+ ## REST API Endpoints
396
+
397
+ ### Actions API
398
+
399
+ | Endpoint | Method | Description |
400
+ |----------|--------|-------------|
401
+ | `/iam/actions/insert` | POST | Create action |
402
+ | `/iam/actions/get-all` | POST | List actions (paginated) |
403
+ | `/iam/actions/get/:id` | GET | Get action by ID |
404
+ | `/iam/actions/tree` | POST | Get hierarchical tree (ALL actions) |
405
+ | `/iam/actions/tree-for-permission` | GET | Get company-filtered actions |
406
+ | `/iam/actions/update` | POST | Update action |
407
+ | `/iam/actions/delete` | POST | Delete action |
408
+
409
+ ### Roles API
410
+
411
+ | Endpoint | Method | Description |
412
+ |----------|--------|-------------|
413
+ | `/iam/roles/insert` | POST | Create role |
414
+ | `/iam/roles/get-all` | POST | List roles (paginated) |
415
+ | `/iam/roles/get/:id` | GET | Get role by ID |
416
+ | `/iam/roles/update` | POST | Update role |
417
+ | `/iam/roles/delete` | POST | Delete role |
418
+
419
+ ### Permissions API
420
+
421
+ | Endpoint | Method | Description |
422
+ |----------|--------|-------------|
423
+ | `/iam/permissions/role-actions/assign` | POST | Assign actions to role |
424
+ | `/iam/permissions/role-actions/get` | POST | Get role actions |
425
+ | `/iam/permissions/user-roles/assign` | POST | Assign roles to user |
426
+ | `/iam/permissions/user-roles/get` | POST | Get user roles |
427
+ | `/iam/permissions/user-actions/assign` | POST | Assign actions to user |
428
+ | `/iam/permissions/user-actions/get` | POST | Get user actions |
429
+ | `/iam/permissions/company-actions/assign` | POST | Company action whitelist |
430
+ | `/iam/permissions/company-actions/get` | POST | Get company actions |
431
+ | `/iam/permissions/my-permissions` | POST | Get current user's permissions |
432
+
433
+ **My Permissions Response:**
434
+ ```typescript
435
+ {
436
+ frontendActions: FrontendActionDto[],
437
+ cachedEndpoints: number
438
+ }
439
+ ```
440
+
441
+ ---
442
+
443
+ ## Multi-Tenant Support
444
+
445
+ ### Company Feature Toggle
446
+
447
+ ```typescript
448
+ // config/app.config.ts
449
+ export const bootstrapAppConfig: IBootstrapAppConfig = {
450
+ databaseMode: 'single',
451
+ enableCompanyFeature: true, // or false
452
+ };
453
+ ```
454
+
455
+ ### When `enableCompanyFeature: true`
456
+
457
+ - `companyId` and `branchId` fields available in DTOs
458
+ - Company-Action Permissions controller registered
459
+ - Three-level permission granularity (Global, Company-wide, Branch-specific)
460
+ - Uses `UserIamPermissionWithCompany` and `RoleWithCompany` entities
461
+
462
+ ### When `enableCompanyFeature: false`
463
+
464
+ - Company endpoints NOT available (404)
465
+ - `companyId`/`branchId` fields visible in Swagger but ignored
466
+ - All permissions are global
467
+ - Uses `UserIamPermission` and `Role` entities
468
+
469
+ ### Permission Merging
470
+
471
+ When user logs in, `getMyPermissions` merges:
472
+ 1. Company-wide roles (branchId=null) + Branch-specific roles
473
+ 2. Actions from all merged roles
474
+ 3. Company-wide user actions + Branch-specific user actions
475
+
476
+ **Result:** Complete permission set without duplicates.
477
+
478
+ ---
479
+
480
+ ## Permission Guard Integration
481
+
482
+ ```typescript
483
+ import { PermissionGuard } from '@flusys/nestjs-shared/guards';
484
+ import { RequirePermission, RequireAnyPermission } from '@flusys/nestjs-shared/decorators';
485
+
486
+ @Controller('users')
487
+ export class UserController {
488
+ @RequirePermission('user.view')
489
+ @Get()
490
+ getUsers() {}
491
+
492
+ @RequireAnyPermission('user.create', 'admin')
493
+ @Post()
494
+ createUser() {}
495
+ }
496
+ ```
497
+
498
+ ---
499
+
500
+ ## Best Practices
501
+
502
+ ### 1. Action Code Naming
503
+
504
+ ```typescript
505
+ // Hierarchical naming for backend
506
+ 'user.view', 'user.create', 'user.delete'
507
+
508
+ // UPPERCASE for frontend actions
509
+ 'MENU_USERS', 'MENU_REPORTS', 'FEATURE_EXPORT'
510
+ ```
511
+
512
+ ### 2. Company-wide vs Branch-specific
513
+
514
+ ```typescript
515
+ // Company-wide for managers across ALL branches
516
+ { companyId: 'company-a', branchId: null }
517
+
518
+ // Branch-specific for location-bound staff
519
+ { companyId: 'company-a', branchId: 'branch-x' }
520
+ ```
521
+
522
+ ### 3. Use Roles for Common Patterns
523
+
524
+ ```typescript
525
+ // Create roles for common permission sets
526
+ const roles = [
527
+ { name: 'Viewer', actions: ['*.view'] },
528
+ { name: 'Editor', actions: ['*.view', '*.create', '*.update'] },
529
+ { name: 'Admin', actions: ['*'] },
530
+ ];
531
+ ```
532
+
533
+ ### 4. Use Direct Actions Sparingly
534
+
535
+ Direct actions should be exceptions and branch-specific overrides, not the primary permission mechanism.
536
+
537
+ ---
538
+
539
+ ## API Reference
540
+
541
+ ### Module
542
+
543
+ ```typescript
544
+ import { IAMModule, IAMPermissionMode } from '@flusys/nestjs-iam';
545
+ ```
546
+
547
+ ### Services
548
+
549
+ ```typescript
550
+ import {
551
+ ActionService,
552
+ RoleService,
553
+ PermissionService,
554
+ PermissionCacheService,
555
+ IAMConfigService,
556
+ IAMDataSourceProvider,
557
+ } from '@flusys/nestjs-iam';
558
+ ```
559
+
560
+ ### Entities
561
+
562
+ ```typescript
563
+ import {
564
+ Action,
565
+ Role,
566
+ RoleWithCompany,
567
+ UserIamPermission,
568
+ UserIamPermissionWithCompany,
569
+ getIAMEntitiesByConfig,
570
+ } from '@flusys/nestjs-iam/entities';
571
+ ```
572
+
573
+ ### DTOs
574
+
575
+ ```typescript
576
+ import {
577
+ CreateActionDto,
578
+ UpdateActionDto,
579
+ CreateRoleDto,
580
+ UpdateRoleDto,
581
+ AssignUserActionsDto,
582
+ AssignUserRolesDto,
583
+ AssignRoleActionsDto,
584
+ AssignCompanyActionsDto,
585
+ MyPermissionsResponseDto,
586
+ FrontendActionDto,
587
+ } from '@flusys/nestjs-iam/dtos';
588
+ ```
589
+
590
+ ### Enums
591
+
592
+ ```typescript
593
+ import {
594
+ ActionType,
595
+ IAMPermissionMode,
596
+ IamPermissionType,
597
+ IamEntityType,
598
+ } from '@flusys/nestjs-iam/enums';
599
+ ```
600
+
601
+ ### Helpers
602
+
603
+ ```typescript
604
+ import {
605
+ PermissionEvaluatorHelper,
606
+ PermissionModeHelper,
607
+ } from '@flusys/nestjs-iam/helpers';
608
+ ```
609
+
610
+ ---
611
+
612
+ ## Package Architecture
613
+
614
+ ```
615
+ nestjs-iam/src/
616
+ ├── modules/
617
+ │ └── iam.module.ts # Main module with dynamic config
618
+ ├── entities/
619
+ │ ├── action-base.entity.ts # Action base fields
620
+ │ ├── action.entity.ts # Action entity
621
+ │ ├── role-base.entity.ts # Role base fields
622
+ │ ├── role.entity.ts # Role (no company)
623
+ │ ├── role-with-company.entity.ts
624
+ │ ├── permission-base.entity.ts # Permission base fields
625
+ │ ├── user-iam-permission.entity.ts
626
+ │ └── permission-with-company.entity.ts
627
+ ├── services/
628
+ │ ├── action.service.ts # Action CRUD
629
+ │ ├── role.service.ts # Role CRUD
630
+ │ ├── permission.service.ts # Permission management
631
+ │ ├── permission-cache.service.ts # Cache management
632
+ │ ├── iam-config.service.ts # Configuration
633
+ │ └── iam-datasource.provider.ts # DataSource provider
634
+ ├── controllers/
635
+ │ ├── action.controller.ts
636
+ │ ├── role.controller.ts
637
+ │ ├── my-permission.controller.ts
638
+ │ ├── role-permission.controller.ts
639
+ │ ├── user-action-permission.controller.ts
640
+ │ └── company-action-permission.controller.ts
641
+ ├── helpers/
642
+ │ ├── permission-evaluator.helper.ts
643
+ │ └── permission-mode.helper.ts
644
+ ├── dtos/
645
+ │ ├── action.dto.ts
646
+ │ ├── role.dto.ts
647
+ │ └── permission.dto.ts
648
+ ├── interfaces/
649
+ │ ├── action.interface.ts
650
+ │ ├── role.interface.ts
651
+ │ └── iam-module-options.interface.ts
652
+ ├── enums/
653
+ │ ├── action-type.enum.ts
654
+ │ └── permission-type.enum.ts
655
+ └── types/
656
+ └── logic-node.type.ts
657
+ ```
658
+
659
+ ---
660
+
661
+ **Last Updated:** 2026-02-09 | **Version:** 4.4.1
662
+
663
+ **Recent Changes (2026-02-09):**
664
+ - Added explicit `@Inject()` decorators to all services for esbuild bundling compatibility
665
+ - All services use REQUEST scope with lazy repository initialization via DataSource Provider pattern
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "IAM_MODULE_OPTIONS", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return IAM_MODULE_OPTIONS;
9
+ }
10
+ });
11
+ const IAM_MODULE_OPTIONS = 'IAM_MODULE_OPTIONS';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ _export_star(require("./iam.constants"), exports);
6
+ function _export_star(from, to) {
7
+ Object.keys(from).forEach(function(k) {
8
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
9
+ Object.defineProperty(to, k, {
10
+ enumerable: true,
11
+ get: function() {
12
+ return from[k];
13
+ }
14
+ });
15
+ }
16
+ });
17
+ return from;
18
+ }