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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/package.json +1 -1
  2. package/src/compile/compileProject.js +1 -2
  3. package/src/compile/loadSchemas.js +29 -17
  4. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +6 -0
  5. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +26 -6
  6. package/src/emit/crud/crudActionPlan.js +3 -1
  7. package/src/emit/crud/emitCrudApplicationArtifacts.js +47 -8
  8. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +136 -25
  9. package/src/emit/crud/templates/CreateConfirmComplete_Main.ejs +54 -0
  10. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +248 -181
  11. package/src/emit/crud/templates/CreateLogicalLib.ejs +1155 -293
  12. package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +221 -0
  13. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +36 -4
  14. package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +20 -120
  15. package/src/emit/crud/templates/FlowEndpoint_HdrWbs.ejs +76 -14
  16. package/src/emit/crud/templates/FlowMain_Wbs.ejs +31 -35
  17. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +35 -3
  18. package/src/emit/crud/templates/UpdateLogicalLib.ejs +754 -353
  19. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +5 -2
  20. package/src/emit/rbac/emitRbacApplicationArtifacts.js +102 -6
  21. package/src/emit/rbac/templates/CancelUsage_Main.ejs +82 -22
  22. package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +130 -14
  23. package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +61 -12
  24. package/src/emit/rbac/templates/DeleteTargetRole_Main.ejs +96 -0
  25. package/src/emit/rbac/templates/GetMyPermissions_Main.ejs +106 -0
  26. package/src/emit/rbac/templates/GetTargetRole_Main.ejs +62 -0
  27. package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +30 -11
  28. package/src/emit/rbac/templates/UpdateTargetRole_Main.ejs +107 -0
  29. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +40 -15
  30. package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +22 -7
  31. package/src/emit/resource/emitResourceArtifacts.js +52 -2
  32. package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +6 -2
  33. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +2 -0
  34. package/src/emit/shared/templates/FlowHandler_HdrSqs.ejs +1 -1
  35. package/src/emit/system/templates/WebSocketConnect_Yaml.ejs +0 -1
  36. package/src/emit/systemText/emitSystemTextSchemas.js +5 -2
  37. package/src/generate.js +18 -12
  38. package/src/generateResources/IntTest/generateResources/generateResources.js +1 -1
  39. package/src/generateResources/IntTest/generateTests/generateTemplate.js +1 -1
  40. package/src/generateResources/IntTest/upload/uploadIntTest.js +8 -2
  41. package/test/createTargetRoleHandler.test.js +42 -1
  42. package/test/crudApplicationArtifacts.test.js +53 -0
  43. package/test/dynamicCrudFlowSchemas.test.js +16 -2
  44. package/test/dynamicRbacFlowSchemas.test.js +5 -2
  45. package/test/publicApi.test.js +18 -14
  46. package/test/resourceArtifacts.test.js +24 -0
