@flusys/nestjs-iam 7.1.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/config/index.d.ts +3 -3
  2. package/config/message-keys.d.ts +2 -0
  3. package/controllers/action.controller.d.ts +4 -4
  4. package/controllers/company-action-permission.controller.d.ts +2 -2
  5. package/controllers/index.d.ts +6 -6
  6. package/controllers/my-permission.controller.d.ts +3 -3
  7. package/controllers/role-permission.controller.d.ts +5 -4
  8. package/controllers/role.controller.d.ts +2 -2
  9. package/controllers/user-action-permission.controller.d.ts +5 -4
  10. package/docs/iam-swagger.config.d.ts +2 -2
  11. package/docs/index.d.ts +1 -1
  12. package/dtos/action.dto.d.ts +2 -2
  13. package/dtos/index.d.ts +3 -3
  14. package/dtos/permission.dto.d.ts +16 -0
  15. package/entities/action.entity.d.ts +2 -2
  16. package/entities/index.d.ts +11 -11
  17. package/entities/permission-with-company.entity.d.ts +1 -1
  18. package/entities/role-with-company.entity.d.ts +1 -1
  19. package/entities/role.entity.d.ts +1 -1
  20. package/entities/user-iam-permission.entity.d.ts +1 -1
  21. package/enums/index.d.ts +4 -4
  22. package/fesm/284.js +1316 -0
  23. package/fesm/867.js +3801 -0
  24. package/fesm/chunks/364.js +86 -0
  25. package/fesm/config/index.js +135 -3
  26. package/fesm/controllers/index.js +18 -7
  27. package/fesm/docs/index.js +240 -1
  28. package/fesm/dtos/index.js +1168 -3
  29. package/fesm/entities/index.js +670 -31
  30. package/fesm/enums/index.js +97 -4
  31. package/fesm/helpers/index.js +125 -2
  32. package/fesm/index.js +818 -11
  33. package/fesm/interfaces/index.js +17 -3
  34. package/fesm/modules/index.js +259 -1
  35. package/fesm/runtime.js +134 -0
  36. package/fesm/services/index.js +43 -6
  37. package/fesm/types/index.js +15 -1
  38. package/helpers/company-access.helper.d.ts +2 -2
  39. package/helpers/index.d.ts +2 -2
  40. package/helpers/permission-mode.helper.d.ts +1 -1
  41. package/index.d.ts +11 -11
  42. package/interfaces/action.interface.d.ts +2 -2
  43. package/interfaces/iam-module-options.interface.d.ts +3 -3
  44. package/interfaces/index.d.ts +3 -3
  45. package/modules/iam.module.d.ts +2 -2
  46. package/modules/index.d.ts +1 -1
  47. package/package.json +30 -37
  48. package/services/action.service.d.ts +9 -9
  49. package/services/iam-config.service.d.ts +4 -4
  50. package/services/iam-datasource.service.d.ts +3 -3
  51. package/services/index.d.ts +6 -6
  52. package/services/permission-cache.service.d.ts +5 -5
  53. package/services/permission.service.d.ts +6 -4
  54. package/services/role.service.d.ts +8 -8
  55. package/types/index.d.ts +1 -1
  56. package/cjs/config/event-actions.js +0 -36
  57. package/cjs/config/iam.constants.js +0 -11
  58. package/cjs/config/index.js +0 -20
  59. package/cjs/config/message-keys.js +0 -71
  60. package/cjs/controllers/action.controller.js +0 -174
  61. package/cjs/controllers/action.controller.spec.js +0 -79
  62. package/cjs/controllers/company-action-permission.controller.js +0 -119
  63. package/cjs/controllers/company-action-permission.controller.spec.js +0 -65
  64. package/cjs/controllers/index.js +0 -23
  65. package/cjs/controllers/my-permission.controller.js +0 -147
  66. package/cjs/controllers/my-permission.controller.spec.js +0 -128
  67. package/cjs/controllers/role-permission.controller.js +0 -191
  68. package/cjs/controllers/role-permission.controller.spec.js +0 -140
  69. package/cjs/controllers/role.controller.js +0 -102
  70. package/cjs/controllers/role.controller.spec.js +0 -86
  71. package/cjs/controllers/user-action-permission.controller.js +0 -129
  72. package/cjs/controllers/user-action-permission.controller.spec.js +0 -68
  73. package/cjs/docs/iam-swagger.config.js +0 -209
  74. package/cjs/docs/iam-swagger.config.spec.js +0 -99
  75. package/cjs/docs/index.js +0 -18
  76. package/cjs/dtos/action.dto.js +0 -282
  77. package/cjs/dtos/index.js +0 -21
  78. package/cjs/dtos/permission.dto.js +0 -637
  79. package/cjs/dtos/role.dto.js +0 -155
  80. package/cjs/entities/action.entity.js +0 -138
  81. package/cjs/entities/index.js +0 -80
  82. package/cjs/entities/index.spec.js +0 -56
  83. package/cjs/entities/permission-base.entity.js +0 -107
  84. package/cjs/entities/permission-with-company.entity.js +0 -100
  85. package/cjs/entities/role-base.entity.js +0 -80
  86. package/cjs/entities/role-with-company.entity.js +0 -55
  87. package/cjs/entities/role.entity.js +0 -25
  88. package/cjs/entities/user-iam-permission.entity.js +0 -43
  89. package/cjs/enums/action-type.enum.js +0 -22
  90. package/cjs/enums/iam-entity-type.enum.js +0 -17
  91. package/cjs/enums/iam-permission-type.enum.js +0 -17
  92. package/cjs/enums/index.js +0 -21
  93. package/cjs/enums/permission-type.enum.js +0 -16
  94. package/cjs/helpers/company-access.helper.js +0 -23
  95. package/cjs/helpers/company-access.helper.spec.js +0 -68
  96. package/cjs/helpers/index.js +0 -19
  97. package/cjs/helpers/permission-mode.helper.js +0 -49
  98. package/cjs/helpers/permission-mode.helper.spec.js +0 -54
  99. package/cjs/index.js +0 -28
  100. package/cjs/interfaces/action.interface.js +0 -4
  101. package/cjs/interfaces/iam-module-options.interface.js +0 -4
  102. package/cjs/interfaces/index.js +0 -20
  103. package/cjs/interfaces/role.interface.js +0 -7
  104. package/cjs/modules/iam.module.js +0 -186
  105. package/cjs/modules/iam.module.spec.js +0 -282
  106. package/cjs/modules/index.js +0 -18
  107. package/cjs/services/action.service.js +0 -337
  108. package/cjs/services/action.service.spec.js +0 -351
  109. package/cjs/services/iam-config.service.js +0 -87
  110. package/cjs/services/iam-config.service.spec.js +0 -110
  111. package/cjs/services/iam-datasource.service.js +0 -129
  112. package/cjs/services/iam-datasource.service.spec.js +0 -110
  113. package/cjs/services/index.js +0 -23
  114. package/cjs/services/permission-cache.service.js +0 -544
  115. package/cjs/services/permission-cache.service.spec.js +0 -718
  116. package/cjs/services/permission.service.js +0 -914
  117. package/cjs/services/permission.service.spec.js +0 -918
  118. package/cjs/services/role.service.js +0 -224
  119. package/cjs/services/role.service.spec.js +0 -347
  120. package/cjs/types/index.js +0 -18
  121. package/cjs/types/logic-node.type.js +0 -30
  122. package/fesm/config/event-actions.js +0 -15
  123. package/fesm/config/iam.constants.js +0 -1
  124. package/fesm/config/message-keys.js +0 -35
  125. package/fesm/controllers/action.controller.js +0 -164
  126. package/fesm/controllers/action.controller.spec.js +0 -75
  127. package/fesm/controllers/company-action-permission.controller.js +0 -109
  128. package/fesm/controllers/company-action-permission.controller.spec.js +0 -61
  129. package/fesm/controllers/my-permission.controller.js +0 -137
  130. package/fesm/controllers/my-permission.controller.spec.js +0 -124
  131. package/fesm/controllers/role-permission.controller.js +0 -181
  132. package/fesm/controllers/role-permission.controller.spec.js +0 -136
  133. package/fesm/controllers/role.controller.js +0 -92
  134. package/fesm/controllers/role.controller.spec.js +0 -82
  135. package/fesm/controllers/user-action-permission.controller.js +0 -119
  136. package/fesm/controllers/user-action-permission.controller.spec.js +0 -64
  137. package/fesm/docs/iam-swagger.config.js +0 -199
  138. package/fesm/docs/iam-swagger.config.spec.js +0 -95
  139. package/fesm/dtos/action.dto.js +0 -252
  140. package/fesm/dtos/permission.dto.js +0 -571
  141. package/fesm/dtos/role.dto.js +0 -134
  142. package/fesm/entities/action.entity.js +0 -128
  143. package/fesm/entities/index.spec.js +0 -52
  144. package/fesm/entities/permission-base.entity.js +0 -100
  145. package/fesm/entities/permission-with-company.entity.js +0 -90
  146. package/fesm/entities/role-base.entity.js +0 -70
  147. package/fesm/entities/role-with-company.entity.js +0 -45
  148. package/fesm/entities/role.entity.js +0 -15
  149. package/fesm/entities/user-iam-permission.entity.js +0 -33
  150. package/fesm/enums/action-type.enum.js +0 -12
  151. package/fesm/enums/iam-entity-type.enum.js +0 -7
  152. package/fesm/enums/iam-permission-type.enum.js +0 -7
  153. package/fesm/enums/permission-type.enum.js +0 -6
  154. package/fesm/helpers/company-access.helper.js +0 -18
  155. package/fesm/helpers/company-access.helper.spec.js +0 -64
  156. package/fesm/helpers/permission-mode.helper.js +0 -49
  157. package/fesm/helpers/permission-mode.helper.spec.js +0 -50
  158. package/fesm/interfaces/action.interface.js +0 -3
  159. package/fesm/interfaces/iam-module-options.interface.js +0 -3
  160. package/fesm/interfaces/role.interface.js +0 -4
  161. package/fesm/modules/iam.module.js +0 -176
  162. package/fesm/modules/iam.module.spec.js +0 -278
  163. package/fesm/services/action.service.js +0 -327
  164. package/fesm/services/action.service.spec.js +0 -347
  165. package/fesm/services/iam-config.service.js +0 -77
  166. package/fesm/services/iam-config.service.spec.js +0 -106
  167. package/fesm/services/iam-datasource.service.js +0 -78
  168. package/fesm/services/iam-datasource.service.spec.js +0 -106
  169. package/fesm/services/permission-cache.service.js +0 -527
  170. package/fesm/services/permission-cache.service.spec.js +0 -714
  171. package/fesm/services/permission.service.js +0 -904
  172. package/fesm/services/permission.service.spec.js +0 -914
  173. package/fesm/services/role.service.js +0 -214
  174. package/fesm/services/role.service.spec.js +0 -343
  175. package/fesm/types/logic-node.type.js +0 -27
