@izara_project/izara-core-generate-service-code 1.0.90 → 1.0.92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -10
- package/src/compile/flowValidator.js +6 -0
- package/src/compile/loadSchemas.js +177 -69
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +2 -2
- package/src/emit/crud/generateCrudApplicationArtifacts.js +15 -17
- package/src/emit/crud/generateDynamicCrudFlowSchemas.js +16 -21
- package/src/emit/crud/loadLocalSchemaArrays.js +4 -8
- package/src/emit/crud/templates/CreateAfterHookCallback_Main.ejs +6 -6
- package/src/emit/crud/templates/CreateBeforeHookCallback_Main.ejs +3 -3
- package/src/emit/crud/templates/CreateComplete_Main.ejs +22 -22
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +18 -18
- package/src/emit/crud/templates/CreateLogicalLib.ejs +47 -47
- package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +24 -24
- package/src/emit/crud/templates/DeleteAfterHookCallback_Main.ejs +5 -5
- package/src/emit/crud/templates/DeleteBeforeHookCallback_Main.ejs +3 -3
- package/src/emit/crud/templates/DeleteComplete_Main.ejs +23 -23
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +15 -15
- package/src/emit/crud/templates/DeleteLogicalLib.ejs +19 -19
- package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +3 -3
- package/src/emit/crud/templates/UpdateAfterHookCallback_Main.ejs +5 -5
- package/src/emit/crud/templates/UpdateBeforeHookCallback_Main.ejs +3 -3
- package/src/emit/crud/templates/UpdateComplete_Main.ejs +22 -22
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +15 -15
- package/src/emit/crud/templates/UpdateLogicalLib.ejs +33 -33
- package/src/emit/custom/customFlowPaths.js +149 -0
- package/src/emit/custom/customFlowS3.js +156 -0
- package/src/emit/custom/customFlowSteps.js +385 -0
- package/src/emit/custom/customFlowTemplates.js +28 -0
- package/src/emit/custom/customFlows.js +48 -19
- package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +57 -692
- package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +27 -25
- package/src/emit/custom/templates/FlowEndpointRbacCallback_Main.ejs +7 -7
- package/src/emit/custom/templates/s3/ConfirmReserved_HdrSqs.ejs +3 -3
- package/src/emit/custom/templates/s3/ConfirmReserved_Main.ejs +3 -3
- package/src/emit/custom/templates/s3/CreatePreSignUrl_HdrSqs.ejs +3 -3
- package/src/emit/custom/templates/s3/CreatePreSignUrl_Main.ejs +4 -4
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +26 -6
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +40 -13
- package/src/emit/rbac/generateCreateTargetRoleHandler.js +11 -13
- package/src/emit/rbac/generateDynamicRbacFlowSchemas.js +14 -18
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +13 -7
- package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +1 -1
- package/src/emit/relationship/generateDynamicRelationshipFlowSchemas.js +16 -19
- package/src/emit/relationship/generateRelationshipApplicationArtifacts.js +19 -19
- package/src/emit/relationship/templates/ChangeRelationshipComplete_HdrSqs.ejs +2 -2
- package/src/emit/relationship/templates/ChangeRelationshipComplete_Main.ejs +6 -6
- package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +17 -17
- package/src/emit/relationship/templates/CreateRelationshipComplete_HdrSqs.ejs +2 -2
- package/src/emit/relationship/templates/CreateRelationshipComplete_Main.ejs +6 -6
- package/src/emit/relationship/templates/CreateRelationship_Main.ejs +14 -14
- package/src/emit/relationship/templates/DeleteRelationshipComplete_HdrSqs.ejs +2 -2
- package/src/emit/relationship/templates/DeleteRelationshipComplete_Main.ejs +6 -6
- package/src/emit/relationship/templates/DeleteRelationship_Main.ejs +10 -10
- package/src/emit/relationship/templates/GetRelationshipComplete_HdrSqs.ejs +2 -2
- package/src/emit/relationship/templates/GetRelationshipComplete_Main.ejs +5 -5
- package/src/emit/relationship/templates/GetRelationship_Main.ejs +9 -9
- package/src/emit/relationship/templates/MoveRelationshipComplete_HdrSqs.ejs +2 -2
- package/src/emit/relationship/templates/MoveRelationshipComplete_Main.ejs +6 -6
- package/src/emit/relationship/templates/MoveRelationship_Main.ejs +15 -15
- package/src/emit/relationship/templates/UpdateRelationshipComplete_HdrSqs.ejs +2 -2
- package/src/emit/relationship/templates/UpdateRelationshipComplete_Main.ejs +6 -6
- package/src/emit/relationship/templates/UpdateRelationship_Main.ejs +11 -11
- package/src/emit/resource/dynamoResourceArtifacts.js +18 -0
- package/src/emit/resource/emitResourceArtifacts.js +13 -1251
- package/src/emit/resource/generateResourceArtifacts.js +20 -20
- package/src/emit/resource/iamResourceArtifacts.js +612 -0
- package/src/emit/resource/resourceState.js +564 -0
- package/src/emit/resource/resourceTemplate.js +30 -0
- package/src/emit/resource/s3ResourceArtifacts.js +14 -0
- package/src/emit/resource/sqsResourceArtifacts.js +113 -0
- package/src/emit/shared/runSubsystemGeneration.js +55 -0
- package/src/emit/shared/templates/FindData_Main.ejs +19 -19
- package/src/emit/shared/templates/PaginateProcessLogical_Main.ejs +3 -3
- package/src/emit/shared/templates/ProcessLogical_Main.ejs +15 -15
- package/src/emit/system/emitSystemWebSocketArtifacts.js +2 -1
- package/test/createTargetRoleHandler.test.js +62 -4
- package/test/crudApplicationArtifacts.test.js +75 -3
- package/test/customFlowApplicationArtifacts.test.js +98 -0
- package/test/dynamicCrudFlowSchemas.test.js +2 -2
- package/test/dynamicRbacFlowSchemas.test.js +32 -4
- package/test/relationshipApplicationArtifacts.test.js +1 -1
- package/test/resourceArtifacts.test.js +99 -0
|
@@ -1,95 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { normalizeYaml } from './resourceTemplate.js';
|
|
2
|
+
import { createResourceState } from './resourceState.js';
|
|
4
3
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from '
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { CRUD_ACTIONS, createCrudActionPlans } from '../crud/crudActionPlan.js';
|
|
4
|
+
renderCrudInSqs,
|
|
5
|
+
renderRelationshipInSqs,
|
|
6
|
+
renderRbacInSqs,
|
|
7
|
+
renderCustomFlowInSqs,
|
|
8
|
+
renderSystemInSqs,
|
|
9
|
+
renderOut
|
|
10
|
+
} from './sqsResourceArtifacts.js';
|
|
11
|
+
import { renderDynamo } from './dynamoResourceArtifacts.js';
|
|
12
|
+
import { renderIam, renderLambdaRoleConfig } from './iamResourceArtifacts.js';
|
|
13
|
+
import { renderS3 } from './s3ResourceArtifacts.js';
|
|
16
14
|
|
|
17
|
-
const TEMPLATE_URL = new URL('./templates/', import.meta.url);
|
|
18
15
|
const RESOURCE_ROOT = 'resource/sls_yaml/generatedCode/source';
|
|
19
16
|
const APP_ROOT = 'app/sls_yaml/generatedCode/source';
|
|
20
|
-
const INITIAL_SETUP_ROOT = 'app/initial_setup/generatedCode/source';
|
|
21
|
-
const RELATIONSHIP_ACTIONS = [
|
|
22
|
-
'CreateRelationship',
|
|
23
|
-
'UpdateRelationship',
|
|
24
|
-
'DeleteRelationship',
|
|
25
|
-
'GetRelationship',
|
|
26
|
-
'ChangeRelationship',
|
|
27
|
-
'MoveRelationship'
|
|
28
|
-
];
|
|
29
|
-
const RBAC_ACTIONS = [
|
|
30
|
-
'CreateTargetRole',
|
|
31
|
-
'UpdateTargetRole',
|
|
32
|
-
'DeleteTargetRole',
|
|
33
|
-
'GetTargetRole',
|
|
34
|
-
'ListTargetRole',
|
|
35
|
-
'CreateRolePermissions',
|
|
36
|
-
'ListRolePermissions',
|
|
37
|
-
'DeleteRolePermissions',
|
|
38
|
-
'CreateUserRole',
|
|
39
|
-
'ListUserInRoles',
|
|
40
|
-
'DeleteUserFromRole',
|
|
41
|
-
'GetMyPermissions',
|
|
42
|
-
'ValidatorRbac',
|
|
43
|
-
'ReservedDynamicUsage',
|
|
44
|
-
'ConfirmUsage',
|
|
45
|
-
'CancelUsage'
|
|
46
|
-
];
|
|
47
|
-
const SYSTEM_TABLES = [
|
|
48
|
-
'WebSocketTask',
|
|
49
|
-
'UserUploadRecords',
|
|
50
|
-
'RegisterRecords',
|
|
51
|
-
'AwaitingMultipleSteps',
|
|
52
|
-
'AwaitingMultipleStepByPending',
|
|
53
|
-
'FindDataMain',
|
|
54
|
-
'LogicalResultsMain',
|
|
55
|
-
'LogicalResultsData',
|
|
56
|
-
'AwaitingStep'
|
|
57
|
-
];
|
|
58
|
-
const RBAC_TABLES = [
|
|
59
|
-
'Roles',
|
|
60
|
-
'TargetRoles',
|
|
61
|
-
'RolePermissions',
|
|
62
|
-
'RoleUsers',
|
|
63
|
-
'UserRoles',
|
|
64
|
-
'RbacPermissionCaches',
|
|
65
|
-
'RunningTotalUsage',
|
|
66
|
-
'RunningTotalReservedUsage',
|
|
67
|
-
'WebSocketTask'
|
|
68
|
-
];
|
|
69
|
-
const LEGACY_PROCESS_QUEUES = [
|
|
70
|
-
'FindDataHdrSqs',
|
|
71
|
-
'ProcessLogicalHdrSqs',
|
|
72
|
-
'PaginateProcessLogicalHdrDsq',
|
|
73
|
-
'PaginateProcessLogicalHdrSqs'
|
|
74
|
-
];
|
|
75
|
-
const DYNAMO_ACTIONS = [
|
|
76
|
-
'dynamodb:DeleteItem',
|
|
77
|
-
'dynamodb:GetItem',
|
|
78
|
-
'dynamodb:PutItem',
|
|
79
|
-
'dynamodb:Query',
|
|
80
|
-
'dynamodb:UpdateItem'
|
|
81
|
-
];
|
|
82
|
-
const SQS_CONSUMER_ACTIONS = [
|
|
83
|
-
'sqs:DeleteMessage',
|
|
84
|
-
'sqs:GetQueueAttributes',
|
|
85
|
-
'sqs:ReceiveMessage'
|
|
86
|
-
];
|
|
87
|
-
const SQS_DLQ_ACTIONS = [
|
|
88
|
-
'sqs:DeleteMessage',
|
|
89
|
-
'sqs:GetQueueAttributes',
|
|
90
|
-
'sqs:ReceiveMessage',
|
|
91
|
-
'sqs:SendMessage'
|
|
92
|
-
];
|
|
93
17
|
|
|
94
18
|
export async function emitResourceArtifacts({
|
|
95
19
|
objects,
|
|
@@ -201,1154 +125,7 @@ export const resourceArtifactPaths = [
|
|
|
201
125
|
`${APP_ROOT}/cors.yml`
|
|
202
126
|
];
|
|
203
127
|
|
|
204
|
-
function
|
|
205
|
-
const crud = objects.some(isCrudObject);
|
|
206
|
-
const selfRbac = objects.some(hasSelfRbacAddOn);
|
|
207
|
-
const rbac = objects.some((obj) => hasRbacAddOn(obj, objects));
|
|
208
|
-
const crudActionPlans = createCrudActionPlans(objects, flows);
|
|
209
|
-
|
|
210
|
-
const crudOwnTopics = crud ? [...CRUD_ACTIONS] : [];
|
|
211
|
-
const crudSqsQueues = [];
|
|
212
|
-
if (crud) {
|
|
213
|
-
for (const action of ['Create', 'Update', 'Delete']) {
|
|
214
|
-
const plan = crudActionPlans[action];
|
|
215
|
-
if (plan.hasCreateNodeCallback) {
|
|
216
|
-
crudSqsQueues.push(`${action}NodeCallbackHdrSqs`);
|
|
217
|
-
}
|
|
218
|
-
if (plan.hasBeforeHookCallback) {
|
|
219
|
-
crudSqsQueues.push(`${action}BeforeHookCallbackHdrSqs`);
|
|
220
|
-
}
|
|
221
|
-
if (plan.hasAfterHookCallback) {
|
|
222
|
-
crudSqsQueues.push(`${action}AfterHookCallbackHdrSqs`);
|
|
223
|
-
}
|
|
224
|
-
if (plan.hasComplete) {
|
|
225
|
-
crudSqsQueues.push(`${action}CompleteHdrSqs`);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const relationshipOwnTopics =
|
|
231
|
-
relationships.length > 0 ? [...RELATIONSHIP_ACTIONS] : [];
|
|
232
|
-
const relationshipSqsQueues =
|
|
233
|
-
relationships.length > 0
|
|
234
|
-
? RELATIONSHIP_ACTIONS.map((action) => `${action}CompleteHdrSqs`)
|
|
235
|
-
: [];
|
|
236
|
-
const relationshipDsqQueues =
|
|
237
|
-
relationships.length > 0 ? ['GetRelationshipHdrDsq'] : [];
|
|
238
|
-
|
|
239
|
-
const rbacOwnTopics = [];
|
|
240
|
-
const rbacSqsQueues = [];
|
|
241
|
-
if (selfRbac) {
|
|
242
|
-
for (const action of RBAC_ACTIONS) {
|
|
243
|
-
rbacOwnTopics.push(action);
|
|
244
|
-
rbacSqsQueues.push(`Process${action}HdrSqs`);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
if (selfRbac) {
|
|
248
|
-
const flowTags = [
|
|
249
|
-
...new Set(objects.filter(hasSelfRbacAddOn).map(rbacFlowTag))
|
|
250
|
-
];
|
|
251
|
-
for (const flowTag of flowTags) {
|
|
252
|
-
rbacOwnTopics.push(flowTag);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
if (crud) {
|
|
256
|
-
for (const action of ['Create', 'Update', 'Delete']) {
|
|
257
|
-
const plan = crudActionPlans[action];
|
|
258
|
-
if (plan.hasRbacCallback) {
|
|
259
|
-
rbacSqsQueues.push(`${action}RbacCallbackHdrSqs`);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const customOwnTopics = flows
|
|
265
|
-
.filter((flow) => includesEvent(flow, 'ownTopic'))
|
|
266
|
-
.map((flow) => upperFirst(flow.flowTag));
|
|
267
|
-
|
|
268
|
-
const customSqsQueues = [
|
|
269
|
-
...flows
|
|
270
|
-
.filter((flow) => includesEvent(flow, 'extTopic'))
|
|
271
|
-
.map((flow) => `Process${upperFirst(flow.flowTag)}HdrSqs`),
|
|
272
|
-
...flows
|
|
273
|
-
.filter(
|
|
274
|
-
(flow) =>
|
|
275
|
-
flow?.outputTopic &&
|
|
276
|
-
!flow?.generatedCodeConfig &&
|
|
277
|
-
upperFirst(flow.flowTag)
|
|
278
|
-
)
|
|
279
|
-
.map((flow) => `${upperFirst(flow.flowTag)}CompleteHdrSqs`)
|
|
280
|
-
];
|
|
281
|
-
for (const { flowTag, stepName } of flowExtTopicSteps(flows)) {
|
|
282
|
-
customSqsQueues.push(`${flowTag}${stepName}HdrSqs`);
|
|
283
|
-
}
|
|
284
|
-
for (const flow of flows) {
|
|
285
|
-
if (flowHasRbac(flow, objects)) {
|
|
286
|
-
const tag = upperFirst(flow.flowTag);
|
|
287
|
-
customSqsQueues.push(`${tag}RbacCallbackHdrSqs`);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
for (const flow of flows.filter((flow) => includesEvent(flow, 's3'))) {
|
|
291
|
-
const tag = upperFirst(flow.flowTag);
|
|
292
|
-
customSqsQueues.push(`${tag}CreatePreSignUrlHdrSqs`);
|
|
293
|
-
customSqsQueues.push(`${tag}ReservedLimitHdrSqs`);
|
|
294
|
-
customSqsQueues.push(`${tag}ConfirmAfterUploadHdrSqs`);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const customDsqQueues = flows
|
|
298
|
-
.filter((flow) => includesEvent(flow, 'dsq'))
|
|
299
|
-
.map((flow) => `${upperFirst(flow.flowTag)}HdrDsq`);
|
|
300
|
-
for (const { flowTag, stepName } of flowDsqSteps(flows)) {
|
|
301
|
-
customDsqQueues.push(`${flowTag}${stepName}HdrDsq`);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
const websocket = hasSystemWebSocket(flows, {
|
|
305
|
-
includeRelationshipOwnTopic: true,
|
|
306
|
-
objects,
|
|
307
|
-
relationships
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
const systemOwnTopics = ['ProcessLogical', 'FindData'];
|
|
311
|
-
const systemSqsQueues = [
|
|
312
|
-
'PaginateProcessLogicalHdrSqs',
|
|
313
|
-
...(websocket ? ['WebSocketCompleteHdrSqs', 'RegisterCompleteHdrSqs'] : [])
|
|
314
|
-
];
|
|
315
|
-
const systemDsqQueues = ['PaginateProcessLogicalHdrDsq'];
|
|
316
|
-
|
|
317
|
-
const ownTopics = new Set([
|
|
318
|
-
...systemOwnTopics,
|
|
319
|
-
...crudOwnTopics,
|
|
320
|
-
...relationshipOwnTopics,
|
|
321
|
-
...rbacOwnTopics,
|
|
322
|
-
...customOwnTopics
|
|
323
|
-
]);
|
|
324
|
-
const sqsQueues = new Set([
|
|
325
|
-
...systemSqsQueues,
|
|
326
|
-
...crudSqsQueues,
|
|
327
|
-
...relationshipSqsQueues,
|
|
328
|
-
...rbacSqsQueues,
|
|
329
|
-
...customSqsQueues
|
|
330
|
-
]);
|
|
331
|
-
const dsqQueues = new Set([
|
|
332
|
-
...systemDsqQueues,
|
|
333
|
-
...relationshipDsqQueues,
|
|
334
|
-
...customDsqQueues
|
|
335
|
-
]);
|
|
336
|
-
|
|
337
|
-
const customRoles = [
|
|
338
|
-
...new Set([
|
|
339
|
-
...supportedCustomFlows(flows).map((flow) =>
|
|
340
|
-
customFlowRoleName(flow.flowTag)
|
|
341
|
-
),
|
|
342
|
-
...generatedOwnTopicFlows(flows).map((flow) =>
|
|
343
|
-
customFlowRoleName(flow.flowTag)
|
|
344
|
-
),
|
|
345
|
-
...generatedDsqFlows(flows).map((flow) =>
|
|
346
|
-
customFlowRoleName(flow.flowTag)
|
|
347
|
-
),
|
|
348
|
-
...flowExtTopicSteps(flows).map(({ flow }) =>
|
|
349
|
-
customFlowRoleName(flow.flowTag)
|
|
350
|
-
),
|
|
351
|
-
...flowDsqSteps(flows).map(({ flow }) => customFlowRoleName(flow.flowTag))
|
|
352
|
-
])
|
|
353
|
-
];
|
|
354
|
-
const webSocketRoles = new Set();
|
|
355
|
-
if (websocket) {
|
|
356
|
-
webSocketRoles.add('WebSocketMainRole');
|
|
357
|
-
webSocketRoles.add('RegisterRole');
|
|
358
|
-
}
|
|
359
|
-
if (crud) webSocketRoles.add('FlowObjectsRole');
|
|
360
|
-
if (relationships.length > 0) webSocketRoles.add('FlowRelationshipRole');
|
|
361
|
-
if (rbac) webSocketRoles.add('FlowRbacRole');
|
|
362
|
-
const filteredWsFlows = [
|
|
363
|
-
...supportedCustomFlows(flows),
|
|
364
|
-
...generatedOwnTopicFlows(flows)
|
|
365
|
-
].filter(
|
|
366
|
-
(flow) => includesEvent(flow, 'ownTopic') || includesEvent(flow, 's3')
|
|
367
|
-
);
|
|
368
|
-
for (const flow of filteredWsFlows) {
|
|
369
|
-
webSocketRoles.add(customFlowRoleName(flow.flowTag));
|
|
370
|
-
}
|
|
371
|
-
const outTopics = new Set([
|
|
372
|
-
...ownTopics,
|
|
373
|
-
...flows
|
|
374
|
-
.filter((flow) => flow?.outputTopic && upperFirst(flow.flowTag))
|
|
375
|
-
.map((flow) => upperFirst(flow.flowTag))
|
|
376
|
-
]);
|
|
377
|
-
const objectTableNames = [...collectTables(objects).keys()];
|
|
378
|
-
const relationshipTableNames = [...collectTables(relationships).keys()];
|
|
379
|
-
const tableMap = new Map([
|
|
380
|
-
...collectTables(objects),
|
|
381
|
-
...collectTables(relationships),
|
|
382
|
-
...collectTables(flows)
|
|
383
|
-
]);
|
|
384
|
-
const externalDynamoTables = objects.flatMap(
|
|
385
|
-
(object) => object.externalDynamoResources ?? []
|
|
386
|
-
);
|
|
387
|
-
const s3Buckets = flows
|
|
388
|
-
.filter((flow) => includesEvent(flow, 's3') && flow.createBucket === true)
|
|
389
|
-
.map((flow) => flow.bucketName)
|
|
390
|
-
.filter(Boolean);
|
|
391
|
-
const s3FlowTags = flows
|
|
392
|
-
.filter((flow) => includesEvent(flow, 's3'))
|
|
393
|
-
.map((flow) => upperFirst(flow.flowTag));
|
|
394
|
-
const s3Subscriptions = flows
|
|
395
|
-
.filter((flow) => includesEvent(flow, 's3'))
|
|
396
|
-
.map((flow) => {
|
|
397
|
-
const tag = upperFirst(flow.flowTag);
|
|
398
|
-
const outputTopicStr =
|
|
399
|
-
typeof flow.outputTopic === 'string' ? flow.outputTopic : null;
|
|
400
|
-
const topicName = outputTopicStr
|
|
401
|
-
? outputTopicStr.startsWith('Out')
|
|
402
|
-
? outputTopicStr
|
|
403
|
-
: `Out${upperFirst(outputTopicStr)}`
|
|
404
|
-
: flow.s3Subscription?.topicName || 'OutCreate';
|
|
405
|
-
const queueName =
|
|
406
|
-
flow.s3Subscription?.queueName || `${tag}ReservedLimitHdrSqs`;
|
|
407
|
-
const subscriptionName =
|
|
408
|
-
flow.s3Subscription?.subscriptionName ||
|
|
409
|
-
`Subscription${topicName}To${queueName}`;
|
|
410
|
-
return { subscriptionName, topicName, queueName };
|
|
411
|
-
});
|
|
412
|
-
const systemTables = [...SYSTEM_TABLES];
|
|
413
|
-
if (rbac) {
|
|
414
|
-
systemTables.push(
|
|
415
|
-
'Roles',
|
|
416
|
-
'TargetRoles',
|
|
417
|
-
'RolePermissions',
|
|
418
|
-
'RoleUsers',
|
|
419
|
-
'UserRoles',
|
|
420
|
-
'RbacPermissionCaches',
|
|
421
|
-
'RunningTotalUsage',
|
|
422
|
-
'RunningTotalReservedUsage'
|
|
423
|
-
);
|
|
424
|
-
}
|
|
425
|
-
if (s3FlowTags.length > 0) {
|
|
426
|
-
systemTables.push('ReservedDataMain');
|
|
427
|
-
}
|
|
428
|
-
const hasHttpApi =
|
|
429
|
-
crud ||
|
|
430
|
-
relationships.length > 0 ||
|
|
431
|
-
rbac ||
|
|
432
|
-
flows.some((flow) => includesEvent(flow, 'lambdaSyncApi'));
|
|
433
|
-
return {
|
|
434
|
-
crud,
|
|
435
|
-
rbac,
|
|
436
|
-
selfRbac,
|
|
437
|
-
crudActionPlans,
|
|
438
|
-
crudOwnTopics: [...new Set(crudOwnTopics)].filter(Boolean).sort(),
|
|
439
|
-
crudSqsQueues: [...new Set(crudSqsQueues)].filter(Boolean).sort(),
|
|
440
|
-
relationshipOwnTopics: [...new Set(relationshipOwnTopics)]
|
|
441
|
-
.filter(Boolean)
|
|
442
|
-
.sort(),
|
|
443
|
-
relationshipSqsQueues: [...new Set(relationshipSqsQueues)]
|
|
444
|
-
.filter(Boolean)
|
|
445
|
-
.sort(),
|
|
446
|
-
relationshipDsqQueues: [...new Set(relationshipDsqQueues)]
|
|
447
|
-
.filter(Boolean)
|
|
448
|
-
.sort(),
|
|
449
|
-
rbacOwnTopics: [...new Set(rbacOwnTopics)].filter(Boolean).sort(),
|
|
450
|
-
rbacSqsQueues: [...new Set(rbacSqsQueues)].filter(Boolean).sort(),
|
|
451
|
-
customOwnTopics: [...new Set(customOwnTopics)].filter(Boolean).sort(),
|
|
452
|
-
customSqsQueues: [...new Set(customSqsQueues)].filter(Boolean).sort(),
|
|
453
|
-
customDsqQueues: [...new Set(customDsqQueues)].filter(Boolean).sort(),
|
|
454
|
-
systemOwnTopics: [...new Set(systemOwnTopics)].filter(Boolean).sort(),
|
|
455
|
-
systemSqsQueues: [...new Set(systemSqsQueues)].filter(Boolean).sort(),
|
|
456
|
-
systemDsqQueues: [...new Set(systemDsqQueues)].filter(Boolean).sort(),
|
|
457
|
-
s3Subscriptions,
|
|
458
|
-
s3FlowTags,
|
|
459
|
-
hasHttpApi,
|
|
460
|
-
relationships: relationships.length > 0,
|
|
461
|
-
ownTopics: [...ownTopics].filter(Boolean).sort(),
|
|
462
|
-
sqsQueues: [...sqsQueues].filter(Boolean).sort(),
|
|
463
|
-
dsqQueues: [...dsqQueues].filter(Boolean).sort(),
|
|
464
|
-
customRoles,
|
|
465
|
-
websocket,
|
|
466
|
-
webSocketRoles,
|
|
467
|
-
webSocketSubscriptions: websocket
|
|
468
|
-
? [...outTopics]
|
|
469
|
-
.filter(
|
|
470
|
-
(topic) =>
|
|
471
|
-
flows.some(
|
|
472
|
-
(flow) =>
|
|
473
|
-
(flow?.outputTopic ||
|
|
474
|
-
(includesEvent(flow, 'ownTopic') &&
|
|
475
|
-
(flow.initiateBy === 'user' ||
|
|
476
|
-
flow.initiateBy === 'systemWithUser'))) &&
|
|
477
|
-
upperFirst(flow.flowTag) === topic
|
|
478
|
-
) ||
|
|
479
|
-
(objects.length > 0 &&
|
|
480
|
-
topic !== 'Get' &&
|
|
481
|
-
CRUD_ACTIONS.includes(topic)) ||
|
|
482
|
-
(relationships.length > 0 &&
|
|
483
|
-
topic !== 'GetRelationship' &&
|
|
484
|
-
RELATIONSHIP_ACTIONS.includes(topic))
|
|
485
|
-
)
|
|
486
|
-
.sort()
|
|
487
|
-
: [],
|
|
488
|
-
outTopics: [...outTopics].filter(Boolean).sort(),
|
|
489
|
-
tables: [...tableMap.entries()].map(([tableName, keys]) => ({
|
|
490
|
-
tableName,
|
|
491
|
-
...keys
|
|
492
|
-
})),
|
|
493
|
-
allTableNames: [...new Set([...systemTables, ...tableMap.keys()])].sort(),
|
|
494
|
-
objectTableNames,
|
|
495
|
-
relationshipTableNames,
|
|
496
|
-
externalDynamoTables,
|
|
497
|
-
objectTablesByType: new Map(
|
|
498
|
-
objects
|
|
499
|
-
.map((object) => [
|
|
500
|
-
object.objectType,
|
|
501
|
-
Object.values(object.storageResources ?? {}).find(
|
|
502
|
-
(resource) =>
|
|
503
|
-
resource?.storageType === 'dynamo' ||
|
|
504
|
-
resource?.storageType === 'dynamoDB' ||
|
|
505
|
-
!resource?.storageType
|
|
506
|
-
)?.tableName
|
|
507
|
-
])
|
|
508
|
-
.filter(([, tableName]) => tableName)
|
|
509
|
-
),
|
|
510
|
-
s3Buckets,
|
|
511
|
-
flows,
|
|
512
|
-
objects
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
function indentYaml(content, spaces = 2) {
|
|
517
|
-
const prefix = ' '.repeat(spaces);
|
|
518
|
-
return content
|
|
519
|
-
.split('\n')
|
|
520
|
-
.map((line) => {
|
|
521
|
-
if (line.trim()) {
|
|
522
|
-
return `${prefix}${line}`;
|
|
523
|
-
}
|
|
524
|
-
return '';
|
|
525
|
-
})
|
|
526
|
-
.join('\n');
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
async function renderS3(state) {
|
|
530
|
-
if (state.s3Buckets.length === 0) return 'Resources:\n';
|
|
531
|
-
const template = await readFile(
|
|
532
|
-
new URL('S3Bucket_Yaml.ejs', TEMPLATE_URL),
|
|
533
|
-
'utf8'
|
|
534
|
-
);
|
|
535
|
-
const chunks = await Promise.all(
|
|
536
|
-
state.s3Buckets.map((bucketName) => ejsLib.render(template, { bucketName }))
|
|
537
|
-
);
|
|
538
|
-
return `Resources:\n${indentYaml(chunks.join('\n'), 2)}`;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
async function renderResourceGroup({
|
|
542
|
-
ownTopics = [],
|
|
543
|
-
sqsQueues = [],
|
|
544
|
-
dsqQueues = [],
|
|
545
|
-
webSocketSubscriptions = [],
|
|
546
|
-
s3Subscriptions = []
|
|
547
|
-
}) {
|
|
548
|
-
const hasResources =
|
|
549
|
-
ownTopics.length > 0 ||
|
|
550
|
-
sqsQueues.length > 0 ||
|
|
551
|
-
dsqQueues.length > 0 ||
|
|
552
|
-
webSocketSubscriptions.length > 0 ||
|
|
553
|
-
s3Subscriptions.length > 0;
|
|
554
|
-
if (!hasResources) return '';
|
|
555
|
-
|
|
556
|
-
const chunks = await Promise.all([
|
|
557
|
-
...ownTopics.map((queueName) => render('ResourceYaml.ejs', { queueName })),
|
|
558
|
-
...sqsQueues.map((queueName) =>
|
|
559
|
-
render('ResourceSqsYaml.ejs', { queueName })
|
|
560
|
-
),
|
|
561
|
-
...dsqQueues.map((queueName) =>
|
|
562
|
-
render('ResourceSqsYaml.ejs', { queueName })
|
|
563
|
-
)
|
|
564
|
-
]);
|
|
565
|
-
const wsSubs = await Promise.all(
|
|
566
|
-
webSocketSubscriptions.map((topicName) =>
|
|
567
|
-
renderWebSocketSubscription(topicName)
|
|
568
|
-
)
|
|
569
|
-
);
|
|
570
|
-
const s3Subs = await Promise.all(
|
|
571
|
-
s3Subscriptions.map(({ subscriptionName, topicName, queueName }) =>
|
|
572
|
-
render('S3Subscription_Yaml.ejs', {
|
|
573
|
-
subscriptionName,
|
|
574
|
-
topicName,
|
|
575
|
-
queueName
|
|
576
|
-
})
|
|
577
|
-
)
|
|
578
|
-
);
|
|
579
|
-
const parts = [chunks.join('\n')];
|
|
580
|
-
if (wsSubs.length > 0) parts.push(wsSubs.join('\n'));
|
|
581
|
-
if (s3Subs.length > 0) parts.push(s3Subs.join('\n'));
|
|
582
|
-
const body = parts.filter(Boolean).join('\n');
|
|
583
|
-
if (!body.trim()) return '';
|
|
584
|
-
return `Resources:\n${indentYaml(body, 2)}`;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
async function renderCrudInSqs(state) {
|
|
588
|
-
return renderResourceGroup({
|
|
589
|
-
ownTopics: state.crudOwnTopics,
|
|
590
|
-
sqsQueues: state.crudSqsQueues
|
|
591
|
-
});
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
async function renderRelationshipInSqs(state) {
|
|
595
|
-
return renderResourceGroup({
|
|
596
|
-
ownTopics: state.relationshipOwnTopics,
|
|
597
|
-
sqsQueues: state.relationshipSqsQueues,
|
|
598
|
-
dsqQueues: state.relationshipDsqQueues
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
async function renderRbacInSqs(state) {
|
|
603
|
-
return renderResourceGroup({
|
|
604
|
-
ownTopics: state.rbacOwnTopics,
|
|
605
|
-
sqsQueues: state.rbacSqsQueues
|
|
606
|
-
});
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
async function renderCustomFlowInSqs(state) {
|
|
610
|
-
return renderResourceGroup({
|
|
611
|
-
ownTopics: state.customOwnTopics,
|
|
612
|
-
sqsQueues: state.customSqsQueues,
|
|
613
|
-
dsqQueues: state.customDsqQueues,
|
|
614
|
-
s3Subscriptions: state.s3Subscriptions
|
|
615
|
-
});
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
async function renderSystemInSqs(state) {
|
|
619
|
-
return renderResourceGroup({
|
|
620
|
-
ownTopics: state.systemOwnTopics,
|
|
621
|
-
sqsQueues: state.systemSqsQueues,
|
|
622
|
-
dsqQueues: state.systemDsqQueues,
|
|
623
|
-
webSocketSubscriptions: state.webSocketSubscriptions
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
async function renderOut(state) {
|
|
628
|
-
const body = (
|
|
629
|
-
await Promise.all(
|
|
630
|
-
state.outTopics.map((topicName) =>
|
|
631
|
-
render('FlowOut_Yaml.ejs', { topicName })
|
|
632
|
-
)
|
|
633
|
-
)
|
|
634
|
-
).join('\n');
|
|
635
|
-
return `Resources:\n${indentYaml(body, 2)}`;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
async function renderDynamo(state) {
|
|
639
|
-
const [system, ...tables] = await Promise.all([
|
|
640
|
-
render('SystemDynamoDB_Yaml.ejs', {
|
|
641
|
-
hasS3: state.s3FlowTags.length > 0,
|
|
642
|
-
hasRbac: state.selfRbac
|
|
643
|
-
}),
|
|
644
|
-
...state.tables.map((table) => render('DynamoDBTable_Yaml.ejs', table))
|
|
645
|
-
]);
|
|
646
|
-
const indentedTables = tables.map((t) => indentYaml(t, 2)).join('\n');
|
|
647
|
-
return indentedTables ? `${system}\n${indentedTables}` : `${system}`;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
async function renderIam(state) {
|
|
651
|
-
const roles = ['ProcFindDataRole', 'RegisterRole'];
|
|
652
|
-
if (state.crud) roles.push('FlowObjectsRole');
|
|
653
|
-
if (state.relationships) roles.push('FlowRelationshipRole');
|
|
654
|
-
if (state.selfRbac) roles.push('FlowRbacRole');
|
|
655
|
-
if (state.websocket) roles.push('WebSocketMainRole');
|
|
656
|
-
roles.push(...state.customRoles);
|
|
657
|
-
const sortedRoles = roles.sort();
|
|
658
|
-
return {
|
|
659
|
-
iamContent: await render('SharedResource_Yaml.ejs', {
|
|
660
|
-
roles: sortedRoles.map((roleName) => ({
|
|
661
|
-
roleName,
|
|
662
|
-
statements: roleStatements(state, roleName)
|
|
663
|
-
}))
|
|
664
|
-
}),
|
|
665
|
-
roleNameConfigContent: renderRoleNameConfigYaml(sortedRoles)
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
function getRbacValidatorServiceTags(state) {
|
|
670
|
-
const tags = new Set();
|
|
671
|
-
for (const obj of state.objects || []) {
|
|
672
|
-
const targets = obj?.belongTo
|
|
673
|
-
? Array.isArray(obj.belongTo)
|
|
674
|
-
? obj.belongTo
|
|
675
|
-
: [obj.belongTo]
|
|
676
|
-
: [];
|
|
677
|
-
for (const target of targets) {
|
|
678
|
-
if (target?.serviceTag && target.serviceTag !== 'Rbac') {
|
|
679
|
-
tags.add(target.serviceTag);
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
if (
|
|
683
|
-
obj.belongToSchema?.serviceTag &&
|
|
684
|
-
obj.belongToSchema.serviceTag !== 'Rbac'
|
|
685
|
-
) {
|
|
686
|
-
tags.add(obj.belongToSchema.serviceTag);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
return Array.from(tags).sort();
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
async function renderLambdaRoleConfig(state) {
|
|
693
|
-
const s3Flows = state.flows
|
|
694
|
-
.filter((flow) => includesEvent(flow, 's3'))
|
|
695
|
-
.map((flow) => ({
|
|
696
|
-
roleName: upperFirst(flow.flowTag)
|
|
697
|
-
}));
|
|
698
|
-
const rbacValidatorServiceTags = getRbacValidatorServiceTags(state);
|
|
699
|
-
return render('GeneratedLambdaRoleServiceConfig.ejs', {
|
|
700
|
-
crud: state.crud,
|
|
701
|
-
relationships: state.relationships,
|
|
702
|
-
rbac: state.rbac,
|
|
703
|
-
rbacValidatorServiceTags,
|
|
704
|
-
objectGraphServiceTags: state.objectGraphServiceTags,
|
|
705
|
-
s3Flows
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
function roleStatements(state, roleName) {
|
|
710
|
-
const statements = [];
|
|
711
|
-
if (roleNeedsSchemaRead(state, roleName)) {
|
|
712
|
-
statements.push({
|
|
713
|
-
action: ['s3:GetObject'],
|
|
714
|
-
resource: ['arn:aws:s3:::${self:custom.iz_serviceSchemaBucketName}/*']
|
|
715
|
-
});
|
|
716
|
-
statements.push({
|
|
717
|
-
action: ['s3:ListBucket'],
|
|
718
|
-
resource: ['arn:aws:s3:::${self:custom.iz_serviceSchemaBucketName}']
|
|
719
|
-
});
|
|
720
|
-
}
|
|
721
|
-
addStatement(statements, dynamoActionsForRole(roleName), [
|
|
722
|
-
...dynamoArns(roleTableNames(state, roleName)),
|
|
723
|
-
...externalDynamoArns(roleExternalDynamoTables(state, roleName))
|
|
724
|
-
]);
|
|
725
|
-
addStatement(
|
|
726
|
-
statements,
|
|
727
|
-
SQS_CONSUMER_ACTIONS,
|
|
728
|
-
queueArns(roleQueueNames(state, roleName))
|
|
729
|
-
);
|
|
730
|
-
addStatement(
|
|
731
|
-
statements,
|
|
732
|
-
SQS_DLQ_ACTIONS,
|
|
733
|
-
queueArns(roleDlqQueueNames(state, roleName))
|
|
734
|
-
);
|
|
735
|
-
addStatement(
|
|
736
|
-
statements,
|
|
737
|
-
['sns:Publish'],
|
|
738
|
-
[
|
|
739
|
-
...topicArns(roleTopicNames(state, roleName)),
|
|
740
|
-
...roleExternalTopicArns(state, roleName)
|
|
741
|
-
]
|
|
742
|
-
);
|
|
743
|
-
addStatement(
|
|
744
|
-
statements,
|
|
745
|
-
['lambda:InvokeFunction'],
|
|
746
|
-
[
|
|
747
|
-
...roleExternalLambdaArns(state, roleName),
|
|
748
|
-
...roleHookLambdaArns(state, roleName)
|
|
749
|
-
]
|
|
750
|
-
);
|
|
751
|
-
if (state.webSocketRoles.has(roleName)) {
|
|
752
|
-
statements.push({
|
|
753
|
-
action: ['execute-api:ManageConnections'],
|
|
754
|
-
resource: [
|
|
755
|
-
'arn:aws:execute-api:${self:custom.iz_region}:${self:custom.iz_accountId}:*/*'
|
|
756
|
-
]
|
|
757
|
-
});
|
|
758
|
-
}
|
|
759
|
-
return statements;
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
function addStatement(statements, action, resource) {
|
|
763
|
-
if (resource.length > 0) statements.push({ action, resource });
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
function roleNeedsSchemaRead(state, roleName) {
|
|
767
|
-
if (!roleName.endsWith('Role') || !roleName) return false;
|
|
768
|
-
return roleName !== 'FlowRbacRole' || state.selfRbac;
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
function roleTableNames(state, roleName) {
|
|
772
|
-
if (roleName === 'RegisterRole') {
|
|
773
|
-
if (state.websocket) return ['WebSocketTask', 'RegisterRecords'];
|
|
774
|
-
return [];
|
|
775
|
-
}
|
|
776
|
-
if (roleName === 'WebSocketMainRole')
|
|
777
|
-
return ['UserUploadRecords', 'WebSocketTask'];
|
|
778
|
-
if (roleName === 'FlowObjectsRole')
|
|
779
|
-
return [
|
|
780
|
-
...state.objectTableNames,
|
|
781
|
-
'AwaitingMultipleSteps',
|
|
782
|
-
'AwaitingMultipleStepByPending',
|
|
783
|
-
'WebSocketTask',
|
|
784
|
-
...(state.selfRbac
|
|
785
|
-
? [
|
|
786
|
-
'Roles',
|
|
787
|
-
'TargetRoles',
|
|
788
|
-
'RolePermissions',
|
|
789
|
-
'RoleUsers',
|
|
790
|
-
'UserRoles',
|
|
791
|
-
'RunningTotalUsage',
|
|
792
|
-
'RunningTotalReservedUsage'
|
|
793
|
-
]
|
|
794
|
-
: [])
|
|
795
|
-
];
|
|
796
|
-
if (roleName === 'FlowRelationshipRole')
|
|
797
|
-
return [
|
|
798
|
-
...state.objectTableNames,
|
|
799
|
-
...state.relationshipTableNames,
|
|
800
|
-
'AwaitingMultipleSteps',
|
|
801
|
-
'AwaitingMultipleStepByPending',
|
|
802
|
-
'WebSocketTask'
|
|
803
|
-
];
|
|
804
|
-
if (roleName === 'FlowRbacRole') return RBAC_TABLES;
|
|
805
|
-
if (roleName === 'ProcFindDataRole')
|
|
806
|
-
return [
|
|
807
|
-
...state.objectTableNames,
|
|
808
|
-
...state.relationshipTableNames,
|
|
809
|
-
'FindDataMain',
|
|
810
|
-
'LogicalResultsMain',
|
|
811
|
-
'LogicalResultsData'
|
|
812
|
-
];
|
|
813
|
-
const flow = state.flows.find(
|
|
814
|
-
(candidate) => customFlowRoleName(candidate?.flowTag ?? '') === roleName
|
|
815
|
-
);
|
|
816
|
-
if (!flow) return [];
|
|
817
|
-
const tables = [];
|
|
818
|
-
if (includesEvent(flow, 'ownTopic') || includesEvent(flow, 's3'))
|
|
819
|
-
tables.push('WebSocketTask');
|
|
820
|
-
if (includesEvent(flow, 's3'))
|
|
821
|
-
tables.push('UserUploadRecords', 'ReservedDataMain');
|
|
822
|
-
if (flow.statusType === 'storedCache') {
|
|
823
|
-
const object = state.objectTablesByType.get(flow.objType?.objectType);
|
|
824
|
-
if (object) tables.push(object);
|
|
825
|
-
}
|
|
826
|
-
return [...new Set(tables)];
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
function dynamoActionsForRole(roleName) {
|
|
830
|
-
if (roleName === 'ProcFindDataRole')
|
|
831
|
-
return [
|
|
832
|
-
'dynamodb:GetItem',
|
|
833
|
-
'dynamodb:PutItem',
|
|
834
|
-
'dynamodb:Query',
|
|
835
|
-
'dynamodb:UpdateItem'
|
|
836
|
-
];
|
|
837
|
-
if (roleName === 'WebSocketMainRole')
|
|
838
|
-
return ['dynamodb:DeleteItem', 'dynamodb:PutItem', 'dynamodb:Query'];
|
|
839
|
-
if (roleName === 'FlowRbacRole' || roleName === 'FlowObjectsRole')
|
|
840
|
-
return [...DYNAMO_ACTIONS, 'dynamodb:TransactWriteItems'];
|
|
841
|
-
return DYNAMO_ACTIONS;
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
function roleQueueNames(state, roleName) {
|
|
845
|
-
if (roleName === 'ProcFindDataRole') {
|
|
846
|
-
return LEGACY_PROCESS_QUEUES;
|
|
847
|
-
}
|
|
848
|
-
if (roleName === 'WebSocketMainRole') {
|
|
849
|
-
if (state.websocket) {
|
|
850
|
-
return ['WebSocketCompleteHdrSqs'];
|
|
851
|
-
}
|
|
852
|
-
return [];
|
|
853
|
-
}
|
|
854
|
-
if (roleName === 'RegisterRole') {
|
|
855
|
-
if (state.websocket) {
|
|
856
|
-
return ['RegisterCompleteHdrSqs'];
|
|
857
|
-
}
|
|
858
|
-
return [];
|
|
859
|
-
}
|
|
860
|
-
if (roleName === 'FlowObjectsRole') {
|
|
861
|
-
return CRUD_ACTIONS.flatMap((action) => {
|
|
862
|
-
const plan = state.crudActionPlans[action];
|
|
863
|
-
if (!plan.outputTopic) return [];
|
|
864
|
-
return [
|
|
865
|
-
`${action}HdrSqs`,
|
|
866
|
-
...(plan.hasCreateNodeCallback ? [`${action}NodeCallbackHdrSqs`] : []),
|
|
867
|
-
...(plan.hasBeforeHookCallback ? [`${action}BeforeHookCallbackHdrSqs`] : []),
|
|
868
|
-
...(plan.hasAfterHookCallback ? [`${action}AfterHookCallbackHdrSqs`] : []),
|
|
869
|
-
...(plan.hasRbacCallback ? [`${action}RbacCallbackHdrSqs`] : []),
|
|
870
|
-
...(plan.hasComplete ? [`${action}CompleteHdrSqs`] : [])
|
|
871
|
-
];
|
|
872
|
-
});
|
|
873
|
-
}
|
|
874
|
-
if (roleName === 'FlowRelationshipRole') {
|
|
875
|
-
return [
|
|
876
|
-
...RELATIONSHIP_ACTIONS.flatMap((action) => [
|
|
877
|
-
`${action}HdrSqs`,
|
|
878
|
-
`${action}CompleteHdrSqs`
|
|
879
|
-
]),
|
|
880
|
-
'GetRelationshipHdrDsq'
|
|
881
|
-
];
|
|
882
|
-
}
|
|
883
|
-
if (roleName === 'FlowRbacRole') {
|
|
884
|
-
return [
|
|
885
|
-
...RBAC_ACTIONS.map((action) => `${action}HdrSqs`),
|
|
886
|
-
...rbacFlowQueueNames(state)
|
|
887
|
-
];
|
|
888
|
-
}
|
|
889
|
-
const flow = state.flows.find(
|
|
890
|
-
(candidate) => customFlowRoleName(candidate?.flowTag ?? '') === roleName
|
|
891
|
-
);
|
|
892
|
-
if (!flow) {
|
|
893
|
-
return [];
|
|
894
|
-
}
|
|
895
|
-
const tag = upperFirst(flow.flowTag);
|
|
896
|
-
const queueList = [];
|
|
897
|
-
if (includesEvent(flow, 'extTopic')) {
|
|
898
|
-
queueList.push(`${tag}HdrSqs`);
|
|
899
|
-
}
|
|
900
|
-
if (includesEvent(flow, 'ownTopic')) {
|
|
901
|
-
queueList.push(`${tag}HdrSqs`);
|
|
902
|
-
}
|
|
903
|
-
if (includesEvent(flow, 'dsq')) {
|
|
904
|
-
queueList.push(`${tag}HdrDsq`);
|
|
905
|
-
}
|
|
906
|
-
if (flowHasRbac(flow, state.objects)) {
|
|
907
|
-
queueList.push(`${tag}RbacCallbackHdrSqs`);
|
|
908
|
-
}
|
|
909
|
-
queueList.push(
|
|
910
|
-
...flowExtTopicSteps([flow]).map(
|
|
911
|
-
({ flowTag, stepName }) => `${flowTag}${stepName}HdrSqs`
|
|
912
|
-
)
|
|
913
|
-
);
|
|
914
|
-
queueList.push(
|
|
915
|
-
...flowDsqSteps([flow]).map(
|
|
916
|
-
({ flowTag, stepName }) => `${flowTag}${stepName}HdrDsq`
|
|
917
|
-
)
|
|
918
|
-
);
|
|
919
|
-
queueList.push(
|
|
920
|
-
...state.sqsQueues.filter(
|
|
921
|
-
(queueName) => includesEvent(flow, 's3') && queueName.startsWith(tag)
|
|
922
|
-
)
|
|
923
|
-
);
|
|
924
|
-
if (flow.outputTopic) {
|
|
925
|
-
queueList.push(`${tag}CompleteHdrSqs`);
|
|
926
|
-
}
|
|
927
|
-
return queueList;
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
function roleDlqQueueNames(state, roleName) {
|
|
931
|
-
const queues = roleQueueNames(state, roleName);
|
|
932
|
-
if (!Array.isArray(queues) || queues.length === 0) {
|
|
933
|
-
return [];
|
|
934
|
-
}
|
|
935
|
-
return queues.map((q) => (q.endsWith('DLQ') ? q : `${q}DLQ`));
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
function roleTopicNames(state, roleName) {
|
|
939
|
-
if (roleName === 'ProcFindDataRole')
|
|
940
|
-
return state.outTopics
|
|
941
|
-
.filter((topic) => topic === 'FindData')
|
|
942
|
-
.map((t) => `${t}_Out`);
|
|
943
|
-
if (roleName === 'FlowObjectsRole') {
|
|
944
|
-
const actions = state.outTopics.filter((topic) =>
|
|
945
|
-
CRUD_ACTIONS.includes(topic)
|
|
946
|
-
);
|
|
947
|
-
const topics = [];
|
|
948
|
-
for (const action of actions) {
|
|
949
|
-
if (action === 'Get') {
|
|
950
|
-
topics.push(`${action}_Out`);
|
|
951
|
-
} else {
|
|
952
|
-
topics.push(`${action}_In`, `${action}_Out`);
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
if (state.rbac) {
|
|
956
|
-
topics.push('ValidatorRbac_In');
|
|
957
|
-
}
|
|
958
|
-
for (const action of ['Create', 'Update', 'Delete']) {
|
|
959
|
-
const plan = state.crudActionPlans?.[action];
|
|
960
|
-
if (plan?.hasBeforeHookAsync) {
|
|
961
|
-
for (const hook of plan.beforeHooks) {
|
|
962
|
-
if (hook?.generatedCodeConfig?.invocationType === 'ownTopic') {
|
|
963
|
-
topics.push(`${upperFirst(hook.flowTag)}_In`);
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
if (plan?.hasAfterHookAsync) {
|
|
968
|
-
for (const hook of plan.afterHooks) {
|
|
969
|
-
if (hook?.generatedCodeConfig?.invocationType === 'ownTopic') {
|
|
970
|
-
topics.push(`${upperFirst(hook.flowTag)}_In`);
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
return [...new Set(topics)];
|
|
976
|
-
}
|
|
977
|
-
if (roleName === 'FlowRelationshipRole') {
|
|
978
|
-
const actions = state.outTopics.filter((topic) =>
|
|
979
|
-
RELATIONSHIP_ACTIONS.includes(topic)
|
|
980
|
-
);
|
|
981
|
-
const topics = [];
|
|
982
|
-
for (const action of actions) {
|
|
983
|
-
if (action === 'GetRelationship') {
|
|
984
|
-
topics.push(`${action}_Out`);
|
|
985
|
-
} else {
|
|
986
|
-
topics.push(`${action}_In`, `${action}_Out`);
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
if (state.rbac) {
|
|
990
|
-
topics.push('ValidatorRbac_In');
|
|
991
|
-
}
|
|
992
|
-
return topics;
|
|
993
|
-
}
|
|
994
|
-
if (roleName === 'FlowRbacRole') {
|
|
995
|
-
const actions = state.outTopics.filter((topic) =>
|
|
996
|
-
RBAC_ACTIONS.includes(topic)
|
|
997
|
-
);
|
|
998
|
-
const topics = [];
|
|
999
|
-
for (const action of actions) {
|
|
1000
|
-
if (action.startsWith('List')) {
|
|
1001
|
-
topics.push(`${action}_Out`);
|
|
1002
|
-
} else {
|
|
1003
|
-
topics.push(`${action}_In`, `${action}_Out`);
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
return topics;
|
|
1007
|
-
}
|
|
1008
|
-
const flow = state.flows.find(
|
|
1009
|
-
(candidate) => customFlowRoleName(candidate?.flowTag ?? '') === roleName
|
|
1010
|
-
);
|
|
1011
|
-
if (flow && flow.flowTag) {
|
|
1012
|
-
const name = upperFirst(flow.flowTag);
|
|
1013
|
-
const topics = [];
|
|
1014
|
-
if (state.outTopics.includes(name)) {
|
|
1015
|
-
topics.push(`${name}_Out`);
|
|
1016
|
-
}
|
|
1017
|
-
if (includesEvent(flow, 'ownTopic')) {
|
|
1018
|
-
topics.push(`${name}_In`);
|
|
1019
|
-
}
|
|
1020
|
-
return topics;
|
|
1021
|
-
}
|
|
1022
|
-
return [];
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
function dynamoArns(tableNames) {
|
|
1026
|
-
return [...new Set(tableNames)]
|
|
1027
|
-
.sort()
|
|
1028
|
-
.map(
|
|
1029
|
-
(tableName) =>
|
|
1030
|
-
`arn:aws:dynamodb:${'${self:custom.iz_region}'}:${'${self:custom.iz_accountId}'}:table/${'${self:custom.iz_resourcePrefix}'}${tableName}`
|
|
1031
|
-
);
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
/**
|
|
1035
|
-
* Generates DynamoDB ARNs for tables that belong to a parent service
|
|
1036
|
-
* (via extendObjType). Uses the parent serviceTag instead of the
|
|
1037
|
-
* current service's resourcePrefix, because those tables are owned
|
|
1038
|
-
* by a different CloudFormation stack.
|
|
1039
|
-
*
|
|
1040
|
-
* ARN format:
|
|
1041
|
-
* ...table/{parentServiceTag}_{iz_stage}_{tableName}
|
|
1042
|
-
*/
|
|
1043
|
-
function externalDynamoArns(externalTables) {
|
|
1044
|
-
const seen = new Set();
|
|
1045
|
-
const unique = [];
|
|
1046
|
-
for (const table of externalTables) {
|
|
1047
|
-
const dedupeKey = `${table.serviceTag}::${table.tableName}`;
|
|
1048
|
-
if (!seen.has(dedupeKey)) {
|
|
1049
|
-
seen.add(dedupeKey);
|
|
1050
|
-
unique.push(table);
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
return unique
|
|
1054
|
-
.sort((a, b) =>
|
|
1055
|
-
`${a.serviceTag}_${a.tableName}`.localeCompare(
|
|
1056
|
-
`${b.serviceTag}_${b.tableName}`
|
|
1057
|
-
)
|
|
1058
|
-
)
|
|
1059
|
-
.map(
|
|
1060
|
-
({ serviceTag, tableName }) =>
|
|
1061
|
-
`arn:aws:dynamodb:${'${self:custom.iz_region}'}:${'${self:custom.iz_accountId}'}:table/${serviceTag}${'${self:custom.iz_stage}'}${tableName}`
|
|
1062
|
-
);
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
/**
|
|
1066
|
-
* Returns the external DynamoDB table references (cross-service)
|
|
1067
|
-
* that should be accessible from a given IAM role.
|
|
1068
|
-
*/
|
|
1069
|
-
function roleExternalDynamoTables(state, roleName) {
|
|
1070
|
-
if (
|
|
1071
|
-
roleName === 'FlowObjectsRole' ||
|
|
1072
|
-
roleName === 'FlowRelationshipRole' ||
|
|
1073
|
-
roleName === 'ProcFindDataRole'
|
|
1074
|
-
) {
|
|
1075
|
-
return state.externalDynamoTables;
|
|
1076
|
-
}
|
|
1077
|
-
return [];
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
function roleExternalTopicArns(state, roleName) {
|
|
1081
|
-
if (!state.rbac) {
|
|
1082
|
-
return [];
|
|
1083
|
-
}
|
|
1084
|
-
const extraTags = getRbacValidatorServiceTags(state).filter(
|
|
1085
|
-
(tag) => tag && tag !== 'Rbac'
|
|
1086
|
-
);
|
|
1087
|
-
const extraTopics = extraTags.map(
|
|
1088
|
-
(tag) =>
|
|
1089
|
-
`arn:aws:sns:\${self:custom.iz_region}:\${self:custom.iz_accountId}:${tag}_\${self:custom.iz_stage}_ValidatorRbac_In`
|
|
1090
|
-
);
|
|
1091
|
-
if (roleName === 'FlowObjectsRole') {
|
|
1092
|
-
return [
|
|
1093
|
-
`arn:aws:sns:\${self:custom.iz_region}:\${self:custom.iz_accountId}:Rbac_\${self:custom.iz_stage}_ValidatorRbac_In`,
|
|
1094
|
-
`arn:aws:sns:\${self:custom.iz_region}:\${self:custom.iz_accountId}:Rbac_\${self:custom.iz_stage}_ConfirmUsage_In`,
|
|
1095
|
-
`arn:aws:sns:\${self:custom.iz_region}:\${self:custom.iz_accountId}:Rbac_\${self:custom.iz_stage}_CancelUsage_In`,
|
|
1096
|
-
...extraTopics
|
|
1097
|
-
];
|
|
1098
|
-
}
|
|
1099
|
-
if (roleName === 'FlowRbacRole' || roleName === 'FlowRelationshipRole') {
|
|
1100
|
-
return [
|
|
1101
|
-
`arn:aws:sns:\${self:custom.iz_region}:\${self:custom.iz_accountId}:Rbac_\${self:custom.iz_stage}_ValidatorRbac_In`,
|
|
1102
|
-
...extraTopics
|
|
1103
|
-
];
|
|
1104
|
-
}
|
|
1105
|
-
return [];
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
function roleExternalLambdaArns(state, roleName) {
|
|
1109
|
-
if (!state.rbac) {
|
|
1110
|
-
return [];
|
|
1111
|
-
}
|
|
1112
|
-
const extraTags = getRbacValidatorServiceTags(state).filter(
|
|
1113
|
-
(tag) => tag && tag !== 'Rbac'
|
|
1114
|
-
);
|
|
1115
|
-
const extraLambdas = extraTags.map(
|
|
1116
|
-
(tag) =>
|
|
1117
|
-
`arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:${tag}\${self:custom.iz_stage}ValidatorRbacHdrInv`
|
|
1118
|
-
);
|
|
1119
|
-
if (roleName === 'FlowObjectsRole') {
|
|
1120
|
-
return [
|
|
1121
|
-
`arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:Rbac\${self:custom.iz_stage}ValidatorRbacHdrInv`,
|
|
1122
|
-
`arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:Rbac\${self:custom.iz_stage}ConfirmUsageHdrInv`,
|
|
1123
|
-
`arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:Rbac\${self:custom.iz_stage}CancelUsageHdrInv`,
|
|
1124
|
-
...extraLambdas
|
|
1125
|
-
];
|
|
1126
|
-
}
|
|
1127
|
-
if (
|
|
1128
|
-
roleName === 'FlowRbacRole' ||
|
|
1129
|
-
roleName === 'FlowRelationshipRole'
|
|
1130
|
-
) {
|
|
1131
|
-
return [
|
|
1132
|
-
`arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:Rbac\${self:custom.iz_stage}ValidatorRbacHdrInv`,
|
|
1133
|
-
...extraLambdas
|
|
1134
|
-
];
|
|
1135
|
-
}
|
|
1136
|
-
return [];
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
function roleHookLambdaArns(state, roleName) {
|
|
1140
|
-
if (roleName !== 'FlowObjectsRole') {
|
|
1141
|
-
return [];
|
|
1142
|
-
}
|
|
1143
|
-
const hookLambdas = [];
|
|
1144
|
-
for (const action of ['Create', 'Update', 'Delete']) {
|
|
1145
|
-
const plan = state.crudActionPlans?.[action];
|
|
1146
|
-
if (plan?.hasBeforeHookSync) {
|
|
1147
|
-
for (const hook of plan.beforeHooks) {
|
|
1148
|
-
if (hook?.generatedCodeConfig?.invocationType === 'lambdaSyncInv') {
|
|
1149
|
-
const hookTag = upperFirst(hook.flowTag);
|
|
1150
|
-
hookLambdas.push(
|
|
1151
|
-
`arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:\${self:custom.iz_resourcePrefix}${hookTag}*`
|
|
1152
|
-
);
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
if (plan?.hasAfterHookSync) {
|
|
1157
|
-
for (const hook of plan.afterHooks) {
|
|
1158
|
-
if (hook?.generatedCodeConfig?.invocationType === 'lambdaSyncInv') {
|
|
1159
|
-
const hookTag = upperFirst(hook.flowTag);
|
|
1160
|
-
hookLambdas.push(
|
|
1161
|
-
`arn:aws:lambda:\${self:custom.iz_region}:\${self:custom.iz_accountId}:function:\${self:custom.iz_resourcePrefix}${hookTag}*`
|
|
1162
|
-
);
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
return [...new Set(hookLambdas)];
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
function queueArns(queueNames) {
|
|
1171
|
-
return [...new Set(queueNames)]
|
|
1172
|
-
.sort()
|
|
1173
|
-
.map(
|
|
1174
|
-
(queueName) =>
|
|
1175
|
-
`arn:aws:sqs:${'${self:custom.iz_region}'}:${'${self:custom.iz_accountId}'}:${'${self:custom.iz_resourcePrefix}'}${queueName}`
|
|
1176
|
-
);
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
function topicArns(topicNames) {
|
|
1180
|
-
return [...new Set(topicNames)]
|
|
1181
|
-
.sort()
|
|
1182
|
-
.map(
|
|
1183
|
-
(topic) =>
|
|
1184
|
-
`arn:aws:sns:${'${self:custom.iz_region}'}:${'${self:custom.iz_accountId}'}:${'${self:custom.iz_serviceTag}'}_${'${self:custom.iz_stage}'}_${topic}`
|
|
1185
|
-
);
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
function renderWebSocketSubscription(topicName) {
|
|
1189
|
-
return render('WebSocketSubscription_Yaml.ejs', { topicName });
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
|
-
function collectTables(schemas) {
|
|
1193
|
-
const tables = new Map();
|
|
1194
|
-
for (const schema of schemas) {
|
|
1195
|
-
if (!schema?.storageResources) continue;
|
|
1196
|
-
const identifiers = Array.isArray(schema.identifiers)
|
|
1197
|
-
? schema.identifiers
|
|
1198
|
-
: [];
|
|
1199
|
-
const pkIdentifier = identifiers.find(
|
|
1200
|
-
(identifier) =>
|
|
1201
|
-
identifier.type === 'partitionKey' || identifier.type === 'identifier'
|
|
1202
|
-
);
|
|
1203
|
-
const skIdentifier = identifiers.find(
|
|
1204
|
-
(identifier) => identifier.type === 'sortKey'
|
|
1205
|
-
);
|
|
1206
|
-
const pk = keyName(pkIdentifier) ?? 'PK';
|
|
1207
|
-
const sk = keyName(skIdentifier);
|
|
1208
|
-
const pkType = keyAttributeType(pkIdentifier, schema);
|
|
1209
|
-
const skType = keyAttributeType(skIdentifier, schema);
|
|
1210
|
-
for (const resource of Object.values(schema.storageResources)) {
|
|
1211
|
-
if (
|
|
1212
|
-
(resource?.storageType === 'dynamo' ||
|
|
1213
|
-
resource?.storageType === 'dynamoDB' ||
|
|
1214
|
-
!resource?.storageType) &&
|
|
1215
|
-
resource.tableName &&
|
|
1216
|
-
!tables.has(resource.tableName)
|
|
1217
|
-
)
|
|
1218
|
-
tables.set(resource.tableName, { pk, sk, pkType, skType });
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
return tables;
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
function keyAttributeType(identifier, schema) {
|
|
1225
|
-
if (!identifier) return 'S';
|
|
1226
|
-
if (identifier.attributeType) {
|
|
1227
|
-
return identifier.attributeType;
|
|
1228
|
-
}
|
|
1229
|
-
if (identifier.dataType) {
|
|
1230
|
-
return mapTypeToAttributeType(identifier.dataType);
|
|
1231
|
-
}
|
|
1232
|
-
if (identifier.fieldType) {
|
|
1233
|
-
return mapTypeToAttributeType(identifier.fieldType);
|
|
1234
|
-
}
|
|
1235
|
-
const fieldName = identifier.fieldName ?? identifier.name;
|
|
1236
|
-
if (fieldName && schema) {
|
|
1237
|
-
let fieldDef =
|
|
1238
|
-
schema.fieldNames?.[fieldName] ?? schema.properties?.[fieldName];
|
|
1239
|
-
if (!fieldDef && Array.isArray(schema.addOnDataStructure)) {
|
|
1240
|
-
for (const addOn of schema.addOnDataStructure) {
|
|
1241
|
-
if (addOn?.fieldNames?.[fieldName]) {
|
|
1242
|
-
fieldDef = addOn.fieldNames[fieldName];
|
|
1243
|
-
break;
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
if (fieldDef?.attributeType) {
|
|
1248
|
-
return fieldDef.attributeType;
|
|
1249
|
-
}
|
|
1250
|
-
const type = fieldDef?.type ?? fieldDef?.dataType;
|
|
1251
|
-
if (type) {
|
|
1252
|
-
return mapTypeToAttributeType(type);
|
|
1253
|
-
}
|
|
1254
|
-
}
|
|
1255
|
-
return 'S';
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
function mapTypeToAttributeType(type) {
|
|
1259
|
-
if (typeof type !== 'string') return 'S';
|
|
1260
|
-
const lower = type.toLowerCase();
|
|
1261
|
-
if (
|
|
1262
|
-
lower === 'number' ||
|
|
1263
|
-
lower === 'numeric' ||
|
|
1264
|
-
lower === 'integer' ||
|
|
1265
|
-
lower === 'float' ||
|
|
1266
|
-
lower === 'int' ||
|
|
1267
|
-
lower === 'double' ||
|
|
1268
|
-
lower === 'n'
|
|
1269
|
-
) {
|
|
1270
|
-
return 'N';
|
|
1271
|
-
}
|
|
1272
|
-
if (lower === 'binary' || lower === 'b') {
|
|
1273
|
-
return 'B';
|
|
1274
|
-
}
|
|
1275
|
-
return 'S';
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
function keyName(identifier) {
|
|
1279
|
-
if (!identifier) return null;
|
|
1280
|
-
return (
|
|
1281
|
-
identifier.name ??
|
|
1282
|
-
identifier.fieldName ??
|
|
1283
|
-
(Array.isArray(identifier.fieldNames)
|
|
1284
|
-
? identifier.fieldNames.join(identifier.deliminator ?? '_')
|
|
1285
|
-
: null)
|
|
1286
|
-
);
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
const VALID_CRUD_GENERATED_BY = new Set([
|
|
1290
|
-
'user',
|
|
1291
|
-
'systemWithUser',
|
|
1292
|
-
'systemNoUser'
|
|
1293
|
-
]);
|
|
1294
|
-
|
|
1295
|
-
function isCrudObject(object) {
|
|
1296
|
-
return VALID_CRUD_GENERATED_BY.has(object?.generatedBy);
|
|
1297
|
-
}
|
|
1298
|
-
function hasSelfRbacAddOn(object) {
|
|
1299
|
-
return (
|
|
1300
|
-
Array.isArray(object?.addOnDataStructure) &&
|
|
1301
|
-
object.addOnDataStructure.some((addOn) => addOn?.type === 'rbac')
|
|
1302
|
-
);
|
|
1303
|
-
}
|
|
1304
|
-
|
|
1305
|
-
function hasRbacAddOn(object, objects = []) {
|
|
1306
|
-
const selfHasRbac = hasSelfRbacAddOn(object);
|
|
1307
|
-
const belongToTargets = object?.belongTo
|
|
1308
|
-
? Array.isArray(object.belongTo)
|
|
1309
|
-
? object.belongTo
|
|
1310
|
-
: [object.belongTo]
|
|
1311
|
-
: [];
|
|
1312
|
-
const belongToHasRbac =
|
|
1313
|
-
(Array.isArray(object?.belongToSchema?.addOnDataStructure) &&
|
|
1314
|
-
object.belongToSchema.addOnDataStructure.some(
|
|
1315
|
-
(addOn) => addOn?.type === 'rbac'
|
|
1316
|
-
)) ||
|
|
1317
|
-
belongToTargets.some((target) => {
|
|
1318
|
-
if (target?.serviceTag === 'UserAccount') return true;
|
|
1319
|
-
const matched = objects.find(
|
|
1320
|
-
(candidate) =>
|
|
1321
|
-
candidate?.serviceTag === target?.serviceTag &&
|
|
1322
|
-
candidate?.objectType === target?.objectType
|
|
1323
|
-
);
|
|
1324
|
-
return hasSelfRbacAddOn(matched);
|
|
1325
|
-
});
|
|
1326
|
-
return selfHasRbac || belongToHasRbac;
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
|
-
/**
|
|
1330
|
-
* Returns the per-object RBAC flow queues (e.g. UserRbacFlowHdrSqs)
|
|
1331
|
-
* created for objects with an 'rbac' add-on. These are consumed by the
|
|
1332
|
-
* UserRbacFlow SQS functions emitted in emitRbacApplicationArtifacts.
|
|
1333
|
-
*/
|
|
1334
|
-
function rbacFlowQueueNames(state) {
|
|
1335
|
-
const flowTags = [
|
|
1336
|
-
...new Set((state.objects ?? []).filter(hasSelfRbacAddOn).map(rbacFlowTag))
|
|
1337
|
-
];
|
|
1338
|
-
return flowTags.map((flowTag) => `${flowTag}HdrSqs`);
|
|
1339
|
-
}
|
|
1340
|
-
function includesEvent(flow, event) {
|
|
1341
|
-
return Array.isArray(flow?.event) && flow.event.includes(event);
|
|
1342
|
-
}
|
|
1343
|
-
function upperFirst(value) {
|
|
1344
|
-
return typeof value === 'string' && value
|
|
1345
|
-
? value[0].toUpperCase() + value.slice(1)
|
|
1346
|
-
: '';
|
|
1347
|
-
}
|
|
1348
|
-
function normalizeYaml(content) {
|
|
1349
|
-
return `${content.trimEnd()}\n`;
|
|
1350
|
-
}
|
|
1351
|
-
function renderCorsYaml() {
|
|
128
|
+
export function renderCorsYaml() {
|
|
1352
129
|
return `allowedOrigins:
|
|
1353
130
|
- '*'
|
|
1354
131
|
allowedHeaders:
|
|
@@ -1366,18 +143,3 @@ maxAge: 0
|
|
|
1366
143
|
allowCredentials: false
|
|
1367
144
|
`;
|
|
1368
145
|
}
|
|
1369
|
-
function renderRoleNameConfigYaml(roles) {
|
|
1370
|
-
return [
|
|
1371
|
-
'# for createIamRole',
|
|
1372
|
-
...roles.map(
|
|
1373
|
-
(roleName) =>
|
|
1374
|
-
`- arn:aws:iam::\${self:custom.iz_accountId}:role/\${self:custom.iz_resourcePrefix}${roleName}`
|
|
1375
|
-
)
|
|
1376
|
-
].join('\n');
|
|
1377
|
-
}
|
|
1378
|
-
async function render(templateName, data) {
|
|
1379
|
-
return ejsLib.render(
|
|
1380
|
-
await readFile(new URL(templateName, TEMPLATE_URL), 'utf8'),
|
|
1381
|
-
{ resourceQueueName: data.queueName, ...data }
|
|
1382
|
-
);
|
|
1383
|
-
}
|