@flusys/nestjs-iam 6.1.0 → 6.1.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 (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
@@ -18,10 +18,8 @@ const _permissionwithcompanyentity = require("../entities/permission-with-compan
18
18
  const _rolewithcompanyentity = require("../entities/role-with-company.entity");
19
19
  const _roleentity = require("../entities/role.entity");
20
20
  const _useriampermissionentity = require("../entities/user-iam-permission.entity");
21
- const _actiontypeenum = require("../enums/action-type.enum");
22
21
  const _iamentitytypeenum = require("../enums/iam-entity-type.enum");
23
22
  const _iampermissiontypeenum = require("../enums/iam-permission-type.enum");
24
- const _permissiontypeenum = require("../enums/permission-type.enum");
25
23
  const _iamconfigservice = require("./iam-config.service");
26
24
  const _iamdatasourceservice = require("./iam-datasource.service");
27
25
  const _permissioncacheservice = require("./permission-cache.service");
@@ -120,7 +118,6 @@ let PermissionService = class PermissionService {
120
118
  sourceId: dto.userId,
121
119
  targetType: _iamentitytypeenum.IamEntityType.ACTION,
122
120
  targetId: item.id,
123
- userId: dto.userId,
124
121
  companyId: enableCompanyFeature ? companyId : null,
125
122
  branchId: enableCompanyFeature ? branchId : null
126
123
  }));
@@ -155,12 +152,12 @@ let PermissionService = class PermissionService {
155
152
  const result = await permissionRepo.delete(whereDelete);
156
153
  removed = result.affected || 0;
157
154
  }
158
- await this.permissionCacheService.invalidateUser(dto.userId, enableCompanyFeature ? companyId : null, [
155
+ await this.permissionCacheService.invalidateUser(dto.userId, enableCompanyFeature ? companyId : null, enableCompanyFeature ? [
159
156
  branchId
160
- ]);
157
+ ] : []);
161
158
  return this.buildOperationResult(dto.items.length, added, removed);
162
159
  }
