@izara_project/izara-core-generate-service-code 1.0.82 → 1.0.84

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 (60) hide show
  1. package/package.json +4 -4
  2. package/src/compile/flowValidator.js +34 -0
  3. package/src/compile/loadSchemas.js +121 -7
  4. package/src/emit/attributeTree/emitAttributeTreeSchemas.js +388 -0
  5. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +29 -1
  6. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +16 -3
  7. package/src/emit/crud/crudActionPlan.js +43 -7
  8. package/src/emit/crud/emitCrudApplicationArtifacts.js +19 -4
  9. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +27 -6
  10. package/src/emit/crud/generateCrudApplicationArtifacts.js +3 -2
  11. package/src/emit/crud/generateDynamicCrudFlowSchemas.js +3 -2
  12. package/src/emit/crud/loadLocalSchemaArrays.js +3 -3
  13. package/src/emit/crud/templates/CreateComplete_Main.ejs +1 -1
  14. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +75 -21
  15. package/src/emit/crud/templates/CreateLogicalLib.ejs +73 -8
  16. package/src/emit/crud/templates/DeleteComplete_Main.ejs +1 -1
  17. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +39 -11
  18. package/src/emit/crud/templates/DeleteLogicalLib.ejs +6 -3
  19. package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +2 -2
  20. package/src/emit/crud/templates/FlowEndpoint_HdrWbs.ejs +7 -0
  21. package/src/emit/crud/templates/FlowMain_Wbs.ejs +5 -2
  22. package/src/emit/crud/templates/GetEndpoint_Main.ejs +13 -0
  23. package/src/emit/crud/templates/UpdateComplete_Main.ejs +1 -1
  24. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +53 -4
  25. package/src/emit/crud/templates/UpdateLogicalLib.ejs +4 -3
  26. package/src/emit/custom/customFlows.js +49 -0
  27. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +168 -49
  28. package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +1 -1
  29. package/src/emit/custom/templates/FlowEndpointRbacCallback_Main.ejs +194 -0
  30. package/src/emit/custom/templates/FlowEndpoint_Main.ejs +14 -22
  31. package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
  32. package/src/emit/function/templates/WbsFunction_Yaml.ejs +0 -2
  33. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +33 -8
  34. package/src/emit/rbac/emitRbacApplicationArtifacts.js +204 -7
  35. package/src/emit/rbac/templates/CancelUsage_Main.ejs +103 -0
  36. package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +71 -0
  37. package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +49 -6
  38. package/src/emit/rbac/templates/ListRbac_Main.ejs +9 -3
  39. package/src/emit/rbac/templates/RbacMutation_Main.ejs +1 -1
  40. package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +147 -0
  41. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +59 -23
  42. package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +1 -1
  43. package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +1 -1
  44. package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +10 -3
  45. package/src/emit/resource/emitResourceArtifacts.js +350 -112
  46. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +53 -2
  47. package/src/emit/system/emitSystemWebSocketArtifacts.js +6 -4
  48. package/src/emit/system/templates/WebSocketConnect.ejs +71 -12
  49. package/src/emit/system/templates/WebSocketConnect_Yaml.ejs +7 -0
  50. package/src/emit/systemText/emitSystemTextSchemas.js +3 -2
  51. package/src/generate.js +41 -10
  52. package/test/attributeTreeSchemas.test.js +219 -0
  53. package/test/createTargetRoleHandler.test.js +59 -4
  54. package/test/crudApplicationArtifacts.test.js +23 -6
  55. package/test/customFlowApplicationArtifacts.test.js +5 -5
  56. package/test/dynamicCrudFlowSchemas.test.js +110 -13
  57. package/test/dynamicRbacFlowSchemas.test.js +15 -2
  58. package/test/publicApi.test.js +7 -7
  59. package/test/resourceArtifacts.test.js +70 -29
  60. package/test/systemTextSchemas.test.js +1 -1