@@ -1,224 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "RoleService", {
6
- enumerable: true,
7
- get: function() {
8
- return RoleService;
9
- }
10
- });
11
- const _classes = require("@flusys/nestjs-shared/classes");
12
- const _modules = require("@flusys/nestjs-shared/modules");
13
- const _utils = require("@flusys/nestjs-shared/utils");
14
- const _common = require("@nestjs/common");
15
- const _typeorm = require("typeorm");
16
- const _config = require("../config");
17
- const _permissionwithcompanyentity = require("../entities/permission-with-company.entity");
18
- const _rolewithcompanyentity = require("../entities/role-with-company.entity");
19
- const _roleentity = require("../entities/role.entity");
20
- const _useriampermissionentity = require("../entities/user-iam-permission.entity");
21
- const _iamentitytypeenum = require("../enums/iam-entity-type.enum");
22
- const _iampermissiontypeenum = require("../enums/iam-permission-type.enum");
23
- const _iamconfigservice = require("./iam-config.service");
24
- const _iamdatasourceservice = require("./iam-datasource.service");
25
- const _permissioncacheservice = require("./permission-cache.service");
26
- function _define_property(obj, key, value) {
27
- if (key in obj) {
28
- Object.defineProperty(obj, key, {
29
- value: value,
30
- enumerable: true,
31
- configurable: true,
32
- writable: true
33
- });
34
- } else {
35
- obj[key] = value;
36
- }
37
- return obj;
38
- }
39
- function _ts_decorate(decorators, target, key, desc) {
40
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
41
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
42
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
43
- return c > 3 && r && Object.defineProperty(target, key, r), r;
44
- }
45
- function _ts_metadata(k, v) {
46
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
47
- }
48
- function _ts_param(paramIndex, decorator) {
49
- return function(target, key) {
50
- decorator(target, key, paramIndex);
51
- };
52
- }
53
- let RoleService = class RoleService extends _classes.ApiService {
54
- async beforeUpdateOperation(dto, _user, _queryRunner) {
55
- const dtos = Array.isArray(dto) ? dto : [
56
- dto
57
- ];
58
- const ids = dtos.map((d)=>d.id);
59
- await this.ensureDataSourceRepository();
60
- const readonlyRoles = await this.repository.find({
61
- where: {
62
- id: (0, _typeorm.In)(ids),
63
- readOnly: true,
64
- deletedAt: (0, _typeorm.IsNull)()
65
- }
66
- });
67
- if (readonlyRoles.length > 0) {
68
- const names = readonlyRoles.map((r)=>r.name).join(', ');
69
- throw new _common.ForbiddenException({
70
- message: `Cannot modify readonly role(s): ${names}`,
71
- messageKey: _config.ROLE_MESSAGES.READONLY_UPDATE_FORBIDDEN,
72
- messageVariables: {
73
- names
74
- }
75
- });
76
- }
77
- }
78
- async beforeDeleteOperation(dto, user, queryRunner) {
79
- await super.beforeDeleteOperation(dto, user, queryRunner);
80
- const roleIds = Array.isArray(dto.id) ? dto.id : [
81
- dto.id
82
- ];
83
- if (roleIds.length === 0) {
84
- return;
85
- }
86
- await this.ensureDataSourceRepository();
87
- const readonlyRoles = await this.repository.find({
88
- where: {
89
- id: (0, _typeorm.In)(roleIds),
90
- readOnly: true,
91
- deletedAt: (0, _typeorm.IsNull)()
92
- }
93
- });
94
- if (readonlyRoles.length > 0) {
95
- const names = readonlyRoles.map((r)=>r.name).join(', ');
96
- throw new _common.ForbiddenException({
97
- message: `Cannot delete readonly role(s): ${names}`,
98
- messageKey: _config.ROLE_MESSAGES.READONLY_DELETE_FORBIDDEN,
99
- messageVariables: {
100
- names
101
- }
102
- });
103
- }
104
- const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
105
- const permissionEntity = enableCompanyFeature ? _permissionwithcompanyentity.UserIamPermissionWithCompany : _useriampermissionentity.UserIamPermission;
106
- const permissionRepo = queryRunner.manager.getRepository(permissionEntity);
107
- const userRoleRows = await permissionRepo.find({
108
- where: {
109
- permissionType: _iampermissiontypeenum.IamPermissionType.USER_ROLE,
110
- sourceType: _iamentitytypeenum.IamEntityType.USER,
111
- targetType: _iamentitytypeenum.IamEntityType.ROLE,
112
- targetId: (0, _typeorm.In)(roleIds)
113
- }
114
- });
115
- const affectedUserIds = [
116
- ...new Set(userRoleRows.map((row)=>row.sourceId))
117
- ];
118
- await permissionRepo.delete({
119
- permissionType: _iampermissiontypeenum.IamPermissionType.ROLE_ACTION,
120
- sourceType: _iamentitytypeenum.IamEntityType.ROLE,
121
- sourceId: (0, _typeorm.In)(roleIds)
122
- });
123
- await permissionRepo.delete({
124
- permissionType: _iampermissiontypeenum.IamPermissionType.USER_ROLE,
125
- targetType: _iamentitytypeenum.IamEntityType.ROLE,
126
- targetId: (0, _typeorm.In)(roleIds)
127
- });
128
- if (affectedUserIds.length > 0) {
129
- await this.permissionCacheService.invalidateUsers(affectedUserIds);
130
- }
131
- }
132
- // Entity Conversion
133
- async convertSingleDtoToEntity(dto, user) {
134
- const entity = await super.convertSingleDtoToEntity(dto, user);
135
- // Handle companyId based on company feature
136
- if (this.iamConfigService.isCompanyFeatureEnabled()) {
137
- const isUpdate = 'id' in dto && dto.id;
138
- // For create: use dto.companyId or user's companyId
139
- // For update: only override if explicitly provided
140
- if (!isUpdate || dto.companyId !== undefined) {
141
- entity.companyId = dto.companyId ?? user?.companyId ?? null;
142
- }
143
- }
144
- return entity;
145
- }
146
- // Query Customization
147
- async getSelectQuery(query, _user, select) {
148
- if (!select?.length) {
149
- select = [
150
- 'id',
151
- 'name',
152
- 'description',
153
- 'isActive',
154
- 'readOnly',
155
- 'serial',
156
- 'createdAt'
157
- ];
158
- if (this.iamConfigService.isCompanyFeatureEnabled()) {
159
- select.push('companyId');
160
- }
161
- }
162
- query.select(select.map((f)=>`${this.entityName}.${f}`));
163
- return {
164
- query,
165
- isRaw: false
166
- };
167
- }
168
- async getGlobalSearchQuery(query, search) {
169
- query.andWhere('(role.name LIKE :search OR role.description LIKE :search)', {
170
- search: `%${search}%`
171
- });
172
- return {
173
- query,
174
- isRaw: false
175
- };
176
- }
177
- async getExtraManipulateQuery(query, filterDto, user) {
178
- const result = await super.getExtraManipulateQuery(query, filterDto, user);
179
- (0, _utils.applyCompanyFilter)(query, {
180
- isCompanyFeatureEnabled: this.iamConfigService.isCompanyFeatureEnabled(),
181
- entityAlias: 'role'
182
- }, user);
183
- return result;
184
- }
185
- // Response Conversion
186
- convertEntityToResponseDto(entity, _isRaw) {
187
- return {
188
- id: entity.id,
189
- readOnly: entity.readOnly,
190
- name: entity.name,
191
- description: entity.description,
192
- isActive: entity.isActive,
193
- serial: entity.serial,
194
- companyId: ('companyId' in entity ? entity.companyId : null) ?? null,
195
- createdAt: entity.createdAt,
196
- updatedAt: entity.updatedAt,
197
- deletedAt: entity.deletedAt,
198
- createdById: entity.createdById,
199
- updatedById: entity.updatedById,
200
- deletedById: entity.deletedById
201
- };
202
- }
203
- constructor(cacheManager, utilsService, iamConfigService, dataSourceProvider, permissionCacheService){
204
- super(_config.IAM_EVENT_ENTITIES.ROLE, cacheManager, utilsService, RoleService.name, true, _config.IAM_EVENT_MODULE, dataSourceProvider, iamConfigService.isCompanyFeatureEnabled() ? _rolewithcompanyentity.RoleWithCompany : _roleentity.Role), _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;
205
- }
206
- };
207
- RoleService = _ts_decorate([
208
- (0, _common.Injectable)({
209
- scope: _common.Scope.REQUEST
210
- }),
211
- _ts_param(0, (0, _common.Inject)('CACHE_INSTANCE')),
212
- _ts_param(1, (0, _common.Inject)(_modules.UtilsService)),
213
- _ts_param(2, (0, _common.Inject)(_iamconfigservice.IAMConfigService)),
214
- _ts_param(3, (0, _common.Inject)(_iamdatasourceservice.IAMDataSourceService)),
215
- _ts_param(4, (0, _common.Inject)(_permissioncacheservice.PermissionCacheService)),
216
- _ts_metadata("design:type", Function),
217
- _ts_metadata("design:paramtypes", [
218
- typeof _classes.HybridCache === "undefined" ? Object : _classes.HybridCache,
219
- typeof _modules.UtilsService === "undefined" ? Object : _modules.UtilsService,
220
- typeof _iamconfigservice.IAMConfigService === "undefined" ? Object : _iamconfigservice.IAMConfigService,
221
- typeof _iamdatasourceservice.IAMDataSourceService === "undefined" ? Object : _iamdatasourceservice.IAMDataSourceService,
222
- typeof _permissioncacheservice.PermissionCacheService === "undefined" ? Object : _permissioncacheservice.PermissionCacheService
223
- ])
224
- ], RoleService);
@@ -1,347 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- const _testing = require("@nestjs/testing");
6
- const _modules = require("@flusys/nestjs-shared/modules");
7
- const _repositorymock = require("@test-utils/mocks/repository.mock");
8
- const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
9
- const _roleentity = require("../entities/role.entity");
10
- const _rolewithcompanyentity = require("../entities/role-with-company.entity");
11
- const _iamconfigservice = require("./iam-config.service");
12
- const _iamdatasourceservice = require("./iam-datasource.service");
13
- const _permissioncacheservice = require("./permission-cache.service");
14
- const _roleservice = require("./role.service");
15
- function buildRole(overrides = {}) {
16
- return {
17
- id: 'role-uuid-1',
18
- readOnly: false,
19
- name: 'Manager',
20
- description: null,
21
- isActive: true,
22
- serial: 1,
23
- createdAt: new Date(),
24
- updatedAt: new Date(),
25
- deletedAt: null,
26
- createdById: null,
27
- updatedById: null,
28
- deletedById: null,
29
- ...overrides
30
- };
31
- }
32
- describe('RoleService', ()=>{
33
- let service;
34
- let module;
35
- let mockRepo;
36
- let mockIamConfigService;
37
- let mockPermissionCacheService;
38
- beforeEach(async ()=>{
39
- mockRepo = (0, _repositorymock.createMockRepository)();
40
- mockRepo.find.mockResolvedValue([]);
41
- const mockDataSourceProvider = (0, _repositorymock.createMockDataSourceProvider)(mockRepo);
42
- mockIamConfigService = {
43
- isCompanyFeatureEnabled: jest.fn().mockReturnValue(false)
44
- };
45
- mockPermissionCacheService = {
46
- invalidateUsers: jest.fn()
47
- };
48
- module = await _testing.Test.createTestingModule({
49
- providers: [
50
- _roleservice.RoleService,
51
- {
52
- provide: 'CACHE_INSTANCE',
53
- useValue: {}
54
- },
55
- {
56
- provide: _modules.UtilsService,
57
- useValue: {}
58
- },
59
- {
60
- provide: _iamconfigservice.IAMConfigService,
61
- useValue: mockIamConfigService
62
- },
63
- {
64
- provide: _iamdatasourceservice.IAMDataSourceService,
65
- useValue: mockDataSourceProvider
66
- },
67
- {
68
- provide: _permissioncacheservice.PermissionCacheService,
69
- useValue: mockPermissionCacheService
70
- }
71
- ]
72
- }).compile();
73
- service = await module.resolve(_roleservice.RoleService);
74
- });
75
- describe('entity selection', ()=>{
76
- it('uses Role when the company feature is disabled', async ()=>{
77
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(false);
78
- const built = await module.resolve(_roleservice.RoleService);
79
- expect(built['_entity']).toBe(_roleentity.Role);
80
- });
81
- it('uses RoleWithCompany when the company feature is enabled', async ()=>{
82
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
83
- const built = await module.resolve(_roleservice.RoleService);
84
- expect(built['_entity']).toBe(_rolewithcompanyentity.RoleWithCompany);
85
- });
86
- });
87
- describe('convertSingleDtoToEntity', ()=>{
88
- it('creates a plain entity without companyId when the company feature is disabled', async ()=>{
89
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(false);
90
- await service.ensureDataSourceRepository();
91
- mockRepo.create.mockReturnValue({});
92
- const entity = await service.convertSingleDtoToEntity({
93
- name: 'Manager'
94
- }, (0, _loggedusermock.buildMockUser)());
95
- expect(entity.companyId).toBeUndefined();
96
- });
97
- it('stamps companyId from the DTO on create when the company feature is enabled', async ()=>{
98
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
99
- await service.ensureDataSourceRepository();
100
- mockRepo.create.mockReturnValue({});
101
- const entity = await service.convertSingleDtoToEntity({
102
- name: 'Manager',
103
- companyId: 'company-explicit'
104
- }, (0, _loggedusermock.buildMockUser)({
105
- companyId: 'company-from-user'
106
- }));
107
- expect(entity.companyId).toBe('company-explicit');
108
- });
109
- it('falls back to the user companyId on create when the DTO omits it', async ()=>{
110
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
111
- await service.ensureDataSourceRepository();
112
- mockRepo.create.mockReturnValue({});
113
- const entity = await service.convertSingleDtoToEntity({
114
- name: 'Manager'
115
- }, (0, _loggedusermock.buildMockUser)({
116
- companyId: 'company-from-user'
117
- }));
118
- expect(entity.companyId).toBe('company-from-user');
119
- });
120
- it('does not override companyId on update when the DTO omits it', async ()=>{
121
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
122
- await service.ensureDataSourceRepository();
123
- const existing = buildRole({
124
- id: 'role-uuid-1',
125
- companyId: 'existing-company'
126
- });
127
- mockRepo.findOne.mockResolvedValue(existing);
128
- const entity = await service.convertSingleDtoToEntity({
129
- id: 'role-uuid-1',
130
- name: 'Manager Updated'
131
- }, (0, _loggedusermock.buildMockUser)({
132
- companyId: 'company-from-user'
133
- }));
134
- expect(entity.companyId).toBe('existing-company');
135
- });
136
- it('overrides companyId on update when explicitly provided in the DTO', async ()=>{
137
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
138
- await service.ensureDataSourceRepository();
139
- const existing = buildRole({
140
- id: 'role-uuid-1',
141
- companyId: 'existing-company'
142
- });
143
- mockRepo.findOne.mockResolvedValue(existing);
144
- const entity = await service.convertSingleDtoToEntity({
145
- id: 'role-uuid-1',
146
- name: 'Manager Updated',
147
- companyId: 'new-company'
148
- }, (0, _loggedusermock.buildMockUser)());
149
- expect(entity.companyId).toBe('new-company');
150
- });
151
- it('throws NotFoundException when updating a role that does not exist', async ()=>{
152
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(false);
153
- await service.ensureDataSourceRepository();
154
- mockRepo.findOne.mockResolvedValue(null);
155
- await expect(service.convertSingleDtoToEntity({
156
- id: 'missing-role'
157
- }, (0, _loggedusermock.buildMockUser)())).rejects.toThrow();
158
- });
159
- });
160
- describe('getSelectQuery', ()=>{
161
- it('selects the default field set without companyId when the company feature is disabled', async ()=>{
162
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(false);
163
- const query = mockRepo.createQueryBuilder();
164
- await service.getSelectQuery(query, (0, _loggedusermock.buildMockUser)());
165
- expect(query.select).toHaveBeenCalledWith(expect.not.arrayContaining([
166
- 'role.companyId'
167
- ]));
168
- });
169
- it('includes companyId in the default field set when the company feature is enabled', async ()=>{
170
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
171
- const query = mockRepo.createQueryBuilder();
172
- await service.getSelectQuery(query, (0, _loggedusermock.buildMockUser)());
173
- expect(query.select).toHaveBeenCalledWith(expect.arrayContaining([
174
- 'role.companyId'
175
- ]));
176
- });
177
- it('uses the explicitly provided select list as-is', async ()=>{
178
- const query = mockRepo.createQueryBuilder();
179
- await service.getSelectQuery(query, (0, _loggedusermock.buildMockUser)(), [
180
- 'id',
181
- 'name'
182
- ]);
183
- expect(query.select).toHaveBeenCalledWith([
184
- 'role.id',
185
- 'role.name'
186
- ]);
187
- });
188
- });
189
- describe('getGlobalSearchQuery', ()=>{
190
- it('filters by name or description', async ()=>{
191
- const query = mockRepo.createQueryBuilder();
192
- await service.getGlobalSearchQuery(query, 'manager');
193
- expect(query.andWhere).toHaveBeenCalledWith('(role.name LIKE :search OR role.description LIKE :search)', {
194
- search: '%manager%'
195
- });
196
- });
197
- });
198
- describe('getExtraManipulateQuery', ()=>{
199
- it('applies a company filter clause when the company feature is enabled and the user has a company', async ()=>{
200
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
201
- const query = mockRepo.createQueryBuilder();
202
- await service.getExtraManipulateQuery(query, {}, (0, _loggedusermock.buildMockUser)({
203
- companyId: 'company-1'
204
- }));
205
- expect(query.andWhere).toHaveBeenCalledWith('role.companyId = :companyId', {
206
- companyId: 'company-1'
207
- });
208
- });
209
- it('does not apply a company filter when the company feature is disabled', async ()=>{
210
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(false);
211
- const query = mockRepo.createQueryBuilder();
212
- await service.getExtraManipulateQuery(query, {}, (0, _loggedusermock.buildMockUser)({
213
- companyId: 'company-1'
214
- }));
215
- expect(query.andWhere).not.toHaveBeenCalled();
216
- });
217
- });
218
- describe('convertEntityToResponseDto', ()=>{
219
- it('defaults companyId to null when the entity has no companyId field', ()=>{
220
- const entity = buildRole();
221
- const dto = service.convertEntityToResponseDto(entity, false);
222
- expect(dto.companyId).toBeNull();
223
- });
224
- it('surfaces companyId when present on the entity', ()=>{
225
- const entity = buildRole({
226
- companyId: 'company-1'
227
- });
228
- const dto = service.convertEntityToResponseDto(entity, false);
229
- expect(dto.companyId).toBe('company-1');
230
- });
231
- });
232
- describe('beforeDeleteOperation', ()=>{
233
- function buildQueryRunner(permissionRepo) {
234
- return {
235
- manager: {
236
- getRepository: jest.fn().mockReturnValue(permissionRepo)
237
- }
238
- };
239
- }
240
- it('does nothing when the delete DTO has no ids', async ()=>{
241
- const permissionRepo = (0, _repositorymock.createMockRepository)();
242
- const queryRunner = buildQueryRunner(permissionRepo);
243
- await service.beforeDeleteOperation({
244
- id: [],
245
- type: 'delete'
246
- }, (0, _loggedusermock.buildMockUser)(), queryRunner);
247
- expect(permissionRepo.find).not.toHaveBeenCalled();
248
- });
249
- it('cascades ROLE_ACTION and USER_ROLE cleanup and invalidates affected users cache', async ()=>{
250
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(false);
251
- const permissionRepo = (0, _repositorymock.createMockRepository)();
252
- permissionRepo.find.mockResolvedValue([
253
- {
254
- sourceId: 'user-1'
255
- },
256
- {
257
- sourceId: 'user-2'
258
- }
259
- ]);
260
- const queryRunner = buildQueryRunner(permissionRepo);
261
- await service.beforeDeleteOperation({
262
- id: 'role-uuid-1',
263
- type: 'delete'
264
- }, (0, _loggedusermock.buildMockUser)(), queryRunner);
265
- expect(permissionRepo.delete).toHaveBeenCalledWith(expect.objectContaining({
266
- permissionType: 'role_action',
267
- sourceType: 'role'
268
- }));
269
- expect(permissionRepo.delete).toHaveBeenCalledWith(expect.objectContaining({
270
- permissionType: 'user_role',
271
- targetType: 'role'
272
- }));
273
- expect(mockPermissionCacheService.invalidateUsers).toHaveBeenCalledWith([
274
- 'user-1',
275
- 'user-2'
276
- ]);
277
- });
278
- it('does not invalidate any cache when no users are affected', async ()=>{
279
- const permissionRepo = (0, _repositorymock.createMockRepository)();
280
- permissionRepo.find.mockResolvedValue([]);
281
- const queryRunner = buildQueryRunner(permissionRepo);
282
- await service.beforeDeleteOperation({
283
- id: [
284
- 'role-uuid-1'
285
- ],
286
- type: 'delete'
287
- }, (0, _loggedusermock.buildMockUser)(), queryRunner);
288
- expect(mockPermissionCacheService.invalidateUsers).not.toHaveBeenCalled();
289
- });
290
- it('supports array ids and dedupes affected user ids', async ()=>{
291
- const permissionRepo = (0, _repositorymock.createMockRepository)();
292
- permissionRepo.find.mockResolvedValue([
293
- {
294
- sourceId: 'user-1'
295
- },
296
- {
297
- sourceId: 'user-1'
298
- }
299
- ]);
300
- const queryRunner = buildQueryRunner(permissionRepo);
301
- await service.beforeDeleteOperation({
302
- id: [
303
- 'role-uuid-1',
304
- 'role-uuid-2'
305
- ],
306
- type: 'delete'
307
- }, (0, _loggedusermock.buildMockUser)(), queryRunner);
308
- expect(mockPermissionCacheService.invalidateUsers).toHaveBeenCalledWith([
309
- 'user-1'
310
- ]);
311
- });
312
- it('rejects deleting a readonly role', async ()=>{
313
- mockRepo.find.mockResolvedValue([
314
- buildRole({
315
- readOnly: true
316
- })
317
- ]);
318
- const permissionRepo = (0, _repositorymock.createMockRepository)();
319
- const queryRunner = buildQueryRunner(permissionRepo);
320
- await expect(service.beforeDeleteOperation({
321
- id: 'role-uuid-1',
322
- type: 'delete'
323
- }, (0, _loggedusermock.buildMockUser)(), queryRunner)).rejects.toThrow('Cannot delete readonly role');
324
- expect(permissionRepo.find).not.toHaveBeenCalled();
325
- });
326
- });
327
- describe('beforeUpdateOperation', ()=>{
328
- it('rejects updating a readonly role', async ()=>{
329
- mockRepo.find.mockResolvedValue([
330
- buildRole({
331
- readOnly: true
332
- })
333
- ]);
334
- await expect(service.beforeUpdateOperation({
335
- id: 'role-uuid-1',
336
- name: 'Renamed'
337
- }, (0, _loggedusermock.buildMockUser)(), {})).rejects.toThrow('Cannot modify readonly role');
338
- });
339
- it('allows updating a non-readonly role', async ()=>{
340
- mockRepo.find.mockResolvedValue([]);
341
- await expect(service.beforeUpdateOperation({
342
- id: 'role-uuid-1',
343
- name: 'Renamed'
344
- }, (0, _loggedusermock.buildMockUser)(), {})).resolves.toBeUndefined();
345
- });
346
- });
347
- });
@@ -1,18 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- _export_star(require("./logic-node.type"), exports);
6
- function _export_star(from, to) {
7
- Object.keys(from).forEach(function(k) {
8
- if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
9
- Object.defineProperty(to, k, {
10
- enumerable: true,
11
- get: function() {
12
- return from[k];
13
- }
14
- });
15
- }
16
- });
17
- return from;
18
- }
@@ -1,30 +0,0 @@
1
- /**
2
- * LogicNode - Represents a node in a permission logic tree
3
- *
4
- * Used for complex permission evaluation with AND/OR logic.
5
- * Supports hierarchical permission structures.
6
- *
7
- * Example:
8
- * ```typescript
9
- * const logic: LogicNode = {
10
- * id: 'root',
11
- * type: 'group',
12
- * operator: 'AND',
13
- * children: [
14
- * { id: '1', type: 'action', actionId: 'create-user' },
15
- * {
16
- * id: '2',
17
- * type: 'group',
18
- * operator: 'OR',
19
- * children: [
20
- * { id: '2-1', type: 'action', actionId: 'view-reports' },
21
- * { id: '2-2', type: 'action', actionId: 'view-dashboard' }
22
- * ]
23
- * }
24
- * ]
25
- * };
26
- * ```
27
- */ "use strict";
28
- Object.defineProperty(exports, "__esModule", {
29
- value: true
30
- });
@@ -1,15 +0,0 @@
1
- /**
2
- * Domain event actions published by the IAM module, alongside the CRUD
3
- * lifecycle actions every ApiService emits.
4
- */ export const IAM_EVENT_ACTIONS = {
5
- PERMISSIONS_ASSIGNED: 'permissions-assigned'
6
- };
7
- /** Every entity the IAM module publishes under, ApiService backed or not */ export const IAM_EVENT_ENTITIES = {
8
- ACTION: 'action',
9
- ROLE: 'role',
10
- USER_ACTION: 'user_action',
11
- ROLE_ACTION: 'role_action',
12
- COMPANY_ACTION: 'company_action',
13
- USER_ROLE: 'user_role'
14
- };
15
- export const IAM_EVENT_MODULE = 'iam';
@@ -1 +0,0 @@
1
- export const IAM_MODULE_OPTIONS = 'IAM_MODULE_OPTIONS';
@@ -1,35 +0,0 @@
1
- // ==================== IAM MODULE MESSAGE KEYS ====================
2
- export const ACTION_MESSAGES = {
3
- GET_ALL_SUCCESS: 'action.get.all.success',
4
- READONLY_UPDATE_FORBIDDEN: 'action.readonly.update.forbidden',
5
- READONLY_DELETE_FORBIDDEN: 'action.readonly.delete.forbidden'
6
- };
7
- export const ROLE_MESSAGES = {
8
- READONLY_UPDATE_FORBIDDEN: 'role.readonly.update.forbidden',
9
- READONLY_DELETE_FORBIDDEN: 'role.readonly.delete.forbidden'
10
- };
11
- export const PERMISSION_OPERATION_MESSAGES = {
12
- PROCESS_SUCCESS: 'permission.process.success',
13
- ALREADY_EXISTS: 'permission.already.exists',
14
- USER_REQUIRED: 'permission.user.required'
15
- };
16
- export const ROLE_PERMISSION_MESSAGES = {
17
- ACTIONS_SUCCESS: 'role.permission.actions.success',
18
- USER_ROLES_SUCCESS: 'role.permission.user.roles.success'
19
- };
20
- export const USER_ACTION_PERMISSION_MESSAGES = {
21
- GET_SUCCESS: 'user.action.permission.get.success'
22
- };
23
- export const COMPANY_ACTION_PERMISSION_MESSAGES = {
24
- GET_SUCCESS: 'company.action.permission.get.success'
25
- };
26
- export const MY_PERMISSION_MESSAGES = {
27
- GET_SUCCESS: 'my.permission.get.success',
28
- MY_ROLES_SUCCESS: 'my.permission.roles.success',
29
- MY_ACTIONS_SUCCESS: 'my.permission.actions.success'
30
- };
31
- export const IAM_MODE_MESSAGES = {
32
- DIRECT_MODE_UNAVAILABLE: 'iam.direct.mode.unavailable',
33
- RBAC_MODE_UNAVAILABLE: 'iam.rbac.mode.unavailable',
34
- ROLE_ASSIGNMENT_UNAVAILABLE: 'iam.role.assignment.unavailable'
35
- };