163
- async getUserActions(userId, branchId, companyId) {
160
+ async getUserActions(userId, companyId, branchId) {
164
161
  const permissionRepo = await this.getPermissionRepository();
165
162
  const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
166
163
  const where = {
@@ -170,7 +167,7 @@ let PermissionService = class PermissionService {
170
167
  };
171
168
  if (enableCompanyFeature) {
172
169
  if (companyId) where.companyId = companyId;
173
- where.branchId = branchId ?? null;
170
+ if (branchId) where.branchId = branchId;
174
171
  }
175
172
  const permissions = await permissionRepo.find({
176
173
  where
@@ -184,10 +181,11 @@ let PermissionService = class PermissionService {
184
181
  const action = actionMap.get(p.targetId);
185
182
  return {
186
183
  id: p.id,
187
- userId: p.userId,
184
+ userId: p.sourceId,
188
185
  actionId: action.id,
189
186
  actionCode: action.code ?? '',
190
187
  actionName: action.name,
188
+ companyId: ('companyId' in p ? p.companyId : null) ?? null,
191
189
  branchId: ('branchId' in p ? p.branchId : null) ?? null,
192
190
  createdAt: p.createdAt
193
191
  };
@@ -241,7 +239,6 @@ let PermissionService = class PermissionService {
241
239
  sourceId: dto.roleId,
242
240
  targetType: _iamentitytypeenum.IamEntityType.ACTION,
243
241
  targetId: item.id,
244
- userId: null,
245
242
  companyId: enableCompanyFeature ? roleCompanyId : null,
246
243
  branchId: null
247
244
  }));
@@ -271,7 +268,7 @@ let PermissionService = class PermissionService {
271
268
  });
272
269
  removed = result.affected || 0;
273
270
  }
274
- await this.invalidateRoleMembersCache(dto.roleId);
271
+ await this.permissionCacheService.invalidateRoleMembersCache(dto.roleId);
275
272
  return this.buildOperationResult(dto.items.length, added, removed);
276
273
  }
277
274
  async getRoleActions(roleId) {
@@ -303,94 +300,88 @@ let PermissionService = class PermissionService {
303
300
  // Company-Action Permissions (Whitelist)
304
301
  /** Assign or remove actions to/from a company (whitelist) */ async assignCompanyActions(dto) {
305
302
  const permissionRepo = await this.getPermissionRepository();
306
- const dataSource = permissionRepo.manager.connection;
303
+ const dataSource = await this.dataSourceProvider.getDataSource();
304
+ const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
307
305
  const { toAdd: itemsToAdd, toRemove: itemsToRemove } = this.splitItemsByAction(dto.items);
308
306
  let added = 0;
309
307
  let removed = 0;
310
308
  await dataSource.transaction(async (manager)=>{
311
309
  const transactionalPermissionRepo = manager.getRepository(permissionRepo.target);
312
310
  if (itemsToAdd.length > 0) {
313
- added = await this.addCompanyActions(transactionalPermissionRepo, dto.companyId, itemsToAdd.map((item)=>item.id));
311
+ const actionIdsToAdd = itemsToAdd.map((item)=>item.id);
312
+ const existingPermissions = await transactionalPermissionRepo.find({
313
+ where: {
314
+ permissionType: _iampermissiontypeenum.IamPermissionType.COMPANY_ACTION,
315
+ sourceType: _iamentitytypeenum.IamEntityType.COMPANY,
316
+ sourceId: dto.companyId,
317
+ targetType: _iamentitytypeenum.IamEntityType.ACTION,
318
+ targetId: (0, _typeorm.In)(actionIdsToAdd)
319
+ },
320
+ select: [
321
+ 'targetId'
322
+ ]
323
+ });
324
+ const existingActionIds = new Set(existingPermissions.map((p)=>p.targetId));
325
+ const newActionIds = actionIdsToAdd.filter((id)=>!existingActionIds.has(id));
326
+ if (newActionIds.length > 0) {
327
+ const newPermissions = newActionIds.map((actionId)=>transactionalPermissionRepo.create({
328
+ permissionType: _iampermissiontypeenum.IamPermissionType.COMPANY_ACTION,
329
+ sourceType: _iamentitytypeenum.IamEntityType.COMPANY,
330
+ sourceId: dto.companyId,
331
+ targetType: _iamentitytypeenum.IamEntityType.ACTION,
332
+ targetId: actionId
333
+ }));
334
+ await transactionalPermissionRepo.save(newPermissions);
335
+ added = newPermissions.length;
336
+ }
314
337
  }
315
338
  if (itemsToRemove.length > 0) {
316
339
  const actionIdsToRemove = itemsToRemove.map((item)=>item.id);
317
- removed = await this.removeCompanyActionsWithCascade(manager, dto.companyId, actionIdsToRemove);
340
+ const companyResult = await transactionalPermissionRepo.delete({
341
+ permissionType: _iampermissiontypeenum.IamPermissionType.COMPANY_ACTION,
342
+ sourceType: _iamentitytypeenum.IamEntityType.COMPANY,
343
+ sourceId: dto.companyId,
344
+ targetType: _iamentitytypeenum.IamEntityType.ACTION,
345
+ targetId: (0, _typeorm.In)(actionIdsToRemove)
346
+ });
347
+ removed = companyResult.affected || 0;
348
+ // Cascade: an action no longer on the company whitelist must not remain
349
+ // reachable via role grants or direct user grants scoped to this company.
350
+ const roleEntity = enableCompanyFeature ? _rolewithcompanyentity.RoleWithCompany : _roleentity.Role;
351
+ const roleRepo = manager.getRepository(roleEntity);
352
+ const companyRoles = await roleRepo.find({
353
+ where: {
354
+ companyId: dto.companyId,
355
+ deletedAt: (0, _typeorm.IsNull)()
356
+ },
357
+ select: [
358
+ 'id'
359
+ ]
360
+ });
361
+ if (companyRoles.length > 0) {
362
+ const roleIds = companyRoles.map((role)=>role.id);
363
+ await transactionalPermissionRepo.delete({
364
+ permissionType: _iampermissiontypeenum.IamPermissionType.ROLE_ACTION,
365
+ sourceType: _iamentitytypeenum.IamEntityType.ROLE,
366
+ sourceId: (0, _typeorm.In)(roleIds),
367
+ targetType: _iamentitytypeenum.IamEntityType.ACTION,
368
+ targetId: (0, _typeorm.In)(actionIdsToRemove)
369
+ });
370
+ }
371
+ if (enableCompanyFeature) {
372
+ await transactionalPermissionRepo.delete({
373
+ permissionType: _iampermissiontypeenum.IamPermissionType.USER_ACTION,
374
+ companyId: dto.companyId,
375
+ targetType: _iamentitytypeenum.IamEntityType.ACTION,
376
+ targetId: (0, _typeorm.In)(actionIdsToRemove)
377
+ });
378
+ }
318
379
  }
319
380
  });
320
- await this.invalidateCompanyMembersCache(dto.companyId);
381
+ await this.permissionCacheService.invalidateCompanyMembersCache(dto.companyId);
321
382
  return this.buildOperationResult(dto.items.length, added, removed);
322
383
  }
323
- async addCompanyActions(permissionRepo, companyId, actionIds) {
324
- const existingPermissions = await permissionRepo.find({
325
- where: {
326
- permissionType: _iampermissiontypeenum.IamPermissionType.COMPANY_ACTION,
327
- sourceType: _iamentitytypeenum.IamEntityType.COMPANY,
328
- sourceId: companyId,
329
- targetType: _iamentitytypeenum.IamEntityType.ACTION,
330
- targetId: (0, _typeorm.In)(actionIds)
331
- },
332
- select: [
333
- 'targetId'
334
- ]
335
- });
336
- const existingActionIds = new Set(existingPermissions.map((p)=>p.targetId));
337
- const newActionIds = actionIds.filter((id)=>!existingActionIds.has(id));
338
- if (newActionIds.length === 0) {
339
- return 0;
340
- }
341
- const newPermissions = newActionIds.map((actionId)=>permissionRepo.create({
342
- permissionType: _iampermissiontypeenum.IamPermissionType.COMPANY_ACTION,
343
- sourceType: _iamentitytypeenum.IamEntityType.COMPANY,
344
- sourceId: companyId,
345
- targetType: _iamentitytypeenum.IamEntityType.ACTION,
346
- targetId: actionId,
347
- userId: null
348
- }));
349
- await permissionRepo.save(newPermissions);
350
- return newPermissions.length;
351
- }
352
- async removeCompanyActionsWithCascade(manager, companyId, actionIds) {
353
- const permissionEntity = this.iamConfigService.isCompanyFeatureEnabled() ? _permissionwithcompanyentity.UserIamPermissionWithCompany : _useriampermissionentity.UserIamPermission;
354
- const permissionRepo = manager.getRepository(permissionEntity);
355
- const companyResult = await permissionRepo.delete({
356
- permissionType: _iampermissiontypeenum.IamPermissionType.COMPANY_ACTION,
357
- sourceType: _iamentitytypeenum.IamEntityType.COMPANY,
358
- sourceId: companyId,
359
- targetType: _iamentitytypeenum.IamEntityType.ACTION,
360
- targetId: (0, _typeorm.In)(actionIds)
361
- });
362
- const roleEntity = this.iamConfigService.isCompanyFeatureEnabled() ? _rolewithcompanyentity.RoleWithCompany : _roleentity.Role;
363
- const roleRepo = manager.getRepository(roleEntity);
364
- const companyRoles = await roleRepo.find({
365
- where: {
366
- companyId,
367
- deletedAt: (0, _typeorm.IsNull)()
368
- },
369
- select: [
370
- 'id'
371
- ]
372
- });
373
- if (companyRoles.length > 0) {
374
- const roleIds = companyRoles.map((role)=>role.id);
375
- await permissionRepo.delete({
376
- permissionType: _iampermissiontypeenum.IamPermissionType.ROLE_ACTION,
377
- sourceType: _iamentitytypeenum.IamEntityType.ROLE,
378
- sourceId: (0, _typeorm.In)(roleIds),
379
- targetType: _iamentitytypeenum.IamEntityType.ACTION,
380
- targetId: (0, _typeorm.In)(actionIds)
381
- });
382
- }
383
- if (this.iamConfigService.isCompanyFeatureEnabled()) {
384
- await permissionRepo.delete({
385
- permissionType: _iampermissiontypeenum.IamPermissionType.USER_ACTION,
386
- companyId,
387
- targetType: _iamentitytypeenum.IamEntityType.ACTION,
388
- targetId: (0, _typeorm.In)(actionIds)
389
- });
390
- }
391
- return companyResult.affected || 0;
392
- }
393
- /** Get all actions assigned to a company (whitelist) */ async getCompanyActions(companyId) {
384
+ /** Get all actions assigned to a company (whitelist) */ async getCompanyActions(companyId, isOnlyId = false) {
394
385
  const permissionRepo = await this.getPermissionRepository();
395
386
  const permissions = await permissionRepo.find({
396
387
  where: {
@@ -403,6 +394,7 @@ let PermissionService = class PermissionService {
403
394
  return [];
404
395
  }
405
396
  const actionIds = permissions.map((p)=>p.targetId);
397
+ if (isOnlyId) return actionIds;
406
398
  const actionMap = await this.getActionsMap(actionIds);
407
399
  return permissions.filter((p)=>actionMap.has(p.targetId)).map((p)=>{
408
400
  const action = actionMap.get(p.targetId);
@@ -416,20 +408,6 @@ let PermissionService = class PermissionService {
416
408
  };
417
409
  });
418
410
  }
419
- /** Get action IDs whitelisted for a company */ async getCompanyActionIds(companyId) {
420
- const permissionRepo = await this.getPermissionRepository();
421
- const permissions = await permissionRepo.find({
422
- where: {
423
- permissionType: _iampermissiontypeenum.IamPermissionType.COMPANY_ACTION,
424
- sourceType: _iamentitytypeenum.IamEntityType.COMPANY,
425
- sourceId: companyId
426
- },
427
- select: [
428
- 'targetId'
429
- ]
430
- });
431
- return permissions.map((p)=>p.targetId);
432
- }
433
411
  // User-Role Permissions
434
412
  /** Assign user to roles (branch-scoped when company feature is enabled) */ async assignUserRoles(dto) {
435
413
  if (!this.iamConfigService.isRbacEnabled()) {
@@ -471,7 +449,6 @@ let PermissionService = class PermissionService {
471
449
  sourceId: dto.userId,
472
450
  targetType: _iamentitytypeenum.IamEntityType.ROLE,
473
451
  targetId: item.id,
474
- userId: dto.userId,
475
452
  companyId: enableCompanyFeature ? companyId : null,
476
453
  branchId: enableCompanyFeature ? branchId : null
477
454
  }));
@@ -522,7 +499,7 @@ let PermissionService = class PermissionService {
522
499
  };
523
500
  if (enableCompanyFeature) {
524
501
  if (companyId) where.companyId = companyId;
525
- where.branchId = branchId ?? null;
502
+ if (branchId) where.branchId = branchId;
526
503
  }
527
504
  const permissions = await permissionRepo.find({
528
505
  where
@@ -546,7 +523,7 @@ let PermissionService = class PermissionService {
546
523
  const permissionEntity = p;
547
524
  return {
548
525
  id: p.id,
549
- userId: p.userId,
526
+ userId: p.sourceId,
550
527
  roleId: role.id,
551
528
  roleName: role.name,
552
529
  branchId: enableCompanyFeature ? permissionEntity.branchId ?? null : null,
@@ -556,129 +533,7 @@ let PermissionService = class PermissionService {
556
533
  }
557
534
  // My Permissions
558
535
  /** Get user's effective permissions (cache-first approach) */ async getMyPermissions(userId, branchId, companyId, parentCodes) {
559
- const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
560
- const cacheOptions = {
561
- userId,
562
- companyId: enableCompanyFeature ? companyId : null,
563
- branchId
564
- };
565
- const cachedData = await this.permissionCacheService.getMyPermissions(cacheOptions);
566
- if (cachedData) {
567
- return this.buildResponseFromCache(cachedData, parentCodes);
568
- }
569
- const freshData = await this.fetchAndCachePermissions(userId, branchId, companyId);
570
- return this.buildResponseFromCache(freshData, parentCodes);
571
- }
572
- /** Build response from cached data, applying optional parentCodes filter */ async buildResponseFromCache(cachedData, parentCodes) {
573
- let frontendActions = cachedData.frontendActions;
574
- if (parentCodes?.length) {
575
- const parentIds = await this.getParentIdsByCodesWithCache(parentCodes);
576
- if (parentIds.size > 0) {
577
- frontendActions = frontendActions.filter((a)=>a.parentId && parentIds.has(a.parentId));
578
- } else {
579
- frontendActions = [];
580
- }
581
- }
582
- return {
583
- frontendActions: frontendActions.map((a)=>({
584
- id: a.id,
585
- code: a.code,
586
- name: a.name,
587
- description: a.description
588
- })),
589
- cachedEndpoints: cachedData.backendCodes.length
590
- };
591
- }
592
- /** Resolve action IDs for the given codes */ async getParentIdsByCodesWithCache(codes) {
593
- const actionRepo = await this.getActionRepository();
594
- const actions = await actionRepo.find({
595
- where: {
596
- code: (0, _typeorm.In)(codes)
597
- },
598
- select: [
599
- 'id',
600
- 'code'
601
- ]
602
- });
603
- return new Set(actions.map((action)=>action.id));
604
- }
605
- /** Fetch permissions from DB and cache them (empty permissions are also cached) */ async fetchAndCachePermissions(userId, branchId, companyId) {
606
- const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
607
- const cacheOptions = {
608
- userId,
609
- companyId: enableCompanyFeature ? companyId : null,
610
- branchId
611
- };
612
- const emptyData = {
613
- frontendActions: [],
614
- backendCodes: []
615
- };
616
- const allActionIds = await this.collectAllActionIds(userId, branchId, companyId);
617
- if (allActionIds.size === 0) {
618
- await this.permissionCacheService.setMyPermissions(cacheOptions, emptyData);
619
- return emptyData;
620
- }
621
- await this.applyCompanyWhitelist(allActionIds, companyId);
622
- if (allActionIds.size === 0) {
623
- await this.permissionCacheService.setMyPermissions(cacheOptions, emptyData);
624
- return emptyData;
625
- }
626
- return this.buildAndCachePermissionData(allActionIds, cacheOptions);
627
- }
628
- /** Collect all action IDs based on permission mode (RBAC, DIRECT, or FULL) */ async collectAllActionIds(userId, branchId, companyId) {
629
- const permissionMode = this.iamConfigService.getPermissionMode();
630
- const allActionIds = new Set();
631
- if (permissionMode === _permissiontypeenum.IAMPermissionMode.RBAC || permissionMode === _permissiontypeenum.IAMPermissionMode.FULL) {
632
- const userRoleIds = await this.getUserRoleIds(userId, branchId, companyId);
633
- if (userRoleIds.length > 0) {
634
- const roleActionIds = await this.getRoleActionIds(userRoleIds);
635
- roleActionIds.forEach((id)=>allActionIds.add(id));
636
- }
637
- }
638
- if (permissionMode === _permissiontypeenum.IAMPermissionMode.DIRECT || permissionMode === _permissiontypeenum.IAMPermissionMode.FULL) {
639
- const userActionIds = await this.getUserActionIds(userId, branchId, companyId);
640
- userActionIds.forEach((id)=>allActionIds.add(id));
641
- }
642
- return allActionIds;
643
- }
644
- /** Apply company whitelist filter to action IDs (mutates the set) */ async applyCompanyWhitelist(actionIds, companyId) {
645
- if (!this.iamConfigService.isCompanyFeatureEnabled() || !companyId) {
646
- return;
647
- }
648
- const companyActionIds = await this.getCompanyActionIds(companyId);
649
- if (companyActionIds.length === 0) {
650
- return;
651
- }
652
- const allowedActionIds = new Set(companyActionIds);
653
- for (const actionId of actionIds){
654
- if (!allowedActionIds.has(actionId)) {
655
- actionIds.delete(actionId);
656
- }
657
- }
658
- }
659
- /** Fetch actions from DB, separate by type, build cache data, and cache it */ async buildAndCachePermissionData(actionIds, cacheOptions) {
660
- const actionRepo = await this.getActionRepository();
661
- const actions = await actionRepo.find({
662
- where: {
663
- id: (0, _typeorm.In)(Array.from(actionIds)),
664
- isActive: true
665
- }
666
- });
667
- const backendActions = actions.filter((a)=>a.actionType === _actiontypeenum.ActionType.BACKEND || a.actionType === _actiontypeenum.ActionType.BOTH);
668
- const frontendActions = actions.filter((a)=>a.actionType === _actiontypeenum.ActionType.FRONTEND || a.actionType === _actiontypeenum.ActionType.BOTH);
669
- const backendCodes = backendActions.map((a)=>a.code).filter((c)=>!!c);
670
- const cacheData = {
671
- frontendActions: frontendActions.map((a)=>({
672
- id: a.id,
673
- code: a.code ?? '',
674
- name: a.name,
675
- description: a.description,
676
- parentId: a.parentId
677
- })),
678
- backendCodes
679
- };
680
- await this.permissionCacheService.setMyPermissions(cacheOptions, cacheData);
681
- return cacheData;
536
+ return this.permissionCacheService.getMyPermissionsResponse(userId, branchId, companyId, parentCodes);
682
537
  }
683
538
  // Helper Methods
684
539
  /** Split permission items into add and remove arrays */ splitItemsByAction(items) {
@@ -694,176 +549,13 @@ let PermissionService = class PermissionService {
694
549
  total: _totalItems
695
550
  };
696
551
  }
697
- /** Get role IDs assigned to a user (merges company-wide + branch-specific roles) */ async getUserRoleIds(userId, branchId, companyId) {
698
- const permissionRepo = await this.getPermissionRepository();
699
- const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
700
- if (!enableCompanyFeature) {
701
- const permissions = await permissionRepo.find({
702
- where: {
703
- permissionType: _iampermissiontypeenum.IamPermissionType.USER_ROLE,
704
- sourceType: _iamentitytypeenum.IamEntityType.USER,
705
- sourceId: userId
706
- }
707
- });
708
- return permissions.filter((p)=>p.isValid()).map((p)=>p.targetId);
709
- }
710
- const roleIds = new Set();
711
- const baseWhere = {
712
- permissionType: _iampermissiontypeenum.IamPermissionType.USER_ROLE,
713
- sourceType: _iamentitytypeenum.IamEntityType.USER,
714
- sourceId: userId
715
- };
716
- if (companyId) {
717
- baseWhere.companyId = companyId;
718
- }
719
- if (branchId) {
720
- // Get company-wide + branch-specific roles
721
- const companyWidePermissions = await permissionRepo.find({
722
- where: {
723
- ...baseWhere,
724
- branchId: (0, _typeorm.IsNull)()
725
- }
726
- });
727
- companyWidePermissions.filter((p)=>p.isValid()).forEach((p)=>roleIds.add(p.targetId));
728
- const branchPermissions = await permissionRepo.find({
729
- where: {
730
- ...baseWhere,
731
- branchId
732
- }
733
- });
734
- branchPermissions.filter((p)=>p.isValid()).forEach((p)=>roleIds.add(p.targetId));
735
- } else {
736
- // No branch context: get all roles for this company
737
- const allPermissions = await permissionRepo.find({
738
- where: baseWhere
739
- });
740
- allPermissions.filter((p)=>p.isValid()).forEach((p)=>roleIds.add(p.targetId));
741
- }
742
- return Array.from(roleIds);
743
- }
744
- async getRoleActionIds(roleIds) {
745
- const permissionRepo = await this.getPermissionRepository();
746
- const permissions = await permissionRepo.find({
747
- where: {
748
- permissionType: _iampermissiontypeenum.IamPermissionType.ROLE_ACTION,
749
- sourceType: _iamentitytypeenum.IamEntityType.ROLE,
750
- sourceId: (0, _typeorm.In)(roleIds)
751
- }
752
- });
753
- return permissions.filter((p)=>p.isValid()).map((p)=>p.targetId);
754
- }
755
- /** Get action IDs directly assigned to a user (merges company-wide + branch-specific actions) */ async getUserActionIds(userId, branchId, companyId) {
756
- const permissionRepo = await this.getPermissionRepository();
757
- const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
758
- if (!enableCompanyFeature) {
759
- const permissions = await permissionRepo.find({
760
- where: {
761
- permissionType: _iampermissiontypeenum.IamPermissionType.USER_ACTION,
762
- sourceType: _iamentitytypeenum.IamEntityType.USER,
763
- sourceId: userId
764
- }
765
- });
766
- return permissions.filter((p)=>p.isValid()).map((p)=>p.targetId);
767
- }
768
- const actionIds = new Set();
769
- const baseWhere = {
770
- permissionType: _iampermissiontypeenum.IamPermissionType.USER_ACTION,
771
- sourceType: _iamentitytypeenum.IamEntityType.USER,
772
- sourceId: userId
773
- };
774
- if (companyId) {
775
- baseWhere.companyId = companyId;
776
- }
777
- if (branchId) {
778
- // Get company-wide + branch-specific actions
779
- const companyWidePermissions = await permissionRepo.find({
780
- where: {
781
- ...baseWhere,
782
- branchId: (0, _typeorm.IsNull)()
783
- }
784
- });
785
- companyWidePermissions.filter((p)=>p.isValid()).forEach((p)=>actionIds.add(p.targetId));
786
- const branchPermissions = await permissionRepo.find({
787
- where: {
788
- ...baseWhere,
789
- branchId
790
- }
791
- });
792
- branchPermissions.filter((p)=>p.isValid()).forEach((p)=>actionIds.add(p.targetId));
793
- } else {
794
- // No branch context: get all actions for this company
795
- const allPermissions = await permissionRepo.find({
796
- where: baseWhere
797
- });
798
- allPermissions.filter((p)=>p.isValid()).forEach((p)=>actionIds.add(p.targetId));
799
- }
800
- return Array.from(actionIds);
801
- }
802
- async invalidateRoleMembersCache(roleId) {
803
- const permissionRepo = await this.getPermissionRepository();
804
- const roleRepo = await this.getRoleRepository();
805
- const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
806
- const userRoles = await permissionRepo.find({
807
- where: {
808
- permissionType: _iampermissiontypeenum.IamPermissionType.USER_ROLE,
809
- sourceType: _iamentitytypeenum.IamEntityType.USER,
810
- targetType: _iamentitytypeenum.IamEntityType.ROLE,
811
- targetId: roleId
812
- }
813
- });
814
- const userIds = [
815
- ...new Set(userRoles.map((ur)=>ur.sourceId))
816
- ];
817
- if (userIds.length === 0) {
818
- return 0;
819
- }
820
- const role = await roleRepo.findOne({
821
- where: {
822
- id: roleId
823
- }
824
- });
825
- const companyId = role?.companyId || null;
826
- let branchIds = [
827
- null
828
- ];
829
- if (enableCompanyFeature && companyId) {
830
- const userBranches = await permissionRepo.createQueryBuilder('p').select('DISTINCT p.branch_id', 'branchId').where('p.user_id IN (:...userIds)', {
831
- userIds
832
- }).andWhere('p.company_id = :companyId', {
833
- companyId
834
- }).getRawMany();
835
- branchIds = [
836
- ...new Set(userBranches.map((p)=>p.branchId))
837
- ];
838
- }
839
- return this.permissionCacheService.invalidateUsers(userIds, companyId, branchIds);
840
- }
841
- /** Invalidate permission cache for all users in a company */ async invalidateCompanyMembersCache(companyId) {
842
- if (!this.iamConfigService.isCompanyFeatureEnabled()) {
843
- return 0;
844
- }
845
- const permissionRepo = await this.getPermissionRepository();
846
- const userPermissions = await permissionRepo.createQueryBuilder('p').select('DISTINCT p.user_id', 'userId').addSelect('p.branch_id', 'branchId').where('p.company_id = :companyId', {
847
- companyId
848
- }).andWhere('p.user_id IS NOT NULL').getRawMany();
849
- const userIds = [
850
- ...new Set(userPermissions.map((p)=>p.userId).filter(Boolean))
851
- ];
852
- const branchIds = [
853
- ...new Set(userPermissions.map((p)=>p.branchId))
854
- ]; // includes null
855
- if (userIds.length === 0) {
856
- return 0;
857
- }
858
- return await this.permissionCacheService.invalidateUsers(userIds, companyId, branchIds);
859
- }
860
552
  async revokeCompanyPermissions(companyId) {
861
553
  if (!this.iamConfigService.isCompanyFeatureEnabled()) {
862
554
  return;
863
555
  }
864
556
  const permissionRepo = await this.getPermissionRepository();
865
557
  const roleRepo = await this.getRoleRepository();
866
- const dataSource = permissionRepo.manager.connection;
558
+ const dataSource = await this.dataSourceProvider.getDataSource();
867
559
  const companyRoles = await roleRepo.find({
868
560
  where: {
869
561
  companyId,
@@ -880,14 +572,15 @@ let PermissionService = class PermissionService {
880
572
  _iampermissiontypeenum.IamPermissionType.USER_ROLE,
881
573
  _iampermissiontypeenum.IamPermissionType.USER_ACTION
882
574
  ]),
575
+ sourceType: _iamentitytypeenum.IamEntityType.USER,
883
576
  companyId
884
577
  },
885
578
  select: [
886
- 'userId'
579
+ 'sourceId'
887
580
  ]
888
581
  });
889
582
  const affectedUserIds = [
890
- ...new Set(affectedUserRows.map((row)=>row.userId).filter((id)=>!!id))
583
+ ...new Set(affectedUserRows.map((row)=>row.sourceId))
891
584
  ];
892
585
  await dataSource.transaction(async (manager)=>{
893
586
  const txRepo = manager.getRepository(permissionRepo.target);
@@ -929,17 +622,20 @@ let PermissionService = class PermissionService {
929
622
  _iampermissiontypeenum.IamPermissionType.USER_ROLE,
930
623
  _iampermissiontypeenum.IamPermissionType.USER_ACTION
931
624
  ]),
932
- branchId,
933
- companyId
625
+ companyId,
626
+ branchId
934
627
  };
935
628
  const affectedUserRows = await permissionRepo.find({
936
- where,
629
+ where: {
630
+ ...where,
631
+ sourceType: _iamentitytypeenum.IamEntityType.USER
632
+ },
937
633
  select: [
938
- 'userId'
634
+ 'sourceId'
939
635
  ]
940
636
  });
941
637
  const affectedUserIds = [
942
- ...new Set(affectedUserRows.map((row)=>row.userId).filter((id)=>!!id))
638
+ ...new Set(affectedUserRows.map((row)=>row.sourceId))
943
639
  ];
944
640
  await permissionRepo.delete(where);
945
641
  if (affectedUserIds.length > 0) {