@flusys/nestjs-iam 6.1.0 → 6.1.1

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 (39) hide show
  1. package/cjs/controllers/company-action-permission.controller.js +1 -1
  2. package/cjs/controllers/company-action-permission.controller.spec.js +1 -1
  3. package/cjs/controllers/user-action-permission.controller.js +1 -1
  4. package/cjs/controllers/user-action-permission.controller.spec.js +1 -1
  5. package/cjs/dtos/permission.dto.js +7 -0
  6. package/cjs/entities/permission-base.entity.js +1 -10
  7. package/cjs/entities/permission-with-company.entity.js +0 -3
  8. package/cjs/entities/user-iam-permission.entity.js +0 -3
  9. package/cjs/modules/iam.module.js +2 -2
  10. package/cjs/services/action.service.js +4 -4
  11. package/cjs/services/action.service.spec.js +11 -11
  12. package/cjs/services/permission-cache.service.js +363 -52
  13. package/cjs/services/permission-cache.service.spec.js +462 -15
  14. package/cjs/services/permission.service.js +92 -396
  15. package/cjs/services/permission.service.spec.js +35 -310
  16. package/cjs/services/role.service.js +1 -1
  17. package/cjs/services/role.service.spec.js +4 -7
  18. package/dtos/permission.dto.d.ts +1 -0
  19. package/entities/permission-base.entity.d.ts +0 -1
  20. package/fesm/controllers/company-action-permission.controller.js +1 -1
  21. package/fesm/controllers/company-action-permission.controller.spec.js +1 -1
  22. package/fesm/controllers/user-action-permission.controller.js +1 -1
  23. package/fesm/controllers/user-action-permission.controller.spec.js +1 -1
  24. package/fesm/dtos/permission.dto.js +7 -0
  25. package/fesm/entities/permission-base.entity.js +1 -10
  26. package/fesm/entities/permission-with-company.entity.js +0 -3
  27. package/fesm/entities/user-iam-permission.entity.js +0 -3
  28. package/fesm/modules/iam.module.js +4 -4
  29. package/fesm/services/action.service.js +4 -4
  30. package/fesm/services/action.service.spec.js +11 -11
  31. package/fesm/services/permission-cache.service.js +365 -51
  32. package/fesm/services/permission-cache.service.spec.js +462 -15
  33. package/fesm/services/permission.service.js +92 -396
  34. package/fesm/services/permission.service.spec.js +35 -310
  35. package/fesm/services/role.service.js +1 -1
  36. package/fesm/services/role.service.spec.js +4 -7
  37. package/package.json +3 -3
  38. package/services/permission-cache.service.d.ts +20 -3
  39. package/services/permission.service.d.ts +2 -16
