@flusys/nestjs-iam 2.0.0 → 3.0.0
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 +382 -37
- package/cjs/entities/action-base.entity.js +3 -3
- package/cjs/entities/permission-base.entity.js +6 -6
- package/entities/permission-base.entity.d.ts +3 -3
- package/fesm/entities/action-base.entity.js +3 -3
- package/fesm/entities/permission-base.entity.js +6 -6
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# IAM Package Guide
|
|
2
2
|
|
|
3
3
|
> **Package:** `@flusys/nestjs-iam`
|
|
4
|
+
> **Version:** 3.0.0
|
|
4
5
|
> **Purpose:** Identity and Access Management with RBAC, ABAC, and permission logic
|
|
5
6
|
|
|
6
7
|
## Table of Contents
|
|
@@ -10,6 +11,7 @@
|
|
|
10
11
|
- [Module Configuration](#module-configuration)
|
|
11
12
|
- [Constants](#constants)
|
|
12
13
|
- [Core Concepts](#core-concepts)
|
|
14
|
+
- [Interfaces](#interfaces)
|
|
13
15
|
- [Entities](#entities)
|
|
14
16
|
- [Permission Modes](#permission-modes)
|
|
15
17
|
- [Permission Logic](#permission-logic)
|
|
@@ -19,6 +21,7 @@
|
|
|
19
21
|
- [Multi-Tenant Support](#multi-tenant-support)
|
|
20
22
|
- [Permission Guard Integration](#permission-guard-integration)
|
|
21
23
|
- [Best Practices](#best-practices)
|
|
24
|
+
- [DTOs Reference](#dtos-reference)
|
|
22
25
|
- [API Reference](#api-reference)
|
|
23
26
|
- [Package Architecture](#package-architecture)
|
|
24
27
|
|
|
@@ -168,6 +171,19 @@ enum IamPermissionType {
|
|
|
168
171
|
}
|
|
169
172
|
```
|
|
170
173
|
|
|
174
|
+
### Entity Types
|
|
175
|
+
|
|
176
|
+
Used for source/target type fields in permissions:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
enum IamEntityType {
|
|
180
|
+
USER = 'user',
|
|
181
|
+
ROLE = 'role',
|
|
182
|
+
ACTION = 'action',
|
|
183
|
+
COMPANY = 'company',
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
171
187
|
### Permission Resolution Order
|
|
172
188
|
|
|
173
189
|
1. **Company-Action Whitelist** - Filter by company (if enabled)
|
|
@@ -198,6 +214,88 @@ Company Action Removed
|
|
|
198
214
|
|
|
199
215
|
---
|
|
200
216
|
|
|
217
|
+
## Interfaces
|
|
218
|
+
|
|
219
|
+
### IAction
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
interface IAction {
|
|
223
|
+
id: string;
|
|
224
|
+
readOnly: boolean;
|
|
225
|
+
name: string;
|
|
226
|
+
description: string | null;
|
|
227
|
+
code: string | null;
|
|
228
|
+
actionType: ActionType;
|
|
229
|
+
permissionLogic: LogicNode | null;
|
|
230
|
+
serial: number | null;
|
|
231
|
+
isActive: boolean;
|
|
232
|
+
parentId: string | null;
|
|
233
|
+
metadata: Record<string, any> | null;
|
|
234
|
+
createdAt: Date;
|
|
235
|
+
updatedAt: Date;
|
|
236
|
+
deletedAt: Date | null;
|
|
237
|
+
createdById: string | null;
|
|
238
|
+
updatedById: string | null;
|
|
239
|
+
deletedById: string | null;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### IActionTree
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
interface IActionTree extends IAction {
|
|
247
|
+
children?: IActionTree[];
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### IRole
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
interface IRole {
|
|
255
|
+
id: string;
|
|
256
|
+
readOnly: boolean;
|
|
257
|
+
name: string;
|
|
258
|
+
description: string | null;
|
|
259
|
+
isActive: boolean;
|
|
260
|
+
serial: number | null;
|
|
261
|
+
companyId: string | null;
|
|
262
|
+
metadata: Record<string, any> | null;
|
|
263
|
+
createdAt: Date;
|
|
264
|
+
updatedAt: Date;
|
|
265
|
+
deletedAt: Date | null;
|
|
266
|
+
createdById: string | null;
|
|
267
|
+
updatedById: string | null;
|
|
268
|
+
deletedById: string | null;
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Module Options
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
// Runtime configuration (currently empty - reserved for future use)
|
|
276
|
+
interface IIAMModuleConfig extends IDataSourceServiceOptions {
|
|
277
|
+
// Future: cache TTL, etc.
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Full module options
|
|
281
|
+
interface IAMModuleOptions extends IDynamicModuleConfig {
|
|
282
|
+
bootstrapAppConfig?: IBootstrapAppConfig;
|
|
283
|
+
config?: IIAMModuleConfig;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Async options
|
|
287
|
+
interface IAMModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'>, IDynamicModuleConfig {
|
|
288
|
+
bootstrapAppConfig?: IBootstrapAppConfig;
|
|
289
|
+
config?: IIAMModuleConfig;
|
|
290
|
+
useFactory?: (...args: any[]) => Promise<IIAMModuleConfig> | IIAMModuleConfig;
|
|
291
|
+
inject?: any[];
|
|
292
|
+
useClass?: Type<IAMOptionsFactory>;
|
|
293
|
+
useExisting?: Type<IAMOptionsFactory>;
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
201
299
|
## Entities
|
|
202
300
|
|
|
203
301
|
### Entity Groups
|
|
@@ -297,6 +395,17 @@ Core permission fields in `permission-base.entity.ts`:
|
|
|
297
395
|
| `reason` | text | Reason for permission |
|
|
298
396
|
| `metadata` | json | Additional data |
|
|
299
397
|
|
|
398
|
+
**Methods:**
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
// Check if permission is currently valid (date constraints)
|
|
402
|
+
isValid(now: Date = new Date()): boolean {
|
|
403
|
+
if (this.validFrom && now < this.validFrom) return false;
|
|
404
|
+
if (this.validUntil && now > this.validUntil) return false;
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
300
409
|
### UserIamPermissionWithCompany
|
|
301
410
|
|
|
302
411
|
Extends PermissionBase with:
|
|
@@ -403,10 +512,44 @@ const logic: LogicNode = {
|
|
|
403
512
|
| `ActionService` | REQUEST | Action CRUD, tree queries |
|
|
404
513
|
| `RoleService` | REQUEST | Role CRUD (RBAC/FULL mode only) |
|
|
405
514
|
| `PermissionService` | REQUEST | Permission assignments, my-permissions |
|
|
406
|
-
| `PermissionCacheService` |
|
|
515
|
+
| `PermissionCacheService` | SINGLETON | Cache management |
|
|
407
516
|
| `IAMConfigService` | SINGLETON | IAM configuration access |
|
|
408
517
|
| `IAMDataSourceService` | REQUEST | DataSource provider for multi-tenant |
|
|
409
518
|
|
|
519
|
+
### IAMConfigService
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
import { IAMConfigService } from '@flusys/nestjs-iam';
|
|
523
|
+
|
|
524
|
+
// Database mode
|
|
525
|
+
const dbMode = config.getDatabaseMode(); // 'single' | 'multi-tenant'
|
|
526
|
+
const isMultiTenant = config.isMultiTenant();
|
|
527
|
+
|
|
528
|
+
// Feature flags
|
|
529
|
+
const hasCompany = config.isCompanyFeatureEnabled();
|
|
530
|
+
|
|
531
|
+
// Permission mode
|
|
532
|
+
const mode = config.getPermissionMode(); // IAMPermissionMode enum
|
|
533
|
+
const isRbac = config.isRbacEnabled(); // true for RBAC or FULL
|
|
534
|
+
const isDirect = config.isDirectPermissionEnabled(); // true for DIRECT or FULL
|
|
535
|
+
|
|
536
|
+
// Get raw options
|
|
537
|
+
const options = config.getOptions();
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### IAMDataSourceService
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
import { IAMDataSourceService } from '@flusys/nestjs-iam';
|
|
544
|
+
|
|
545
|
+
// Get repository for entity
|
|
546
|
+
const actionRepo = await dataSourceProvider.getRepository(Action);
|
|
547
|
+
|
|
548
|
+
// Tenant-specific features
|
|
549
|
+
const enableCompany = dataSourceProvider.getEnableCompanyFeatureForCurrentTenant();
|
|
550
|
+
const entities = await dataSourceProvider.getIAMEntities();
|
|
551
|
+
```
|
|
552
|
+
|
|
410
553
|
### ActionService
|
|
411
554
|
|
|
412
555
|
```typescript
|
|
@@ -475,31 +618,74 @@ const permissions = await permissionService.getMyPermissions(
|
|
|
475
618
|
|
|
476
619
|
### PermissionCacheService
|
|
477
620
|
|
|
621
|
+
Centralized cache management for IAM permissions. Cache key format matches PermissionGuard in nestjs-shared.
|
|
622
|
+
|
|
623
|
+
**Cache TTLs:**
|
|
624
|
+
- Permissions: 1 hour (3600000ms)
|
|
625
|
+
- Action codes: 2 hours (7200000ms)
|
|
626
|
+
|
|
627
|
+
**Interfaces:**
|
|
628
|
+
|
|
629
|
+
```typescript
|
|
630
|
+
interface PermissionCacheKeyOptions {
|
|
631
|
+
userId: string;
|
|
632
|
+
companyId?: string | null;
|
|
633
|
+
branchId?: string | null;
|
|
634
|
+
enableCompanyFeature: boolean;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
interface CachedMyPermissions {
|
|
638
|
+
frontendActions: Array<{
|
|
639
|
+
id: string;
|
|
640
|
+
code: string;
|
|
641
|
+
name: string;
|
|
642
|
+
description: string | null;
|
|
643
|
+
parentId: string | null;
|
|
644
|
+
}>;
|
|
645
|
+
backendCodes: string[];
|
|
646
|
+
}
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
**Usage:**
|
|
650
|
+
|
|
478
651
|
```typescript
|
|
479
652
|
import { PermissionCacheService } from '@flusys/nestjs-iam';
|
|
480
653
|
|
|
481
|
-
// Set permissions
|
|
654
|
+
// Set permissions (backend codes for PermissionGuard)
|
|
482
655
|
await cacheService.setPermissions(
|
|
483
656
|
{ userId, companyId, branchId, enableCompanyFeature: true },
|
|
484
657
|
['users.read', 'users.write']
|
|
485
658
|
);
|
|
486
659
|
|
|
487
|
-
//
|
|
660
|
+
// Set my-permissions (full response with frontend actions)
|
|
661
|
+
await cacheService.setMyPermissions(cacheOptions, {
|
|
662
|
+
frontendActions: [...],
|
|
663
|
+
backendCodes: ['users.read', 'users.write'],
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
// Get cached my-permissions
|
|
667
|
+
const cached = await cacheService.getMyPermissions(cacheOptions);
|
|
668
|
+
|
|
669
|
+
// Invalidate single user cache
|
|
488
670
|
await cacheService.invalidateUser('user-id', 'company-id', ['branch-id']);
|
|
489
671
|
|
|
490
|
-
// Invalidate
|
|
491
|
-
await cacheService.
|
|
672
|
+
// Invalidate multiple users cache
|
|
673
|
+
await cacheService.invalidateUsers(userIds, 'company-id', branchIds);
|
|
674
|
+
|
|
675
|
+
// Invalidate role members (all users assigned to role)
|
|
676
|
+
await cacheService.invalidateRole('role-id', userIds, 'company-id', branchIds);
|
|
492
677
|
|
|
493
678
|
// Tenant-aware action code cache
|
|
494
679
|
await cacheService.setActionCodeMap(codeToIdMap, tenantId);
|
|
495
680
|
await cacheService.getActionIdsByCodes(['user.view'], tenantId);
|
|
496
|
-
await cacheService.invalidateActionCodeCache(tenantId);
|
|
497
681
|
```
|
|
498
682
|
|
|
499
683
|
**Cache Key Formats:**
|
|
500
684
|
```
|
|
501
685
|
permissions:user:{userId} // Without company
|
|
502
686
|
permissions:company:{companyId}:branch:{branchId}:user:{userId} // With company
|
|
687
|
+
my-permissions:user:{userId} // My-permissions (no company)
|
|
688
|
+
my-permissions:company:{companyId}:branch:{branchId}:user:{userId} // My-permissions (with company)
|
|
503
689
|
action-codes:map // Single tenant
|
|
504
690
|
action-codes:tenant:{tenantId}:map // Multi-tenant
|
|
505
691
|
```
|
|
@@ -555,39 +741,67 @@ validateCompanyAccess(
|
|
|
555
741
|
|
|
556
742
|
### Actions API
|
|
557
743
|
|
|
558
|
-
| Endpoint | Method | Description |
|
|
559
|
-
|
|
560
|
-
| `/iam/actions/insert` | POST | Create action |
|
|
561
|
-
| `/iam/actions/
|
|
562
|
-
| `/iam/actions/get
|
|
563
|
-
| `/iam/actions/
|
|
564
|
-
| `/iam/actions/tree
|
|
565
|
-
| `/iam/actions/
|
|
566
|
-
| `/iam/actions/
|
|
744
|
+
| Endpoint | Method | Permission | Description |
|
|
745
|
+
|----------|--------|------------|-------------|
|
|
746
|
+
| `/iam/actions/insert` | POST | `action.create` | Create action |
|
|
747
|
+
| `/iam/actions/insert-many` | POST | `action.create` | Create multiple actions |
|
|
748
|
+
| `/iam/actions/get-all` | POST | `action.read` | List actions (paginated) |
|
|
749
|
+
| `/iam/actions/get` | POST | `action.read` | Get action by ID |
|
|
750
|
+
| `/iam/actions/tree` | POST | JWT Auth | Get hierarchical tree (ALL actions) |
|
|
751
|
+
| `/iam/actions/tree-for-permission` | POST | JWT Auth | Get company-filtered actions |
|
|
752
|
+
| `/iam/actions/update` | POST | `action.update` | Update action |
|
|
753
|
+
| `/iam/actions/update-many` | POST | `action.update` | Update multiple actions |
|
|
754
|
+
| `/iam/actions/delete` | POST | `action.delete` | Delete action |
|
|
567
755
|
|
|
568
756
|
### Roles API (RBAC/FULL mode only)
|
|
569
757
|
|
|
570
|
-
| Endpoint | Method | Description |
|
|
571
|
-
|
|
572
|
-
| `/iam/roles/insert` | POST | Create role |
|
|
573
|
-
| `/iam/roles/
|
|
574
|
-
| `/iam/roles/get
|
|
575
|
-
| `/iam/roles/
|
|
576
|
-
| `/iam/roles/
|
|
758
|
+
| Endpoint | Method | Permission | Description |
|
|
759
|
+
|----------|--------|------------|-------------|
|
|
760
|
+
| `/iam/roles/insert` | POST | `role.create` | Create role |
|
|
761
|
+
| `/iam/roles/insert-many` | POST | `role.create` | Create multiple roles |
|
|
762
|
+
| `/iam/roles/get-all` | POST | `role.read` | List roles (paginated, auto-filtered by company) |
|
|
763
|
+
| `/iam/roles/get` | POST | `role.read` | Get role by ID |
|
|
764
|
+
| `/iam/roles/update` | POST | `role.update` | Update role |
|
|
765
|
+
| `/iam/roles/update-many` | POST | `role.update` | Update multiple roles |
|
|
766
|
+
| `/iam/roles/delete` | POST | `role.delete` | Delete role |
|
|
577
767
|
|
|
578
768
|
### Permissions API
|
|
579
769
|
|
|
580
|
-
| Endpoint | Method | Modes | Description |
|
|
581
|
-
|
|
582
|
-
| `/iam/permissions/role-actions/assign` | POST | RBAC, FULL | Assign actions to role |
|
|
583
|
-
| `/iam/permissions/role-actions
|
|
584
|
-
| `/iam/permissions/user-roles/assign` | POST | RBAC, FULL | Assign roles to user |
|
|
585
|
-
| `/iam/permissions/user-roles
|
|
586
|
-
| `/iam/permissions/user-actions/assign` | POST | DIRECT, FULL | Assign actions to user |
|
|
587
|
-
| `/iam/permissions/user-actions
|
|
588
|
-
| `/iam/permissions/company-actions/assign` | POST |
|
|
589
|
-
| `/iam/permissions/company-actions
|
|
590
|
-
| `/iam/permissions/my-permissions` | POST | All | Get current user's permissions |
|
|
770
|
+
| Endpoint | Method | Permission | Modes | Description |
|
|
771
|
+
|----------|--------|------------|-------|-------------|
|
|
772
|
+
| `/iam/permissions/role-actions/assign` | POST | `role-action.assign` | RBAC, FULL | Assign actions to role |
|
|
773
|
+
| `/iam/permissions/get-role-actions` | POST | `role-action.read` | RBAC, FULL | Get role actions |
|
|
774
|
+
| `/iam/permissions/user-roles/assign` | POST | `user-role.assign` | RBAC, FULL | Assign roles to user |
|
|
775
|
+
| `/iam/permissions/get-user-roles` | POST | `user-role.read` | RBAC, FULL | Get user roles |
|
|
776
|
+
| `/iam/permissions/user-actions/assign` | POST | `user-action.assign` | DIRECT, FULL | Assign actions to user |
|
|
777
|
+
| `/iam/permissions/get-user-actions` | POST | `user-action.read` | DIRECT, FULL | Get user actions |
|
|
778
|
+
| `/iam/permissions/company-actions/assign` | POST | `company-action.assign` | Company enabled | Company action whitelist |
|
|
779
|
+
| `/iam/permissions/get-company-actions` | POST | `company-action.read` | Company enabled | Get company actions |
|
|
780
|
+
| `/iam/permissions/my-permissions` | POST | JWT Auth | All | Get current user's permissions |
|
|
781
|
+
|
|
782
|
+
### Permission Constants
|
|
783
|
+
|
|
784
|
+
These permission codes are defined in `@flusys/nestjs-shared`:
|
|
785
|
+
|
|
786
|
+
```typescript
|
|
787
|
+
// Actions
|
|
788
|
+
ACTION_PERMISSIONS = { CREATE: 'action.create', READ: 'action.read', UPDATE: 'action.update', DELETE: 'action.delete' }
|
|
789
|
+
|
|
790
|
+
// Roles
|
|
791
|
+
ROLE_PERMISSIONS = { CREATE: 'role.create', READ: 'role.read', UPDATE: 'role.update', DELETE: 'role.delete' }
|
|
792
|
+
|
|
793
|
+
// Role-Action assignments
|
|
794
|
+
ROLE_ACTION_PERMISSIONS = { ASSIGN: 'role-action.assign', READ: 'role-action.read' }
|
|
795
|
+
|
|
796
|
+
// User-Role assignments
|
|
797
|
+
USER_ROLE_PERMISSIONS = { ASSIGN: 'user-role.assign', READ: 'user-role.read' }
|
|
798
|
+
|
|
799
|
+
// User-Action assignments (direct)
|
|
800
|
+
USER_ACTION_PERMISSIONS = { ASSIGN: 'user-action.assign', READ: 'user-action.read' }
|
|
801
|
+
|
|
802
|
+
// Company-Action assignments
|
|
803
|
+
COMPANY_ACTION_PERMISSIONS = { ASSIGN: 'company-action.assign', READ: 'company-action.read' }
|
|
804
|
+
```
|
|
591
805
|
|
|
592
806
|
**Controller Registration by Mode:**
|
|
593
807
|
|
|
@@ -596,6 +810,7 @@ validateCompanyAccess(
|
|
|
596
810
|
| DIRECT | ActionController, MyPermissionController, UserActionPermissionController |
|
|
597
811
|
| RBAC | ActionController, MyPermissionController, RoleController, RolePermissionController |
|
|
598
812
|
| FULL | All controllers |
|
|
813
|
+
| Company Enabled | + CompanyActionPermissionController |
|
|
599
814
|
|
|
600
815
|
---
|
|
601
816
|
|
|
@@ -654,17 +869,16 @@ When `getMyPermissions` is called:
|
|
|
654
869
|
## Permission Guard Integration
|
|
655
870
|
|
|
656
871
|
```typescript
|
|
657
|
-
import { PermissionGuard } from '@flusys/nestjs-shared/guards';
|
|
658
872
|
import { RequirePermission, RequireAnyPermission } from '@flusys/nestjs-shared/decorators';
|
|
659
873
|
|
|
660
874
|
@Controller('users')
|
|
661
875
|
export class UserController {
|
|
662
876
|
@RequirePermission('user.view')
|
|
663
|
-
@
|
|
877
|
+
@Post('get-all')
|
|
664
878
|
getUsers() {}
|
|
665
879
|
|
|
666
880
|
@RequireAnyPermission('user.create', 'admin')
|
|
667
|
-
@Post()
|
|
881
|
+
@Post('insert')
|
|
668
882
|
createUser() {}
|
|
669
883
|
}
|
|
670
884
|
```
|
|
@@ -710,6 +924,99 @@ Direct actions should be exceptions and branch-specific overrides, not the prima
|
|
|
710
924
|
|
|
711
925
|
---
|
|
712
926
|
|
|
927
|
+
## DTOs Reference
|
|
928
|
+
|
|
929
|
+
### Permission Operation DTOs
|
|
930
|
+
|
|
931
|
+
```typescript
|
|
932
|
+
// Permission action enum for add/remove operations
|
|
933
|
+
enum PermissionAction {
|
|
934
|
+
ADD = 'add',
|
|
935
|
+
REMOVE = 'remove',
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// Common item structure for permission assignments
|
|
939
|
+
interface PermissionItemDto {
|
|
940
|
+
id: string; // ID of target (action or role)
|
|
941
|
+
action: PermissionAction; // ADD or REMOVE
|
|
942
|
+
}
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
### Assignment DTOs
|
|
946
|
+
|
|
947
|
+
```typescript
|
|
948
|
+
// Assign actions directly to user
|
|
949
|
+
interface AssignUserActionsDto {
|
|
950
|
+
userId: string;
|
|
951
|
+
companyId?: string; // Company scope (when enabled)
|
|
952
|
+
branchId?: string; // Branch scope (null = company-wide)
|
|
953
|
+
items: PermissionItemDto[];
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// Assign roles to user
|
|
957
|
+
interface AssignUserRolesDto {
|
|
958
|
+
userId: string;
|
|
959
|
+
companyId?: string;
|
|
960
|
+
branchId?: string;
|
|
961
|
+
items: PermissionItemDto[];
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// Assign actions to role
|
|
965
|
+
interface AssignRoleActionsDto {
|
|
966
|
+
roleId: string;
|
|
967
|
+
items: PermissionItemDto[];
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// Assign actions to company (whitelist)
|
|
971
|
+
interface AssignCompanyActionsDto {
|
|
972
|
+
companyId: string;
|
|
973
|
+
items: PermissionItemDto[];
|
|
974
|
+
}
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
### Query DTOs
|
|
978
|
+
|
|
979
|
+
```typescript
|
|
980
|
+
// Query user's permissions (my-permissions)
|
|
981
|
+
interface MyPermissionsQueryDto {
|
|
982
|
+
parentCodes?: string[]; // Filter by parent action codes
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
// Query action tree
|
|
986
|
+
interface ActionTreeQueryDto {
|
|
987
|
+
search?: string; // Filter by name or code
|
|
988
|
+
isActive?: boolean; // Filter by active status
|
|
989
|
+
withDeleted?: boolean; // Include deleted actions
|
|
990
|
+
}
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
### Response DTOs
|
|
994
|
+
|
|
995
|
+
```typescript
|
|
996
|
+
// My-permissions response
|
|
997
|
+
interface MyPermissionsResponseDto {
|
|
998
|
+
frontendActions: FrontendActionDto[];
|
|
999
|
+
cachedEndpoints: number; // Count of backend codes cached
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
interface FrontendActionDto {
|
|
1003
|
+
id: string;
|
|
1004
|
+
code: string;
|
|
1005
|
+
name: string;
|
|
1006
|
+
description: string | null;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
// Permission operation result
|
|
1010
|
+
interface PermissionOperationResultDto {
|
|
1011
|
+
success: boolean;
|
|
1012
|
+
added: number;
|
|
1013
|
+
removed: number;
|
|
1014
|
+
message: string;
|
|
1015
|
+
}
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
---
|
|
1019
|
+
|
|
713
1020
|
## API Reference
|
|
714
1021
|
|
|
715
1022
|
### Exports
|
|
@@ -753,14 +1060,52 @@ export { LogicNode } from './types/logic-node.type';
|
|
|
753
1060
|
|
|
754
1061
|
// DTOs
|
|
755
1062
|
export * from './dtos';
|
|
1063
|
+
// Key DTOs:
|
|
1064
|
+
// - CreateActionDto, UpdateActionDto, ActionResponseDto, ActionTreeDto, ActionTreeQueryDto
|
|
1065
|
+
// - CreateRoleDto, UpdateRoleDto, RoleResponseDto
|
|
1066
|
+
// - PermissionAction (enum: ADD, REMOVE), PermissionItemDto
|
|
1067
|
+
// - AssignUserActionsDto, AssignRoleActionsDto, AssignUserRolesDto, AssignCompanyActionsDto
|
|
1068
|
+
// - GetUserActionsDto, GetRoleActionsDto, GetUserRolesDto, GetCompanyActionsDto
|
|
1069
|
+
// - UserActionResponseDto, RoleActionResponseDto, UserRoleResponseDto, CompanyActionResponseDto
|
|
1070
|
+
// - MyPermissionsQueryDto, MyPermissionsResponseDto, FrontendActionDto
|
|
1071
|
+
// - PermissionOperationResultDto
|
|
756
1072
|
|
|
757
1073
|
// Interfaces
|
|
758
1074
|
export * from './interfaces';
|
|
1075
|
+
// Key Interfaces:
|
|
1076
|
+
// - IAction, IActionTree (for action responses)
|
|
1077
|
+
// - IRole (for role responses)
|
|
1078
|
+
// - IIAMModuleConfig, IAMModuleOptions, IAMOptionsFactory, IAMModuleAsyncOptions
|
|
759
1079
|
|
|
760
1080
|
// Swagger Config
|
|
761
1081
|
export { iamSwaggerConfig } from './docs';
|
|
762
1082
|
```
|
|
763
1083
|
|
|
1084
|
+
### Swagger Configuration
|
|
1085
|
+
|
|
1086
|
+
```typescript
|
|
1087
|
+
import { iamSwaggerConfig } from '@flusys/nestjs-iam';
|
|
1088
|
+
|
|
1089
|
+
// Generate swagger config based on features
|
|
1090
|
+
const swaggerOptions = iamSwaggerConfig(
|
|
1091
|
+
enableCompanyFeature, // boolean
|
|
1092
|
+
permissionMode, // IAMPermissionMode
|
|
1093
|
+
);
|
|
1094
|
+
|
|
1095
|
+
// Returns IModuleSwaggerOptions with:
|
|
1096
|
+
// - title, description, version, path, bearerAuth
|
|
1097
|
+
// - excludeSchemaProperties (hides companyId/branchId when company disabled)
|
|
1098
|
+
// - excludeTags (hides unused controllers based on mode)
|
|
1099
|
+
// - excludeQueryParameters (hides unused query params)
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
The swagger config automatically:
|
|
1103
|
+
- Excludes Auth-related tags (Authentication, Users, Companies, etc.)
|
|
1104
|
+
- Hides Company Action endpoints when company feature is disabled
|
|
1105
|
+
- Hides RBAC endpoints (Roles, User-Roles) in DIRECT mode
|
|
1106
|
+
- Hides Direct endpoints (User-Actions) in RBAC mode
|
|
1107
|
+
- Shows appropriate documentation based on current configuration
|
|
1108
|
+
|
|
764
1109
|
### Module Static Methods
|
|
765
1110
|
|
|
766
1111
|
```typescript
|
|
@@ -828,4 +1173,4 @@ nestjs-iam/src/
|
|
|
828
1173
|
|
|
829
1174
|
---
|
|
830
1175
|
|
|
831
|
-
**Last Updated:** 2026-02-
|
|
1176
|
+
**Last Updated:** 2026-02-25
|
|
@@ -74,10 +74,10 @@ _ts_decorate([
|
|
|
74
74
|
], ActionBase.prototype, "code", void 0);
|
|
75
75
|
_ts_decorate([
|
|
76
76
|
(0, _typeorm.Column)({
|
|
77
|
-
type: '
|
|
78
|
-
|
|
77
|
+
type: 'varchar',
|
|
78
|
+
length: 50,
|
|
79
79
|
nullable: false,
|
|
80
|
-
default:
|
|
80
|
+
default: 'BACKEND',
|
|
81
81
|
name: 'action_type'
|
|
82
82
|
}),
|
|
83
83
|
_ts_metadata("design:type", typeof _enums.ActionType === "undefined" ? Object : _enums.ActionType)
|
|
@@ -69,16 +69,16 @@ let PermissionBase = class PermissionBase extends _nestjsshared.Identity {
|
|
|
69
69
|
};
|
|
70
70
|
_ts_decorate([
|
|
71
71
|
(0, _typeorm.Column)({
|
|
72
|
-
type: '
|
|
73
|
-
|
|
72
|
+
type: 'varchar',
|
|
73
|
+
length: 50,
|
|
74
74
|
name: 'permission_type'
|
|
75
75
|
}),
|
|
76
76
|
_ts_metadata("design:type", String)
|
|
77
77
|
], PermissionBase.prototype, "permissionType", void 0);
|
|
78
78
|
_ts_decorate([
|
|
79
79
|
(0, _typeorm.Column)({
|
|
80
|
-
type: '
|
|
81
|
-
|
|
80
|
+
type: 'varchar',
|
|
81
|
+
length: 50,
|
|
82
82
|
name: 'source_type'
|
|
83
83
|
}),
|
|
84
84
|
_ts_metadata("design:type", String)
|
|
@@ -92,8 +92,8 @@ _ts_decorate([
|
|
|
92
92
|
], PermissionBase.prototype, "sourceId", void 0);
|
|
93
93
|
_ts_decorate([
|
|
94
94
|
(0, _typeorm.Column)({
|
|
95
|
-
type: '
|
|
96
|
-
|
|
95
|
+
type: 'varchar',
|
|
96
|
+
length: 50,
|
|
97
97
|
name: 'target_type'
|
|
98
98
|
}),
|
|
99
99
|
_ts_metadata("design:type", String)
|
|
@@ -12,10 +12,10 @@ export declare enum IamEntityType {
|
|
|
12
12
|
COMPANY = "company"
|
|
13
13
|
}
|
|
14
14
|
export declare abstract class PermissionBase extends Identity {
|
|
15
|
-
permissionType:
|
|
16
|
-
sourceType:
|
|
15
|
+
permissionType: string;
|
|
16
|
+
sourceType: string;
|
|
17
17
|
sourceId: string;
|
|
18
|
-
targetType:
|
|
18
|
+
targetType: string;
|
|
19
19
|
targetId: string;
|
|
20
20
|
userId: string | null;
|
|
21
21
|
validFrom: Date | null;
|
|
@@ -67,10 +67,10 @@ _ts_decorate([
|
|
|
67
67
|
], ActionBase.prototype, "code", void 0);
|
|
68
68
|
_ts_decorate([
|
|
69
69
|
Column({
|
|
70
|
-
type: '
|
|
71
|
-
|
|
70
|
+
type: 'varchar',
|
|
71
|
+
length: 50,
|
|
72
72
|
nullable: false,
|
|
73
|
-
default:
|
|
73
|
+
default: 'BACKEND',
|
|
74
74
|
name: 'action_type'
|
|
75
75
|
}),
|
|
76
76
|
_ts_metadata("design:type", typeof ActionType === "undefined" ? Object : ActionType)
|
|
@@ -51,16 +51,16 @@ export var IamEntityType = /*#__PURE__*/ function(IamEntityType) {
|
|
|
51
51
|
}
|
|
52
52
|
_ts_decorate([
|
|
53
53
|
Column({
|
|
54
|
-
type: '
|
|
55
|
-
|
|
54
|
+
type: 'varchar',
|
|
55
|
+
length: 50,
|
|
56
56
|
name: 'permission_type'
|
|
57
57
|
}),
|
|
58
58
|
_ts_metadata("design:type", String)
|
|
59
59
|
], PermissionBase.prototype, "permissionType", void 0);
|
|
60
60
|
_ts_decorate([
|
|
61
61
|
Column({
|
|
62
|
-
type: '
|
|
63
|
-
|
|
62
|
+
type: 'varchar',
|
|
63
|
+
length: 50,
|
|
64
64
|
name: 'source_type'
|
|
65
65
|
}),
|
|
66
66
|
_ts_metadata("design:type", String)
|
|
@@ -74,8 +74,8 @@ _ts_decorate([
|
|
|
74
74
|
], PermissionBase.prototype, "sourceId", void 0);
|
|
75
75
|
_ts_decorate([
|
|
76
76
|
Column({
|
|
77
|
-
type: '
|
|
78
|
-
|
|
77
|
+
type: 'varchar',
|
|
78
|
+
length: 50,
|
|
79
79
|
name: 'target_type'
|
|
80
80
|
}),
|
|
81
81
|
_ts_metadata("design:type", String)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flusys/nestjs-iam",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Identity and Access Management (IAM) module for NestJS applications",
|
|
5
5
|
"main": "cjs/index.js",
|
|
6
6
|
"module": "fesm/index.js",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"typeorm": "^0.3.0"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@flusys/nestjs-core": "
|
|
93
|
-
"@flusys/nestjs-shared": "
|
|
92
|
+
"@flusys/nestjs-core": "3.0.0",
|
|
93
|
+
"@flusys/nestjs-shared": "3.0.0"
|
|
94
94
|
}
|
|
95
95
|
}
|