@@ -10,6 +10,7 @@ import {
10
10
  import { rbacFlowTag } from './rbacFlowTag.js';
11
11
 
12
12
  const FLOW_RBAC_YAML_PATH = 'app/sls_yaml/generatedCode/source/flow-rbac.yml';
13
+ const FLOW_LIMITS_YAML_PATH = 'app/sls_yaml/generatedCode/source/flow-limits.yml';
13
14
  const CRUD_TEMPLATE_URL = new URL('../crud/templates/', import.meta.url);
14
15
  const RBAC_TEMPLATE_URL = new URL('./templates/', import.meta.url);
15
16
 
@@ -23,7 +24,8 @@ export async function emitRbacApplicationArtifacts(objects) {
23
24
  }
24
25
  const hasSelfRbac = objects.some(hasSelfRbacAddOn);
25
26
  const flowTags = [...new Set(rbacObjects.map(rbacFlowTag))];
26
- const handlers = await Promise.all([
27
+
28
+ const rbacHandlers = await Promise.all([
27
29
  ...(hasSelfRbac
28
30
  ? [
29
31
  createTargetRoleHandler(),
@@ -34,23 +36,47 @@ export async function emitRbacApplicationArtifacts(objects) {
34
36
  : []),
35
37
  ...flowTags.map(createUserRbacFlowHandler)
36
38
  ]);
37
- return [
38
- ...handlers.flatMap((handler) => handler.artifacts),
39
+
40
+ const limitHandlers = await Promise.all(
41
+ hasSelfRbac
42
+ ? [
43
+ ...LIMIT_LIST_DEFINITIONS.map(createLimitListHandler),
44
+ ...LIMIT_MUTATION_DEFINITIONS.map(createLimitMutationHandler),
45
+ ...ACCOUNT_LIMIT_HANDLERS.map(createAccountLimitHandler)
46
+ ]
47
+ : []
48
+ );
49
+
50
+ const artifacts = [
51
+ ...rbacHandlers.flatMap((handler) => handler.artifacts),
52
+ ...limitHandlers.flatMap((handler) => handler.artifacts),
39
53
  {
40
54
  path: FLOW_RBAC_YAML_PATH,
41
- content: handlers
55
+ content: rbacHandlers
42
56
  .flatMap((handler) => handler.functions)
43
57
  .map(renderFunctionYaml)
44
58
  .join('\n')
45
59
  }
46
60
  ];
61
+
62
+ if (hasSelfRbac) {
63
+ artifacts.push({
64
+ path: FLOW_LIMITS_YAML_PATH,
65
+ content: limitHandlers
66
+ .flatMap((handler) => handler.functions)
67
+ .map(renderFunctionYaml)
68
+ .join('\n')
69
+ });
70
+ }
71
+
72
+ return artifacts;
47
73
  }
48
74
 
49
75
  const LIST_DEFINITIONS = [
50
76
  {
51
77
  flowTag: 'ListTargetRole',
52
78
  tableName: 'TargetRoles',
53
- requestProperty: 'userId',
79
+ requestProperty: 'identifiersConcat',
54
80
  useContextUserId: true
55
81
  },
56
82
  {
@@ -64,6 +90,15 @@ const LIST_DEFINITIONS = [
64
90
  requestProperty: 'roleIdKey'
65
91
  }
66
92
  ];
93
+
94
+ const LIMIT_LIST_DEFINITIONS = [
95
+ {
96
+ flowTag: 'ListRoleLimits',
97
+ tableName: 'RoleLimit',
98
+ requestProperty: 'roleLimitId'
99
+ }
100
+ ];
101
+
67
102
  const MUTATION_DEFINITIONS = [
68
103
  {
69
104
  flowTag: 'CreateRolePermissions',
@@ -81,14 +116,36 @@ const MUTATION_DEFINITIONS = [
81
116
  flowTag: 'DeleteTargetRole',
82
117
  tableName: 'TargetRoles',
83
118
  method: 'deleteItem',
84
- fields: ['targetId', 'roleIdKey']
119
+ fields: ['identifiersConcat', 'roleIdKey']
85
120
  }
86
121
  ];
122
+
123
+ const LIMIT_MUTATION_DEFINITIONS = [
124
+ {
125
+ flowTag: 'CreateRoleLimit',
126
+ tableName: 'RoleLimit',
127
+ method: 'putItem',
128
+ fields: ['roleLimitId', 'limitType', 'limitValue', 'actionType']
129
+ },
130
+ {
131
+ flowTag: 'DeleteRoleLimit',
132
+ tableName: 'RoleLimit',
133
+ method: 'deleteItem',
134
+ fields: ['roleLimitId', 'limitType']
135
+ }
136
+ ];
137
+
87
138
  const USER_ROLE_MUTATIONS = [
88
139
  { flowTag: 'CreateUserRole', operation: 'Put' },
89
140
  { flowTag: 'DeleteUserFromRole', operation: 'Delete' }
90
141
  ];
91
142
 
143
+ const ACCOUNT_LIMIT_HANDLERS = [
144
+ 'ReservedDynamicUsage',
145
+ 'ConfirmUsage',
146
+ 'CancelUsage'
147
+ ];
148
+
92
149
  const STATIC_RBAC_APPLICATION_PATHS = [
93
150
  'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_Main.js',
94
151
  'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_HdrSqs.js',
@@ -118,6 +175,27 @@ const STATIC_RBAC_APPLICATION_PATHS = [
118
175
  FLOW_RBAC_YAML_PATH
119
176
  ];
120
177
 
178
+ const STATIC_LIMIT_APPLICATION_PATHS = [
179
+ ...LIMIT_LIST_DEFINITIONS.flatMap(({ flowTag }) => [
180
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_Main.js`,
181
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrSqs.js`,
182
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrApi.js`
183
+ ]),
184
+ ...LIMIT_MUTATION_DEFINITIONS.flatMap(({ flowTag }) => [
185
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_Main.js`,
186
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrSqs.js`,
187
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_WbsMain.js`,
188
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrWbs.js`
189
+ ]),
190
+ ...ACCOUNT_LIMIT_HANDLERS.flatMap((flowTag) => [
191
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_Main.js`,
192
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrSqs.js`,
193
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_WbsMain.js`,
194
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrWbs.js`
195
+ ]),
196
+ FLOW_LIMITS_YAML_PATH
197
+ ];
198
+
121
199
  export function rbacApplicationManagedPaths(objects = []) {
122
200
  if (!Array.isArray(objects)) {
123
201
  throw new TypeError('objects must be an array');
@@ -131,7 +209,126 @@ export function rbacApplicationManagedPaths(objects = []) {
131
209
  `${sourcePath}/${flowTag}_HdrSqs.js`
132
210
  ];
133
211
  });
134
- return [...new Set([...STATIC_RBAC_APPLICATION_PATHS, ...sourcePaths])];
212
+ return [
213
+ ...new Set([
214
+ ...STATIC_RBAC_APPLICATION_PATHS,
215
+ ...STATIC_LIMIT_APPLICATION_PATHS,
216
+ ...sourcePaths
217
+ ])
218
+ ];
219
+ }
220
+
221
+ async function createAccountLimitHandler(flowTag) {
222
+ const sourcePath = `app/src/generatedCode/FlowLimit/${flowTag}/source`;
223
+ const handlerPath = `src/generatedCode/FlowLimit/${flowTag}/source`;
224
+ const webSocket = await createWebSocketEntry(
225
+ flowTag,
226
+ sourcePath,
227
+ handlerPath
228
+ );
229
+ return {
230
+ artifacts: [
231
+ {
232
+ path: `${sourcePath}/${flowTag}_Main.js`,
233
+ content: await renderRbacTemplate(`${flowTag}_Main.ejs`, { flowTag })
234
+ },
235
+ {
236
+ path: `${sourcePath}/${flowTag}_HdrSqs.js`,
237
+ content: await renderRbacTemplate('ListRbac_HdrSqs.ejs', { flowTag })
238
+ },
239
+ ...webSocket.artifacts
240
+ ],
241
+ functions: [
242
+ {
243
+ type: 'sqs',
244
+ functionName: `${flowTag}HdrSqs`,
245
+ handlerPath: `${handlerPath}/${flowTag}_HdrSqs.main`,
246
+ roleName: 'FlowRbacRole',
247
+ queueName: `${flowTag}HdrSqs`,
248
+ flowTag: flowTag,
249
+ flowStepName: ''
250
+ },
251
+ ...webSocket.functions
252
+ ]
253
+ };
254
+ }
255
+
256
+ async function createLimitListHandler(definition) {
257
+ const sourcePath = `app/src/generatedCode/FlowLimit/${definition.flowTag}/source`;
258
+ const handlerPath = `src/generatedCode/FlowLimit/${definition.flowTag}/source`;
259
+ return {
260
+ artifacts: [
261
+ {
262
+ path: `${sourcePath}/${definition.flowTag}_Main.js`,
263
+ content: await renderRbacTemplate('ListRbac_Main.ejs', {
264
+ ...definition,
265
+ useContextUserId: definition.useContextUserId ?? false
266
+ })
267
+ },
268
+ {
269
+ path: `${sourcePath}/${definition.flowTag}_HdrSqs.js`,
270
+ content: await renderRbacTemplate('ListRbac_HdrSqs.ejs', definition)
271
+ },
272
+ {
273
+ path: `${sourcePath}/${definition.flowTag}_HdrApi.js`,
274
+ content: await renderRbacTemplate('ListRbac_HdrApi.ejs', definition)
275
+ }
276
+ ],
277
+ functions: [
278
+ {
279
+ type: 'sqs',
280
+ functionName: `${definition.flowTag}HdrSqs`,
281
+ handlerPath: `${handlerPath}/${definition.flowTag}_HdrSqs.main`,
282
+ roleName: 'FlowRbacRole',
283
+ queueName: `${definition.flowTag}HdrSqs`,
284
+ flowTag: definition.flowTag,
285
+ flowStepName: ''
286
+ },
287
+ {
288
+ type: 'api',
289
+ functionName: `${definition.flowTag}HdrApi`,
290
+ handlerPath: `${handlerPath}/${definition.flowTag}_HdrApi.main`,
291
+ roleName: 'FlowRbacRole',
292
+ flowTag: definition.flowTag,
293
+ flowStepName: ''
294
+ }
295
+ ]
296
+ };
297
+ }
298
+
299
+ async function createLimitMutationHandler(definition) {
300
+ const sourcePath = `app/src/generatedCode/FlowLimit/${definition.flowTag}/source`;
301
+ const handlerPath = `src/generatedCode/FlowLimit/${definition.flowTag}/source`;
302
+ const webSocket = await createWebSocketEntry(
303
+ definition.flowTag,
304
+ sourcePath,
305
+ handlerPath
306
+ );
307
+ return {
308
+ artifacts: [
309
+ {
310
+ path: `${sourcePath}/${definition.flowTag}_Main.js`,
311
+ content: await renderRbacTemplate('RbacMutation_Main.ejs', definition)
312
+ },
313
+ {
314
+ path: `${sourcePath}/${definition.flowTag}_HdrSqs.js`,
315
+ content: await renderRbacTemplate('ListRbac_HdrSqs.ejs', definition)
316
+ },
317
+ ...webSocket.artifacts
318
+ ],
319
+ functions: [
320
+ {
321
+ type: 'sqs',
322
+ functionName: `${definition.flowTag}HdrSqs`,
323
+ handlerPath: `${handlerPath}/${definition.flowTag}_HdrSqs.main`,
324
+ roleName: 'FlowRbacRole',
325
+ queueName: `${definition.flowTag}HdrSqs`,
326
+ flowTag: definition.flowTag,
327
+ flowStepName: ''
328
+ },
329
+ ...webSocket.functions
330
+ ]
331
+ };
135
332
  }
136
333
 
137
334
  async function createTargetRoleHandler() {
@@ -0,0 +1,103 @@
1
+ /*
2
+ Copyright (C) 2020 Sven Mason <http://izara.io>
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU Affero General Public License as
6
+ published by the Free Software Foundation, either version 3 of the
7
+ License, or (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU Affero General Public License for more details.
13
+
14
+ You should have received a copy of the GNU Affero General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
19
+ import snsSharedLib from '@izara_project/izara-core-library-sns';
20
+ import { sns } from '@izara_project/izara-core-library-external-request';
21
+ import { consts, NoRetryError } from '@izara_project/izara-core-library-core';
22
+
23
+ export default async function CancelUsage(_izContext, requestParams) {
24
+ try {
25
+ const submittedByUserId =
26
+ requestParams.submittedByUserId ||
27
+ _izContext.correlationIds?.get(consts.SUBMITTED_BY_USER_ID);
28
+ const { limitTag, uniqueIdentify } = requestParams;
29
+
30
+ const targetIdentifiers = requestParams.targetIdentifiers;
31
+ let identifiersConcat = requestParams.identifiersConcat;
32
+ if (!identifiersConcat && targetIdentifiers && typeof targetIdentifiers === 'object') {
33
+ identifiersConcat = Object.entries(targetIdentifiers)
34
+ .map(([k, v]) => `${k}#${v}`)
35
+ .join('_');
36
+ }
37
+ if (!identifiersConcat) {
38
+ identifiersConcat = submittedByUserId;
39
+ }
40
+
41
+ if (!identifiersConcat || !limitTag || !uniqueIdentify) {
42
+ throw new NoRetryError(
43
+ 'identifiersConcat, limitTag, and uniqueIdentify are required.'
44
+ );
45
+ }
46
+
47
+ const runningTotalReservedId = `${identifiersConcat}_${limitTag}`;
48
+ const reservedRecord = await dynamodbSharedLib.getItem(
49
+ _izContext,
50
+ dynamodbSharedLib.tableName(_izContext, 'RunningTotalReservedUsage'),
51
+ {
52
+ runningTotalReservedId,
53
+ usedTimestampId: uniqueIdentify
54
+ }
55
+ );
56
+
57
+ const usageCount = reservedRecord?.usageCount || 0;
58
+
59
+ await dynamodbSharedLib.updateItem(
60
+ _izContext,
61
+ dynamodbSharedLib.tableName(_izContext, 'RunningTotalReservedUsage'),
62
+ {
63
+ runningTotalReservedId,
64
+ usedTimestampId: uniqueIdentify
65
+ },
66
+ {
67
+ runningTotalUsageStatus: 'cancelled'
68
+ }
69
+ );
70
+
71
+ if (usageCount > 0) {
72
+ const usageRecord = await dynamodbSharedLib.getItem(
73
+ _izContext,
74
+ dynamodbSharedLib.tableName(_izContext, 'RunningTotalUsage'),
75
+ { identifiersConcat, limitTag }
76
+ );
77
+ if (usageRecord) {
78
+ const newTotal = Math.max(0, (usageRecord.totalCount || 0) - usageCount);
79
+ await dynamodbSharedLib.putItem(
80
+ _izContext,
81
+ dynamodbSharedLib.tableName(_izContext, 'RunningTotalUsage'),
82
+ {
83
+ identifiersConcat,
84
+ limitTag,
85
+ totalCount: newTotal,
86
+ updateUuid: _izContext.uniqueRequestId || `${Date.now()}`
87
+ }
88
+ );
89
+ }
90
+ }
91
+
92
+ await sns.publishMessage(_izContext, {
93
+ message: { returnResult: { status: true, uniqueIdentify } },
94
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
95
+ _izContext,
96
+ 'CancelUsage_Out'
97
+ )
98
+ });
99
+ } catch (error) {
100
+ _izContext.logger.error(`[${process.env.iz_serviceTag}:CancelUsage] error:`, error);
101
+ throw error;
102
+ }
103
+ }
@@ -0,0 +1,71 @@
1
+ /*
2
+ Copyright (C) 2020 Sven Mason <http://izara.io>
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU Affero General Public License as
6
+ published by the Free Software Foundation, either version 3 of the
7
+ License, or (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU Affero General Public License for more details.
13
+
14
+ You should have received a copy of the GNU Affero General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
19
+ import snsSharedLib from '@izara_project/izara-core-library-sns';
20
+ import { sns } from '@izara_project/izara-core-library-external-request';
21
+ import { consts, NoRetryError } from '@izara_project/izara-core-library-core';
22
+
23
+ export default async function ConfirmUsage(_izContext, requestParams) {
24
+ try {
25
+ const submittedByUserId =
26
+ requestParams.submittedByUserId ||
27
+ _izContext.correlationIds?.get(consts.SUBMITTED_BY_USER_ID);
28
+ const { limitTag, uniqueIdentify } = requestParams;
29
+
30
+ const targetIdentifiers = requestParams.targetIdentifiers;
31
+ let identifiersConcat = requestParams.identifiersConcat;
32
+ if (!identifiersConcat && targetIdentifiers && typeof targetIdentifiers === 'object') {
33
+ identifiersConcat = Object.entries(targetIdentifiers)
34
+ .map(([k, v]) => `${k}#${v}`)
35
+ .join('_');
36
+ }
37
+ if (!identifiersConcat) {
38
+ identifiersConcat = submittedByUserId;
39
+ }
40
+
41
+ if (!identifiersConcat || !limitTag || !uniqueIdentify) {
42
+ throw new NoRetryError(
43
+ 'identifiersConcat, limitTag, and uniqueIdentify are required.'
44
+ );
45
+ }
46
+
47
+ const runningTotalReservedId = `${identifiersConcat}_${limitTag}`;
48
+ await dynamodbSharedLib.updateItem(
49
+ _izContext,
50
+ dynamodbSharedLib.tableName(_izContext, 'RunningTotalReservedUsage'),
51
+ {
52
+ runningTotalReservedId,
53
+ usedTimestampId: uniqueIdentify
54
+ },
55
+ {
56
+ runningTotalUsageStatus: 'confirmed'
57
+ }
58
+ );
59
+
60
+ await sns.publishMessage(_izContext, {
61
+ message: { returnResult: { status: true, uniqueIdentify } },
62
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
63
+ _izContext,
64
+ 'ConfirmUsage_Out'
65
+ )
66
+ });
67
+ } catch (error) {
68
+ _izContext.logger.error(`[${process.env.iz_serviceTag}:ConfirmUsage] error:`, error);
69
+ throw error;
70
+ }
71
+ }
@@ -23,23 +23,66 @@ import { consts } from '@izara_project/izara-core-library-core';
23
23
 
24
24
  export default async function CreateTargetRole(_izContext, requestParams) {
25
25
  try {
26
- const userId = _izContext.correlationIds.get(consts.BASE_USER_ID);
27
- const { roleName } = requestParams;
28
- const roleId = identifierUuid();
26
+ const submittedByUserId =
27
+ requestParams.submittedByUserId ||
28
+ _izContext.correlationIds?.get(consts.SUBMITTED_BY_USER_ID);
29
+
30
+ const targetIdentifiers = requestParams.targetIdentifiers;
31
+ let identifiersConcat = requestParams.identifiersConcat;
32
+ if (!identifiersConcat && targetIdentifiers && typeof targetIdentifiers === 'object') {
33
+ identifiersConcat = Object.entries(targetIdentifiers)
34
+ .map(([k, v]) => `${k}#${v}`)
35
+ .join('_');
36
+ }
37
+ if (!identifiersConcat) {
38
+ identifiersConcat = submittedByUserId;
39
+ }
40
+
41
+ const { roleName = 'owner', roleId: inputRoleId } = requestParams;
42
+ const roleId = inputRoleId || roleName || identifierUuid();
43
+ const roleIdKey = `${identifiersConcat}_${roleId}`;
44
+
29
45
  await dynamodbSharedLib.putItem(
30
46
  _izContext,
31
47
  dynamodbSharedLib.tableName(_izContext, 'TargetRoles'),
32
- { targetId: userId, roleIdKey: `${userId}_${roleId}`, roleName }
48
+ {
49
+ identifiersConcat,
50
+ roleIdKey,
51
+ roleName,
52
+ submittedByUserId
53
+ }
33
54
  );
55
+
56
+ if (submittedByUserId) {
57
+ try {
58
+ await dynamodbSharedLib.transactWriteItems(_izContext, [
59
+ {
60
+ Put: {
61
+ TableName: dynamodbSharedLib.tableName(_izContext, 'RoleUsers'),
62
+ Item: { roleIdKey, submittedByUserId }
63
+ }
64
+ },
65
+ {
66
+ Put: {
67
+ TableName: dynamodbSharedLib.tableName(_izContext, 'UserRoles'),
68
+ Item: { submittedByUserId, roleIdKey }
69
+ }
70
+ }
71
+ ]);
72
+ } catch (assignError) {
73
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:CreateTargetRole] UserRoles transactWrite ignored:', assignError);
74
+ }
75
+ }
76
+
34
77
  await sns.publishMessage(_izContext, {
35
- message: { returnResult: { roleId } },
78
+ message: { returnResult: { roleId, roleIdKey } },
36
79
  TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
37
80
  _izContext,
38
81
  'CreateTargetRole_Out'
39
82
  )
40
83
  });
41
84
  } catch (error) {
42
- _izContext.logger.error('[Rbac:CreateTargetRole] error:', error);
85
+ _izContext.logger.error(`[${process.env.iz_serviceTag}:CreateTargetRole] error:`, error);
43
86
  throw error;
44
87
  }
45
88
  }
@@ -22,8 +22,14 @@ import { consts, NoRetryError } from '@izara_project/izara-core-library-core';
22
22
 
23
23
  export default async function <%- flowTag %>(_izContext, requestParams) {
24
24
  try {
25
- <% if (useContextUserId) { -%>
26
- const userId = _izContext.correlationIds.get(consts.BASE_USER_ID);
25
+ <% if (flowTag === 'ListTargetRole') { -%>
26
+ const userId = requestParams.submittedByUserId || _izContext.correlationIds.get(consts.SUBMITTED_BY_USER_ID);
27
+ const identifiersConcat =
28
+ requestParams.identifiersConcat || requestParams.targetId || userId;
29
+ if (!identifiersConcat) throw new NoRetryError('Identifier not found.');
30
+ const queryParams = { identifiersConcat };
31
+ <% } else if (useContextUserId) { -%>
32
+ const userId = requestParams.submittedByUserId || _izContext.correlationIds.get(consts.SUBMITTED_BY_USER_ID);
27
33
  if (!userId) throw new NoRetryError('User Id not found.');
28
34
  const queryParams = { userId };
29
35
  <% } else { -%>
@@ -43,7 +49,7 @@ export default async function <%- flowTag %>(_izContext, requestParams) {
43
49
  )
44
50
  });
45
51
  } catch (error) {
46
- _izContext.logger.error('[Rbac:<%- flowTag %>] error:', error);
52
+ _izContext.logger.error(`[${process.env.iz_serviceTag}:<%- flowTag %>] error:`, error);
47
53
  throw error;
48
54
  }
49
55
  }
@@ -36,7 +36,7 @@ export default async function <%- flowTag %>(_izContext, requestParams) {
36
36
  )
37
37
  });
38
38
  } catch (error) {
39
- _izContext.logger.error('[Rbac:<%- flowTag %>] error:', error);
39
+ _izContext.logger.error(`[${process.env.iz_serviceTag}:<%- flowTag %>] error:`, error);
40
40
  throw error;
41
41
  }
42
42
  }