@@ -0,0 +1,221 @@
1
+ /*
2
+ Copyright (C) 2021 Sven Mason <http://izara.io>
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU Affero General Public License as
6
+ published by the Free Software Foundation, either version 3 of the
7
+ License, or (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU Affero General Public License for more details.
13
+
14
+ You should have received a copy of the GNU Affero General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ import asyncFlowSharedLib from '@izara_project/izara-core-library-asynchronous-flow';
19
+ import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
20
+ import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
21
+ import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
22
+ import snsSharedLib from '@izara_project/izara-core-library-sns';
23
+ import { sns } from '@izara_project/izara-core-library-external-request';
24
+ import { consts } from '@izara_project/izara-core-library-service-schemas';
25
+ import {
26
+ consts as coreConsts,
27
+ NoRetryError
28
+ } from '@izara_project/izara-core-library-core';
29
+
30
+ import {
31
+ saveDynamoDbRecords,
32
+ autoProvisionOwnerTargetRole,
33
+ resolveQuotaDeductionKeys,
34
+ forwardToQuotaConfirmation
35
+ } from './CreateLogicalLib.js';
36
+
37
+ //(<optionalRequire>)
38
+ //(</optionalRequire>)
39
+
40
+ const PREFIX = { ASYNC: 'CreateAsyncEndpoint' };
41
+
42
+ function empty(value) {
43
+ return (
44
+ value == null ||
45
+ (typeof value === 'object' && Object.keys(value).length === 0)
46
+ );
47
+ }
48
+
49
+ function validateInput(returnValue, status, graphServiceTag, errorsFound) {
50
+ if (!returnValue?.queryResult)
51
+ errorsFound.push(
52
+ 'message is not have property queryResult, should be not happen'
53
+ );
54
+ if (!returnValue?.requestParams?.objType)
55
+ errorsFound.push(
56
+ 'message is not have property objType, should be not happen'
57
+ );
58
+ if (!returnValue?.requestParams?.objInstanceFull)
59
+ errorsFound.push(
60
+ 'message is not have property objInstance, should be not objInstance'
61
+ );
62
+ if (status === 'error' && errorsFound.length === 0)
63
+ errorsFound.push(
64
+ '[invalid]status is error not have errorsFound form graphService'
65
+ );
66
+ if (status === 'complete' && errorsFound.length > 0)
67
+ errorsFound.push(
68
+ '[Invalid] status is complete should be not have errorsFound'
69
+ );
70
+ if (graphServiceTag == null)
71
+ errorsFound.push('[Invalid] graphServerTag is not empty string');
72
+ }
73
+
74
+ /**
75
+ * Handles callback after Graph creation node completion
76
+ * @param {Object} _izContext - Izara context object
77
+ * @param {Object} requestParams - Callback request parameters
78
+ * @param {Object} passBackProperties - Pass-back properties
79
+ * @returns {Promise<Object>} Result object
80
+ */
81
+ export default async function CreateNodeCallbackMain(
82
+ _izContext,
83
+ requestParams,
84
+ passBackProperties
85
+ //(<additionalParams>)
86
+ //(</additionalParams>)
87
+ ) {
88
+ try {
89
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:CreateNodeCallback] started`, {
90
+ requestParams,
91
+ passBackProperties
92
+ });
93
+ const {
94
+ returnValue,
95
+ status,
96
+ errorsFound = [],
97
+ graphServiceTag,
98
+ parentFlowId
99
+ } = requestParams;
100
+ if (empty(returnValue?.requestParams))
101
+ throw new NoRetryError('message not an object');
102
+ validateInput(returnValue, status, graphServiceTag, errorsFound);
103
+ if (errorsFound.length > 0) errorsFound.push(errorsFound.join(','));
104
+
105
+ const awaitingStepId = await asyncFlowSharedLib.createAwaitingStepId(
106
+ parentFlowId,
107
+ PREFIX.ASYNC
108
+ );
109
+ const pending =
110
+ await asyncFlowSharedLib.findPendingStepAwaitingMultipleSteps(
111
+ _izContext,
112
+ awaitingStepId
113
+ );
114
+ _izContext.logger.debug('[CreateNodeCallback] awaiting step', {
115
+ awaitingStepId,
116
+ pending
117
+ });
118
+ if (!pending) {
119
+ _izContext.logger.warn(
120
+ `No pending step found for awaitingStepId: ${awaitingStepId}`
121
+ );
122
+ return { returnValue, status, errorsFound };
123
+ }
124
+ const result =
125
+ await asyncFlowSharedLib.checkAllAwaitingStepsFinishedWithReturnParams(
126
+ _izContext,
127
+ pending.pendingStepId,
128
+ awaitingStepId,
129
+ errorsFound
130
+ );
131
+ _izContext.logger.debug(
132
+ '[CreateNodeCallback] all awaiting steps result',
133
+ {
134
+ isComplete: result.isComplete,
135
+ awaitingStepId,
136
+ pendingStepId: pending.pendingStepId
137
+ }
138
+ );
139
+
140
+ if (result.isComplete) {
141
+ const nodeResultKey = `returnCreatedNode`;
142
+ const fallbackNodeResultKey = `returnCreateNode`;
143
+ const nodeResult =
144
+ returnValue.queryResult[nodeResultKey] ??
145
+ returnValue.queryResult[fallbackNodeResultKey] ??
146
+ {};
147
+ const node = nodeResult.createNodeResult ?? nodeResult;
148
+ const existsNode =
149
+ node.existsNode && Object.keys(node.existsNode).length
150
+ ? {
151
+ objType: returnValue.requestParams.objType,
152
+ objInstanceFull: node.existsNode.objInstanceFull
153
+ }
154
+ : null;
155
+
156
+ // ── Step 1: Persist DynamoDB records ──────────────────────────────────
157
+ if (status === 'complete' && errorsFound.length === 0) {
158
+ const listOfRecords = result?.additionalAttributes?.listOfRecords ?? [];
159
+ await saveDynamoDbRecords(_izContext, listOfRecords);
160
+
161
+ // ── Step 2: Auto-provision TargetRole (Owner) after DynamoDB write ─
162
+ const submittedByUserId =
163
+ returnValue?.requestParams?.submittedByUserId ||
164
+ node?.objInstanceFull?.identifiers?.submittedByUserId ||
165
+ requestParams?.passBackProperties?.submittedByUserId ||
166
+ passBackProperties?.passBackProperties?.submittedByUserId ||
167
+ _izContext.correlationIds?.get(coreConsts.SUBMITTED_BY_USER_ID) ||
168
+ _izContext.correlationIds?.get('submittedByUserId');
169
+
170
+ await autoProvisionOwnerTargetRole(_izContext, {
171
+ node,
172
+ submittedByUserId
173
+ });
174
+ }
175
+
176
+ const callingFlowConfig =
177
+ result?.additionalAttributes?.callingFlowConfig ||
178
+ requestParams?.passBackProperties?.parentPassBackProperties ||
179
+ passBackProperties?.passBackProperties?.parentPassBackProperties ||
180
+ passBackProperties;
181
+
182
+ const actionData = {
183
+ objType: returnValue.requestParams.objType,
184
+ objInstanceFull: node.objInstanceFull,
185
+ relationships: node.relationships,
186
+ parentFlowId: parentFlowId || returnValue?.parentFlowId,
187
+ existsNode,
188
+ status,
189
+ errorsFound
190
+ };
191
+
192
+ // ── Step 3: Resolve Quota deduction keys and forward confirmation ─────
193
+ const quotaKeys = resolveQuotaDeductionKeys(
194
+ requestParams,
195
+ passBackProperties,
196
+ returnValue,
197
+ callingFlowConfig,
198
+ _izContext
199
+ );
200
+
201
+ await forwardToQuotaConfirmation(_izContext, {
202
+ status,
203
+ errorsFound,
204
+ quotaKeys,
205
+ actionData,
206
+ callingFlowConfig
207
+ });
208
+ }
209
+
210
+ await asyncFlowSharedLib.removeAwaitingMultipleStep(
211
+ _izContext,
212
+ awaitingStepId,
213
+ pending.pendingStepId,
214
+ errorsFound
215
+ );
216
+ return { returnValue, status, errorsFound };
217
+ } catch (error) {
218
+ _izContext.logger.error('[CreateNodeCallback] error:', error);
219
+ throw error;
220
+ }
221
+ }
@@ -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: requestParams.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
- ? o.belongTo
135
- : [o.belongTo]
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,6 +195,7 @@ 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
  },
@@ -30,7 +30,11 @@ import { sns } from '@izara_project/izara-core-library-external-request';
30
30
 
31
31
  const { createObjType } = utils;
32
32
 
33
- import { <%- flowTag %>LogicalLib } from './<%- upperCaseFlowTag %>LogicalLib.js';
33
+ import {
34
+ <%- flowTag %>LogicalLib,
35
+ collectRbacAwaitingResults,
36
+ assertRbacPermission
37
+ } from './<%- upperCaseFlowTag %>LogicalLib.js';
34
38
 
35
39
  //(<optionalRequire>)
36
40
  //(</optionalRequire>)
@@ -39,6 +43,7 @@ import { <%- flowTag %>LogicalLib } from './<%- upperCaseFlowTag %>LogicalLib.js
39
43
  * Handles callback after RbacCallback phase — verifies awaitingStep then proceeds to next phase
40
44
  * @param {Object} _izContext - Context object with logger
41
45
  * @param {Object} requestParams - { fieldNames, relationships[] }
46
+ * @param {string} flowTag - Flow tag name
42
47
  * @param {Object} callingFlowConfig - Calling flow configuration
43
48
  * @returns {Promise<Object>}
44
49
  */
@@ -49,149 +54,44 @@ export default async function <%- flowTag %>RbacCallbackMain(
49
54
  callingFlowConfig = {}
50
55
  ) {
51
56
  try {
52
- _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>RbacCallback] Started with params:`, {
57
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- flowTag %>RbacCallback] Started with params:`, {
53
58
  requestParams,
54
59
  flowTag,
55
60
  callingFlowConfig
56
61
  });
57
62
 
58
- const parts = requestParams.parentFlowId.split('_');
59
- const rbacType = parts.pop();
60
- const rbacPendingStepId = '<%- flowTag %>RbacCallback_' + parts.join('_');
61
- const currentAwaitingStepId = requestParams.parentFlowId;
62
-
63
- _izContext.logger.debug(
64
- '[<%- flowTag %>RbacCallbackMain] Parsed RBAC pending details:',
65
- {
66
- rbacType,
67
- rbacPendingStepId,
68
- currentAwaitingStepId,
69
- parentFlowId: requestParams.parentFlowId
70
- }
71
- );
72
-
73
- const rbacAwaitingStepsResult =
74
- await asyncFlowSharedLib.checkAllAwaitingStepsFinishedWithReturnParams(
75
- _izContext,
76
- rbacPendingStepId,
77
- currentAwaitingStepId,
78
- requestParams.errorsFound,
79
- {
80
- returnValue: requestParams.returnValue,
81
- rbacType
82
- }
83
- );
84
-
85
- _izContext.logger.debug(
86
- '[<%- flowTag %>RbacCallbackMain] checkAllAwaitingStepsFinishedWithReturnParams result:',
87
- {
88
- rbacAwaitingStepsResult
89
- }
90
- );
91
-
63
+ // 1. Wait until all awaiting steps (App/Target RBAC) are complete
92
64
  const {
93
65
  isComplete,
94
- collectedReturnValueByAwaitingStepId,
95
- collectedErrors: errorsFound = [],
96
- additionalAttributes
97
- } = rbacAwaitingStepsResult;
66
+ rbacResults,
67
+ originalRequestParams,
68
+ collectedErrors = []
69
+ } = await collectRbacAwaitingResults(_izContext, requestParams);
98
70
 
99
71
  if (isComplete === false) {
100
- _izContext.logger.debug(
101
- '[<%- flowTag %>RbacCallbackMain] Awaiting steps still pending completion:',
102
- {
103
- rbacPendingStepId,
104
- isComplete
105
- }
106
- );
107
-
108
72
  return 'all task not completed';
109
73
  }
110
74
 
111
- _izContext.logger.debug(
112
- '[<%- flowTag %>RbacCallbackMain] All awaiting steps completed — clearing awaiting steps:',
113
- {
114
- rbacPendingStepId
115
- }
116
- );
75
+ const errorsFound = [...collectedErrors];
117
76
 
118
- await asyncFlowSharedLib.clearAllAwaitingSteps(
77
+ // 2. Validate RBAC permission results
78
+ const { hasError, errorResult, rbacCallbackResults } = await assertRbacPermission(
119
79
  _izContext,
120
- rbacPendingStepId
121
- );
122
-
123
- const originalRequestParams = additionalAttributes?.requestParams || {};
124
-
125
- _izContext.logger.debug(
126
- '[<%- flowTag %>RbacCallbackMain] Retrieved originalRequestParams:',
127
80
  {
128
- originalRequestParams
129
- }
130
- );
131
-
132
- const rbacResults = Object.fromEntries(
133
- Object.entries(collectedReturnValueByAwaitingStepId || {}).map(
134
- ([stepId, attrs]) => {
135
- const type = stepId.split('_').pop();
136
- return [type, attrs];
137
- }
138
- )
139
- );
140
-
141
- const rbacCallbackResults = {};
142
- const hasError = Object.entries(rbacResults).some(([type, result]) => {
143
- if (result && result.error) {
144
- errorsFound.push(result.error);
145
- return true;
146
- }
147
- rbacCallbackResults[type] = result;
148
- return false;
149
- });
150
-
151
- const isAllowed = Object.values(rbacCallbackResults).some(
152
- item => item?.returnValue?.permission === true
153
- );
154
-
155
- if (!isAllowed) {
156
- errorsFound.push('Permission denied');
157
- }
158
-
159
- _izContext.logger.debug(
160
- '[<%- flowTag %>RbacCallbackMain] Final rbacCallbackResults before calling <%- flowTag %>MainLogical:',
161
- {
162
- rbacCallbackResults,
163
- isAllowed,
81
+ rbacResults,
82
+ originalRequestParams,
164
83
  errorsFound
165
84
  }
166
85
  );
167
86
 
168
- if (hasError || errorsFound.length > 0) {
169
- const errorResult = {
170
- errorsFound,
171
- status: 'rejected',
172
- requestParams: originalRequestParams
173
- };
174
-
175
- _izContext.logger.debug(
176
- '[<%- flowTag %>RbacCallbackMain] RBAC check failed, publishing rejected status:',
177
- errorResult
178
- );
179
-
180
- await sns.publishAsync(_izContext, {
181
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
182
- _izContext,
183
- '<%- upperCaseFlowTag %>_Out',
184
- process.env.iz_serviceTag
185
- ),
186
- Message: JSON.stringify(errorResult)
187
- });
188
-
87
+ if (hasError) {
189
88
  return errorResult;
190
89
  }
191
90
 
192
91
  //(<rbacCallbackMain>)
193
92
  //(</rbacCallbackMain>)
194
93
 
94
+ // 3. Permission granted -> Proceed with core logical processing
195
95
  const logicalResult = await <%- flowTag %>LogicalLib(
196
96
  _izContext,
197
97
  originalRequestParams,
@@ -209,7 +109,7 @@ export default async function <%- flowTag %>RbacCallbackMain(
209
109
 
210
110
  return logicalResult;
211
111
  } catch (err) {
212
- _izContext.logger.error(`[${process.env.iz_serviceTag}:<%- flowTag %>RbacCallback] Error caught:`, {
112
+ _izContext.logger.error(`[${process.env.iz_serviceTag}:<%- flowTag %>RbacCallback] Error caught:`, {
213
113
  error: err
214
114
  });
215
115
  throw err;
@@ -39,7 +39,7 @@ import <%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag
39
39
  //(</optionalRequire>)
40
40
 
41
41
  export const main = middleware.wrap(async (event, context) => {
42
- event._izContext.logger.debug('Event:', event);
42
+ event._izContext.logger.debug('[FlowEndpoint_HdrWbs] WebSocket event received', { event });
43
43
 
44
44
  try {
45
45
  if (event.requestContext) {
@@ -49,12 +49,21 @@ export const main = middleware.wrap(async (event, context) => {
49
49
  consts.X_CORRELATION_ID
50
50
  );
51
51
 
52
+ event._izContext.logger.debug('[FlowEndpoint_HdrWbs] request context info', {
53
+ route,
54
+ connectionId,
55
+ correlationId
56
+ });
57
+
52
58
  switch (route) {
53
59
  case '$default':
54
- console.log('Received unknown route:', route);
60
+ event._izContext.logger.debug('[FlowEndpoint_HdrWbs] Received unknown route', { route });
55
61
  break;
56
62
  case '<%- flowTag %>':
57
- console.log('event in route webSocket', event);
63
+ event._izContext.logger.debug('[FlowEndpoint_HdrWbs] matched route <%- flowTag %>', {
64
+ route,
65
+ body: event.body
66
+ });
58
67
  let eventParams = JSON.parse(event.body);
59
68
 
60
69
  //(<createIdentifiersFlow>)
@@ -69,11 +78,22 @@ export const main = middleware.wrap(async (event, context) => {
69
78
  }
70
79
  );
71
80
 
81
+ event._izContext.logger.debug('[FlowEndpoint_HdrWbs] flow schema resolved', {
82
+ flowTag: '<%- flowTag %>',
83
+ statusType: flowSchema?.statusType
84
+ });
85
+
72
86
  if (
73
87
  flowSchema.statusType === 'statusField' ||
74
88
  flowSchema.statusType === 'storedCache' ||
75
89
  flowSchema.statusType === 'triggerCache'
76
90
  ) {
91
+ const taskKey = `${createFlowTypeConcat(event._izContext, { flowTag: '<%- flowTag %>', serviceTag: process.env.iz_serviceTag })}${identifiers}`;
92
+ event._izContext.logger.debug('[FlowEndpoint_HdrWbs] registering WebSocketTask with ttl', {
93
+ taskKey,
94
+ connectionId,
95
+ ttl: 600
96
+ });
77
97
  await dynamodbSharedLib.putItem(
78
98
  event._izContext,
79
99
  await dynamodbSharedLib.tableName(
@@ -81,12 +101,17 @@ export const main = middleware.wrap(async (event, context) => {
81
101
  'WebSocketTask'
82
102
  ),
83
103
  {
84
- taskKey: `${createFlowTypeConcat(event._izContext, { flowTag: '<%- flowTag %>', serviceTag: process.env.iz_serviceTag })}${identifiers}`,
104
+ taskKey,
85
105
  connectionId: connectionId,
86
106
  ttl: 600
87
107
  }
88
108
  );
89
109
  } else if (flowSchema.statusType === 'none') {
110
+ const taskKey = `${createFlowTypeConcat(event._izContext, { flowTag: '<%- flowTag %>', serviceTag: process.env.iz_serviceTag })}${correlationId}`;
111
+ event._izContext.logger.debug('[FlowEndpoint_HdrWbs] registering WebSocketTask for status none', {
112
+ taskKey,
113
+ connectionId
114
+ });
90
115
  await dynamodbSharedLib.putItem(
91
116
  event._izContext,
92
117
  await dynamodbSharedLib.tableName(
@@ -94,22 +119,52 @@ export const main = middleware.wrap(async (event, context) => {
94
119
  'WebSocketTask'
95
120
  ),
96
121
  {
97
- taskKey: `${createFlowTypeConcat(event._izContext, { flowTag: '<%- flowTag %>', serviceTag: process.env.iz_serviceTag })}${correlationId}`,
122
+ taskKey,
98
123
  connectionId: connectionId
99
124
  }
100
125
  );
101
126
  }
102
127
 
103
- if (!eventParams.submittedByUserId) {
104
- const contextUserId = event._izContext.correlationIds?.get(consts.SUBMITTED_BY_USER_ID);
105
- if (contextUserId) {
106
- eventParams.submittedByUserId = contextUserId;
128
+ const authorizerUserId =
129
+ event.requestContext?.authorizer?.submittedByUserId ||
130
+ event.requestContext?.authorizer?.principalId;
131
+ const resolvedUserId =
132
+ authorizerUserId ||
133
+ eventParams.submittedByUserId ||
134
+ event._izContext?.correlationIds?.get(consts.SUBMITTED_BY_USER_ID);
135
+
136
+ if (resolvedUserId) {
137
+ if (event._izContext?.correlationIds) {
138
+ event._izContext.correlationIds.set(
139
+ consts.SUBMITTED_BY_USER_ID,
140
+ resolvedUserId
141
+ );
107
142
  }
143
+ if (
144
+ !eventParams.targetIdentifiers ||
145
+ typeof eventParams.targetIdentifiers !== 'object'
146
+ ) {
147
+ eventParams.targetIdentifiers = {};
148
+ }
149
+ eventParams.targetIdentifiers.submittedByUserId = resolvedUserId;
108
150
  }
109
151
 
152
+ event._izContext.logger.debug('[FlowEndpoint_HdrWbs] resolved user and target identifiers', {
153
+ authorizerUserId,
154
+ resolvedUserId,
155
+ targetIdentifiers: eventParams.targetIdentifiers
156
+ });
157
+
110
158
  let callingFlow = eventParams?.callingFlow
111
159
  ? eventParams.callingFlow
112
160
  : {};
161
+
162
+ event._izContext.logger.debug('[FlowEndpoint_HdrWbs] invoking main function', {
163
+ flowTag: '<%- flowTag %>',
164
+ eventParams,
165
+ callingFlow
166
+ });
167
+
113
168
  await <%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag %>(
114
169
  event._izContext,
115
170
  eventParams,
@@ -122,16 +177,23 @@ export const main = middleware.wrap(async (event, context) => {
122
177
  }
123
178
  } else {
124
179
  const connId = event.connId;
125
- // await postMessage({ message: event.message }, connId);
180
+ event._izContext.logger.debug('[FlowEndpoint_HdrWbs] direct postToConnection', {
181
+ connId,
182
+ message: event.message
183
+ });
126
184
  await postToConnection(event._izContext, { message: event.message }, connId);
127
185
  }
128
186
 
129
187
  return response.webSocketSuccess();
130
188
  } catch (err) {
131
- const connId = event.requestContext.connectionId;
132
- event._izContext.logger.error('Error, WebSocket: ', err);
133
- // await sendErrorMessage({ message: err.message }, connId);
134
- await postToConnection(event._izContext, { message: err.message }, connId);
189
+ const connId = event.requestContext?.connectionId;
190
+ event._izContext.logger.error('[FlowEndpoint_HdrWbs] Error, WebSocket: ', {
191
+ error: err,
192
+ connectionId: connId
193
+ });
194
+ if (connId) {
195
+ await postToConnection(event._izContext, { message: err.message }, connId);
196
+ }
135
197
  return response.failure(err);
136
198
  }
137
199
  });