@@ -21,7 +21,6 @@ function buildPermissionRow(overrides = {}) {
21
21
  sourceId: 'user-1',
22
22
  targetType: IamEntityType.ACTION,
23
23
  targetId: 'action-1',
24
- userId: 'user-1',
25
24
  companyId: null,
26
25
  branchId: null,
27
26
  validFrom: null,
@@ -95,8 +94,9 @@ describe('PermissionService', ()=>{
95
94
  mockPermissionCacheService = {
96
95
  invalidateUser: jest.fn(),
97
96
  invalidateUsers: jest.fn(),
98
- getMyPermissions: jest.fn(),
99
- setMyPermissions: jest.fn()
97
+ invalidateRoleMembersCache: jest.fn(),
98
+ invalidateCompanyMembersCache: jest.fn(),
99
+ getMyPermissionsResponse: jest.fn()
100
100
  };
101
101
  const module = await Test.createTestingModule({
102
102
  providers: [
@@ -168,9 +168,7 @@ describe('PermissionService', ()=>{
168
168
  removed: 1,
169
169
  total: 3
170
170
  });
171
- expect(mockPermissionCacheService.invalidateUser).toHaveBeenCalledWith('user-1', null, [
172
- null
173
- ]);
171
+ expect(mockPermissionCacheService.invalidateUser).toHaveBeenCalledWith('user-1', null, []);
174
172
  });
175
173
  it('scopes new permissions and cache invalidation to the company/branch when the company feature is enabled', async ()=>{
176
174
  mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
@@ -241,7 +239,7 @@ describe('PermissionService', ()=>{
241
239
  describe('getUserActions', ()=>{
242
240
  it('returns an empty array without querying actions when the user has no permissions', async ()=>{
243
241
  mockPermissionRepo.find.mockResolvedValue([]);
244
- const result = await service.getUserActions('user-1', undefined);
242
+ const result = await service.getUserActions('user-1', undefined, undefined);
245
243
  expect(result).toEqual([]);
246
244
  expect(mockActionRepo.find).not.toHaveBeenCalled();
247
245
  });
@@ -260,7 +258,7 @@ describe('PermissionService', ()=>{
260
258
  id: 'action-1'
261
259
  })
262
260
  ]);
263
- const result = await service.getUserActions('user-1', undefined);
261
+ const result = await service.getUserActions('user-1', undefined, undefined);
264
262
  expect(result).toHaveLength(1);
265
263
  expect(result[0]).toEqual(expect.objectContaining({
266
264
  actionId: 'action-1',
@@ -270,7 +268,7 @@ describe('PermissionService', ()=>{
270
268
  it('filters by companyId/branchId when the company feature is enabled', async ()=>{
271
269
  mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
272
270
  mockPermissionRepo.find.mockResolvedValue([]);
273
- await service.getUserActions('user-1', 'branch-1', 'company-1');
271
+ await service.getUserActions('user-1', 'company-1', 'branch-1');
274
272
  expect(mockPermissionRepo.find).toHaveBeenCalledWith({
275
273
  where: expect.objectContaining({
276
274
  companyId: 'company-1',
@@ -332,31 +330,18 @@ describe('PermissionService', ()=>{
332
330
  });
333
331
  });
334
332
  it('removes role actions and reports counts and invalidates role member caches', async ()=>{
335
- mockPermissionRepo.find.mockResolvedValueOnce([]) // existing check for add
336
- .mockResolvedValueOnce([
337
- buildPermissionRow({
338
- sourceId: 'user-9'
339
- })
340
- ]); // invalidateRoleMembersCache lookup (sourceId = the user who holds the role)
333
+ mockPermissionRepo.find.mockResolvedValue([]); // existing check for add
341
334
  mockPermissionRepo.save.mockResolvedValue([
342
335
  {}
343
336
  ]);
344
337
  mockPermissionRepo.delete.mockResolvedValue(buildDeleteResult(1));
345
- mockRoleRepo.findOne.mockResolvedValue({
346
- id: 'role-1',
347
- companyId: null
348
- });
349
338
  const result = await service.assignRoleActions(dto);
350
339
  expect(result).toEqual({
351
340
  added: 1,
352
341
  removed: 1,
353
342
  total: 2
354
343
  });
355
- expect(mockPermissionCacheService.invalidateUsers).toHaveBeenCalledWith([
356
- 'user-9'
357
- ], null, [
358
- null
359
- ]);
344
+ expect(mockPermissionCacheService.invalidateRoleMembersCache).toHaveBeenCalledWith('role-1');
360
345
  });
361
346
  });
362
347
  describe('getRoleActions', ()=>{
@@ -395,7 +380,9 @@ describe('PermissionService', ()=>{
395
380
  return mockPermissionRepo;
396
381
  })
397
382
  };
398
- mockPermissionRepo.manager.connection.transaction = jest.fn().mockImplementation((cb)=>cb(fakeManager));
383
+ mockDataSourceProvider.getDataSource.mockResolvedValue({
384
+ transaction: jest.fn().mockImplementation((cb)=>cb(fakeManager))
385
+ });
399
386
  return fakeManager;
400
387
  }
401
388
  it('adds new company-whitelisted actions inside a transaction, skipping duplicates', async ()=>{
@@ -429,7 +416,7 @@ describe('PermissionService', ()=>{
429
416
  })
430
417
  ]);
431
418
  expect(result.added).toBe(1);
432
- expect(mockPermissionCacheService.invalidateUsers).not.toHaveBeenCalled(); // no company feature -> invalidateCompanyMembersCache no-ops
419
+ expect(mockPermissionCacheService.invalidateCompanyMembersCache).toHaveBeenCalledWith('company-1');
433
420
  });
434
421
  it('cascades removal to role-action and user-action permissions for the company', async ()=>{
435
422
  mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
@@ -497,7 +484,7 @@ describe('PermissionService', ()=>{
497
484
  targetId: 'action-2'
498
485
  }
499
486
  ]);
500
- const result = await service.getCompanyActionIds('company-1');
487
+ const result = await service.getCompanyActions('company-1', true);
501
488
  expect(result).toEqual([
502
489
  'action-1',
503
490
  'action-2'
@@ -584,287 +571,26 @@ describe('PermissionService', ()=>{
584
571
  });
585
572
  // ==================== My Permissions / permission-mode branching ====================
586
573
  describe('getMyPermissions', ()=>{
587
- it('returns the response built directly from cached data on a cache hit', async ()=>{
588
- mockPermissionCacheService.getMyPermissions.mockResolvedValue({
574
+ it('delegates to the cache service and returns its response', async ()=>{
575
+ const response = {
589
576
  frontendActions: [
590
577
  {
591
578
  id: 'action-1',
592
579
  code: 'user.view',
593
580
  name: 'View',
594
- description: null,
595
- parentId: null
596
- }
597
- ],
598
- backendCodes: [
599
- 'user.read'
600
- ]
601
- });
602
- const result = await service.getMyPermissions('user-1', null, 'company-1');
603
- expect(result.frontendActions).toHaveLength(1);
604
- expect(result.cachedEndpoints).toBe(1);
605
- expect(mockPermissionRepo.find).not.toHaveBeenCalled();
606
- });
607
- it('fetches from the database and caches the result on a cache miss', async ()=>{
608
- mockPermissionCacheService.getMyPermissions.mockResolvedValue(null);
609
- mockPermissionRepo.find.mockResolvedValue([]);
610
- const result = await service.getMyPermissions('user-1', null, null);
611
- expect(result).toEqual({
612
- frontendActions: [],
613
- cachedEndpoints: 0
614
- });
615
- expect(mockPermissionCacheService.setMyPermissions).toHaveBeenCalled();
616
- });
617
- it('filters frontend actions by parentCodes when provided', async ()=>{
618
- mockPermissionCacheService.getMyPermissions.mockResolvedValue({
619
- frontendActions: [
620
- {
621
- id: 'child-1',
622
- code: 'user.view',
623
- name: 'View',
624
- description: null,
625
- parentId: 'parent-1'
626
- },
627
- {
628
- id: 'child-2',
629
- code: 'other.view',
630
- name: 'View 2',
631
- description: null,
632
- parentId: 'other-parent'
581
+ description: null
633
582
  }
634
583
  ],
635
- backendCodes: []
636
- });
637
- mockActionRepo.find.mockResolvedValue([
638
- {
639
- id: 'parent-1',
640
- code: 'user'
641
- }
642
- ]);
643
- const result = await service.getMyPermissions('user-1', null, null, [
644
- 'user'
645
- ]);
646
- expect(result.frontendActions).toHaveLength(1);
647
- expect(result.frontendActions[0].id).toBe('child-1');
648
- });
649
- it('returns an empty frontendActions list when parentCodes resolve to no known parents', async ()=>{
650
- mockPermissionCacheService.getMyPermissions.mockResolvedValue({
651
- frontendActions: [
652
- {
653
- id: 'child-1',
654
- code: 'user.view',
655
- name: 'View',
656
- description: null,
657
- parentId: 'parent-1'
658
- }
659
- ],
660
- backendCodes: []
661
- });
662
- mockActionRepo.find.mockResolvedValue([]);
663
- const result = await service.getMyPermissions('user-1', null, null, [
664
- 'unknown-parent-code'
665
- ]);
666
- expect(result.frontendActions).toEqual([]);
667
- });
668
- });
669
- describe('collectAllActionIds (permission-mode branching)', ()=>{
670
- it('RBAC mode: collects only role-derived action ids, ignoring direct user actions', async ()=>{
671
- mockIamConfigService.getPermissionMode.mockReturnValue(IAMPermissionMode.RBAC);
672
- mockPermissionRepo.find.mockImplementation(async ({ where })=>{
673
- if (where.permissionType === IamPermissionType.USER_ROLE) {
674
- return [
675
- buildPermissionRow({
676
- permissionType: IamPermissionType.USER_ROLE,
677
- targetId: 'role-1'
678
- })
679
- ];
680
- }
681
- if (where.permissionType === IamPermissionType.ROLE_ACTION) {
682
- return [
683
- buildPermissionRow({
684
- permissionType: IamPermissionType.ROLE_ACTION,
685
- targetId: 'action-role-1'
686
- })
687
- ];
688
- }
689
- if (where.permissionType === IamPermissionType.USER_ACTION) {
690
- throw new Error('DIRECT lookup should not run in RBAC mode');
691
- }
692
- return [];
693
- });
694
- const result = await service.collectAllActionIds('user-1', null, null);
695
- expect(Array.from(result)).toEqual([
696
- 'action-role-1'
697
- ]);
698
- });
699
- it('DIRECT mode: collects only directly-assigned user action ids, ignoring roles', async ()=>{
700
- mockIamConfigService.getPermissionMode.mockReturnValue(IAMPermissionMode.DIRECT);
701
- mockPermissionRepo.find.mockImplementation(async ({ where })=>{
702
- if (where.permissionType === IamPermissionType.USER_ROLE) {
703
- throw new Error('RBAC lookup should not run in DIRECT mode');
704
- }
705
- if (where.permissionType === IamPermissionType.USER_ACTION) {
706
- return [
707
- buildPermissionRow({
708
- permissionType: IamPermissionType.USER_ACTION,
709
- targetId: 'action-direct-1'
710
- })
711
- ];
712
- }
713
- return [];
714
- });
715
- const result = await service.collectAllActionIds('user-1', null, null);
716
- expect(Array.from(result)).toEqual([
717
- 'action-direct-1'
718
- ]);
719
- });
720
- it('FULL mode: merges role-derived and direct action ids, de-duplicating overlaps', async ()=>{
721
- mockIamConfigService.getPermissionMode.mockReturnValue(IAMPermissionMode.FULL);
722
- mockPermissionRepo.find.mockImplementation(async ({ where })=>{
723
- if (where.permissionType === IamPermissionType.USER_ROLE) {
724
- return [
725
- buildPermissionRow({
726
- permissionType: IamPermissionType.USER_ROLE,
727
- targetId: 'role-1'
728
- })
729
- ];
730
- }
731
- if (where.permissionType === IamPermissionType.ROLE_ACTION) {
732
- return [
733
- buildPermissionRow({
734
- permissionType: IamPermissionType.ROLE_ACTION,
735
- targetId: 'action-shared'
736
- })
737
- ];
738
- }
739
- if (where.permissionType === IamPermissionType.USER_ACTION) {
740
- return [
741
- buildPermissionRow({
742
- permissionType: IamPermissionType.USER_ACTION,
743
- targetId: 'action-shared'
744
- }),
745
- buildPermissionRow({
746
- permissionType: IamPermissionType.USER_ACTION,
747
- targetId: 'action-direct-only'
748
- })
749
- ];
750
- }
751
- return [];
752
- });
753
- const result = await service.collectAllActionIds('user-1', null, null);
754
- expect(Array.from(result).sort()).toEqual([
755
- 'action-direct-only',
756
- 'action-shared'
757
- ]);
758
- });
759
- it('excludes expired/not-yet-valid permission rows via isValid()', async ()=>{
760
- mockIamConfigService.getPermissionMode.mockReturnValue(IAMPermissionMode.DIRECT);
761
- const expired = buildPermissionRow({
762
- permissionType: IamPermissionType.USER_ACTION,
763
- targetId: 'action-expired',
764
- validUntil: new Date('2000-01-01')
765
- });
766
- const active = buildPermissionRow({
767
- permissionType: IamPermissionType.USER_ACTION,
768
- targetId: 'action-active'
769
- });
770
- mockPermissionRepo.find.mockResolvedValue([
771
- expired,
772
- active
773
- ]);
774
- const result = await service.collectAllActionIds('user-1', null, null);
775
- expect(Array.from(result)).toEqual([
776
- 'action-active'
777
- ]);
778
- });
779
- });
780
- describe('applyCompanyWhitelist', ()=>{
781
- it('is a no-op when the company feature is disabled', async ()=>{
782
- const actionIds = new Set([
783
- 'action-1',
784
- 'action-2'
785
- ]);
786
- await service.applyCompanyWhitelist(actionIds, 'company-1');
787
- expect(actionIds).toEqual(new Set([
788
- 'action-1',
789
- 'action-2'
790
- ]));
791
- expect(mockPermissionRepo.find).not.toHaveBeenCalled();
792
- });
793
- it('is a no-op when companyId is missing even if the company feature is enabled', async ()=>{
794
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
795
- const actionIds = new Set([
796
- 'action-1'
797
- ]);
798
- await service.applyCompanyWhitelist(actionIds, null);
799
- expect(actionIds).toEqual(new Set([
800
- 'action-1'
801
- ]));
802
- });
803
- it('does not filter anything when the company has an empty whitelist', async ()=>{
804
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
805
- mockPermissionRepo.find.mockResolvedValue([]);
806
- const actionIds = new Set([
807
- 'action-1',
808
- 'action-2'
809
- ]);
810
- await service.applyCompanyWhitelist(actionIds, 'company-1');
811
- expect(actionIds).toEqual(new Set([
812
- 'action-1',
813
- 'action-2'
814
- ]));
815
- });
816
- it('removes action ids that are not present in the company whitelist', async ()=>{
817
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
818
- mockPermissionRepo.find.mockResolvedValue([
819
- {
820
- targetId: 'action-1'
821
- }
822
- ]);
823
- const actionIds = new Set([
824
- 'action-1',
825
- 'action-2'
826
- ]);
827
- await service.applyCompanyWhitelist(actionIds, 'company-1');
828
- expect(actionIds).toEqual(new Set([
829
- 'action-1'
830
- ]));
831
- });
832
- });
833
- // ==================== Cache invalidation helpers ====================
834
- describe('invalidateCompanyMembersCache', ()=>{
835
- it('returns 0 without querying when the company feature is disabled', async ()=>{
836
- const result = await service.invalidateCompanyMembersCache('company-1');
837
- expect(result).toBe(0);
838
- expect(mockPermissionRepo.createQueryBuilder).not.toHaveBeenCalled();
839
- });
840
- it('returns 0 when the company has no members with permissions', async ()=>{
841
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
842
- mockRawMany(mockPermissionRepo, []);
843
- const result = await service.invalidateCompanyMembersCache('company-1');
844
- expect(result).toBe(0);
845
- });
846
- it('invalidates every distinct member user id for the company', async ()=>{
847
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
848
- mockRawMany(mockPermissionRepo, [
849
- {
850
- userId: 'user-1',
851
- branchId: 'branch-1'
852
- },
853
- {
854
- userId: 'user-2',
855
- branchId: null
856
- }
584
+ cachedEndpoints: 1
585
+ };
586
+ mockPermissionCacheService.getMyPermissionsResponse.mockResolvedValue(response);
587
+ const result = await service.getMyPermissions('user-1', null, 'company-1', [
588
+ 'parent-code'
857
589
  ]);
858
- mockPermissionCacheService.invalidateUsers.mockResolvedValue(2);
859
- const result = await service.invalidateCompanyMembersCache('company-1');
860
- expect(mockPermissionCacheService.invalidateUsers).toHaveBeenCalledWith([
861
- 'user-1',
862
- 'user-2'
863
- ], 'company-1', [
864
- 'branch-1',
865
- null
590
+ expect(mockPermissionCacheService.getMyPermissionsResponse).toHaveBeenCalledWith('user-1', null, 'company-1', [
591
+ 'parent-code'
866
592
  ]);
867
- expect(result).toBe(2);
593
+ expect(result).toBe(response);
868
594
  });
869
595
  });
870
596
  describe('revokeCompanyPermissions', ()=>{
@@ -882,10 +608,7 @@ describe('PermissionService', ()=>{
882
608
  ]);
883
609
  mockPermissionRepo.find.mockResolvedValue([
884
610
  {
885
- userId: 'user-1'
886
- },
887
- {
888
- userId: null
611
+ sourceId: 'user-1'
889
612
  }
890
613
  ]);
891
614
  const fakeTxRepo = {
@@ -894,12 +617,14 @@ describe('PermissionService', ()=>{
894
617
  const fakeTxRoleRepo = {
895
618
  delete: jest.fn().mockResolvedValue(buildDeleteResult(1))
896
619
  };
897
- mockPermissionRepo.manager.connection.transaction = jest.fn().mockImplementation((cb)=>cb({
898
- getRepository: jest.fn((target)=>{
899
- if (target === mockRoleRepo.target) return fakeTxRoleRepo;
900
- return fakeTxRepo;
901
- })
902
- }));
620
+ mockDataSourceProvider.getDataSource.mockResolvedValue({
621
+ transaction: jest.fn().mockImplementation((cb)=>cb({
622
+ getRepository: jest.fn((target)=>{
623
+ if (target === mockRoleRepo.target) return fakeTxRoleRepo;
624
+ return fakeTxRepo;
625
+ })
626
+ }))
627
+ });
903
628
  await service.revokeCompanyPermissions('company-1');
904
629
  expect(fakeTxRepo.delete).toHaveBeenCalledWith(expect.objectContaining({
905
630
  permissionType: IamPermissionType.COMPANY_ACTION
@@ -921,7 +646,7 @@ describe('PermissionService', ()=>{
921
646
  mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
922
647
  mockPermissionRepo.find.mockResolvedValue([
923
648
  {
924
- userId: 'user-1'
649
+ sourceId: 'user-1'
925
650
  }
926
651
  ]);
927
652
  mockPermissionRepo.delete.mockResolvedValue(buildDeleteResult(1));
@@ -60,7 +60,7 @@ export class RoleService extends ApiService {
60
60
  }
61
61
  });
62
62
  const affectedUserIds = [
63
- ...new Set(userRoleRows.map((row)=>row.userId).filter((id)=>!!id))
63
+ ...new Set(userRoleRows.map((row)=>row.sourceId))
64
64
  ];
65
65
  await permissionRepo.delete({
66
66
  permissionType: IamPermissionType.ROLE_ACTION,
@@ -243,13 +243,10 @@ describe('RoleService', ()=>{
243
243
  const permissionRepo = createMockRepository();
244
244
  permissionRepo.find.mockResolvedValue([
245
245
  {
246
- userId: 'user-1'
246
+ sourceId: 'user-1'
247
247
  },
248
248
  {
249
- userId: 'user-2'
250
- },
251
- {
252
- userId: null
249
+ sourceId: 'user-2'
253
250
  }
254
251
  ]);
255
252
  const queryRunner = buildQueryRunner(permissionRepo);
@@ -286,10 +283,10 @@ describe('RoleService', ()=>{
286
283
  const permissionRepo = createMockRepository();
287
284
  permissionRepo.find.mockResolvedValue([
288
285
  {
289
- userId: 'user-1'
286
+ sourceId: 'user-1'
290
287
  },
291
288
  {
292
- userId: 'user-1'
289
+ sourceId: 'user-1'
293
290
  }
294
291
  ]);
295
292
  const queryRunner = buildQueryRunner(permissionRepo);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flusys/nestjs-iam",
3
- "version": "6.1.0",
3
+ "version": "6.1.1",
4
4
  "description": "Identity and Access Management (IAM) module for NestJS applications",
5
5
  "main": "cjs/index.js",
6
6
  "module": "fesm/index.js",
@@ -90,7 +90,7 @@
90
90
  "express": "^5.0.0"
91
91
  },
92
92
  "dependencies": {
93
- "@flusys/nestjs-core": "6.1.0",
94
- "@flusys/nestjs-shared": "6.1.0"
93
+ "@flusys/nestjs-core": "6.1.1",
94
+ "@flusys/nestjs-shared": "6.1.1"
95
95
  }
96
96
  }
@@ -1,4 +1,7 @@
1
1
  import { HybridCache, PermissionCacheKeyOptions, PermissionGuardConfig } from '@flusys/nestjs-shared';
2
+ import { MyPermissionsResponseDto } from '../dtos/permission.dto';
3
+ import { IAMConfigService } from './iam-config.service';
4
+ import { IAMDataSourceService } from './iam-datasource.service';
2
5
  export { PermissionCacheKeyOptions } from '@flusys/nestjs-shared';
3
6
  export interface CachedMyPermissions {
4
7
  frontendActions: Array<{
@@ -10,14 +13,18 @@ export interface CachedMyPermissions {
10
13
  }>;
11
14
  backendCodes: string[];
12
15
  }
13
- export declare const MY_PERMISSIONS_CACHE_PREFIX = "my-permissions";
14
16
  export declare class PermissionCacheService {
15
17
  private readonly cacheManager;
18
+ private readonly iamConfigService;
19
+ private readonly dataSourceProvider;
16
20
  private readonly guardConfig?;
17
21
  private readonly TRACKED_KEYS_PREFIX;
18
22
  private readonly TRACKED_SCOPES_PREFIX;
19
23
  private readonly TTL;
20
- constructor(cacheManager: HybridCache, guardConfig?: PermissionGuardConfig | undefined);
24
+ constructor(cacheManager: HybridCache, iamConfigService: IAMConfigService, dataSourceProvider: IAMDataSourceService, guardConfig?: PermissionGuardConfig | undefined);
25
+ private getPermissionRepository;
26
+ private getActionRepository;
27
+ private getRoleRepository;
21
28
  private parseDurationMs;
22
29
  private buildCacheKey;
23
30
  private scopeToken;
@@ -26,7 +33,17 @@ export declare class PermissionCacheService {
26
33
  setMyPermissions(options: PermissionCacheKeyOptions, data: CachedMyPermissions): Promise<void>;
27
34
  getMyPermissions(options: PermissionCacheKeyOptions): Promise<CachedMyPermissions | null>;
28
35
  private trackKey;
36
+ getMyPermissionsResponse(userId: string, branchId: string | null, companyId?: string | null, parentCodes?: string[]): Promise<MyPermissionsResponseDto>;
37
+ private buildResponseFromCache;
38
+ private getParentIdsByCodesWithCache;
39
+ private fetchAndCachePermissions;
40
+ private collectAllActionIds;
41
+ private buildAndCachePermissionData;
42
+ private getUserRoleIds;
43
+ private getRoleActionIds;
44
+ private getUserActionIds;
29
45
  invalidateUser(userId: string, companyId?: string | null, branchIds?: (string | null)[]): Promise<void>;
30
- private invalidateScope;
31
46
  invalidateUsers(userIds: string[], companyId?: string | null, branchIds?: (string | null)[]): Promise<number>;
47
+ invalidateRoleMembersCache(roleId: string): Promise<number>;
48
+ invalidateCompanyMembersCache(companyId: string): Promise<number>;
32
49
  }
@@ -12,30 +12,16 @@ export declare class PermissionService {
12
12
  private getRoleRepository;
13
13
  private getActionsMap;
14
14
  assignUserActions(dto: AssignUserActionsDto): Promise<PermissionOperationResultDto>;
15
- getUserActions(userId: string, branchId: string | undefined, companyId?: string | undefined): Promise<UserActionResponseDto[]>;
15
+ getUserActions(userId: string, companyId: string | undefined, branchId: string | undefined): Promise<UserActionResponseDto[]>;
16
16
  assignRoleActions(dto: AssignRoleActionsDto): Promise<PermissionOperationResultDto>;
17
17
  getRoleActions(roleId: string): Promise<RoleActionResponseDto[]>;
18
18
  assignCompanyActions(dto: AssignCompanyActionsDto): Promise<PermissionOperationResultDto>;
19
- private addCompanyActions;
20
- private removeCompanyActionsWithCascade;
21
- getCompanyActions(companyId: string): Promise<CompanyActionResponseDto[]>;
22
- getCompanyActionIds(companyId: string): Promise<string[]>;
19
+ getCompanyActions(companyId: string, isOnlyId?: boolean): Promise<CompanyActionResponseDto[] | string[]>;
23
20
  assignUserRoles(dto: AssignUserRolesDto): Promise<PermissionOperationResultDto>;
24
21
  getUserRoles(userId: string, branchId?: string | undefined, companyId?: string | undefined): Promise<UserRoleResponseDto[]>;
25
22
  getMyPermissions(userId: string, branchId: string | null, companyId?: string | null, parentCodes?: string[]): Promise<MyPermissionsResponseDto>;
26
- private buildResponseFromCache;
27
- private getParentIdsByCodesWithCache;
28
- private fetchAndCachePermissions;
29
- private collectAllActionIds;
30
- private applyCompanyWhitelist;
31
- private buildAndCachePermissionData;
32
23
  private splitItemsByAction;
33
24
  private buildOperationResult;
34
- private getUserRoleIds;
35
- private getRoleActionIds;
36
- private getUserActionIds;
37
- private invalidateRoleMembersCache;
38
- invalidateCompanyMembersCache(companyId: string): Promise<number>;
39
25
  revokeCompanyPermissions(companyId: string): Promise<void>;
40
26
  revokeBranchPermissions(branchId: string, companyId: string): Promise<void>;
41
27
  revokeUserCompanyAccess(userId: string, companyId: string): Promise<void>;