@flusys/nestjs-iam 7.0.2 → 8.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/config/index.d.ts +3 -3
  2. package/controllers/action.controller.d.ts +4 -4
  3. package/controllers/company-action-permission.controller.d.ts +2 -2
  4. package/controllers/index.d.ts +6 -6
  5. package/controllers/my-permission.controller.d.ts +3 -3
  6. package/controllers/role-permission.controller.d.ts +4 -4
  7. package/controllers/role.controller.d.ts +2 -2
  8. package/controllers/user-action-permission.controller.d.ts +4 -4
  9. package/docs/iam-swagger.config.d.ts +2 -2
  10. package/docs/index.d.ts +1 -1
  11. package/dtos/action.dto.d.ts +2 -2
  12. package/dtos/index.d.ts +3 -3
  13. package/entities/action.entity.d.ts +2 -2
  14. package/entities/index.d.ts +11 -11
  15. package/entities/permission-with-company.entity.d.ts +1 -1
  16. package/entities/role-with-company.entity.d.ts +1 -1
  17. package/entities/role.entity.d.ts +1 -1
  18. package/entities/user-iam-permission.entity.d.ts +1 -1
  19. package/enums/index.d.ts +4 -4
  20. package/fesm/284.js +1262 -0
  21. package/fesm/867.js +3699 -0
  22. package/fesm/chunks/364.js +86 -0
  23. package/fesm/config/index.js +133 -3
  24. package/fesm/controllers/index.js +18 -7
  25. package/fesm/docs/index.js +240 -1
  26. package/fesm/dtos/index.js +1090 -3
  27. package/fesm/entities/index.js +670 -31
  28. package/fesm/enums/index.js +97 -4
  29. package/fesm/helpers/index.js +125 -2
  30. package/fesm/index.js +806 -11
  31. package/fesm/interfaces/index.js +17 -3
  32. package/fesm/modules/index.js +259 -1
  33. package/fesm/runtime.js +134 -0
  34. package/fesm/services/index.js +43 -6
  35. package/fesm/types/index.js +15 -1
  36. package/helpers/company-access.helper.d.ts +2 -2
  37. package/helpers/index.d.ts +2 -2
  38. package/helpers/permission-mode.helper.d.ts +1 -1
  39. package/index.d.ts +11 -11
  40. package/interfaces/action.interface.d.ts +2 -2
  41. package/interfaces/iam-module-options.interface.d.ts +3 -3
  42. package/interfaces/index.d.ts +3 -3
  43. package/modules/iam.module.d.ts +2 -2
  44. package/modules/index.d.ts +1 -1
  45. package/package.json +30 -37
  46. package/services/action.service.d.ts +9 -9
  47. package/services/iam-config.service.d.ts +4 -4
  48. package/services/iam-datasource.service.d.ts +3 -3
  49. package/services/index.d.ts +6 -6
  50. package/services/permission-cache.service.d.ts +5 -5
  51. package/services/permission.service.d.ts +4 -4
  52. package/services/role.service.d.ts +8 -8
  53. package/types/index.d.ts +1 -1
  54. package/cjs/config/event-actions.js +0 -36
  55. package/cjs/config/iam.constants.js +0 -11
  56. package/cjs/config/index.js +0 -20
  57. package/cjs/config/message-keys.js +0 -71
  58. package/cjs/controllers/action.controller.js +0 -174
  59. package/cjs/controllers/action.controller.spec.js +0 -79
  60. package/cjs/controllers/company-action-permission.controller.js +0 -119
  61. package/cjs/controllers/company-action-permission.controller.spec.js +0 -65
  62. package/cjs/controllers/index.js +0 -23
  63. package/cjs/controllers/my-permission.controller.js +0 -147
  64. package/cjs/controllers/my-permission.controller.spec.js +0 -128
  65. package/cjs/controllers/role-permission.controller.js +0 -191
  66. package/cjs/controllers/role-permission.controller.spec.js +0 -140
  67. package/cjs/controllers/role.controller.js +0 -102
  68. package/cjs/controllers/role.controller.spec.js +0 -86
  69. package/cjs/controllers/user-action-permission.controller.js +0 -129
  70. package/cjs/controllers/user-action-permission.controller.spec.js +0 -68
  71. package/cjs/docs/iam-swagger.config.js +0 -209
  72. package/cjs/docs/iam-swagger.config.spec.js +0 -99
  73. package/cjs/docs/index.js +0 -18
  74. package/cjs/dtos/action.dto.js +0 -282
  75. package/cjs/dtos/index.js +0 -21
  76. package/cjs/dtos/permission.dto.js +0 -637
  77. package/cjs/dtos/role.dto.js +0 -155
  78. package/cjs/entities/action.entity.js +0 -138
  79. package/cjs/entities/index.js +0 -80
  80. package/cjs/entities/index.spec.js +0 -56
  81. package/cjs/entities/permission-base.entity.js +0 -107
  82. package/cjs/entities/permission-with-company.entity.js +0 -100
  83. package/cjs/entities/role-base.entity.js +0 -80
  84. package/cjs/entities/role-with-company.entity.js +0 -55
  85. package/cjs/entities/role.entity.js +0 -25
  86. package/cjs/entities/user-iam-permission.entity.js +0 -43
  87. package/cjs/enums/action-type.enum.js +0 -22
  88. package/cjs/enums/iam-entity-type.enum.js +0 -17
  89. package/cjs/enums/iam-permission-type.enum.js +0 -17
  90. package/cjs/enums/index.js +0 -21
  91. package/cjs/enums/permission-type.enum.js +0 -16
  92. package/cjs/helpers/company-access.helper.js +0 -23
  93. package/cjs/helpers/company-access.helper.spec.js +0 -68
  94. package/cjs/helpers/index.js +0 -19
  95. package/cjs/helpers/permission-mode.helper.js +0 -49
  96. package/cjs/helpers/permission-mode.helper.spec.js +0 -54
  97. package/cjs/index.js +0 -28
  98. package/cjs/interfaces/action.interface.js +0 -4
  99. package/cjs/interfaces/iam-module-options.interface.js +0 -4
  100. package/cjs/interfaces/index.js +0 -20
  101. package/cjs/interfaces/role.interface.js +0 -7
  102. package/cjs/modules/iam.module.js +0 -186
  103. package/cjs/modules/iam.module.spec.js +0 -282
  104. package/cjs/modules/index.js +0 -18
  105. package/cjs/services/action.service.js +0 -337
  106. package/cjs/services/action.service.spec.js +0 -351
  107. package/cjs/services/iam-config.service.js +0 -87
  108. package/cjs/services/iam-config.service.spec.js +0 -110
  109. package/cjs/services/iam-datasource.service.js +0 -129
  110. package/cjs/services/iam-datasource.service.spec.js +0 -110
  111. package/cjs/services/index.js +0 -23
  112. package/cjs/services/permission-cache.service.js +0 -544
  113. package/cjs/services/permission-cache.service.spec.js +0 -718
  114. package/cjs/services/permission.service.js +0 -914
  115. package/cjs/services/permission.service.spec.js +0 -918
  116. package/cjs/services/role.service.js +0 -224
  117. package/cjs/services/role.service.spec.js +0 -347
  118. package/cjs/types/index.js +0 -18
  119. package/cjs/types/logic-node.type.js +0 -30
  120. package/fesm/config/event-actions.js +0 -15
  121. package/fesm/config/iam.constants.js +0 -1
  122. package/fesm/config/message-keys.js +0 -35
  123. package/fesm/controllers/action.controller.js +0 -164
  124. package/fesm/controllers/action.controller.spec.js +0 -75
  125. package/fesm/controllers/company-action-permission.controller.js +0 -109
  126. package/fesm/controllers/company-action-permission.controller.spec.js +0 -61
  127. package/fesm/controllers/my-permission.controller.js +0 -137
  128. package/fesm/controllers/my-permission.controller.spec.js +0 -124
  129. package/fesm/controllers/role-permission.controller.js +0 -181
  130. package/fesm/controllers/role-permission.controller.spec.js +0 -136
  131. package/fesm/controllers/role.controller.js +0 -92
  132. package/fesm/controllers/role.controller.spec.js +0 -82
  133. package/fesm/controllers/user-action-permission.controller.js +0 -119
  134. package/fesm/controllers/user-action-permission.controller.spec.js +0 -64
  135. package/fesm/docs/iam-swagger.config.js +0 -199
  136. package/fesm/docs/iam-swagger.config.spec.js +0 -95
  137. package/fesm/dtos/action.dto.js +0 -252
  138. package/fesm/dtos/permission.dto.js +0 -571
  139. package/fesm/dtos/role.dto.js +0 -134
  140. package/fesm/entities/action.entity.js +0 -128
  141. package/fesm/entities/index.spec.js +0 -52
  142. package/fesm/entities/permission-base.entity.js +0 -100
  143. package/fesm/entities/permission-with-company.entity.js +0 -90
  144. package/fesm/entities/role-base.entity.js +0 -70
  145. package/fesm/entities/role-with-company.entity.js +0 -45
  146. package/fesm/entities/role.entity.js +0 -15
  147. package/fesm/entities/user-iam-permission.entity.js +0 -33
  148. package/fesm/enums/action-type.enum.js +0 -12
  149. package/fesm/enums/iam-entity-type.enum.js +0 -7
  150. package/fesm/enums/iam-permission-type.enum.js +0 -7
  151. package/fesm/enums/permission-type.enum.js +0 -6
  152. package/fesm/helpers/company-access.helper.js +0 -18
  153. package/fesm/helpers/company-access.helper.spec.js +0 -64
  154. package/fesm/helpers/permission-mode.helper.js +0 -49
  155. package/fesm/helpers/permission-mode.helper.spec.js +0 -50
  156. package/fesm/interfaces/action.interface.js +0 -3
  157. package/fesm/interfaces/iam-module-options.interface.js +0 -3
  158. package/fesm/interfaces/role.interface.js +0 -4
  159. package/fesm/modules/iam.module.js +0 -176
  160. package/fesm/modules/iam.module.spec.js +0 -278
  161. package/fesm/services/action.service.js +0 -327
  162. package/fesm/services/action.service.spec.js +0 -347
  163. package/fesm/services/iam-config.service.js +0 -77
  164. package/fesm/services/iam-config.service.spec.js +0 -106
  165. package/fesm/services/iam-datasource.service.js +0 -78
  166. package/fesm/services/iam-datasource.service.spec.js +0 -106
  167. package/fesm/services/permission-cache.service.js +0 -527
  168. package/fesm/services/permission-cache.service.spec.js +0 -714
  169. package/fesm/services/permission.service.js +0 -904
  170. package/fesm/services/permission.service.spec.js +0 -914
  171. package/fesm/services/role.service.js +0 -214
  172. package/fesm/services/role.service.spec.js +0 -343
  173. package/fesm/types/logic-node.type.js +0 -27
