@flusys/nestjs-iam 6.0.0 → 6.0.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.
- package/cjs/controllers/action.controller.js +17 -9
- package/cjs/controllers/user-action-permission.controller.js +0 -3
- package/cjs/docs/iam-swagger.config.js +6 -0
- package/cjs/dtos/action.dto.js +17 -0
- package/cjs/modules/iam.module.js +3 -1
- package/cjs/services/action.service.js +90 -7
- package/cjs/services/permission-cache.service.js +113 -110
- package/cjs/services/permission.service.js +213 -92
- package/cjs/services/role.service.js +47 -3
- package/controllers/action.controller.d.ts +5 -3
- package/dtos/action.dto.d.ts +3 -0
- package/entities/index.d.ts +2 -2
- package/fesm/controllers/action.controller.js +18 -10
- package/fesm/controllers/user-action-permission.controller.js +0 -3
- package/fesm/docs/iam-swagger.config.js +6 -0
- package/fesm/dtos/action.dto.js +14 -0
- package/fesm/modules/iam.module.js +4 -2
- package/fesm/services/action.service.js +90 -7
- package/fesm/services/permission-cache.service.js +101 -108
- package/fesm/services/permission.service.js +213 -92
- package/fesm/services/role.service.js +48 -4
- package/package.json +3 -3
- package/services/action.service.d.ts +7 -3
- package/services/permission-cache.service.d.ts +13 -19
- package/services/permission.service.d.ts +6 -3
- package/services/role.service.d.ts +7 -3
|
@@ -18,9 +18,9 @@ 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");
|
|
21
22
|
const _iamentitytypeenum = require("../enums/iam-entity-type.enum");
|
|
22
23
|
const _iampermissiontypeenum = require("../enums/iam-permission-type.enum");
|
|
23
|
-
const _actiontypeenum = require("../enums/action-type.enum");
|
|
24
24
|
const _permissiontypeenum = require("../enums/permission-type.enum");
|
|
25
25
|
const _iamconfigservice = require("./iam-config.service");
|
|
26
26
|
const _iamdatasourceservice = require("./iam-datasource.service");
|
|
@@ -67,6 +67,18 @@ let PermissionService = class PermissionService {
|
|
|
67
67
|
const entity = enableCompanyFeature ? _rolewithcompanyentity.RoleWithCompany : _roleentity.Role;
|
|
68
68
|
return this.dataSourceProvider.getRepository(entity);
|
|
69
69
|
}
|
|
70
|
+
async getActionsMap(actionIds) {
|
|
71
|
+
const actionRepo = await this.getActionRepository();
|
|
72
|
+
const actions = await actionRepo.find({
|
|
73
|
+
where: {
|
|
74
|
+
id: (0, _typeorm.In)(actionIds)
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
return new Map(actions.map((a)=>[
|
|
78
|
+
a.id,
|
|
79
|
+
a
|
|
80
|
+
]));
|
|
81
|
+
}
|
|
70
82
|
// User-Action Permissions
|
|
71
83
|
async assignUserActions(dto) {
|
|
72
84
|
if (!this.iamConfigService.isDirectPermissionEnabled()) {
|
|
@@ -143,12 +155,13 @@ let PermissionService = class PermissionService {
|
|
|
143
155
|
const result = await permissionRepo.delete(whereDelete);
|
|
144
156
|
removed = result.affected || 0;
|
|
145
157
|
}
|
|
146
|
-
await this.
|
|
158
|
+
await this.permissionCacheService.invalidateUser(dto.userId, enableCompanyFeature ? companyId : null, [
|
|
159
|
+
branchId
|
|
160
|
+
]);
|
|
147
161
|
return this.buildOperationResult(dto.items.length, added, removed);
|
|
148
162
|
}
|
|
149
163
|
async getUserActions(userId, branchId, companyId) {
|
|
150
164
|
const permissionRepo = await this.getPermissionRepository();
|
|
151
|
-
const actionRepo = await this.getActionRepository();
|
|
152
165
|
const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
|
|
153
166
|
const where = {
|
|
154
167
|
permissionType: _iampermissiontypeenum.IamPermissionType.USER_ACTION,
|
|
@@ -166,16 +179,7 @@ let PermissionService = class PermissionService {
|
|
|
166
179
|
return [];
|
|
167
180
|
}
|
|
168
181
|
const actionIds = permissions.map((p)=>p.targetId);
|
|
169
|
-
const
|
|
170
|
-
id: (0, _typeorm.In)(actionIds)
|
|
171
|
-
};
|
|
172
|
-
const actions = await actionRepo.find({
|
|
173
|
-
where: actionWhere
|
|
174
|
-
});
|
|
175
|
-
const actionMap = new Map(actions.map((a)=>[
|
|
176
|
-
a.id,
|
|
177
|
-
a
|
|
178
|
-
]));
|
|
182
|
+
const actionMap = await this.getActionsMap(actionIds);
|
|
179
183
|
return permissions.filter((p)=>actionMap.has(p.targetId)).map((p)=>{
|
|
180
184
|
const action = actionMap.get(p.targetId);
|
|
181
185
|
return {
|
|
@@ -272,7 +276,6 @@ let PermissionService = class PermissionService {
|
|
|
272
276
|
}
|
|
273
277
|
async getRoleActions(roleId) {
|
|
274
278
|
const permissionRepo = await this.getPermissionRepository();
|
|
275
|
-
const actionRepo = await this.getActionRepository();
|
|
276
279
|
const permissions = await permissionRepo.find({
|
|
277
280
|
where: {
|
|
278
281
|
permissionType: _iampermissiontypeenum.IamPermissionType.ROLE_ACTION,
|
|
@@ -284,16 +287,7 @@ let PermissionService = class PermissionService {
|
|
|
284
287
|
return [];
|
|
285
288
|
}
|
|
286
289
|
const actionIds = permissions.map((p)=>p.targetId);
|
|
287
|
-
const
|
|
288
|
-
id: (0, _typeorm.In)(actionIds)
|
|
289
|
-
};
|
|
290
|
-
const actions = await actionRepo.find({
|
|
291
|
-
where: actionWhere
|
|
292
|
-
});
|
|
293
|
-
const actionMap = new Map(actions.map((a)=>[
|
|
294
|
-
a.id,
|
|
295
|
-
a
|
|
296
|
-
]));
|
|
290
|
+
const actionMap = await this.getActionsMap(actionIds);
|
|
297
291
|
return permissions.filter((p)=>actionMap.has(p.targetId)).map((p)=>{
|
|
298
292
|
const action = actionMap.get(p.targetId);
|
|
299
293
|
return {
|
|
@@ -320,8 +314,7 @@ let PermissionService = class PermissionService {
|
|
|
320
314
|
}
|
|
321
315
|
if (itemsToRemove.length > 0) {
|
|
322
316
|
const actionIdsToRemove = itemsToRemove.map((item)=>item.id);
|
|
323
|
-
|
|
324
|
-
removed = cascadeResult.removedCompanyActions;
|
|
317
|
+
removed = await this.removeCompanyActionsWithCascade(manager, dto.companyId, actionIdsToRemove);
|
|
325
318
|
}
|
|
326
319
|
});
|
|
327
320
|
await this.invalidateCompanyMembersCache(dto.companyId);
|
|
@@ -377,37 +370,28 @@ let PermissionService = class PermissionService {
|
|
|
377
370
|
'id'
|
|
378
371
|
]
|
|
379
372
|
});
|
|
380
|
-
let removedRoleActions = 0;
|
|
381
|
-
let removedUserActions = 0;
|
|
382
373
|
if (companyRoles.length > 0) {
|
|
383
374
|
const roleIds = companyRoles.map((role)=>role.id);
|
|
384
|
-
|
|
375
|
+
await permissionRepo.delete({
|
|
385
376
|
permissionType: _iampermissiontypeenum.IamPermissionType.ROLE_ACTION,
|
|
386
377
|
sourceType: _iamentitytypeenum.IamEntityType.ROLE,
|
|
387
378
|
sourceId: (0, _typeorm.In)(roleIds),
|
|
388
379
|
targetType: _iamentitytypeenum.IamEntityType.ACTION,
|
|
389
380
|
targetId: (0, _typeorm.In)(actionIds)
|
|
390
381
|
});
|
|
391
|
-
removedRoleActions = roleResult.affected || 0;
|
|
392
382
|
}
|
|
393
383
|
if (this.iamConfigService.isCompanyFeatureEnabled()) {
|
|
394
|
-
|
|
384
|
+
await permissionRepo.delete({
|
|
395
385
|
permissionType: _iampermissiontypeenum.IamPermissionType.USER_ACTION,
|
|
396
386
|
companyId,
|
|
397
387
|
targetType: _iamentitytypeenum.IamEntityType.ACTION,
|
|
398
388
|
targetId: (0, _typeorm.In)(actionIds)
|
|
399
389
|
});
|
|
400
|
-
removedUserActions = userResult.affected || 0;
|
|
401
390
|
}
|
|
402
|
-
return
|
|
403
|
-
removedCompanyActions: companyResult.affected || 0,
|
|
404
|
-
removedRoleActions,
|
|
405
|
-
removedUserActions
|
|
406
|
-
};
|
|
391
|
+
return companyResult.affected || 0;
|
|
407
392
|
}
|
|
408
393
|
/** Get all actions assigned to a company (whitelist) */ async getCompanyActions(companyId) {
|
|
409
394
|
const permissionRepo = await this.getPermissionRepository();
|
|
410
|
-
const actionRepo = await this.getActionRepository();
|
|
411
395
|
const permissions = await permissionRepo.find({
|
|
412
396
|
where: {
|
|
413
397
|
permissionType: _iampermissiontypeenum.IamPermissionType.COMPANY_ACTION,
|
|
@@ -419,15 +403,7 @@ let PermissionService = class PermissionService {
|
|
|
419
403
|
return [];
|
|
420
404
|
}
|
|
421
405
|
const actionIds = permissions.map((p)=>p.targetId);
|
|
422
|
-
const
|
|
423
|
-
where: {
|
|
424
|
-
id: (0, _typeorm.In)(actionIds)
|
|
425
|
-
}
|
|
426
|
-
});
|
|
427
|
-
const actionMap = new Map(actions.map((a)=>[
|
|
428
|
-
a.id,
|
|
429
|
-
a
|
|
430
|
-
]));
|
|
406
|
+
const actionMap = await this.getActionsMap(actionIds);
|
|
431
407
|
return permissions.filter((p)=>actionMap.has(p.targetId)).map((p)=>{
|
|
432
408
|
const action = actionMap.get(p.targetId);
|
|
433
409
|
return {
|
|
@@ -530,7 +506,9 @@ let PermissionService = class PermissionService {
|
|
|
530
506
|
const result = await permissionRepo.delete(whereDelete);
|
|
531
507
|
removed = result.affected || 0;
|
|
532
508
|
}
|
|
533
|
-
await this.
|
|
509
|
+
await this.permissionCacheService.invalidateUser(dto.userId, enableCompanyFeature ? companyId : null, [
|
|
510
|
+
branchId
|
|
511
|
+
]);
|
|
534
512
|
return this.buildOperationResult(dto.items.length, added, removed);
|
|
535
513
|
}
|
|
536
514
|
/** Get user's roles (branch-scoped, filtered by companyId and branchId if provided) */ async getUserRoles(userId, branchId, companyId) {
|
|
@@ -581,9 +559,8 @@ let PermissionService = class PermissionService {
|
|
|
581
559
|
const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
|
|
582
560
|
const cacheOptions = {
|
|
583
561
|
userId,
|
|
584
|
-
companyId,
|
|
585
|
-
branchId
|
|
586
|
-
enableCompanyFeature
|
|
562
|
+
companyId: enableCompanyFeature ? companyId : null,
|
|
563
|
+
branchId
|
|
587
564
|
};
|
|
588
565
|
const cachedData = await this.permissionCacheService.getMyPermissions(cacheOptions);
|
|
589
566
|
if (cachedData) {
|
|
@@ -612,42 +589,25 @@ let PermissionService = class PermissionService {
|
|
|
612
589
|
cachedEndpoints: cachedData.backendCodes.length
|
|
613
590
|
};
|
|
614
591
|
}
|
|
615
|
-
/**
|
|
616
|
-
if (!this.iamConfigService.isMultiTenant()) {
|
|
617
|
-
return undefined;
|
|
618
|
-
}
|
|
619
|
-
const tenant = this.dataSourceProvider.getCurrentTenant();
|
|
620
|
-
return tenant?.id;
|
|
621
|
-
}
|
|
622
|
-
/** Get parent IDs by codes, using cache first (tenant-aware) */ async getParentIdsByCodesWithCache(codes) {
|
|
623
|
-
const tenantId = this.getCurrentTenantId();
|
|
624
|
-
const cachedMap = await this.permissionCacheService.getActionIdsByCodes(codes, tenantId);
|
|
625
|
-
if (cachedMap) {
|
|
626
|
-
return new Set(Object.values(cachedMap));
|
|
627
|
-
}
|
|
592
|
+
/** Resolve action IDs for the given codes */ async getParentIdsByCodesWithCache(codes) {
|
|
628
593
|
const actionRepo = await this.getActionRepository();
|
|
629
|
-
const
|
|
594
|
+
const actions = await actionRepo.find({
|
|
595
|
+
where: {
|
|
596
|
+
code: (0, _typeorm.In)(codes)
|
|
597
|
+
},
|
|
630
598
|
select: [
|
|
631
599
|
'id',
|
|
632
600
|
'code'
|
|
633
601
|
]
|
|
634
602
|
});
|
|
635
|
-
|
|
636
|
-
for (const action of allActions){
|
|
637
|
-
if (action.code) {
|
|
638
|
-
fullMap[action.code] = action.id;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
await this.permissionCacheService.setActionCodeMap(fullMap, tenantId);
|
|
642
|
-
return new Set(codes.map((code)=>fullMap[code]).filter(Boolean));
|
|
603
|
+
return new Set(actions.map((action)=>action.id));
|
|
643
604
|
}
|
|
644
605
|
/** Fetch permissions from DB and cache them (empty permissions are also cached) */ async fetchAndCachePermissions(userId, branchId, companyId) {
|
|
645
606
|
const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
|
|
646
607
|
const cacheOptions = {
|
|
647
608
|
userId,
|
|
648
|
-
companyId,
|
|
649
|
-
branchId
|
|
650
|
-
enableCompanyFeature
|
|
609
|
+
companyId: enableCompanyFeature ? companyId : null,
|
|
610
|
+
branchId
|
|
651
611
|
};
|
|
652
612
|
const emptyData = {
|
|
653
613
|
frontendActions: [],
|
|
@@ -700,7 +660,8 @@ let PermissionService = class PermissionService {
|
|
|
700
660
|
const actionRepo = await this.getActionRepository();
|
|
701
661
|
const actions = await actionRepo.find({
|
|
702
662
|
where: {
|
|
703
|
-
id: (0, _typeorm.In)(Array.from(actionIds))
|
|
663
|
+
id: (0, _typeorm.In)(Array.from(actionIds)),
|
|
664
|
+
isActive: true
|
|
704
665
|
}
|
|
705
666
|
});
|
|
706
667
|
const backendActions = actions.filter((a)=>a.actionType === _actiontypeenum.ActionType.BACKEND || a.actionType === _actiontypeenum.ActionType.BOTH);
|
|
@@ -716,10 +677,7 @@ let PermissionService = class PermissionService {
|
|
|
716
677
|
})),
|
|
717
678
|
backendCodes
|
|
718
679
|
};
|
|
719
|
-
await
|
|
720
|
-
this.permissionCacheService.setMyPermissions(cacheOptions, cacheData),
|
|
721
|
-
this.permissionCacheService.setPermissions(cacheOptions, backendCodes)
|
|
722
|
-
]);
|
|
680
|
+
await this.permissionCacheService.setMyPermissions(cacheOptions, cacheData);
|
|
723
681
|
return cacheData;
|
|
724
682
|
}
|
|
725
683
|
// Helper Methods
|
|
@@ -753,9 +711,11 @@ let PermissionService = class PermissionService {
|
|
|
753
711
|
const baseWhere = {
|
|
754
712
|
permissionType: _iampermissiontypeenum.IamPermissionType.USER_ROLE,
|
|
755
713
|
sourceType: _iamentitytypeenum.IamEntityType.USER,
|
|
756
|
-
sourceId: userId
|
|
757
|
-
companyId: companyId
|
|
714
|
+
sourceId: userId
|
|
758
715
|
};
|
|
716
|
+
if (companyId) {
|
|
717
|
+
baseWhere.companyId = companyId;
|
|
718
|
+
}
|
|
759
719
|
if (branchId) {
|
|
760
720
|
// Get company-wide + branch-specific roles
|
|
761
721
|
const companyWidePermissions = await permissionRepo.find({
|
|
@@ -839,14 +799,6 @@ let PermissionService = class PermissionService {
|
|
|
839
799
|
}
|
|
840
800
|
return Array.from(actionIds);
|
|
841
801
|
}
|
|
842
|
-
/** Invalidate permission cache for a user */ async invalidateUserPermissionCache(userId, branchId, companyId) {
|
|
843
|
-
const branchIds = branchId !== undefined ? [
|
|
844
|
-
branchId
|
|
845
|
-
] : [
|
|
846
|
-
null
|
|
847
|
-
];
|
|
848
|
-
await this.permissionCacheService.invalidateUser(userId, companyId, branchIds);
|
|
849
|
-
}
|
|
850
802
|
async invalidateRoleMembersCache(roleId) {
|
|
851
803
|
const permissionRepo = await this.getPermissionRepository();
|
|
852
804
|
const roleRepo = await this.getRoleRepository();
|
|
@@ -884,7 +836,7 @@ let PermissionService = class PermissionService {
|
|
|
884
836
|
...new Set(userBranches.map((p)=>p.branchId))
|
|
885
837
|
];
|
|
886
838
|
}
|
|
887
|
-
return this.permissionCacheService.
|
|
839
|
+
return this.permissionCacheService.invalidateUsers(userIds, companyId, branchIds);
|
|
888
840
|
}
|
|
889
841
|
/** Invalidate permission cache for all users in a company */ async invalidateCompanyMembersCache(companyId) {
|
|
890
842
|
if (!this.iamConfigService.isCompanyFeatureEnabled()) {
|
|
@@ -905,6 +857,127 @@ let PermissionService = class PermissionService {
|
|
|
905
857
|
}
|
|
906
858
|
return await this.permissionCacheService.invalidateUsers(userIds, companyId, branchIds);
|
|
907
859
|
}
|
|
860
|
+
async revokeCompanyPermissions(companyId) {
|
|
861
|
+
if (!this.iamConfigService.isCompanyFeatureEnabled()) {
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
const permissionRepo = await this.getPermissionRepository();
|
|
865
|
+
const roleRepo = await this.getRoleRepository();
|
|
866
|
+
const dataSource = permissionRepo.manager.connection;
|
|
867
|
+
const companyRoles = await roleRepo.find({
|
|
868
|
+
where: {
|
|
869
|
+
companyId,
|
|
870
|
+
deletedAt: (0, _typeorm.IsNull)()
|
|
871
|
+
},
|
|
872
|
+
select: [
|
|
873
|
+
'id'
|
|
874
|
+
]
|
|
875
|
+
});
|
|
876
|
+
const roleIds = companyRoles.map((role)=>role.id);
|
|
877
|
+
const affectedUserRows = await permissionRepo.find({
|
|
878
|
+
where: {
|
|
879
|
+
permissionType: (0, _typeorm.In)([
|
|
880
|
+
_iampermissiontypeenum.IamPermissionType.USER_ROLE,
|
|
881
|
+
_iampermissiontypeenum.IamPermissionType.USER_ACTION
|
|
882
|
+
]),
|
|
883
|
+
companyId
|
|
884
|
+
},
|
|
885
|
+
select: [
|
|
886
|
+
'userId'
|
|
887
|
+
]
|
|
888
|
+
});
|
|
889
|
+
const affectedUserIds = [
|
|
890
|
+
...new Set(affectedUserRows.map((row)=>row.userId).filter((id)=>!!id))
|
|
891
|
+
];
|
|
892
|
+
await dataSource.transaction(async (manager)=>{
|
|
893
|
+
const txRepo = manager.getRepository(permissionRepo.target);
|
|
894
|
+
await txRepo.delete({
|
|
895
|
+
permissionType: _iampermissiontypeenum.IamPermissionType.COMPANY_ACTION,
|
|
896
|
+
sourceType: _iamentitytypeenum.IamEntityType.COMPANY,
|
|
897
|
+
sourceId: companyId
|
|
898
|
+
});
|
|
899
|
+
if (roleIds.length > 0) {
|
|
900
|
+
await txRepo.delete({
|
|
901
|
+
permissionType: _iampermissiontypeenum.IamPermissionType.ROLE_ACTION,
|
|
902
|
+
sourceType: _iamentitytypeenum.IamEntityType.ROLE,
|
|
903
|
+
sourceId: (0, _typeorm.In)(roleIds)
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
await txRepo.delete({
|
|
907
|
+
permissionType: (0, _typeorm.In)([
|
|
908
|
+
_iampermissiontypeenum.IamPermissionType.USER_ROLE,
|
|
909
|
+
_iampermissiontypeenum.IamPermissionType.USER_ACTION
|
|
910
|
+
]),
|
|
911
|
+
companyId
|
|
912
|
+
});
|
|
913
|
+
if (roleIds.length > 0) {
|
|
914
|
+
const txRoleRepo = manager.getRepository(roleRepo.target);
|
|
915
|
+
await txRoleRepo.delete(roleIds);
|
|
916
|
+
}
|
|
917
|
+
});
|
|
918
|
+
if (affectedUserIds.length > 0) {
|
|
919
|
+
await this.permissionCacheService.invalidateUsers(affectedUserIds, companyId);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
async revokeBranchPermissions(branchId, companyId) {
|
|
923
|
+
if (!this.iamConfigService.isCompanyFeatureEnabled()) {
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
const permissionRepo = await this.getPermissionRepository();
|
|
927
|
+
const where = {
|
|
928
|
+
permissionType: (0, _typeorm.In)([
|
|
929
|
+
_iampermissiontypeenum.IamPermissionType.USER_ROLE,
|
|
930
|
+
_iampermissiontypeenum.IamPermissionType.USER_ACTION
|
|
931
|
+
]),
|
|
932
|
+
branchId,
|
|
933
|
+
companyId
|
|
934
|
+
};
|
|
935
|
+
const affectedUserRows = await permissionRepo.find({
|
|
936
|
+
where,
|
|
937
|
+
select: [
|
|
938
|
+
'userId'
|
|
939
|
+
]
|
|
940
|
+
});
|
|
941
|
+
const affectedUserIds = [
|
|
942
|
+
...new Set(affectedUserRows.map((row)=>row.userId).filter((id)=>!!id))
|
|
943
|
+
];
|
|
944
|
+
await permissionRepo.delete(where);
|
|
945
|
+
if (affectedUserIds.length > 0) {
|
|
946
|
+
await this.permissionCacheService.invalidateUsers(affectedUserIds, companyId, [
|
|
947
|
+
branchId
|
|
948
|
+
]);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
async revokeUserCompanyAccess(userId, companyId) {
|
|
952
|
+
const permissionRepo = await this.getPermissionRepository();
|
|
953
|
+
await permissionRepo.delete({
|
|
954
|
+
permissionType: (0, _typeorm.In)([
|
|
955
|
+
_iampermissiontypeenum.IamPermissionType.USER_ROLE,
|
|
956
|
+
_iampermissiontypeenum.IamPermissionType.USER_ACTION
|
|
957
|
+
]),
|
|
958
|
+
sourceType: _iamentitytypeenum.IamEntityType.USER,
|
|
959
|
+
sourceId: userId,
|
|
960
|
+
companyId
|
|
961
|
+
});
|
|
962
|
+
await this.permissionCacheService.invalidateUser(userId, companyId);
|
|
963
|
+
}
|
|
964
|
+
async revokeUserBranchAccess(userId, branchId, companyId) {
|
|
965
|
+
const permissionRepo = await this.getPermissionRepository();
|
|
966
|
+
const where = {
|
|
967
|
+
permissionType: (0, _typeorm.In)([
|
|
968
|
+
_iampermissiontypeenum.IamPermissionType.USER_ROLE,
|
|
969
|
+
_iampermissiontypeenum.IamPermissionType.USER_ACTION
|
|
970
|
+
]),
|
|
971
|
+
sourceType: _iamentitytypeenum.IamEntityType.USER,
|
|
972
|
+
sourceId: userId,
|
|
973
|
+
branchId,
|
|
974
|
+
companyId
|
|
975
|
+
};
|
|
976
|
+
await permissionRepo.delete(where);
|
|
977
|
+
await this.permissionCacheService.invalidateUser(userId, companyId, [
|
|
978
|
+
branchId
|
|
979
|
+
]);
|
|
980
|
+
}
|
|
908
981
|
// NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
|
|
909
982
|
constructor(permissionCacheService, iamConfigService, dataSourceProvider){
|
|
910
983
|
_define_property(this, "permissionCacheService", void 0);
|
|
@@ -959,6 +1032,54 @@ _ts_decorate([
|
|
|
959
1032
|
]),
|
|
960
1033
|
_ts_metadata("design:returntype", Promise)
|
|
961
1034
|
], PermissionService.prototype, "assignUserRoles", null);
|
|
1035
|
+
_ts_decorate([
|
|
1036
|
+
(0, _nestjsshared.LogAction)({
|
|
1037
|
+
action: 'iam.revokeCompanyPermissions',
|
|
1038
|
+
module: 'iam'
|
|
1039
|
+
}),
|
|
1040
|
+
_ts_metadata("design:type", Function),
|
|
1041
|
+
_ts_metadata("design:paramtypes", [
|
|
1042
|
+
String
|
|
1043
|
+
]),
|
|
1044
|
+
_ts_metadata("design:returntype", Promise)
|
|
1045
|
+
], PermissionService.prototype, "revokeCompanyPermissions", null);
|
|
1046
|
+
_ts_decorate([
|
|
1047
|
+
(0, _nestjsshared.LogAction)({
|
|
1048
|
+
action: 'iam.revokeBranchPermissions',
|
|
1049
|
+
module: 'iam'
|
|
1050
|
+
}),
|
|
1051
|
+
_ts_metadata("design:type", Function),
|
|
1052
|
+
_ts_metadata("design:paramtypes", [
|
|
1053
|
+
String,
|
|
1054
|
+
String
|
|
1055
|
+
]),
|
|
1056
|
+
_ts_metadata("design:returntype", Promise)
|
|
1057
|
+
], PermissionService.prototype, "revokeBranchPermissions", null);
|
|
1058
|
+
_ts_decorate([
|
|
1059
|
+
(0, _nestjsshared.LogAction)({
|
|
1060
|
+
action: 'iam.revokeUserCompanyAccess',
|
|
1061
|
+
module: 'iam'
|
|
1062
|
+
}),
|
|
1063
|
+
_ts_metadata("design:type", Function),
|
|
1064
|
+
_ts_metadata("design:paramtypes", [
|
|
1065
|
+
String,
|
|
1066
|
+
String
|
|
1067
|
+
]),
|
|
1068
|
+
_ts_metadata("design:returntype", Promise)
|
|
1069
|
+
], PermissionService.prototype, "revokeUserCompanyAccess", null);
|
|
1070
|
+
_ts_decorate([
|
|
1071
|
+
(0, _nestjsshared.LogAction)({
|
|
1072
|
+
action: 'iam.revokeUserBranchAccess',
|
|
1073
|
+
module: 'iam'
|
|
1074
|
+
}),
|
|
1075
|
+
_ts_metadata("design:type", Function),
|
|
1076
|
+
_ts_metadata("design:paramtypes", [
|
|
1077
|
+
String,
|
|
1078
|
+
String,
|
|
1079
|
+
String
|
|
1080
|
+
]),
|
|
1081
|
+
_ts_metadata("design:returntype", Promise)
|
|
1082
|
+
], PermissionService.prototype, "revokeUserBranchAccess", null);
|
|
962
1083
|
PermissionService = _ts_decorate([
|
|
963
1084
|
(0, _common.Injectable)({
|
|
964
1085
|
scope: _common.Scope.REQUEST
|
|
@@ -12,10 +12,16 @@ const _classes = require("@flusys/nestjs-shared/classes");
|
|
|
12
12
|
const _modules = require("@flusys/nestjs-shared/modules");
|
|
13
13
|
const _utils = require("@flusys/nestjs-shared/utils");
|
|
14
14
|
const _common = require("@nestjs/common");
|
|
15
|
+
const _typeorm = require("typeorm");
|
|
16
|
+
const _permissionwithcompanyentity = require("../entities/permission-with-company.entity");
|
|
15
17
|
const _rolewithcompanyentity = require("../entities/role-with-company.entity");
|
|
16
18
|
const _roleentity = require("../entities/role.entity");
|
|
19
|
+
const _useriampermissionentity = require("../entities/user-iam-permission.entity");
|
|
20
|
+
const _iamentitytypeenum = require("../enums/iam-entity-type.enum");
|
|
21
|
+
const _iampermissiontypeenum = require("../enums/iam-permission-type.enum");
|
|
17
22
|
const _iamconfigservice = require("./iam-config.service");
|
|
18
23
|
const _iamdatasourceservice = require("./iam-datasource.service");
|
|
24
|
+
const _permissioncacheservice = require("./permission-cache.service");
|
|
19
25
|
function _define_property(obj, key, value) {
|
|
20
26
|
if (key in obj) {
|
|
21
27
|
Object.defineProperty(obj, key, {
|
|
@@ -44,6 +50,42 @@ function _ts_param(paramIndex, decorator) {
|
|
|
44
50
|
};
|
|
45
51
|
}
|
|
46
52
|
let RoleService = class RoleService extends _classes.ApiService {
|
|
53
|
+
async beforeDeleteOperation(dto, user, queryRunner) {
|
|
54
|
+
await super.beforeDeleteOperation(dto, user, queryRunner);
|
|
55
|
+
const roleIds = Array.isArray(dto.id) ? dto.id : [
|
|
56
|
+
dto.id
|
|
57
|
+
];
|
|
58
|
+
if (roleIds.length === 0) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
|
|
62
|
+
const permissionEntity = enableCompanyFeature ? _permissionwithcompanyentity.UserIamPermissionWithCompany : _useriampermissionentity.UserIamPermission;
|
|
63
|
+
const permissionRepo = queryRunner.manager.getRepository(permissionEntity);
|
|
64
|
+
const userRoleRows = await permissionRepo.find({
|
|
65
|
+
where: {
|
|
66
|
+
permissionType: _iampermissiontypeenum.IamPermissionType.USER_ROLE,
|
|
67
|
+
sourceType: _iamentitytypeenum.IamEntityType.USER,
|
|
68
|
+
targetType: _iamentitytypeenum.IamEntityType.ROLE,
|
|
69
|
+
targetId: (0, _typeorm.In)(roleIds)
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const affectedUserIds = [
|
|
73
|
+
...new Set(userRoleRows.map((row)=>row.userId).filter((id)=>!!id))
|
|
74
|
+
];
|
|
75
|
+
await permissionRepo.delete({
|
|
76
|
+
permissionType: _iampermissiontypeenum.IamPermissionType.ROLE_ACTION,
|
|
77
|
+
sourceType: _iamentitytypeenum.IamEntityType.ROLE,
|
|
78
|
+
sourceId: (0, _typeorm.In)(roleIds)
|
|
79
|
+
});
|
|
80
|
+
await permissionRepo.delete({
|
|
81
|
+
permissionType: _iampermissiontypeenum.IamPermissionType.USER_ROLE,
|
|
82
|
+
targetType: _iamentitytypeenum.IamEntityType.ROLE,
|
|
83
|
+
targetId: (0, _typeorm.In)(roleIds)
|
|
84
|
+
});
|
|
85
|
+
if (affectedUserIds.length > 0) {
|
|
86
|
+
await this.permissionCacheService.invalidateUsers(affectedUserIds);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
47
89
|
resolveEntity() {
|
|
48
90
|
return this.iamConfigService.isCompanyFeatureEnabled() ? _rolewithcompanyentity.RoleWithCompany : _roleentity.Role;
|
|
49
91
|
}
|
|
@@ -117,8 +159,8 @@ let RoleService = class RoleService extends _classes.ApiService {
|
|
|
117
159
|
deletedById: entity.deletedById
|
|
118
160
|
};
|
|
119
161
|
}
|
|
120
|
-
constructor(cacheManager, utilsService, iamConfigService, dataSourceProvider){
|
|
121
|
-
super('role', cacheManager, utilsService, RoleService.name, true, 'iam', undefined, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "iamConfigService", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.iamConfigService = iamConfigService;
|
|
162
|
+
constructor(cacheManager, utilsService, iamConfigService, dataSourceProvider, permissionCacheService){
|
|
163
|
+
super('role', cacheManager, utilsService, RoleService.name, true, 'iam', undefined, dataSourceProvider), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "iamConfigService", void 0), _define_property(this, "permissionCacheService", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.iamConfigService = iamConfigService, this.permissionCacheService = permissionCacheService;
|
|
122
164
|
}
|
|
123
165
|
};
|
|
124
166
|
RoleService = _ts_decorate([
|
|
@@ -129,11 +171,13 @@ RoleService = _ts_decorate([
|
|
|
129
171
|
_ts_param(1, (0, _common.Inject)(_modules.UtilsService)),
|
|
130
172
|
_ts_param(2, (0, _common.Inject)(_iamconfigservice.IAMConfigService)),
|
|
131
173
|
_ts_param(3, (0, _common.Inject)(_iamdatasourceservice.IAMDataSourceService)),
|
|
174
|
+
_ts_param(4, (0, _common.Inject)(_permissioncacheservice.PermissionCacheService)),
|
|
132
175
|
_ts_metadata("design:type", Function),
|
|
133
176
|
_ts_metadata("design:paramtypes", [
|
|
134
177
|
typeof _classes.HybridCache === "undefined" ? Object : _classes.HybridCache,
|
|
135
178
|
typeof _modules.UtilsService === "undefined" ? Object : _modules.UtilsService,
|
|
136
179
|
typeof _iamconfigservice.IAMConfigService === "undefined" ? Object : _iamconfigservice.IAMConfigService,
|
|
137
|
-
typeof _iamdatasourceservice.IAMDataSourceService === "undefined" ? Object : _iamdatasourceservice.IAMDataSourceService
|
|
180
|
+
typeof _iamdatasourceservice.IAMDataSourceService === "undefined" ? Object : _iamdatasourceservice.IAMDataSourceService,
|
|
181
|
+
typeof _permissioncacheservice.PermissionCacheService === "undefined" ? Object : _permissioncacheservice.PermissionCacheService
|
|
138
182
|
])
|
|
139
183
|
], RoleService);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ILoggedUserInfo, SingleResponseDto } from '@flusys/nestjs-shared';
|
|
2
|
-
import { ActionResponseDto, ActionTreeQueryDto, CreateActionDto, UpdateActionDto } from '../dtos/action.dto';
|
|
2
|
+
import { ActionResponseDto, ActionTreeForPermissionDto, ActionTreeQueryDto, CreateActionDto, UpdateActionDto } from '../dtos/action.dto';
|
|
3
3
|
import { ActionService } from '../services/action.service';
|
|
4
|
+
import { IAMConfigService } from '../services/iam-config.service';
|
|
4
5
|
declare const ActionController_base: abstract new (service: ActionService) => {
|
|
5
6
|
readonly enabledEndpoints: import("@flusys/nestjs-shared").ApiEndpoint[] | "all";
|
|
6
7
|
service: ActionService;
|
|
@@ -18,8 +19,9 @@ declare const ActionController_base: abstract new (service: ActionService) => {
|
|
|
18
19
|
};
|
|
19
20
|
export declare class ActionController extends ActionController_base {
|
|
20
21
|
actionService: ActionService;
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
private readonly iamConfigService;
|
|
23
|
+
constructor(actionService: ActionService, iamConfigService: IAMConfigService);
|
|
24
|
+
getActionsForPermission(dto: ActionTreeForPermissionDto, user: ILoggedUserInfo): Promise<SingleResponseDto<ActionResponseDto[]>>;
|
|
23
25
|
getActionTree(query: ActionTreeQueryDto, user: ILoggedUserInfo): Promise<SingleResponseDto<ActionResponseDto[]>>;
|
|
24
26
|
}
|
|
25
27
|
export {};
|
package/dtos/action.dto.d.ts
CHANGED
|
@@ -29,6 +29,9 @@ export declare class ActionResponseDto extends IdentityResponseDto {
|
|
|
29
29
|
export declare class ActionTreeDto extends ActionResponseDto {
|
|
30
30
|
children: ActionTreeDto[];
|
|
31
31
|
}
|
|
32
|
+
export declare class ActionTreeForPermissionDto {
|
|
33
|
+
companyId?: string;
|
|
34
|
+
}
|
|
32
35
|
export declare class ActionTreeQueryDto {
|
|
33
36
|
search?: string;
|
|
34
37
|
isActive?: boolean;
|
package/entities/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { UserIamPermissionWithCompany } from './permission-with-company.entity';
|
|
|
9
9
|
import { RoleWithCompany } from './role-with-company.entity';
|
|
10
10
|
import { Role } from './role.entity';
|
|
11
11
|
import { UserIamPermission } from './user-iam-permission.entity';
|
|
12
|
-
export declare const IAMCoreEntities: (typeof
|
|
12
|
+
export declare const IAMCoreEntities: (typeof UserIamPermission | typeof Role)[];
|
|
13
13
|
export declare const IAMCompanyEntities: (typeof UserIamPermissionWithCompany | typeof RoleWithCompany)[];
|
|
14
|
-
export declare const IAMAllEntities: (typeof
|
|
14
|
+
export declare const IAMAllEntities: (typeof UserIamPermission | typeof Role)[];
|
|
15
15
|
export declare function getIAMEntitiesByConfig(enableCompanyFeature: boolean, permissionMode?: 'FULL' | 'RBAC' | 'DIRECT'): any[];
|
|
@@ -25,13 +25,14 @@ function _ts_param(paramIndex, decorator) {
|
|
|
25
25
|
decorator(target, key, paramIndex);
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
+
import { ACTION_PERMISSIONS, createApiController, CurrentUser, ILoggedUserInfo, SingleResponseDto } from '@flusys/nestjs-shared';
|
|
28
29
|
import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
|
|
29
|
-
import { createApiController, CurrentUser, ILoggedUserInfo, SingleResponseDto, ACTION_PERMISSIONS } from '@flusys/nestjs-shared';
|
|
30
|
-
import { ACTION_MESSAGES } from '../config';
|
|
31
30
|
import { Body, Controller, Inject, Post, UseGuards } from '@nestjs/common';
|
|
32
31
|
import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
|
33
|
-
import {
|
|
32
|
+
import { ACTION_MESSAGES } from '../config';
|
|
33
|
+
import { ActionResponseDto, ActionTreeForPermissionDto, ActionTreeQueryDto, CreateActionDto, UpdateActionDto } from '../dtos/action.dto';
|
|
34
34
|
import { ActionService } from '../services/action.service';
|
|
35
|
+
import { IAMConfigService } from '../services/iam-config.service';
|
|
35
36
|
export class ActionController extends createApiController(CreateActionDto, UpdateActionDto, ActionResponseDto, {
|
|
36
37
|
entityName: 'action',
|
|
37
38
|
security: {
|
|
@@ -79,8 +80,8 @@ export class ActionController extends createApiController(CreateActionDto, Updat
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
}) {
|
|
82
|
-
async getActionsForPermission(user) {
|
|
83
|
-
const actions = await this.actionService.getActionsForPermission(user);
|
|
83
|
+
async getActionsForPermission(dto, user) {
|
|
84
|
+
const actions = await this.actionService.getActionsForPermission(user, dto?.companyId);
|
|
84
85
|
return {
|
|
85
86
|
success: true,
|
|
86
87
|
message: 'Actions retrieved successfully',
|
|
@@ -97,8 +98,8 @@ export class ActionController extends createApiController(CreateActionDto, Updat
|
|
|
97
98
|
data: tree
|
|
98
99
|
};
|
|
99
100
|
}
|
|
100
|
-
constructor(actionService){
|
|
101
|
-
super(actionService), _define_property(this, "actionService", void 0), this.actionService = actionService;
|
|
101
|
+
constructor(actionService, iamConfigService){
|
|
102
|
+
super(actionService), _define_property(this, "actionService", void 0), _define_property(this, "iamConfigService", void 0), this.actionService = actionService, this.iamConfigService = iamConfigService;
|
|
102
103
|
}
|
|
103
104
|
}
|
|
104
105
|
_ts_decorate([
|
|
@@ -107,15 +108,20 @@ _ts_decorate([
|
|
|
107
108
|
ApiBearerAuth(),
|
|
108
109
|
ApiOperation({
|
|
109
110
|
summary: 'Get actions for permission assignment',
|
|
110
|
-
description:
|
|
111
|
+
description: "Returns actions available for permission assignment, filtered by company whitelist when company feature is enabled. Optional companyId scopes the whitelist to a specific company (must match the caller's own company); defaults to the caller's session company when omitted."
|
|
111
112
|
}),
|
|
112
113
|
ApiResponse({
|
|
113
114
|
status: 200,
|
|
114
115
|
type: SingleResponseDto
|
|
115
116
|
}),
|
|
116
|
-
|
|
117
|
+
ApiBody({
|
|
118
|
+
type: ActionTreeForPermissionDto
|
|
119
|
+
}),
|
|
120
|
+
_ts_param(0, Body()),
|
|
121
|
+
_ts_param(1, CurrentUser()),
|
|
117
122
|
_ts_metadata("design:type", Function),
|
|
118
123
|
_ts_metadata("design:paramtypes", [
|
|
124
|
+
typeof ActionTreeForPermissionDto === "undefined" ? Object : ActionTreeForPermissionDto,
|
|
119
125
|
typeof ILoggedUserInfo === "undefined" ? Object : ILoggedUserInfo
|
|
120
126
|
]),
|
|
121
127
|
_ts_metadata("design:returntype", Promise)
|
|
@@ -149,8 +155,10 @@ ActionController = _ts_decorate([
|
|
|
149
155
|
ApiTags('IAM - Actions'),
|
|
150
156
|
Controller('iam/actions'),
|
|
151
157
|
_ts_param(0, Inject(ActionService)),
|
|
158
|
+
_ts_param(1, Inject(IAMConfigService)),
|
|
152
159
|
_ts_metadata("design:type", Function),
|
|
153
160
|
_ts_metadata("design:paramtypes", [
|
|
154
|
-
typeof ActionService === "undefined" ? Object : ActionService
|
|
161
|
+
typeof ActionService === "undefined" ? Object : ActionService,
|
|
162
|
+
typeof IAMConfigService === "undefined" ? Object : IAMConfigService
|
|
155
163
|
])
|
|
156
164
|
], ActionController);
|