@izara_project/izara-core-generate-service-code 1.0.83 → 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.
- package/package.json +4 -4
- package/src/compile/flowValidator.js +13 -2
- package/src/compile/loadSchemas.js +116 -7
- package/src/emit/attributeTree/emitAttributeTreeSchemas.js +388 -0
- package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +29 -1
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +16 -3
- package/src/emit/crud/crudActionPlan.js +38 -5
- package/src/emit/crud/emitCrudApplicationArtifacts.js +19 -4
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +27 -6
- package/src/emit/crud/generateCrudApplicationArtifacts.js +3 -2
- package/src/emit/crud/generateDynamicCrudFlowSchemas.js +3 -2
- package/src/emit/crud/loadLocalSchemaArrays.js +3 -3
- package/src/emit/crud/templates/CreateComplete_Main.ejs +1 -1
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +50 -19
- package/src/emit/crud/templates/CreateLogicalLib.ejs +73 -8
- package/src/emit/crud/templates/DeleteComplete_Main.ejs +1 -1
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +33 -8
- package/src/emit/crud/templates/DeleteLogicalLib.ejs +6 -3
- package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +2 -2
- package/src/emit/crud/templates/FlowEndpoint_HdrWbs.ejs +7 -0
- package/src/emit/crud/templates/FlowMain_Wbs.ejs +1 -1
- package/src/emit/crud/templates/GetEndpoint_Main.ejs +13 -0
- package/src/emit/crud/templates/UpdateComplete_Main.ejs +1 -1
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +52 -3
- package/src/emit/crud/templates/UpdateLogicalLib.ejs +4 -3
- package/src/emit/custom/customFlows.js +47 -0
- package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +168 -49
- package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +1 -1
- package/src/emit/custom/templates/FlowEndpointRbacCallback_Main.ejs +194 -0
- package/src/emit/custom/templates/FlowEndpoint_Main.ejs +14 -22
- package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
- package/src/emit/function/templates/WbsFunction_Yaml.ejs +0 -2
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +33 -8
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +204 -7
- package/src/emit/rbac/templates/CancelUsage_Main.ejs +103 -0
- package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +71 -0
- package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +49 -6
- package/src/emit/rbac/templates/ListRbac_Main.ejs +9 -3
- package/src/emit/rbac/templates/RbacMutation_Main.ejs +1 -1
- package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +147 -0
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +59 -23
- package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +1 -1
- package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +1 -1
- package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +4 -4
- package/src/emit/resource/emitResourceArtifacts.js +342 -108
- package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +53 -2
- package/src/emit/system/emitSystemWebSocketArtifacts.js +6 -5
- package/src/emit/system/templates/WebSocketConnect.ejs +71 -12
- package/src/emit/system/templates/WebSocketConnect_Yaml.ejs +7 -0
- package/src/emit/systemText/emitSystemTextSchemas.js +1 -1
- package/src/generate.js +41 -10
- package/test/attributeTreeSchemas.test.js +219 -0
- package/test/createTargetRoleHandler.test.js +59 -4
- package/test/crudApplicationArtifacts.test.js +20 -3
- package/test/customFlowApplicationArtifacts.test.js +5 -5
- package/test/dynamicCrudFlowSchemas.test.js +91 -4
- package/test/dynamicRbacFlowSchemas.test.js +15 -2
- package/test/publicApi.test.js +6 -6
- package/test/resourceArtifacts.test.js +68 -27
|
@@ -70,6 +70,10 @@ const externalServices = {
|
|
|
70
70
|
dynamoTableNames.add('RolePermissions');
|
|
71
71
|
dynamoTableNames.add('RoleUsers');
|
|
72
72
|
dynamoTableNames.add('UserRoles');
|
|
73
|
+
dynamoTableNames.add('RbacPermissionCaches');
|
|
74
|
+
dynamoTableNames.add('RoleLimit');
|
|
75
|
+
dynamoTableNames.add('RunningTotalUsage');
|
|
76
|
+
dynamoTableNames.add('RunningTotalReservedUsage');
|
|
73
77
|
}
|
|
74
78
|
if (typeof s3Flows !== 'undefined' && (s3Flows || []).length > 0) {
|
|
75
79
|
dynamoTableNames.add('ReservedDataMain');
|
|
@@ -176,16 +180,25 @@ const tableConfigs = {
|
|
|
176
180
|
if (crud && typeof rbacValidatorServiceTags !== 'undefined' && rbacValidatorServiceTags && rbacValidatorServiceTags.length > 0) {
|
|
177
181
|
const allRbacTags = Array.from(new Set(['Rbac', ...rbacValidatorServiceTags]));
|
|
178
182
|
const hasGraph = typeof objectGraphServiceTags !== 'undefined' && objectGraphServiceTags && objectGraphServiceTags.length > 0;
|
|
183
|
+
const createEndpoint = hasGraph ? 'CreateRbacCallbackHdrSqs' : 'CreateCompleteHdrSqs';
|
|
179
184
|
const updateEndpoint = hasGraph ? 'UpdateRbacCallbackHdrSqs' : 'UpdateCompleteHdrSqs';
|
|
180
185
|
const deleteEndpoint = hasGraph ? 'DeleteRbacCallbackHdrSqs' : 'DeleteCompleteHdrSqs';
|
|
181
186
|
allRbacTags.forEach(function(tag) {
|
|
182
|
-
|
|
183
|
-
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: 'CreateCompleteHdrSqs' });
|
|
184
|
-
}
|
|
187
|
+
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: createEndpoint });
|
|
185
188
|
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: updateEndpoint });
|
|
186
189
|
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: deleteEndpoint });
|
|
187
190
|
});
|
|
188
191
|
}
|
|
192
|
+
|
|
193
|
+
if (typeof customRbacFlowTags !== 'undefined' && customRbacFlowTags && customRbacFlowTags.length > 0) {
|
|
194
|
+
const allRbacTags = Array.from(new Set(['Rbac', ...(typeof rbacValidatorServiceTags !== 'undefined' ? rbacValidatorServiceTags : [])]));
|
|
195
|
+
customRbacFlowTags.forEach(function(flowTag) {
|
|
196
|
+
const tagUpper = flowTag[0].toUpperCase() + flowTag.slice(1);
|
|
197
|
+
allRbacTags.forEach(function(tag) {
|
|
198
|
+
rbacSubs.push({ serviceTag: tag, topicName: 'ValidatorRbac_Out', sqsEndpoint: `${tagUpper}RbacCallbackHdrSqs` });
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
}
|
|
189
202
|
-%>
|
|
190
203
|
const snsTopicSubscriptions = [
|
|
191
204
|
<% if (relSubs.length > 0) { -%>
|
|
@@ -5,36 +5,41 @@ export function createCrudActionPlans(objects = []) {
|
|
|
5
5
|
const hasRbac = objects.some(
|
|
6
6
|
(object) => isCrudObject(object) && hasRbacObject(object, objects)
|
|
7
7
|
);
|
|
8
|
+
const isBillable = objects.some(
|
|
9
|
+
(object) => isCrudObject(object) && isBillableObject(object, objects)
|
|
10
|
+
);
|
|
8
11
|
|
|
9
12
|
return Object.fromEntries(
|
|
10
13
|
CRUD_ACTIONS.map((action) => [
|
|
11
14
|
action,
|
|
12
|
-
createCrudActionPlan(action, { hasGraph, hasRbac })
|
|
15
|
+
createCrudActionPlan(action, { hasGraph, hasRbac, isBillable })
|
|
13
16
|
])
|
|
14
17
|
);
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
export function createCrudActionPlan(
|
|
18
21
|
action,
|
|
19
|
-
{ hasGraph = false, hasRbac = false } = {}
|
|
22
|
+
{ hasGraph = false, hasRbac = false, isBillable = true } = {}
|
|
20
23
|
) {
|
|
21
|
-
const actionHasRbac = action !== '
|
|
24
|
+
const actionHasRbac = action !== 'Get' && hasRbac;
|
|
22
25
|
const outputTopic = action !== 'Get';
|
|
26
|
+
const hasQuotaReservation = action === 'Create' && hasRbac && isBillable;
|
|
23
27
|
|
|
24
28
|
return {
|
|
25
29
|
action,
|
|
26
30
|
outputTopic,
|
|
27
31
|
hasGraph: outputTopic && hasGraph,
|
|
28
32
|
hasRbac: actionHasRbac,
|
|
33
|
+
hasQuotaReservation,
|
|
29
34
|
hasComplete: outputTopic && (actionHasRbac || hasGraph),
|
|
30
35
|
hasRbacCallback: outputTopic && actionHasRbac && hasGraph
|
|
31
36
|
};
|
|
32
37
|
}
|
|
33
38
|
|
|
34
|
-
const VALID_CRUD_GENERATED_BY = new Set([
|
|
39
|
+
export const VALID_CRUD_GENERATED_BY = new Set([
|
|
35
40
|
'user',
|
|
36
41
|
'systemWithUser',
|
|
37
|
-
'
|
|
42
|
+
'systemNoUser'
|
|
38
43
|
]);
|
|
39
44
|
|
|
40
45
|
export function isCrudObject(object) {
|
|
@@ -83,3 +88,31 @@ function normalizeBelongTo(object) {
|
|
|
83
88
|
if (!object?.belongTo) return [];
|
|
84
89
|
return Array.isArray(object.belongTo) ? object.belongTo : [object.belongTo];
|
|
85
90
|
}
|
|
91
|
+
|
|
92
|
+
export function isBillableObject(object, objects = []) {
|
|
93
|
+
if (!isCrudObject(object)) return false;
|
|
94
|
+
|
|
95
|
+
const targets = normalizeBelongTo(object);
|
|
96
|
+
if (targets.length > 0) {
|
|
97
|
+
for (const target of targets) {
|
|
98
|
+
if (typeof target?.billable === 'boolean') {
|
|
99
|
+
return target.billable;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (Array.isArray(object?.addOnDataStructure)) {
|
|
105
|
+
const rbacAddOn = object.addOnDataStructure.find(
|
|
106
|
+
(addOn) => addOn?.type === 'rbac'
|
|
107
|
+
);
|
|
108
|
+
if (typeof rbacAddOn?.billable === 'boolean') {
|
|
109
|
+
return rbacAddOn.billable;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (typeof object?.billable === 'boolean') {
|
|
114
|
+
return object.billable;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
CRUD_ACTIONS,
|
|
13
13
|
createCrudActionPlans,
|
|
14
|
-
isCrudObject
|
|
14
|
+
isCrudObject,
|
|
15
|
+
VALID_CRUD_GENERATED_BY
|
|
15
16
|
} from './crudActionPlan.js';
|
|
16
17
|
|
|
17
18
|
const ACTIONS = CRUD_ACTIONS;
|
|
@@ -22,12 +23,26 @@ const SHARED_TEMPLATE_URL = new URL('../shared/templates/', import.meta.url);
|
|
|
22
23
|
export async function emitCrudApplicationArtifacts({
|
|
23
24
|
objects,
|
|
24
25
|
flows = [],
|
|
25
|
-
serviceTag
|
|
26
|
+
serviceTag,
|
|
27
|
+
logger
|
|
26
28
|
}) {
|
|
27
29
|
if (!Array.isArray(objects) || !Array.isArray(flows)) {
|
|
28
30
|
throw new TypeError('objects and flows must be arrays');
|
|
29
31
|
}
|
|
30
|
-
if (!objects.some(isCrudObject))
|
|
32
|
+
if (!objects.some(isCrudObject)) {
|
|
33
|
+
if (objects.length > 0) {
|
|
34
|
+
const summary = objects.map((obj) => ({
|
|
35
|
+
objectType: obj?.objectType ?? '(undefined)',
|
|
36
|
+
generatedBy: obj?.generatedBy ?? '(missing)'
|
|
37
|
+
}));
|
|
38
|
+
logger?.warn?.(
|
|
39
|
+
`[WARN] [CRUD Application] Skipped FlowObjects application artifacts generation: No valid CRUD ObjectSchema found. ` +
|
|
40
|
+
`Checked ${objects.length} object(s): ${JSON.stringify(summary)}. ` +
|
|
41
|
+
`Expected "generatedBy" to be one of: ${Array.from(VALID_CRUD_GENERATED_BY).join(', ')}`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
31
46
|
|
|
32
47
|
const handlers = await Promise.all(
|
|
33
48
|
ACTIONS.map((action) => emitAction(action, objects, serviceTag))
|
|
@@ -87,7 +102,7 @@ async function emitAction(action, objects, serviceTag) {
|
|
|
87
102
|
flow: null,
|
|
88
103
|
flowStepName: '',
|
|
89
104
|
startConfig: null,
|
|
90
|
-
objects:
|
|
105
|
+
objects: objects,
|
|
91
106
|
isCrudObject,
|
|
92
107
|
hasRbacAddOn: (object) => hasRbacAddOn(object, objects),
|
|
93
108
|
plan
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
CRUD_ACTIONS,
|
|
4
4
|
createCrudActionPlans,
|
|
5
5
|
hasGraphStorageResource,
|
|
6
|
-
isCrudObject
|
|
6
|
+
isCrudObject,
|
|
7
|
+
VALID_CRUD_GENERATED_BY
|
|
7
8
|
} from './crudActionPlan.js';
|
|
8
9
|
|
|
9
10
|
const MESSAGE_ATTRIBUTES = ['userId', 'correlationId'];
|
|
@@ -13,24 +14,44 @@ export const dynamicCrudFlowSchemaPaths = CRUD_ACTIONS.map(
|
|
|
13
14
|
`app/src/schemas/FlowSchemas/generateCode/FlowObjects/${action}.js`
|
|
14
15
|
);
|
|
15
16
|
|
|
16
|
-
export function emitDynamicCrudFlowSchemas({
|
|
17
|
+
export function emitDynamicCrudFlowSchemas({
|
|
18
|
+
objects,
|
|
19
|
+
flows = [],
|
|
20
|
+
serviceTag,
|
|
21
|
+
logger
|
|
22
|
+
}) {
|
|
17
23
|
if (!Array.isArray(objects) || !Array.isArray(flows)) {
|
|
18
24
|
throw new TypeError('objects and flows must be arrays');
|
|
19
25
|
}
|
|
20
|
-
if (!objects.some(isCrudObject))
|
|
26
|
+
if (!objects.some(isCrudObject)) {
|
|
27
|
+
if (objects.length > 0) {
|
|
28
|
+
const summary = objects.map((obj) => ({
|
|
29
|
+
objectType: obj?.objectType ?? '(undefined)',
|
|
30
|
+
generatedBy: obj?.generatedBy ?? '(missing)'
|
|
31
|
+
}));
|
|
32
|
+
logger?.warn?.(
|
|
33
|
+
`[WARN] [CRUD FlowSchemas] Skipped FlowObjects FlowSchemas generation: No valid CRUD ObjectSchema found. ` +
|
|
34
|
+
`Checked ${objects.length} object(s): ${JSON.stringify(summary)}. ` +
|
|
35
|
+
`Expected "generatedBy" to be one of: ${Array.from(VALID_CRUD_GENERATED_BY).join(', ')}`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
21
40
|
|
|
22
41
|
const plans = createCrudActionPlans(objects);
|
|
42
|
+
const primaryObject = objects.find(isCrudObject);
|
|
43
|
+
const initiateBy = primaryObject?.generatedBy || 'user';
|
|
23
44
|
|
|
24
45
|
return CRUD_ACTIONS.map((action, index) => ({
|
|
25
46
|
path: dynamicCrudFlowSchemaPaths[index],
|
|
26
47
|
content: renderDynamicCrudFlowSchema(
|
|
27
48
|
action,
|
|
28
|
-
_createDynamicFlow(action, plans[action], serviceTag)
|
|
49
|
+
_createDynamicFlow(action, plans[action], serviceTag, initiateBy)
|
|
29
50
|
)
|
|
30
51
|
}));
|
|
31
52
|
}
|
|
32
53
|
|
|
33
|
-
function _createDynamicFlow(action, plan, serviceTag = '') {
|
|
54
|
+
function _createDynamicFlow(action, plan, serviceTag = '', initiateBy = 'user') {
|
|
34
55
|
const flowSteps = [
|
|
35
56
|
{
|
|
36
57
|
stepName: 'Start',
|
|
@@ -103,7 +124,7 @@ function _createDynamicFlow(action, plan, serviceTag = '') {
|
|
|
103
124
|
|
|
104
125
|
return {
|
|
105
126
|
flowTag: action,
|
|
106
|
-
initiateBy
|
|
127
|
+
initiateBy,
|
|
107
128
|
handleObj: 'one',
|
|
108
129
|
statusType: 'none',
|
|
109
130
|
event: plan.outputTopic ? ['ownTopic'] : ['lambdaSyncInv', 'lambdaSyncApi'],
|
|
@@ -9,10 +9,11 @@ import {
|
|
|
9
9
|
|
|
10
10
|
export async function generateCrudApplicationArtifacts(rootPath, options = {}) {
|
|
11
11
|
const project = compileProject({ ...options, rootPath });
|
|
12
|
-
const schemas = await loadLocalSchemaArrays(project);
|
|
12
|
+
const schemas = await loadLocalSchemaArrays(project, options);
|
|
13
13
|
const artifacts = await emitCrudApplicationArtifacts({
|
|
14
14
|
...schemas,
|
|
15
|
-
serviceTag: project.serviceTag
|
|
15
|
+
serviceTag: project.serviceTag,
|
|
16
|
+
logger: options.logger
|
|
16
17
|
});
|
|
17
18
|
const files = await commitArtifacts(
|
|
18
19
|
buildGenerationPlan(project, artifacts, {
|
|
@@ -9,12 +9,13 @@ import { loadLocalSchemaArrays } from './loadLocalSchemaArrays.js';
|
|
|
9
9
|
|
|
10
10
|
export async function generateDynamicCrudFlowSchemas(rootPath, options = {}) {
|
|
11
11
|
const project = compileProject({ ...options, rootPath });
|
|
12
|
-
const schemaInputs = await loadLocalSchemaArrays(project);
|
|
12
|
+
const schemaInputs = await loadLocalSchemaArrays(project, options);
|
|
13
13
|
const plan = buildGenerationPlan(
|
|
14
14
|
project,
|
|
15
15
|
emitDynamicCrudFlowSchemas({
|
|
16
16
|
...schemaInputs,
|
|
17
|
-
serviceTag: project.serviceTag
|
|
17
|
+
serviceTag: project.serviceTag,
|
|
18
|
+
logger: options.logger
|
|
18
19
|
}),
|
|
19
20
|
{
|
|
20
21
|
managedPaths: dynamicCrudFlowSchemaPaths,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { loadLocalSchemaDirectory } from '../../compile/loadSchemas.js';
|
|
2
2
|
|
|
3
|
-
export async function loadLocalSchemaArrays(project) {
|
|
3
|
+
export async function loadLocalSchemaArrays(project, options = {}) {
|
|
4
4
|
return {
|
|
5
|
-
objects: await loadLocalSchemaDirectory(project, 'ObjectSchemas'),
|
|
6
|
-
flows: await loadLocalSchemaDirectory(project, 'FlowSchemas')
|
|
5
|
+
objects: await loadLocalSchemaDirectory(project, 'ObjectSchemas', options),
|
|
6
|
+
flows: await loadLocalSchemaDirectory(project, 'FlowSchemas', options)
|
|
7
7
|
};
|
|
8
8
|
}
|
|
@@ -52,7 +52,7 @@ export default async function CreateComplete(
|
|
|
52
52
|
//(</additionalParams>)
|
|
53
53
|
) {
|
|
54
54
|
try {
|
|
55
|
-
_izContext.logger.debug(
|
|
55
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:CreateComplete] started`, {
|
|
56
56
|
requestParams
|
|
57
57
|
});
|
|
58
58
|
const {
|
|
@@ -65,7 +65,7 @@ export default async function <%- flowTag %>(
|
|
|
65
65
|
//(</additionalParams>)
|
|
66
66
|
) {
|
|
67
67
|
try {
|
|
68
|
-
_izContext.logger.debug(
|
|
68
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] createMain:`, {
|
|
69
69
|
requestParams,
|
|
70
70
|
callingFlowConfig
|
|
71
71
|
});
|
|
@@ -78,19 +78,42 @@ export default async function <%- flowTag %>(
|
|
|
78
78
|
_izContext,
|
|
79
79
|
objType
|
|
80
80
|
);
|
|
81
|
-
_izContext.logger.debug(
|
|
81
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] objectSchema:`, objectSchema);
|
|
82
82
|
|
|
83
|
-
// ── Resolve
|
|
84
|
-
let
|
|
83
|
+
// ── Resolve submittedByUserId / targetIdentifiers ─────────────────────────
|
|
84
|
+
let submittedByUserId, targetIdentifiers;
|
|
85
85
|
if (
|
|
86
86
|
objectSchema.generatedBy === 'user' ||
|
|
87
87
|
objectSchema.generatedBy === 'systemWithUser'
|
|
88
88
|
) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
submittedByUserId =
|
|
90
|
+
requestParams.submittedByUserId ||
|
|
91
|
+
_izContext.correlationIds.get(coreConsts.SUBMITTED_BY_USER_ID);
|
|
92
|
+
|
|
93
|
+
targetIdentifiers = requestParams.targetIdentifiers;
|
|
94
|
+
|
|
95
|
+
if (!targetIdentifiers && objectSchema.belongTo?.objectType === 'user' && submittedByUserId) {
|
|
96
|
+
targetIdentifiers = { submittedByUserId };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!submittedByUserId) errorsFound.push('Not have submittedByUserId');
|
|
100
|
+
if (objectSchema.hasOwnProperty('belongTo') && !targetIdentifiers)
|
|
101
|
+
errorsFound.push('not have targetIdentifiers');
|
|
102
|
+
|
|
103
|
+
requestParams.submittedByUserId = submittedByUserId;
|
|
104
|
+
if (targetIdentifiers) {
|
|
105
|
+
if (!targetIdentifiers.submittedByUserId && submittedByUserId) {
|
|
106
|
+
targetIdentifiers.submittedByUserId = submittedByUserId;
|
|
107
|
+
}
|
|
108
|
+
requestParams.targetIdentifiers = targetIdentifiers;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] Identity & Target Context Resolved:`, {
|
|
112
|
+
submittedByUserId: requestParams.submittedByUserId,
|
|
113
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
114
|
+
belongTo: objectSchema.belongTo,
|
|
115
|
+
generatedBy: objectSchema.generatedBy
|
|
116
|
+
});
|
|
94
117
|
} else if (objectSchema.generatedBy === 'searchResultGenerated') {
|
|
95
118
|
throw new NoRetryError(
|
|
96
119
|
'error searchResultGenerated should not happen here'
|
|
@@ -106,14 +129,14 @@ export default async function <%- flowTag %>(
|
|
|
106
129
|
_izContext,
|
|
107
130
|
objectSchema
|
|
108
131
|
);
|
|
109
|
-
_izContext.logger.debug(
|
|
132
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] objectSchemas:`, objectSchemas);
|
|
110
133
|
|
|
111
134
|
// ── Build createDataDetails ───────────────────────────────────────────────
|
|
112
135
|
const createDataDetails = await createDataDetailsLib(
|
|
113
136
|
_izContext,
|
|
114
137
|
objectSchemas
|
|
115
138
|
);
|
|
116
|
-
_izContext.logger.debug(
|
|
139
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] createDataDetails:`, createDataDetails);
|
|
117
140
|
|
|
118
141
|
if (requestParams.relationships?.length > 0) {
|
|
119
142
|
//(<beforeValidateRelationships>)
|
|
@@ -127,7 +150,7 @@ export default async function <%- flowTag %>(
|
|
|
127
150
|
requestParams.relationships
|
|
128
151
|
))
|
|
129
152
|
);
|
|
130
|
-
_izContext.logger.debug(
|
|
153
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] errorsFound:`, errorsFound);
|
|
131
154
|
|
|
132
155
|
// ── Resolve fromRequiredOnCreate fields ──────────────────────────────────
|
|
133
156
|
if (objectSchemas.fieldNames) {
|
|
@@ -136,8 +159,12 @@ export default async function <%- flowTag %>(
|
|
|
136
159
|
if (val.fromRequiredOnCreate && requestParams.fieldNames[fieldName] === undefined) {
|
|
137
160
|
const fromConfig = val.fromRequiredOnCreate;
|
|
138
161
|
const sourceField = fromConfig.fieldName || fieldName;
|
|
139
|
-
if (fromConfig.belongToObjType === true &&
|
|
140
|
-
|
|
162
|
+
if (fromConfig.belongToObjType === true && targetIdentifiers) {
|
|
163
|
+
const targetValue =
|
|
164
|
+
targetIdentifiers[sourceField] !== undefined
|
|
165
|
+
? targetIdentifiers[sourceField]
|
|
166
|
+
: Object.values(targetIdentifiers)[0];
|
|
167
|
+
requestParams.fieldNames[fieldName] = targetValue;
|
|
141
168
|
} else if (fromConfig.relType && requestParams.relationships?.length > 0) {
|
|
142
169
|
const matchedRel = requestParams.relationships.find(
|
|
143
170
|
(rel) =>
|
|
@@ -152,6 +179,9 @@ export default async function <%- flowTag %>(
|
|
|
152
179
|
}
|
|
153
180
|
}
|
|
154
181
|
|
|
182
|
+
const listOfRequiredOnCreate = [];
|
|
183
|
+
const listOfOptionalOnCreate = [];
|
|
184
|
+
|
|
155
185
|
for (const [key, val] of Object.entries(objectSchemas.fieldNames)) {
|
|
156
186
|
if (
|
|
157
187
|
val.randomOnCreate === true ||
|
|
@@ -200,9 +230,9 @@ export default async function <%- flowTag %>(
|
|
|
200
230
|
}
|
|
201
231
|
}
|
|
202
232
|
|
|
203
|
-
_izContext.logger.debug(
|
|
233
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] requestParams:`, requestParams);
|
|
204
234
|
errorsFound.push(...errors);
|
|
205
|
-
_izContext.logger.debug(
|
|
235
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] errorsFound after identifiers:`, errorsFound);
|
|
206
236
|
|
|
207
237
|
if (errorsFound.length > 0)
|
|
208
238
|
return await <%- flowTag %>LogicalLib(
|
|
@@ -239,7 +269,7 @@ export default async function <%- flowTag %>(
|
|
|
239
269
|
});
|
|
240
270
|
}
|
|
241
271
|
if (errorsFound.length > 0) {
|
|
242
|
-
_izContext.logger.debug(
|
|
272
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>] HaveError:`, errorsFound);
|
|
243
273
|
break;
|
|
244
274
|
}
|
|
245
275
|
}
|
|
@@ -288,12 +318,12 @@ export default async function <%- flowTag %>(
|
|
|
288
318
|
serviceTag: <%- rbacServiceTags.length === 1 ? rbacServiceTags[0] : `{ ${Object.entries(rbacServiceTagMap).map(([k, v]) => `'${k}': ${v}`).join(', ')} }[requestParams.objectType] || process.env.iz_serviceTag` %>
|
|
289
319
|
},
|
|
290
320
|
requestParams: requestParams,
|
|
291
|
-
nextFlowStepName: '<%- flowTag %>
|
|
321
|
+
nextFlowStepName: '<%- plan?.hasRbacCallback ? `${flowTag}RbacCallback` : `${flowTag}Complete` %>'
|
|
292
322
|
}
|
|
293
323
|
);
|
|
294
324
|
|
|
295
325
|
_izContext.logger.debug(
|
|
296
|
-
|
|
326
|
+
`[${process.env.iz_serviceTag}:<%- flowTag %>] checkRbacPermission result:`,
|
|
297
327
|
resultPermissionCheck
|
|
298
328
|
);
|
|
299
329
|
|
|
@@ -459,6 +489,7 @@ export default async function <%- flowTag %>(
|
|
|
459
489
|
errorsFound
|
|
460
490
|
);
|
|
461
491
|
} catch (err) {
|
|
492
|
+
_izContext.logger.error(`[${process.env.iz_serviceTag}:<%- flowTag %>] error:`, err);
|
|
462
493
|
throw err;
|
|
463
494
|
}
|
|
464
495
|
}
|
|
@@ -77,10 +77,11 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
77
77
|
phaseResults = {}
|
|
78
78
|
) {
|
|
79
79
|
try {
|
|
80
|
-
_izContext.logger.debug(
|
|
80
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] started`, {
|
|
81
81
|
requestParams,
|
|
82
82
|
callingFlowConfig,
|
|
83
|
-
phaseResults
|
|
83
|
+
phaseResults,
|
|
84
|
+
targetIdentifiers: requestParams.targetIdentifiers
|
|
84
85
|
});
|
|
85
86
|
|
|
86
87
|
//(<beforeCreateMainLogical>)
|
|
@@ -93,14 +94,14 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
93
94
|
_izContext,
|
|
94
95
|
objType
|
|
95
96
|
);
|
|
96
|
-
_izContext.logger.debug(
|
|
97
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] objectSchema:`, objectSchema);
|
|
97
98
|
|
|
98
99
|
const objectSchemas =
|
|
99
100
|
uploadUseCase.generateObjectSchemaForCombineFieldNames(
|
|
100
101
|
_izContext,
|
|
101
102
|
objectSchema
|
|
102
103
|
);
|
|
103
|
-
_izContext.logger.debug(
|
|
104
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] objectSchemas:`, objectSchemas);
|
|
104
105
|
|
|
105
106
|
// ── Parent object ─────────────────────────────────────────────────────────
|
|
106
107
|
let parentObject;
|
|
@@ -121,7 +122,7 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
121
122
|
_izContext,
|
|
122
123
|
objectSchemas
|
|
123
124
|
);
|
|
124
|
-
_izContext.logger.debug(
|
|
125
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] createDataDetails:`, createDataDetails);
|
|
125
126
|
|
|
126
127
|
// ── Build objInstanceFull identifiers ─────────────────────────────────────
|
|
127
128
|
const objInstanceFull = { identifiers: {}, fields: {} };
|
|
@@ -177,7 +178,7 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
177
178
|
|
|
178
179
|
// ── DynamoDB ──────────────────────────────────────────────────────────
|
|
179
180
|
if (createDataDetail.storageType === consts.STORAGE_TYPES.dynamoDB) {
|
|
180
|
-
_izContext.logger.debug(
|
|
181
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] DynamoDB:`, {
|
|
181
182
|
storageTag,
|
|
182
183
|
objInstanceFull
|
|
183
184
|
});
|
|
@@ -256,6 +257,66 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
256
257
|
);
|
|
257
258
|
|
|
258
259
|
objInstanceFullForDynamoDb.fields = {};
|
|
260
|
+
|
|
261
|
+
// ── Auto-provision owner TargetRole for Root Object with RBAC ─────
|
|
262
|
+
const hasRbacAddOn = Array.isArray(objectSchema?.addOnDataStructure) &&
|
|
263
|
+
objectSchema.addOnDataStructure.some((addOn) => addOn?.type === 'rbac');
|
|
264
|
+
const isRootRbacObject =
|
|
265
|
+
hasRbacAddOn &&
|
|
266
|
+
!objectSchema?.belongTo &&
|
|
267
|
+
objectSchema?.objectType !== 'user' &&
|
|
268
|
+
objectSchema?.generatedBy !== 'systemNoUser';
|
|
269
|
+
|
|
270
|
+
if (isRootRbacObject) {
|
|
271
|
+
try {
|
|
272
|
+
const submittedByUserId = requestParams.submittedByUserId || _izContext.correlationIds.get(coreConsts.SUBMITTED_BY_USER_ID);
|
|
273
|
+
if (submittedByUserId) {
|
|
274
|
+
const targetIdentKeys = Object.entries(identifiersForCreateData)
|
|
275
|
+
.map(([k, v]) => `${k}#${v}`)
|
|
276
|
+
.join('_');
|
|
277
|
+
const targetIdentifiersConcat = targetIdentKeys || (identifiersForCreateData[Object.keys(identifiersForCreateData)[0]] ? `${Object.keys(identifiersForCreateData)[0]}#${identifiersForCreateData[Object.keys(identifiersForCreateData)[0]]}` : '');
|
|
278
|
+
|
|
279
|
+
if (targetIdentifiersConcat) {
|
|
280
|
+
const roleIdKey = `${targetIdentifiersConcat}_owner`;
|
|
281
|
+
_izContext.logger.debug('[CreateLogicalLib] Auto-provisioning owner TargetRole:', {
|
|
282
|
+
identifiersConcat: targetIdentifiersConcat,
|
|
283
|
+
roleIdKey,
|
|
284
|
+
submittedByUserId,
|
|
285
|
+
roleName: 'owner'
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
await dynamodbSharedLib.putItem(
|
|
289
|
+
_izContext,
|
|
290
|
+
dynamodbSharedLib.tableName(_izContext, 'TargetRoles'),
|
|
291
|
+
{
|
|
292
|
+
identifiersConcat: targetIdentifiersConcat,
|
|
293
|
+
roleIdKey,
|
|
294
|
+
submittedByUserId,
|
|
295
|
+
roleName: 'owner',
|
|
296
|
+
assignedAt: new Date().toISOString()
|
|
297
|
+
}
|
|
298
|
+
).catch(() => {});
|
|
299
|
+
|
|
300
|
+
await dynamodbSharedLib.transactWriteItems(_izContext, [
|
|
301
|
+
{
|
|
302
|
+
Put: {
|
|
303
|
+
TableName: dynamodbSharedLib.tableName(_izContext, 'RoleUsers'),
|
|
304
|
+
Item: { roleIdKey, submittedByUserId }
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
Put: {
|
|
309
|
+
TableName: dynamodbSharedLib.tableName(_izContext, 'UserRoles'),
|
|
310
|
+
Item: { submittedByUserId, roleIdKey }
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
]).catch(() => {});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
} catch (roleError) {
|
|
317
|
+
_izContext.logger.warn('[CreateLogicalLib] Failed to auto-provision owner TargetRole:', { roleError });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
259
320
|
}
|
|
260
321
|
|
|
261
322
|
//(<afterCreateRecordDynamo>)
|
|
@@ -267,7 +328,7 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
267
328
|
) {
|
|
268
329
|
//(<beforeCreateNode>)
|
|
269
330
|
//(</beforeCreateNode>)
|
|
270
|
-
_izContext.logger.debug(
|
|
331
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] Graph:`, {
|
|
271
332
|
storageTag,
|
|
272
333
|
objInstanceFull
|
|
273
334
|
});
|
|
@@ -435,6 +496,7 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
435
496
|
objType,
|
|
436
497
|
objInstanceFull: objInstanceFullForGraph,
|
|
437
498
|
relationships: requestParams.relationships || [],
|
|
499
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
438
500
|
status: 'complete',
|
|
439
501
|
errorsFound
|
|
440
502
|
};
|
|
@@ -444,7 +506,7 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
444
506
|
|
|
445
507
|
// ── Handle errors ─────────────────────────────────────────────────────────
|
|
446
508
|
if (errorsFound.length > 0) {
|
|
447
|
-
_izContext.logger.debug(
|
|
509
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] errorsFound:`, errorsFound);
|
|
448
510
|
|
|
449
511
|
await asyncFlowSharedLib.clearAllAwaitingSteps(
|
|
450
512
|
_izContext,
|
|
@@ -479,6 +541,7 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
479
541
|
objType,
|
|
480
542
|
objInstanceFull,
|
|
481
543
|
relationships: requestParams.relationships || [],
|
|
544
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
482
545
|
status: 'error',
|
|
483
546
|
errorsFound
|
|
484
547
|
};
|
|
@@ -529,10 +592,12 @@ export async function <%- flowTag %>LogicalLib(
|
|
|
529
592
|
fields: objInstanceFullForDynamoDb.fields
|
|
530
593
|
},
|
|
531
594
|
relationships: requestParams.relationships || [],
|
|
595
|
+
targetIdentifiers: requestParams.targetIdentifiers,
|
|
532
596
|
status: 'complete',
|
|
533
597
|
errorsFound
|
|
534
598
|
};
|
|
535
599
|
} catch (err) {
|
|
600
|
+
_izContext.logger.error(`[${process.env.iz_serviceTag}:<%- flowTag %>LogicalLib] error:`, err);
|
|
536
601
|
throw err;
|
|
537
602
|
}
|
|
538
603
|
}
|
|
@@ -52,7 +52,7 @@ export default async function DeleteComplete(
|
|
|
52
52
|
//(</additionalParams>)
|
|
53
53
|
) {
|
|
54
54
|
try {
|
|
55
|
-
_izContext.logger.debug(
|
|
55
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:DeleteComplete] started`, {
|
|
56
56
|
requestParams
|
|
57
57
|
});
|
|
58
58
|
const {
|