@izara_project/izara-core-generate-service-code 1.0.85 → 1.0.87
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 +1 -1
- package/src/compile/compileProject.js +1 -2
- package/src/compile/loadSchemas.js +29 -17
- package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +2 -1
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +32 -14
- package/src/emit/crud/crudActionPlan.js +1 -1
- package/src/emit/crud/emitCrudApplicationArtifacts.js +10 -4
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +16 -8
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +12 -3
- package/src/emit/crud/templates/CreateLogicalLib.ejs +85 -20
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +48 -7
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +47 -6
- package/src/emit/crud/templates/UpdateLogicalLib.ejs +754 -353
- package/src/emit/function/functionYamlArtifact.js +4 -2
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +5 -5
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +70 -89
- package/src/emit/rbac/templates/CancelUsage_Main.ejs +14 -10
- package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +14 -10
- package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +56 -16
- package/src/emit/rbac/templates/DeleteTargetRole_Main.ejs +96 -0
- package/src/emit/rbac/templates/GetMyPermissions_Main.ejs +110 -0
- package/src/emit/rbac/templates/GetTargetRole_Main.ejs +62 -0
- package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +76 -34
- package/src/emit/rbac/templates/UpdateTargetRole_Main.ejs +107 -0
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +24 -21
- package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +12 -0
- package/src/emit/resource/emitResourceArtifacts.js +75 -8
- package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +4 -2
- package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +14 -18
- package/src/emit/system/templates/WebSocketComplete_Yaml.ejs +4 -2
- package/src/emit/systemText/emitSystemTextSchemas.js +5 -2
- package/src/generate.js +18 -12
- package/src/generateResources/IntTest/generateResources/generateResources.js +1 -1
- package/src/generateResources/IntTest/generateTests/generateTemplate.js +1 -1
- package/src/generateResources/IntTest/upload/uploadIntTest.js +8 -2
- package/test/createTargetRoleHandler.test.js +42 -15
- package/test/crudApplicationArtifacts.test.js +62 -3
- package/test/customFlowApplicationArtifacts.test.js +3 -5
- package/test/dynamicCrudFlowSchemas.test.js +5 -17
- package/test/dynamicRbacFlowSchemas.test.js +5 -5
- package/test/functionYamlArtifact.test.js +4 -2
- package/test/publicApi.test.js +18 -14
- package/test/resourceArtifacts.test.js +7 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@izara_project/izara-core-generate-service-code",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.87",
|
|
4
4
|
"description": "Code for locally generating per service files",
|
|
5
5
|
"homepage": "https://bitbucket.org/izara-core-support-services/izara-core-support-services-generate-service-code#readme",
|
|
6
6
|
"repository": {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import Logger from '@izara_project/izara-core-library-logger';
|
|
2
1
|
import { join, resolve } from 'node:path';
|
|
3
2
|
import { readFileSync, existsSync } from 'node:fs';
|
|
4
3
|
import { parse as parseYaml } from 'yaml';
|
|
@@ -33,7 +32,7 @@ export function compileProject(request = {}) {
|
|
|
33
32
|
}
|
|
34
33
|
}
|
|
35
34
|
} catch (err) {
|
|
36
|
-
|
|
35
|
+
console.log('Could not read serverless.config.yml', err);
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
38
|
|
|
@@ -7,9 +7,15 @@ import {
|
|
|
7
7
|
} from '@izara_project/izara-core-library-service-schemas';
|
|
8
8
|
import { basicValidatorSchema } from '@izara_project/izara-shared-service-schemas';
|
|
9
9
|
import { s3 } from '@izara_project/izara-core-library-s3';
|
|
10
|
-
import Logger from '@izara_project/izara-core-library-logger';
|
|
11
10
|
import { validateFlowSchema } from './flowValidator.js';
|
|
12
11
|
|
|
12
|
+
const consoleLogger = {
|
|
13
|
+
debug: console.log,
|
|
14
|
+
info: console.log,
|
|
15
|
+
warn: console.log,
|
|
16
|
+
error: console.error
|
|
17
|
+
};
|
|
18
|
+
|
|
13
19
|
const VALID_INITIATE_BY_ENUM = [
|
|
14
20
|
'user',
|
|
15
21
|
'systemWithUser',
|
|
@@ -66,7 +72,7 @@ export async function loadLocalSchemaDirectory(
|
|
|
66
72
|
options = {}
|
|
67
73
|
) {
|
|
68
74
|
const directoryPath = join(project.schemaRoot, directoryName);
|
|
69
|
-
const logger = options.logger ||
|
|
75
|
+
const logger = options.logger || consoleLogger;
|
|
70
76
|
let entries;
|
|
71
77
|
try {
|
|
72
78
|
entries = await readdir(directoryPath, { withFileTypes: true });
|
|
@@ -229,8 +235,9 @@ export async function resolveExtendedObjectSchemas(
|
|
|
229
235
|
let currentSchema = schema;
|
|
230
236
|
if (currentSchema.hasOwnProperty('extendObjType')) {
|
|
231
237
|
try {
|
|
232
|
-
|
|
233
|
-
`[DEBUG] [resolveExtendedObjectSchemas] Merging extendObjType
|
|
238
|
+
console.log(
|
|
239
|
+
`[DEBUG] [resolveExtendedObjectSchemas] Merging extendObjType ` +
|
|
240
|
+
`for objectType=${currentSchema.objectType}`,
|
|
234
241
|
{ extendObjType: currentSchema.extendObjType }
|
|
235
242
|
);
|
|
236
243
|
const initialResources = currentSchema.storageResources || {};
|
|
@@ -238,7 +245,7 @@ export async function resolveExtendedObjectSchemas(
|
|
|
238
245
|
const parentServiceTag = currentSchema.extendObjType.serviceTag;
|
|
239
246
|
|
|
240
247
|
const mergedSchema = await getObjectSchema.mergeExtendObjSchema(
|
|
241
|
-
{ logger:
|
|
248
|
+
{ logger: consoleLogger },
|
|
242
249
|
currentSchema,
|
|
243
250
|
bucketName
|
|
244
251
|
);
|
|
@@ -270,8 +277,9 @@ export async function resolveExtendedObjectSchemas(
|
|
|
270
277
|
|
|
271
278
|
currentSchema = mergedSchema;
|
|
272
279
|
} catch (error) {
|
|
273
|
-
|
|
274
|
-
`[ERROR] [resolveExtendedObjectSchemas] Failed to merge
|
|
280
|
+
console.log(
|
|
281
|
+
`[ERROR] [resolveExtendedObjectSchemas] Failed to merge ` +
|
|
282
|
+
`extendObjType for objectType=${currentSchema.objectType}`,
|
|
275
283
|
{ error }
|
|
276
284
|
);
|
|
277
285
|
throw error;
|
|
@@ -289,8 +297,9 @@ export async function resolveExtendedObjectSchemas(
|
|
|
289
297
|
belongToTarget.objectType
|
|
290
298
|
) {
|
|
291
299
|
try {
|
|
292
|
-
|
|
293
|
-
`[DEBUG] [resolveExtendedObjectSchemas] Fetching belongTo
|
|
300
|
+
console.log(
|
|
301
|
+
`[DEBUG] [resolveExtendedObjectSchemas] Fetching belongTo ` +
|
|
302
|
+
`schema for objectType=${currentSchema.objectType}`,
|
|
294
303
|
{ belongTo: belongToTarget }
|
|
295
304
|
);
|
|
296
305
|
const belongToObjType = {
|
|
@@ -298,19 +307,21 @@ export async function resolveExtendedObjectSchemas(
|
|
|
298
307
|
objectType: belongToTarget.objectType
|
|
299
308
|
};
|
|
300
309
|
const belongToSchema = await getObjectSchema.getObjSchemaS3(
|
|
301
|
-
{ logger:
|
|
310
|
+
{ logger: consoleLogger },
|
|
302
311
|
belongToObjType,
|
|
303
312
|
false,
|
|
304
313
|
bucketName
|
|
305
314
|
);
|
|
306
315
|
currentSchema.belongToSchema = belongToSchema;
|
|
307
|
-
|
|
308
|
-
`[DEBUG] [resolveExtendedObjectSchemas] Successfully fetched
|
|
316
|
+
console.log(
|
|
317
|
+
`[DEBUG] [resolveExtendedObjectSchemas] Successfully fetched ` +
|
|
318
|
+
`belongTo schema for objectType=${currentSchema.objectType}`,
|
|
309
319
|
{ belongToObjectType: belongToSchema?.objectType }
|
|
310
320
|
);
|
|
311
321
|
} catch (error) {
|
|
312
|
-
|
|
313
|
-
`[WARN] [resolveExtendedObjectSchemas] Failed to fetch
|
|
322
|
+
console.log(
|
|
323
|
+
`[WARN] [resolveExtendedObjectSchemas] Failed to fetch ` +
|
|
324
|
+
`belongTo schema for objectType=${currentSchema.objectType}`,
|
|
314
325
|
{ error }
|
|
315
326
|
);
|
|
316
327
|
}
|
|
@@ -361,7 +372,7 @@ export async function resolveGraphServiceTags(
|
|
|
361
372
|
let graphServerTagsMap = {};
|
|
362
373
|
if (bucketName) {
|
|
363
374
|
try {
|
|
364
|
-
const _izContext = { logger:
|
|
375
|
+
const _izContext = { logger: consoleLogger };
|
|
365
376
|
const s3Data = await s3.getObjectS3(_izContext, {
|
|
366
377
|
Bucket: bucketName,
|
|
367
378
|
Key: 'serviceConfig/GraphServerTags.json'
|
|
@@ -370,8 +381,9 @@ export async function resolveGraphServiceTags(
|
|
|
370
381
|
graphServerTagsMap = s3Data;
|
|
371
382
|
}
|
|
372
383
|
} catch (error) {
|
|
373
|
-
|
|
374
|
-
`[DEBUG] [resolveGraphServiceTags] Could not fetch
|
|
384
|
+
console.log(
|
|
385
|
+
`[DEBUG] [resolveGraphServiceTags] Could not fetch ` +
|
|
386
|
+
`GraphServerTags.json from bucket=${bucketName}`,
|
|
375
387
|
error
|
|
376
388
|
);
|
|
377
389
|
}
|
|
@@ -95,12 +95,12 @@ function _extractDynamoTableNames({
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
if (rbac) {
|
|
98
|
+
dynamoTableNames.add('Roles');
|
|
98
99
|
dynamoTableNames.add('TargetRoles');
|
|
99
100
|
dynamoTableNames.add('RolePermissions');
|
|
100
101
|
dynamoTableNames.add('RoleUsers');
|
|
101
102
|
dynamoTableNames.add('UserRoles');
|
|
102
103
|
dynamoTableNames.add('RbacPermissionCaches');
|
|
103
|
-
dynamoTableNames.add('RoleLimit');
|
|
104
104
|
dynamoTableNames.add('RunningTotalUsage');
|
|
105
105
|
dynamoTableNames.add('RunningTotalReservedUsage');
|
|
106
106
|
}
|
|
@@ -244,6 +244,7 @@ export async function emitCoreFunctionArtifacts({ project, objects = [], relatio
|
|
|
244
244
|
const hasQuotaReservation = crudPlans?.Create?.hasQuotaReservation ?? false;
|
|
245
245
|
|
|
246
246
|
const state = {
|
|
247
|
+
serviceTag: project?.serviceTag || '',
|
|
247
248
|
project,
|
|
248
249
|
objects,
|
|
249
250
|
relationships,
|
|
@@ -66,12 +66,12 @@ const externalServices = {
|
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
68
|
if (typeof rbac !== 'undefined' && rbac) {
|
|
69
|
+
dynamoTableNames.add('Roles');
|
|
69
70
|
dynamoTableNames.add('TargetRoles');
|
|
70
71
|
dynamoTableNames.add('RolePermissions');
|
|
71
72
|
dynamoTableNames.add('RoleUsers');
|
|
72
73
|
dynamoTableNames.add('UserRoles');
|
|
73
74
|
dynamoTableNames.add('RbacPermissionCaches');
|
|
74
|
-
dynamoTableNames.add('RoleLimit');
|
|
75
75
|
dynamoTableNames.add('RunningTotalUsage');
|
|
76
76
|
dynamoTableNames.add('RunningTotalReservedUsage');
|
|
77
77
|
}
|
|
@@ -179,18 +179,9 @@ const tableConfigs = {
|
|
|
179
179
|
});
|
|
180
180
|
});
|
|
181
181
|
|
|
182
|
+
const currentServiceTag = (typeof serviceTag !== 'undefined' && serviceTag) ? serviceTag : ((typeof project !== 'undefined' && project?.serviceTag) ? project.serviceTag : '');
|
|
182
183
|
const rbacSubs = [];
|
|
183
184
|
if (crud && rbac) {
|
|
184
|
-
const allRbacTags = Array.from(new Set(['Rbac', ...(typeof rbacValidatorServiceTags !== 'undefined' && rbacValidatorServiceTags ? rbacValidatorServiceTags : [])]));
|
|
185
|
-
const hasGraph = typeof objectGraphServiceTags !== 'undefined' && objectGraphServiceTags && objectGraphServiceTags.length > 0;
|
|
186
|
-
const createEndpoint = hasGraph ? 'CreateRbacCallbackHdrSqs' : 'CreateCompleteHdrSqs';
|
|
187
|
-
const updateEndpoint = hasGraph ? 'UpdateRbacCallbackHdrSqs' : 'UpdateCompleteHdrSqs';
|
|
188
|
-
const deleteEndpoint = hasGraph ? 'DeleteRbacCallbackHdrSqs' : 'DeleteCompleteHdrSqs';
|
|
189
|
-
allRbacTags.forEach(function(tag) {
|
|
190
|
-
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: createEndpoint });
|
|
191
|
-
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: updateEndpoint });
|
|
192
|
-
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: deleteEndpoint });
|
|
193
|
-
});
|
|
194
185
|
if (typeof hasQuotaReservation !== 'undefined' && hasQuotaReservation) {
|
|
195
186
|
rbacSubs.push({ serviceTag: 'Rbac', topicName: 'ConfirmUsage_Out', sqsEndpoint: 'CreateCompleteHdrSqs' });
|
|
196
187
|
rbacSubs.push({ serviceTag: 'Rbac', topicName: 'CancelUsage_Out', sqsEndpoint: 'CreateCompleteHdrSqs' });
|
|
@@ -198,7 +189,11 @@ const tableConfigs = {
|
|
|
198
189
|
}
|
|
199
190
|
|
|
200
191
|
if (typeof customRbacFlowTags !== 'undefined' && customRbacFlowTags && customRbacFlowTags.length > 0) {
|
|
201
|
-
const allRbacTags = Array.from(new Set([
|
|
192
|
+
const allRbacTags = Array.from(new Set([
|
|
193
|
+
'Rbac',
|
|
194
|
+
currentServiceTag,
|
|
195
|
+
...(typeof rbacValidatorServiceTags !== 'undefined' ? rbacValidatorServiceTags : [])
|
|
196
|
+
])).filter(Boolean);
|
|
202
197
|
customRbacFlowTags.forEach(function(flowTag) {
|
|
203
198
|
const tagUpper = flowTag[0].toUpperCase() + flowTag.slice(1);
|
|
204
199
|
allRbacTags.forEach(function(tag) {
|
|
@@ -309,6 +304,17 @@ function roleConfigs() {
|
|
|
309
304
|
<% }); -%>
|
|
310
305
|
<% } -%>
|
|
311
306
|
<% if (rbac || (rbacValidatorServiceTags && rbacValidatorServiceTags.length > 0)) { -%>
|
|
307
|
+
{
|
|
308
|
+
Sid: 'FlowObjectsInvokeValidatorRbac',
|
|
309
|
+
Effect: 'Allow',
|
|
310
|
+
Action: ['lambda:InvokeFunction'],
|
|
311
|
+
Resource: [
|
|
312
|
+
`arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'ValidatorRbacHdrInv', 'Rbac')}`<% if (rbac) { %>,
|
|
313
|
+
`arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'ValidatorRbacHdrInv')}`<% } %><% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
|
|
314
|
+
`arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'ValidatorRbacHdrInv', '<%= tag %>')}`<% }); %>
|
|
315
|
+
]
|
|
316
|
+
},
|
|
317
|
+
|
|
312
318
|
{
|
|
313
319
|
Sid: 'FlowObjectsPublishValidatorRbacTopics',
|
|
314
320
|
Effect: 'Allow',
|
|
@@ -316,7 +322,8 @@ function roleConfigs() {
|
|
|
316
322
|
Resource: [
|
|
317
323
|
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', 'Rbac')}`,
|
|
318
324
|
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ConfirmUsage_In', 'Rbac')}`,
|
|
319
|
-
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'CancelUsage_In', 'Rbac')}`<%
|
|
325
|
+
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'CancelUsage_In', 'Rbac')}`<% if (rbac) { %>,
|
|
326
|
+
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In')}`<% } %><% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
|
|
320
327
|
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', '<%= tag %>')}`<% }); %>
|
|
321
328
|
]
|
|
322
329
|
},
|
|
@@ -330,12 +337,23 @@ function roleConfigs() {
|
|
|
330
337
|
{
|
|
331
338
|
roleName: 'FlowRbac',
|
|
332
339
|
statement: [
|
|
340
|
+
{
|
|
341
|
+
Sid: 'FlowRbacInvokeValidatorRbac',
|
|
342
|
+
Effect: 'Allow',
|
|
343
|
+
Action: ['lambda:InvokeFunction'],
|
|
344
|
+
Resource: [
|
|
345
|
+
`arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'ValidatorRbacHdrInv', 'Rbac')}`<% if (rbac) { %>,
|
|
346
|
+
`arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'ValidatorRbacHdrInv')}`<% } %><% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
|
|
347
|
+
`arn:aws:lambda:${process.env.iz_region}:${process.env.iz_accountId}:function:${lambdaSharedLib.lambdaFunctionName(_izContext, 'ValidatorRbacHdrInv', '<%= tag %>')}`<% }); %>
|
|
348
|
+
]
|
|
349
|
+
},
|
|
333
350
|
{
|
|
334
351
|
Sid: 'FlowRbacPublishValidatorRbacTopics',
|
|
335
352
|
Effect: 'Allow',
|
|
336
353
|
Action: ['sns:Publish'],
|
|
337
354
|
Resource: [
|
|
338
|
-
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', 'Rbac')}
|
|
355
|
+
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', 'Rbac')}`,
|
|
356
|
+
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In')}`<% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
|
|
339
357
|
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', '<%= tag %>')}`<% }); %>
|
|
340
358
|
]
|
|
341
359
|
}
|
|
@@ -32,7 +32,7 @@ export function createCrudActionPlan(
|
|
|
32
32
|
hasRbac: actionHasRbac,
|
|
33
33
|
hasQuotaReservation,
|
|
34
34
|
hasComplete: outputTopic && (actionHasRbac || hasGraph),
|
|
35
|
-
hasRbacCallback:
|
|
35
|
+
hasRbacCallback: false,
|
|
36
36
|
hasCreateNodeCallback:
|
|
37
37
|
outputTopic && action === 'Create' && actionHasRbac && hasGraph && hasQuotaReservation
|
|
38
38
|
};
|
|
@@ -35,11 +35,17 @@ export async function emitCrudApplicationArtifacts({
|
|
|
35
35
|
objectType: obj?.objectType ?? '(undefined)',
|
|
36
36
|
generatedBy: obj?.generatedBy ?? '(missing)'
|
|
37
37
|
}));
|
|
38
|
-
|
|
39
|
-
`[WARN] [CRUD Application] Skipped FlowObjects application artifacts
|
|
38
|
+
const warnMsg =
|
|
39
|
+
`[WARN] [CRUD Application] Skipped FlowObjects application artifacts ` +
|
|
40
|
+
`generation: No valid CRUD ObjectSchema found. ` +
|
|
40
41
|
`Checked ${objects.length} object(s): ${JSON.stringify(summary)}. ` +
|
|
41
|
-
`Expected "generatedBy" to be one of:
|
|
42
|
-
|
|
42
|
+
`Expected "generatedBy" to be one of: ` +
|
|
43
|
+
`${Array.from(VALID_CRUD_GENERATED_BY).join(', ')}`;
|
|
44
|
+
if (logger?.warn) {
|
|
45
|
+
logger.warn(warnMsg);
|
|
46
|
+
} else {
|
|
47
|
+
console.log(warnMsg);
|
|
48
|
+
}
|
|
43
49
|
}
|
|
44
50
|
return [];
|
|
45
51
|
}
|
|
@@ -29,11 +29,17 @@ export function emitDynamicCrudFlowSchemas({
|
|
|
29
29
|
objectType: obj?.objectType ?? '(undefined)',
|
|
30
30
|
generatedBy: obj?.generatedBy ?? '(missing)'
|
|
31
31
|
}));
|
|
32
|
-
|
|
33
|
-
`[WARN] [CRUD FlowSchemas] Skipped FlowObjects FlowSchemas
|
|
32
|
+
const warnMsg =
|
|
33
|
+
`[WARN] [CRUD FlowSchemas] Skipped FlowObjects FlowSchemas ` +
|
|
34
|
+
`generation: No valid CRUD ObjectSchema found. ` +
|
|
34
35
|
`Checked ${objects.length} object(s): ${JSON.stringify(summary)}. ` +
|
|
35
|
-
`Expected "generatedBy" to be one of:
|
|
36
|
-
|
|
36
|
+
`Expected "generatedBy" to be one of: ` +
|
|
37
|
+
`${Array.from(VALID_CRUD_GENERATED_BY).join(', ')}`;
|
|
38
|
+
if (logger?.warn) {
|
|
39
|
+
logger.warn(warnMsg);
|
|
40
|
+
} else {
|
|
41
|
+
console.log(warnMsg);
|
|
42
|
+
}
|
|
37
43
|
}
|
|
38
44
|
return [];
|
|
39
45
|
}
|
|
@@ -67,16 +73,17 @@ function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user')
|
|
|
67
73
|
}
|
|
68
74
|
);
|
|
69
75
|
} else if (plan.hasComplete) {
|
|
76
|
+
const nextStepName = plan.hasCreateNodeCallback ? 'CreateNodeCallback' : 'Complete';
|
|
70
77
|
startNextSteps.push({
|
|
71
78
|
targetType: 'ownTopic',
|
|
72
|
-
stepName:
|
|
79
|
+
stepName: nextStepName
|
|
73
80
|
});
|
|
74
81
|
if (plan.hasGraph) {
|
|
75
82
|
startNextSteps.push({
|
|
76
83
|
targetType: 'extTopic',
|
|
77
84
|
serviceTag: 'GraphHandler',
|
|
78
85
|
topicName: `${action}Node_In`,
|
|
79
|
-
toStepNames: [
|
|
86
|
+
toStepNames: [nextStepName]
|
|
80
87
|
});
|
|
81
88
|
}
|
|
82
89
|
}
|
|
@@ -137,19 +144,20 @@ function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user')
|
|
|
137
144
|
}
|
|
138
145
|
|
|
139
146
|
if (plan.hasCreateNodeCallback) {
|
|
147
|
+
const prevStepName = plan.hasRbacCallback ? 'RbacCallback' : 'Start';
|
|
140
148
|
flowSteps.push({
|
|
141
149
|
stepName: 'CreateNodeCallback',
|
|
142
150
|
event: ['extTopic'],
|
|
143
151
|
previousSteps: [
|
|
144
152
|
{
|
|
145
153
|
sourceType: 'ownTopic',
|
|
146
|
-
stepName:
|
|
154
|
+
stepName: prevStepName
|
|
147
155
|
},
|
|
148
156
|
{
|
|
149
157
|
sourceType: 'extTopic',
|
|
150
158
|
serviceTag: 'GraphHandler',
|
|
151
159
|
topicName: 'CreateNode_Out',
|
|
152
|
-
fromStepNames: [
|
|
160
|
+
fromStepNames: [prevStepName]
|
|
153
161
|
}
|
|
154
162
|
],
|
|
155
163
|
nextSteps: [
|
|
@@ -381,11 +381,12 @@ export default async function <%- flowTag %>(
|
|
|
381
381
|
},
|
|
382
382
|
parameterGroups,
|
|
383
383
|
{
|
|
384
|
+
targetIdentifiers,
|
|
384
385
|
rbacObjType: {
|
|
385
386
|
serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
|
|
386
387
|
},
|
|
387
388
|
requestParams: requestParams,
|
|
388
|
-
|
|
389
|
+
sync: true
|
|
389
390
|
}
|
|
390
391
|
);
|
|
391
392
|
|
|
@@ -394,10 +395,18 @@ export default async function <%- flowTag %>(
|
|
|
394
395
|
resultPermissionCheck
|
|
395
396
|
);
|
|
396
397
|
|
|
398
|
+
if (resultPermissionCheck && resultPermissionCheck.permission !== true) {
|
|
399
|
+
errorsFound.push('Permission denied');
|
|
400
|
+
return await <%- flowTag %>LogicalLib(
|
|
401
|
+
_izContext,
|
|
402
|
+
requestParams,
|
|
403
|
+
callingFlowConfig,
|
|
404
|
+
errorsFound
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
|
|
397
408
|
//(<rbacPublish_<%- flowTag %>)
|
|
398
409
|
//(</rbacPublish_<%- flowTag %>)
|
|
399
|
-
|
|
400
|
-
return resultPermissionCheck;
|
|
401
410
|
}
|
|
402
411
|
<%_ } _%>
|
|
403
412
|
|
|
@@ -385,21 +385,51 @@ export async function autoProvisionOwnerTargetRole(_izContext, { node, submitted
|
|
|
385
385
|
}
|
|
386
386
|
|
|
387
387
|
const identifiers = node.objInstanceFull.identifiers;
|
|
388
|
-
const
|
|
389
|
-
.filter(
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
388
|
+
const sortedKeys = Object.keys(identifiers)
|
|
389
|
+
.filter(
|
|
390
|
+
(k) =>
|
|
391
|
+
k !== 'submittedByUserId' &&
|
|
392
|
+
k !== 'identifierConcat' &&
|
|
393
|
+
k !== 'identifiersConcat'
|
|
394
|
+
)
|
|
395
|
+
.sort();
|
|
396
|
+
const parts = [];
|
|
397
|
+
for (const key of sortedKeys) {
|
|
398
|
+
const value = identifiers[key];
|
|
399
|
+
if (value !== undefined && value !== null) {
|
|
400
|
+
parts.push(`${key}#${value}`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
const targetIdentifiersConcat = parts.join('|');
|
|
398
404
|
|
|
399
405
|
if (!targetIdentifiersConcat) {
|
|
400
406
|
return;
|
|
401
407
|
}
|
|
402
408
|
|
|
409
|
+
const targetPlanTier =
|
|
410
|
+
node?.objInstanceFull?.planTier ||
|
|
411
|
+
node?.objInstanceFull?.targetIdentifiers?.planTier ||
|
|
412
|
+
'tier-free';
|
|
413
|
+
let planTierName = 'Free Plan';
|
|
414
|
+
if (targetPlanTier === 'tier-pro') {
|
|
415
|
+
planTierName = 'Professional Plan';
|
|
416
|
+
} else if (targetPlanTier === 'tier-enterprise') {
|
|
417
|
+
planTierName = 'Enterprise Plan';
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
await dynamodbSharedLib.putItem(
|
|
421
|
+
_izContext,
|
|
422
|
+
dynamodbSharedLib.tableName(_izContext, 'TargetRoles'),
|
|
423
|
+
{
|
|
424
|
+
identifiersConcat: targetIdentifiersConcat,
|
|
425
|
+
roleIdKey: targetPlanTier,
|
|
426
|
+
roleType: 'plan_tier',
|
|
427
|
+
roleName: planTierName,
|
|
428
|
+
submittedByUserId,
|
|
429
|
+
createdAt: new Date().toISOString()
|
|
430
|
+
}
|
|
431
|
+
);
|
|
432
|
+
|
|
403
433
|
const roleIdKey = `${targetIdentifiersConcat}_owner`;
|
|
404
434
|
_izContext.logger.debug(
|
|
405
435
|
'[CreateNodeCallback] Auto-provisioning owner TargetRole:',
|
|
@@ -417,8 +447,9 @@ export async function autoProvisionOwnerTargetRole(_izContext, { node, submitted
|
|
|
417
447
|
{
|
|
418
448
|
identifiersConcat: targetIdentifiersConcat,
|
|
419
449
|
roleIdKey,
|
|
450
|
+
roleType: 'tenant_role',
|
|
451
|
+
roleName: 'Owner',
|
|
420
452
|
submittedByUserId,
|
|
421
|
-
roleName: 'owner',
|
|
422
453
|
assignedAt: new Date().toISOString()
|
|
423
454
|
}
|
|
424
455
|
);
|
|
@@ -816,16 +847,49 @@ export async function autoProvisionOwnerTargetRoleForDynamoOnly(
|
|
|
816
847
|
_izContext.correlationIds?.get(coreConsts.SUBMITTED_BY_USER_ID);
|
|
817
848
|
|
|
818
849
|
if (submittedByUserId) {
|
|
819
|
-
const
|
|
820
|
-
.
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
850
|
+
const sortedKeys = Object.keys(identifiersForCreateData)
|
|
851
|
+
.filter(
|
|
852
|
+
(k) =>
|
|
853
|
+
k !== 'submittedByUserId' &&
|
|
854
|
+
k !== 'identifierConcat' &&
|
|
855
|
+
k !== 'identifiersConcat'
|
|
856
|
+
)
|
|
857
|
+
.sort();
|
|
858
|
+
const parts = [];
|
|
859
|
+
for (const key of sortedKeys) {
|
|
860
|
+
const value = identifiersForCreateData[key];
|
|
861
|
+
if (value !== undefined && value !== null) {
|
|
862
|
+
parts.push(`${key}#${value}`);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
const targetIdentifiersConcat = parts.join('|');
|
|
827
866
|
|
|
828
867
|
if (targetIdentifiersConcat) {
|
|
868
|
+
const targetPlanTier =
|
|
869
|
+
actionData?.planTier ||
|
|
870
|
+
requestParams?.planTier ||
|
|
871
|
+
requestParams?.passBackProperties?.planTier ||
|
|
872
|
+
'tier-free';
|
|
873
|
+
let planTierName = 'Free Plan';
|
|
874
|
+
if (targetPlanTier === 'tier-pro') {
|
|
875
|
+
planTierName = 'Professional Plan';
|
|
876
|
+
} else if (targetPlanTier === 'tier-enterprise') {
|
|
877
|
+
planTierName = 'Enterprise Plan';
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
await dynamodbSharedLib.putItem(
|
|
881
|
+
_izContext,
|
|
882
|
+
dynamodbSharedLib.tableName(_izContext, 'TargetRoles'),
|
|
883
|
+
{
|
|
884
|
+
identifiersConcat: targetIdentifiersConcat,
|
|
885
|
+
roleIdKey: targetPlanTier,
|
|
886
|
+
roleType: 'plan_tier',
|
|
887
|
+
roleName: planTierName,
|
|
888
|
+
submittedByUserId,
|
|
889
|
+
createdAt: new Date().toISOString()
|
|
890
|
+
}
|
|
891
|
+
);
|
|
892
|
+
|
|
829
893
|
const roleIdKey = `${targetIdentifiersConcat}_owner`;
|
|
830
894
|
_izContext.logger.debug(
|
|
831
895
|
'[<%- flowTag %>LogicalLib] Auto-provisioning owner TargetRole for DynamoDB-only:',
|
|
@@ -843,8 +907,9 @@ export async function autoProvisionOwnerTargetRoleForDynamoOnly(
|
|
|
843
907
|
{
|
|
844
908
|
identifiersConcat: targetIdentifiersConcat,
|
|
845
909
|
roleIdKey,
|
|
910
|
+
roleType: 'tenant_role',
|
|
911
|
+
roleName: 'Owner',
|
|
846
912
|
submittedByUserId,
|
|
847
|
-
roleName: 'owner',
|
|
848
913
|
assignedAt: new Date().toISOString()
|
|
849
914
|
}
|
|
850
915
|
);
|
|
@@ -85,6 +85,7 @@ export default async function <%- flowTag %>(
|
|
|
85
85
|
_izContext.correlationIds.get(coreConsts.SUBMITTED_BY_USER_ID);
|
|
86
86
|
|
|
87
87
|
targetIdentifiers = requestParams.targetIdentifiers;
|
|
88
|
+
delete requestParams.targetIdentifiers;
|
|
88
89
|
|
|
89
90
|
if (!targetIdentifiers && objectSchema.belongTo?.objectType === 'user' && submittedByUserId) {
|
|
90
91
|
targetIdentifiers = { submittedByUserId };
|
|
@@ -99,12 +100,11 @@ export default async function <%- flowTag %>(
|
|
|
99
100
|
if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
|
|
100
101
|
targetIdentifiers.submittedByUserId = submittedByUserId;
|
|
101
102
|
}
|
|
102
|
-
requestParams.targetIdentifiers = targetIdentifiers;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
|
|
106
106
|
submittedByUserId: requestParams.submittedByUserId,
|
|
107
|
-
targetIdentifiers
|
|
107
|
+
targetIdentifiers,
|
|
108
108
|
belongTo: objectSchema.belongTo,
|
|
109
109
|
generatedBy: objectSchema.generatedBy
|
|
110
110
|
});
|
|
@@ -116,6 +116,37 @@ export default async function <%- flowTag %>(
|
|
|
116
116
|
// ── Build identifiers used by asynchronous processing ────────────────────
|
|
117
117
|
const identifiers = requestParams.identifiers;
|
|
118
118
|
|
|
119
|
+
if (!objectSchema.hasOwnProperty('belongTo')) {
|
|
120
|
+
if (!targetIdentifiers && identifiers) {
|
|
121
|
+
targetIdentifiers = { ...identifiers };
|
|
122
|
+
} else if (targetIdentifiers && identifiers) {
|
|
123
|
+
for (const [key, value] of Object.entries(identifiers)) {
|
|
124
|
+
if (targetIdentifiers[key] === undefined && value !== undefined) {
|
|
125
|
+
targetIdentifiers[key] = value;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (targetIdentifiers) {
|
|
130
|
+
if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
|
|
131
|
+
targetIdentifiers.submittedByUserId = submittedByUserId;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (targetIdentifiers && identifiers) {
|
|
137
|
+
for (const [key, value] of Object.entries(identifiers)) {
|
|
138
|
+
if (
|
|
139
|
+
targetIdentifiers[key] !== undefined &&
|
|
140
|
+
value !== undefined &&
|
|
141
|
+
targetIdentifiers[key] !== value
|
|
142
|
+
) {
|
|
143
|
+
errorsFound.push(
|
|
144
|
+
`targetIdentifiers.${key} must match identifiers.${key}`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
119
150
|
if (errorsFound.length > 0)
|
|
120
151
|
return await <%- flowTag %>LogicalLib(
|
|
121
152
|
_izContext,
|
|
@@ -131,8 +162,8 @@ export default async function <%- flowTag %>(
|
|
|
131
162
|
for (const o of rbacObjects) {
|
|
132
163
|
const belongToTargets = o?.belongTo
|
|
133
164
|
? Array.isArray(o.belongTo)
|
|
134
|
-
|
|
135
|
-
|
|
165
|
+
? o.belongTo
|
|
166
|
+
: [o.belongTo]
|
|
136
167
|
: [];
|
|
137
168
|
if (belongToTargets.length > 0 && belongToTargets[0]?.serviceTag) {
|
|
138
169
|
rbacServiceTagMap[o.objectType] = `'${belongToTargets[0].serviceTag}'`;
|
|
@@ -164,11 +195,13 @@ export default async function <%- flowTag %>(
|
|
|
164
195
|
},
|
|
165
196
|
parameterGroups,
|
|
166
197
|
{
|
|
198
|
+
targetIdentifiers,
|
|
167
199
|
rbacObjType: {
|
|
168
200
|
serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
|
|
169
201
|
},
|
|
170
202
|
requestParams: requestParams,
|
|
171
|
-
nextFlowStepName: '<%- plan?.hasRbacCallback ? `${flowTag}RbacCallback` : `${flowTag}Complete` %>'
|
|
203
|
+
nextFlowStepName: '<%- plan?.hasRbacCallback ? `${flowTag}RbacCallback` : `${flowTag}Complete` %>',
|
|
204
|
+
sync: true
|
|
172
205
|
}
|
|
173
206
|
);
|
|
174
207
|
|
|
@@ -177,10 +210,18 @@ export default async function <%- flowTag %>(
|
|
|
177
210
|
resultPermissionCheck
|
|
178
211
|
);
|
|
179
212
|
|
|
213
|
+
if (resultPermissionCheck && resultPermissionCheck.permission !== true) {
|
|
214
|
+
errorsFound.push('Permission denied');
|
|
215
|
+
return await <%- flowTag %>LogicalLib(
|
|
216
|
+
_izContext,
|
|
217
|
+
requestParams,
|
|
218
|
+
callingFlowConfig,
|
|
219
|
+
errorsFound
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
180
223
|
//(<rbacPublish_<%- flowTag %>)
|
|
181
224
|
//(</rbacPublish_<%- flowTag %>)
|
|
182
|
-
|
|
183
|
-
return resultPermissionCheck;
|
|
184
225
|
}
|
|
185
226
|
<%_ } _%>
|
|
186
227
|
|