@@ -1,337 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "ActionService", {
6
- enumerable: true,
7
- get: function() {
8
- return ActionService;
9
- }
10
- });
11
- const _classes = require("@flusys/nestjs-shared/classes");
12
- const _modules = require("@flusys/nestjs-shared/modules");
13
- const _common = require("@nestjs/common");
14
- const _typeorm = require("typeorm");
15
- const _config = require("../config");
16
- const _actionentity = require("../entities/action.entity");
17
- const _permissionwithcompanyentity = require("../entities/permission-with-company.entity");
18
- const _useriampermissionentity = require("../entities/user-iam-permission.entity");
19
- const _iamentitytypeenum = require("../enums/iam-entity-type.enum");
20
- const _iampermissiontypeenum = require("../enums/iam-permission-type.enum");
21
- const _iamconfigservice = require("./iam-config.service");
22
- const _iamdatasourceservice = require("./iam-datasource.service");
23
- const _permissioncacheservice = require("./permission-cache.service");
24
- const _permissionservice = require("./permission.service");
25
- function _define_property(obj, key, value) {
26
- if (key in obj) {
27
- Object.defineProperty(obj, key, {
28
- value: value,
29
- enumerable: true,
30
- configurable: true,
31
- writable: true
32
- });
33
- } else {
34
- obj[key] = value;
35
- }
36
- return obj;
37
- }
38
- function _ts_decorate(decorators, target, key, desc) {
39
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
40
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
41
- 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;
42
- return c > 3 && r && Object.defineProperty(target, key, r), r;
43
- }
44
- function _ts_metadata(k, v) {
45
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
46
- }
47
- function _ts_param(paramIndex, decorator) {
48
- return function(target, key) {
49
- decorator(target, key, paramIndex);
50
- };
51
- }
52
- let ActionService = class ActionService extends _classes.ApiService {
53
- async beforeUpdateOperation(dto, _user, _queryRunner) {
54
- const dtos = Array.isArray(dto) ? dto : [
55
- dto
56
- ];
57
- const ids = dtos.map((d)=>d.id);
58
- await this.ensureDataSourceRepository();
59
- const readonlyActions = await this.repository.find({
60
- where: {
61
- id: (0, _typeorm.In)(ids),
62
- readOnly: true,
63
- deletedAt: (0, _typeorm.IsNull)()
64
- }
65
- });
66
- if (readonlyActions.length > 0) {
67
- const names = readonlyActions.map((a)=>a.name).join(', ');
68
- throw new _common.ForbiddenException({
69
- message: `Cannot modify readonly action(s): ${names}`,
70
- messageKey: _config.ACTION_MESSAGES.READONLY_UPDATE_FORBIDDEN,
71
- messageVariables: {
72
- names
73
- }
74
- });
75
- }
76
- }
77
- async beforeDeleteOperation(dto, user, queryRunner) {
78
- const actionIds = Array.isArray(dto.id) ? dto.id : [
79
- dto.id
80
- ];
81
- if (actionIds.length === 0) {
82
- return;
83
- }
84
- await this.ensureDataSourceRepository();
85
- const readonlyActions = await this.repository.find({
86
- where: {
87
- id: (0, _typeorm.In)(actionIds),
88
- readOnly: true,
89
- deletedAt: (0, _typeorm.IsNull)()
90
- }
91
- });
92
- if (readonlyActions.length > 0) {
93
- const names = readonlyActions.map((a)=>a.name).join(', ');
94
- throw new _common.ForbiddenException({
95
- message: `Cannot delete readonly action(s): ${names}`,
96
- messageKey: _config.ACTION_MESSAGES.READONLY_DELETE_FORBIDDEN,
97
- messageVariables: {
98
- names
99
- }
100
- });
101
- }
102
- const enableCompanyFeature = this.iamConfigService.isCompanyFeatureEnabled();
103
- const permissionEntity = enableCompanyFeature ? _permissionwithcompanyentity.UserIamPermissionWithCompany : _useriampermissionentity.UserIamPermission;
104
- const permissionRepo = queryRunner.manager.getRepository(permissionEntity);
105
- const [roleActionRows, userActionRows, companyActionRows] = await Promise.all([
106
- permissionRepo.find({
107
- where: {
108
- permissionType: _iampermissiontypeenum.IamPermissionType.ROLE_ACTION,
109
- sourceType: _iamentitytypeenum.IamEntityType.ROLE,
110
- targetType: _iamentitytypeenum.IamEntityType.ACTION,
111
- targetId: (0, _typeorm.In)(actionIds)
112
- }
113
- }),
114
- permissionRepo.find({
115
- where: {
116
- permissionType: _iampermissiontypeenum.IamPermissionType.USER_ACTION,
117
- targetType: _iamentitytypeenum.IamEntityType.ACTION,
118
- targetId: (0, _typeorm.In)(actionIds)
119
- }
120
- }),
121
- enableCompanyFeature ? permissionRepo.find({
122
- where: {
123
- permissionType: _iampermissiontypeenum.IamPermissionType.COMPANY_ACTION,
124
- sourceType: _iamentitytypeenum.IamEntityType.COMPANY,
125
- targetType: _iamentitytypeenum.IamEntityType.ACTION,
126
- targetId: (0, _typeorm.In)(actionIds)
127
- }
128
- }) : Promise.resolve([])
129
- ]);
130
- const affectedUserIds = new Set(userActionRows.map((row)=>row.sourceId));
131
- const affectedCompanyIds = [
132
- ...new Set(companyActionRows.map((row)=>row.sourceId).filter((id)=>!!id))
133
- ];
134
- const affectedRoleIds = [
135
- ...new Set(roleActionRows.map((row)=>row.sourceId))
136
- ];
137
- if (affectedRoleIds.length > 0) {
138
- const userRoleRows = await permissionRepo.find({
139
- where: {
140
- permissionType: _iampermissiontypeenum.IamPermissionType.USER_ROLE,
141
- targetType: _iamentitytypeenum.IamEntityType.ROLE,
142
- targetId: (0, _typeorm.In)(affectedRoleIds)
143
- }
144
- });
145
- userRoleRows.forEach((row)=>affectedUserIds.add(row.sourceId));
146
- }
147
- await permissionRepo.delete({
148
- permissionType: _iampermissiontypeenum.IamPermissionType.ROLE_ACTION,
149
- targetType: _iamentitytypeenum.IamEntityType.ACTION,
150
- targetId: (0, _typeorm.In)(actionIds)
151
- });
152
- await permissionRepo.delete({
153
- permissionType: _iampermissiontypeenum.IamPermissionType.USER_ACTION,
154
- targetType: _iamentitytypeenum.IamEntityType.ACTION,
155
- targetId: (0, _typeorm.In)(actionIds)
156
- });
157
- await permissionRepo.delete({
158
- permissionType: _iampermissiontypeenum.IamPermissionType.COMPANY_ACTION,
159
- sourceType: _iamentitytypeenum.IamEntityType.COMPANY,
160
- targetType: _iamentitytypeenum.IamEntityType.ACTION,
161
- targetId: (0, _typeorm.In)(actionIds)
162
- });
163
- await Promise.all([
164
- affectedUserIds.size > 0 ? this.permissionCacheService.invalidateUsers([
165
- ...affectedUserIds
166
- ]) : Promise.resolve(),
167
- ...affectedCompanyIds.map((companyId)=>this.permissionCacheService.invalidateCompanyMembersCache(companyId))
168
- ]);
169
- }
170
- // Query Customization
171
- async getSelectQuery(query, _user, select) {
172
- if (!select?.length) {
173
- select = [
174
- 'id',
175
- 'name',
176
- 'code',
177
- 'description',
178
- 'actionType',
179
- 'permissionLogic',
180
- 'isActive',
181
- 'readOnly',
182
- 'parentId',
183
- 'serial',
184
- 'createdAt'
185
- ];
186
- }
187
- query.select(select.map((f)=>`${this.entityName}.${f}`));
188
- return {
189
- query,
190
- isRaw: false
191
- };
192
- }
193
- async getGlobalSearchQuery(query, search) {
194
- query.andWhere('(action.name LIKE :search OR action.code LIKE :search OR action.description LIKE :search)', {
195
- search: `%${search}%`
196
- });
197
- return {
198
- query,
199
- isRaw: false
200
- };
201
- }
202
- // Response Conversion
203
- convertEntityToResponseDto(entity, _isRaw) {
204
- return {
205
- id: entity.id,
206
- readOnly: entity.readOnly,
207
- name: entity.name,
208
- description: entity.description,
209
- code: entity.code,
210
- actionType: entity.actionType,
211
- permissionLogic: entity.permissionLogic,
212
- serial: entity.serial,
213
- isActive: entity.isActive,
214
- parentId: entity.parentId,
215
- createdAt: entity.createdAt,
216
- updatedAt: entity.updatedAt,
217
- deletedAt: entity.deletedAt,
218
- createdById: entity.createdById,
219
- updatedById: entity.updatedById,
220
- deletedById: entity.deletedById
221
- };
222
- }
223
- requireUser(user, methodName) {
224
- if (!user) {
225
- throw new _common.BadRequestException({
226
- message: `User is required for ${methodName}`,
227
- messageKey: _config.PERMISSION_OPERATION_MESSAGES.USER_REQUIRED,
228
- messageVariables: {
229
- method: methodName
230
- }
231
- });
232
- }
233
- }
234
- /** Get actions available for permission assignment (filtered by company whitelist) */ async getActionsForPermission(user, companyId) {
235
- await this.ensureDataSourceRepository();
236
- this.requireUser(user, 'getActionsForPermission');
237
- let whereClause = {};
238
- const targetCompanyId = companyId || user.companyId;
239
- if (this.iamConfigService.isCompanyFeatureEnabled() && targetCompanyId) {
240
- const companyActionIds = await this.permissionService.getCompanyActions(targetCompanyId, true);
241
- if (companyActionIds.length === 0) {
242
- return [];
243
- }
244
- whereClause = {
245
- id: (0, _typeorm.In)(companyActionIds)
246
- };
247
- }
248
- const actions = await this.repository.find({
249
- where: whereClause,
250
- select: this.actionSelectFields
251
- });
252
- return actions.map((action)=>this.convertEntityToResponseDto(action, false));
253
- }
254
- /** Get actions in hierarchical tree structure */ async getActionTree(user, search, isActive, withDeleted = false) {
255
- await this.ensureDataSourceRepository();
256
- this.requireUser(user, 'getActionTree');
257
- const query = this.repository.createQueryBuilder('action');
258
- if (!withDeleted) {
259
- query.andWhere('action.deletedAt IS NULL');
260
- }
261
- if (isActive !== undefined) {
262
- query.andWhere('action.isActive = :isActive', {
263
- isActive
264
- });
265
- }
266
- if (search?.trim()) {
267
- query.andWhere('(action.name LIKE :search OR action.code LIKE :search)', {
268
- search: `%${search.trim()}%`
269
- });
270
- }
271
- const actions = await query.orderBy('action.serial', 'ASC').getMany();
272
- return this.buildActionTree(actions);
273
- }
274
- buildActionTree(actions) {
275
- if (!actions?.length) {
276
- return [];
277
- }
278
- const map = new Map();
279
- const rootNodes = [];
280
- for (const action of actions){
281
- const treeNode = {
282
- ...this.convertEntityToResponseDto(action, false),
283
- children: []
284
- };
285
- map.set(action.id, treeNode);
286
- }
287
- for (const action of actions){
288
- const node = map.get(action.id);
289
- if (!node) {
290
- continue;
291
- }
292
- if (action.parentId && map.has(action.parentId)) {
293
- const parent = map.get(action.parentId);
294
- if (parent?.children) {
295
- parent.children.push(node);
296
- }
297
- } else {
298
- rootNodes.push(node);
299
- }
300
- }
301
- return rootNodes;
302
- }
303
- constructor(cacheManager, utilsService, iamConfigService, dataSourceProvider, permissionService, permissionCacheService){
304
- super(_config.IAM_EVENT_ENTITIES.ACTION, cacheManager, utilsService, ActionService.name, true, _config.IAM_EVENT_MODULE, dataSourceProvider, _actionentity.Action), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "iamConfigService", void 0), _define_property(this, "permissionService", void 0), _define_property(this, "permissionCacheService", void 0), // Custom Methods
305
- _define_property(this, "actionSelectFields", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.iamConfigService = iamConfigService, this.permissionService = permissionService, this.permissionCacheService = permissionCacheService, this.actionSelectFields = [
306
- 'id',
307
- 'code',
308
- 'name',
309
- 'description',
310
- 'actionType',
311
- 'permissionLogic',
312
- 'isActive',
313
- 'parentId',
314
- 'serial'
315
- ];
316
- }
317
- };
318
- ActionService = _ts_decorate([
319
- (0, _common.Injectable)({
320
- scope: _common.Scope.REQUEST
321
- }),
322
- _ts_param(0, (0, _common.Inject)('CACHE_INSTANCE')),
323
- _ts_param(1, (0, _common.Inject)(_modules.UtilsService)),
324
- _ts_param(2, (0, _common.Inject)(_iamconfigservice.IAMConfigService)),
325
- _ts_param(3, (0, _common.Inject)(_iamdatasourceservice.IAMDataSourceService)),
326
- _ts_param(4, (0, _common.Inject)(_permissionservice.PermissionService)),
327
- _ts_param(5, (0, _common.Inject)(_permissioncacheservice.PermissionCacheService)),
328
- _ts_metadata("design:type", Function),
329
- _ts_metadata("design:paramtypes", [
330
- typeof _classes.HybridCache === "undefined" ? Object : _classes.HybridCache,
331
- typeof _modules.UtilsService === "undefined" ? Object : _modules.UtilsService,
332
- typeof _iamconfigservice.IAMConfigService === "undefined" ? Object : _iamconfigservice.IAMConfigService,
333
- typeof _iamdatasourceservice.IAMDataSourceService === "undefined" ? Object : _iamdatasourceservice.IAMDataSourceService,
334
- typeof _permissionservice.PermissionService === "undefined" ? Object : _permissionservice.PermissionService,
335
- typeof _permissioncacheservice.PermissionCacheService === "undefined" ? Object : _permissioncacheservice.PermissionCacheService
336
- ])
337
- ], ActionService);
@@ -1,351 +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 _enums = require("../enums");
10
- const _actionservice = require("./action.service");
11
- const _iamconfigservice = require("./iam-config.service");
12
- const _iamdatasourceservice = require("./iam-datasource.service");
13
- const _permissioncacheservice = require("./permission-cache.service");
14
- const _permissionservice = require("./permission.service");
15
- function buildAction(overrides = {}) {
16
- return {
17
- id: 'action-uuid-1',
18
- readOnly: false,
19
- name: 'View Products',
20
- description: null,
21
- code: 'products.read',
22
- actionType: _enums.ActionType.BACKEND,
23
- permissionLogic: null,
24
- serial: 1,
25
- isActive: true,
26
- parentId: null,
27
- createdAt: new Date(),
28
- updatedAt: new Date(),
29
- deletedAt: null,
30
- createdById: null,
31
- updatedById: null,
32
- deletedById: null,
33
- ...overrides
34
- };
35
- }
36
- describe('ActionService', ()=>{
37
- let service;
38
- let mockRepo;
39
- let mockIamConfigService;
40
- let mockPermissionService;
41
- let mockPermissionCacheService;
42
- beforeEach(async ()=>{
43
- mockRepo = (0, _repositorymock.createMockRepository)();
44
- mockRepo.find.mockResolvedValue([]);
45
- const mockDataSourceProvider = (0, _repositorymock.createMockDataSourceProvider)(mockRepo);
46
- mockIamConfigService = {
47
- isCompanyFeatureEnabled: jest.fn().mockReturnValue(false)
48
- };
49
- mockPermissionService = {
50
- getCompanyActions: jest.fn()
51
- };
52
- mockPermissionCacheService = {
53
- invalidateUsers: jest.fn(),
54
- invalidateCompanyMembersCache: jest.fn()
55
- };
56
- const module = await _testing.Test.createTestingModule({
57
- providers: [
58
- _actionservice.ActionService,
59
- {
60
- provide: 'CACHE_INSTANCE',
61
- useValue: {}
62
- },
63
- {
64
- provide: _modules.UtilsService,
65
- useValue: {}
66
- },
67
- {
68
- provide: _iamconfigservice.IAMConfigService,
69
- useValue: mockIamConfigService
70
- },
71
- {
72
- provide: _iamdatasourceservice.IAMDataSourceService,
73
- useValue: mockDataSourceProvider
74
- },
75
- {
76
- provide: _permissionservice.PermissionService,
77
- useValue: mockPermissionService
78
- },
79
- {
80
- provide: _permissioncacheservice.PermissionCacheService,
81
- useValue: mockPermissionCacheService
82
- }
83
- ]
84
- }).compile();
85
- service = await module.resolve(_actionservice.ActionService);
86
- });
87
- describe('getActionsForPermission', ()=>{
88
- it('returns all actions when the company feature is disabled', async ()=>{
89
- mockRepo.find.mockResolvedValue([
90
- buildAction()
91
- ]);
92
- const result = await service.getActionsForPermission((0, _loggedusermock.buildMockUser)());
93
- expect(mockPermissionService.getCompanyActions).not.toHaveBeenCalled();
94
- expect(result).toHaveLength(1);
95
- expect(result[0].code).toBe('products.read');
96
- });
97
- it('scopes actions to the company whitelist when the company feature is enabled', async ()=>{
98
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
99
- mockPermissionService.getCompanyActions.mockResolvedValue([
100
- 'action-uuid-1'
101
- ]);
102
- mockRepo.find.mockResolvedValue([
103
- buildAction()
104
- ]);
105
- await service.getActionsForPermission((0, _loggedusermock.buildMockUser)(), 'company-uuid-1');
106
- expect(mockPermissionService.getCompanyActions).toHaveBeenCalledWith('company-uuid-1', true);
107
- expect(mockRepo.find).toHaveBeenCalledWith(expect.objectContaining({
108
- where: {
109
- id: expect.anything()
110
- }
111
- }));
112
- });
113
- it('short-circuits without querying when the company has no whitelisted actions', async ()=>{
114
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
115
- mockPermissionService.getCompanyActions.mockResolvedValue([]);
116
- const result = await service.getActionsForPermission((0, _loggedusermock.buildMockUser)(), 'company-uuid-1');
117
- expect(result).toEqual([]);
118
- expect(mockRepo.find).not.toHaveBeenCalled();
119
- });
120
- it('throws when no user is provided', async ()=>{
121
- await expect(service.getActionsForPermission(null)).rejects.toThrow();
122
- });
123
- });
124
- describe('getActionTree', ()=>{
125
- it('nests child actions under their parent', async ()=>{
126
- const parent = buildAction({
127
- id: 'parent-1',
128
- parentId: null,
129
- serial: 1
130
- });
131
- const child = buildAction({
132
- id: 'child-1',
133
- parentId: 'parent-1',
134
- serial: 2,
135
- code: 'products.create'
136
- });
137
- mockRepo.createQueryBuilder().getMany.mockResolvedValue([
138
- parent,
139
- child
140
- ]);
141
- const tree = await service.getActionTree((0, _loggedusermock.buildMockUser)());
142
- expect(tree).toHaveLength(1);
143
- expect(tree[0].id).toBe('parent-1');
144
- expect(tree[0].children).toHaveLength(1);
145
- expect(tree[0].children?.[0].id).toBe('child-1');
146
- });
147
- it('throws when no user is provided', async ()=>{
148
- await expect(service.getActionTree(null)).rejects.toThrow();
149
- });
150
- it('treats an action with a missing/unknown parentId as a root node', async ()=>{
151
- const orphan = buildAction({
152
- id: 'orphan-1',
153
- parentId: 'does-not-exist'
154
- });
155
- mockRepo.createQueryBuilder().getMany.mockResolvedValue([
156
- orphan
157
- ]);
158
- const tree = await service.getActionTree((0, _loggedusermock.buildMockUser)());
159
- expect(tree).toHaveLength(1);
160
- expect(tree[0].id).toBe('orphan-1');
161
- });
162
- it('excludes soft-deleted actions by default and applies search/isActive filters', async ()=>{
163
- const query = mockRepo.createQueryBuilder();
164
- query.getMany.mockResolvedValue([]);
165
- await service.getActionTree((0, _loggedusermock.buildMockUser)(), 'view', true, false);
166
- expect(query.andWhere).toHaveBeenCalledWith('action.deletedAt IS NULL');
167
- expect(query.andWhere).toHaveBeenCalledWith('action.isActive = :isActive', {
168
- isActive: true
169
- });
170
- expect(query.andWhere).toHaveBeenCalledWith('(action.name LIKE :search OR action.code LIKE :search)', {
171
- search: '%view%'
172
- });
173
- });
174
- it('includes soft-deleted actions when withDeleted is true', async ()=>{
175
- const query = mockRepo.createQueryBuilder();
176
- query.getMany.mockResolvedValue([]);
177
- await service.getActionTree((0, _loggedusermock.buildMockUser)(), undefined, undefined, true);
178
- expect(query.andWhere).not.toHaveBeenCalledWith('action.deletedAt IS NULL');
179
- });
180
- });
181
- describe('getSelectQuery', ()=>{
182
- it('selects the default field set when none is provided', async ()=>{
183
- const query = mockRepo.createQueryBuilder();
184
- await service.getSelectQuery(query, (0, _loggedusermock.buildMockUser)());
185
- expect(query.select).toHaveBeenCalledWith(expect.arrayContaining([
186
- 'action.code',
187
- 'action.actionType',
188
- 'action.permissionLogic'
189
- ]));
190
- });
191
- it('uses the explicitly provided select list as-is', async ()=>{
192
- const query = mockRepo.createQueryBuilder();
193
- await service.getSelectQuery(query, (0, _loggedusermock.buildMockUser)(), [
194
- 'id',
195
- 'code'
196
- ]);
197
- expect(query.select).toHaveBeenCalledWith([
198
- 'action.id',
199
- 'action.code'
200
- ]);
201
- });
202
- });
203
- describe('getGlobalSearchQuery', ()=>{
204
- it('filters by name, code, or description', async ()=>{
205
- const query = mockRepo.createQueryBuilder();
206
- await service.getGlobalSearchQuery(query, 'view');
207
- expect(query.andWhere).toHaveBeenCalledWith('(action.name LIKE :search OR action.code LIKE :search OR action.description LIKE :search)', {
208
- search: '%view%'
209
- });
210
- });
211
- });
212
- describe('convertEntityToResponseDto', ()=>{
213
- it('maps every entity field onto the response shape', ()=>{
214
- const entity = buildAction({
215
- code: 'user.view'
216
- });
217
- const dto = service.convertEntityToResponseDto(entity, false);
218
- expect(dto).toEqual(expect.objectContaining({
219
- id: entity.id,
220
- code: 'user.view',
221
- actionType: _enums.ActionType.BACKEND
222
- }));
223
- });
224
- });
225
- describe('beforeDeleteOperation', ()=>{
226
- function buildQueryRunner(permissionRepo) {
227
- return {
228
- manager: {
229
- getRepository: jest.fn().mockReturnValue(permissionRepo)
230
- }
231
- };
232
- }
233
- it('does nothing when the delete DTO has no ids', async ()=>{
234
- const permissionRepo = (0, _repositorymock.createMockRepository)();
235
- const queryRunner = buildQueryRunner(permissionRepo);
236
- await service.beforeDeleteOperation({
237
- id: [],
238
- type: 'delete'
239
- }, (0, _loggedusermock.buildMockUser)(), queryRunner);
240
- expect(permissionRepo.find).not.toHaveBeenCalled();
241
- });
242
- it('cascades role/user/company action-permission cleanup and invalidates affected caches', async ()=>{
243
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(false);
244
- const permissionRepo = (0, _repositorymock.createMockRepository)();
245
- // Company feature is disabled, so companyActionRows resolves via Promise.resolve([]) and
246
- // never calls permissionRepo.find() — only 3 real find() calls happen: role-action,
247
- // user-action, then the role -> user cascade lookup.
248
- permissionRepo.find.mockResolvedValueOnce([
249
- {
250
- sourceId: 'role-1'
251
- }
252
- ]) // role-action rows referencing the deleted action
253
- .mockResolvedValueOnce([
254
- {
255
- sourceId: 'user-1'
256
- }
257
- ]) // direct user-action rows
258
- .mockResolvedValueOnce([
259
- {
260
- sourceId: 'user-2'
261
- }
262
- ]); // users holding role-1 (cascaded lookup)
263
- const queryRunner = buildQueryRunner(permissionRepo);
264
- await service.beforeDeleteOperation({
265
- id: 'action-uuid-1',
266
- type: 'delete'
267
- }, (0, _loggedusermock.buildMockUser)(), queryRunner);
268
- expect(permissionRepo.delete).toHaveBeenCalledWith(expect.objectContaining({
269
- permissionType: 'role_action'
270
- }));
271
- expect(permissionRepo.delete).toHaveBeenCalledWith(expect.objectContaining({
272
- permissionType: 'user_action'
273
- }));
274
- expect(permissionRepo.delete).toHaveBeenCalledWith(expect.objectContaining({
275
- permissionType: 'company_action'
276
- }));
277
- expect(mockPermissionCacheService.invalidateUsers).toHaveBeenCalledWith(expect.arrayContaining([
278
- 'user-1',
279
- 'user-2'
280
- ]));
281
- expect(mockPermissionCacheService.invalidateCompanyMembersCache).not.toHaveBeenCalled();
282
- });
283
- it('also queries and invalidates company whitelist entries when the company feature is enabled', async ()=>{
284
- mockIamConfigService.isCompanyFeatureEnabled.mockReturnValue(true);
285
- const permissionRepo = (0, _repositorymock.createMockRepository)();
286
- permissionRepo.find.mockResolvedValueOnce([]) // role-action rows
287
- .mockResolvedValueOnce([]) // direct user-action rows
288
- .mockResolvedValueOnce([
289
- {
290
- sourceId: 'company-1'
291
- }
292
- ]); // company-action rows
293
- const queryRunner = buildQueryRunner(permissionRepo);
294
- await service.beforeDeleteOperation({
295
- id: [
296
- 'action-uuid-1'
297
- ],
298
- type: 'delete'
299
- }, (0, _loggedusermock.buildMockUser)(), queryRunner);
300
- expect(mockPermissionCacheService.invalidateCompanyMembersCache).toHaveBeenCalledWith('company-1');
301
- });
302
- it('does not invalidate any cache when nothing is affected', async ()=>{
303
- const permissionRepo = (0, _repositorymock.createMockRepository)();
304
- permissionRepo.find.mockResolvedValue([]);
305
- const queryRunner = buildQueryRunner(permissionRepo);
306
- await service.beforeDeleteOperation({
307
- id: [
308
- 'action-uuid-1'
309
- ],
310
- type: 'delete'
311
- }, (0, _loggedusermock.buildMockUser)(), queryRunner);
312
- expect(mockPermissionCacheService.invalidateUsers).not.toHaveBeenCalled();
313
- });
314
- it('rejects deleting a readonly action', async ()=>{
315
- mockRepo.find.mockResolvedValue([
316
- buildAction({
317
- readOnly: true
318
- })
319
- ]);
320
- const permissionRepo = (0, _repositorymock.createMockRepository)();
321
- const queryRunner = buildQueryRunner(permissionRepo);
322
- await expect(service.beforeDeleteOperation({
323
- id: 'action-uuid-1',
324
- type: 'delete'
325
- }, (0, _loggedusermock.buildMockUser)(), queryRunner)).rejects.toThrow('Cannot delete readonly action');
326
- expect(permissionRepo.find).not.toHaveBeenCalled();
327
- });
328
- });
329
- describe('beforeUpdateOperation', ()=>{
330
- it('rejects updating a readonly action', async ()=>{
331
- mockRepo.find.mockResolvedValue([
332
- buildAction({
333
- readOnly: true
334
- })
335
- ]);
336
- await expect(service.beforeUpdateOperation({
337
- id: 'action-uuid-1',
338
- name: 'Renamed'
339
- }, (0, _loggedusermock.buildMockUser)(), {})).rejects.toThrow('Cannot modify readonly action');
340
- });
341
- it('allows updating a non-readonly action', async ()=>{
342
- // The service filters readOnly: true in the query itself, so a non-readonly
343
- // action never comes back — simulate that by resolving an empty array.
344
- mockRepo.find.mockResolvedValue([]);
345
- await expect(service.beforeUpdateOperation({
346
- id: 'action-uuid-1',
347
- name: 'Renamed'
348
- }, (0, _loggedusermock.buildMockUser)(), {})).resolves.toBeUndefined();
349
- });
350
- });
351
- });