@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.
Files changed (59) hide show
  1. package/package.json +4 -4
  2. package/src/compile/flowValidator.js +13 -2
  3. package/src/compile/loadSchemas.js +116 -7
  4. package/src/emit/attributeTree/emitAttributeTreeSchemas.js +388 -0
  5. package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +29 -1
  6. package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +16 -3
  7. package/src/emit/crud/crudActionPlan.js +38 -5
  8. package/src/emit/crud/emitCrudApplicationArtifacts.js +19 -4
  9. package/src/emit/crud/emitDynamicCrudFlowSchemas.js +27 -6
  10. package/src/emit/crud/generateCrudApplicationArtifacts.js +3 -2
  11. package/src/emit/crud/generateDynamicCrudFlowSchemas.js +3 -2
  12. package/src/emit/crud/loadLocalSchemaArrays.js +3 -3
  13. package/src/emit/crud/templates/CreateComplete_Main.ejs +1 -1
  14. package/src/emit/crud/templates/CreateEndpoint_Main.ejs +50 -19
  15. package/src/emit/crud/templates/CreateLogicalLib.ejs +73 -8
  16. package/src/emit/crud/templates/DeleteComplete_Main.ejs +1 -1
  17. package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +33 -8
  18. package/src/emit/crud/templates/DeleteLogicalLib.ejs +6 -3
  19. package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +2 -2
  20. package/src/emit/crud/templates/FlowEndpoint_HdrWbs.ejs +7 -0
  21. package/src/emit/crud/templates/FlowMain_Wbs.ejs +1 -1
  22. package/src/emit/crud/templates/GetEndpoint_Main.ejs +13 -0
  23. package/src/emit/crud/templates/UpdateComplete_Main.ejs +1 -1
  24. package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +52 -3
  25. package/src/emit/crud/templates/UpdateLogicalLib.ejs +4 -3
  26. package/src/emit/custom/customFlows.js +47 -0
  27. package/src/emit/custom/emitCustomFlowApplicationArtifacts.js +168 -49
  28. package/src/emit/custom/generateCustomFlowApplicationArtifacts.js +1 -1
  29. package/src/emit/custom/templates/FlowEndpointRbacCallback_Main.ejs +194 -0
  30. package/src/emit/custom/templates/FlowEndpoint_Main.ejs +14 -22
  31. package/src/emit/custom/templates/FlowStep_Main.ejs +1 -1
  32. package/src/emit/function/templates/WbsFunction_Yaml.ejs +0 -2
  33. package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +33 -8
  34. package/src/emit/rbac/emitRbacApplicationArtifacts.js +204 -7
  35. package/src/emit/rbac/templates/CancelUsage_Main.ejs +103 -0
  36. package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +71 -0
  37. package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +49 -6
  38. package/src/emit/rbac/templates/ListRbac_Main.ejs +9 -3
  39. package/src/emit/rbac/templates/RbacMutation_Main.ejs +1 -1
  40. package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +147 -0
  41. package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +59 -23
  42. package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +1 -1
  43. package/src/emit/relationship/emitDynamicRelationshipFlowSchemas.js +1 -1
  44. package/src/emit/relationship/templates/ChangeRelationship_Main.ejs +4 -4
  45. package/src/emit/resource/emitResourceArtifacts.js +342 -108
  46. package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +53 -2
  47. package/src/emit/system/emitSystemWebSocketArtifacts.js +6 -5
  48. package/src/emit/system/templates/WebSocketConnect.ejs +71 -12
  49. package/src/emit/system/templates/WebSocketConnect_Yaml.ejs +7 -0
  50. package/src/emit/systemText/emitSystemTextSchemas.js +1 -1
  51. package/src/generate.js +41 -10
  52. package/test/attributeTreeSchemas.test.js +219 -0
  53. package/test/createTargetRoleHandler.test.js +59 -4
  54. package/test/crudApplicationArtifacts.test.js +20 -3
  55. package/test/customFlowApplicationArtifacts.test.js +5 -5
  56. package/test/dynamicCrudFlowSchemas.test.js +91 -4
  57. package/test/dynamicRbacFlowSchemas.test.js +15 -2
  58. package/test/publicApi.test.js +6 -6
  59. package/test/resourceArtifacts.test.js +68 -27
@@ -0,0 +1,194 @@
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 snsSharedLib from '@izara_project/izara-core-library-sns';
20
+ import { sns } from '@izara_project/izara-core-library-external-request';
21
+
22
+ //(<optionalRequire>)
23
+ //(</optionalRequire>)
24
+
25
+ /**
26
+ * Handles callback after RbacCallback phase for custom flow — verifies awaitingStep then proceeds to next flow steps
27
+ * @param {Object} _izContext - Context object with logger
28
+ * @param {Object} requestParams - Request parameters
29
+ * @param {string} flowTag - Flow tag
30
+ * @param {Object} callingFlowConfig - Calling flow configuration
31
+ * @returns {Promise<Object>}
32
+ */
33
+ export default async function <%- functionName %>(
34
+ _izContext,
35
+ requestParams,
36
+ flowTag,
37
+ callingFlowConfig = {}
38
+ ) {
39
+ try {
40
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- functionName %>] Started with params:`, {
41
+ requestParams,
42
+ flowTag,
43
+ callingFlowConfig
44
+ });
45
+
46
+ const parts = requestParams.parentFlowId.split('_');
47
+ const rbacType = parts.pop();
48
+ const rbacPendingStepId = '<%- flowTag %>RbacCallback_' + parts.join('_');
49
+ const currentAwaitingStepId = requestParams.parentFlowId;
50
+
51
+ _izContext.logger.debug(
52
+ `[${process.env.iz_serviceTag}:<%- functionName %>] Parsed RBAC pending details:`,
53
+ {
54
+ rbacType,
55
+ rbacPendingStepId,
56
+ currentAwaitingStepId,
57
+ parentFlowId: requestParams.parentFlowId
58
+ }
59
+ );
60
+
61
+ const rbacAwaitingStepsResult =
62
+ await asyncFlowSharedLib.checkAllAwaitingStepsFinishedWithReturnParams(
63
+ _izContext,
64
+ rbacPendingStepId,
65
+ currentAwaitingStepId,
66
+ requestParams.errorsFound,
67
+ {
68
+ returnValue: requestParams.returnValue,
69
+ rbacType
70
+ }
71
+ );
72
+
73
+ _izContext.logger.debug(
74
+ `[${process.env.iz_serviceTag}:<%- functionName %>] checkAllAwaitingStepsFinishedWithReturnParams result:`,
75
+ {
76
+ rbacAwaitingStepsResult
77
+ }
78
+ );
79
+
80
+ const {
81
+ isComplete,
82
+ collectedReturnValueByAwaitingStepId,
83
+ collectedErrors: errorsFound = [],
84
+ additionalAttributes
85
+ } = rbacAwaitingStepsResult;
86
+
87
+ if (isComplete === false) {
88
+ _izContext.logger.debug(
89
+ `[${process.env.iz_serviceTag}:<%- functionName %>] Awaiting steps still pending completion:`,
90
+ {
91
+ rbacPendingStepId,
92
+ isComplete
93
+ }
94
+ );
95
+
96
+ return 'all task not completed';
97
+ }
98
+
99
+ _izContext.logger.debug(
100
+ `[${process.env.iz_serviceTag}:<%- functionName %>] All awaiting steps completed — clearing awaiting steps:`,
101
+ {
102
+ rbacPendingStepId
103
+ }
104
+ );
105
+
106
+ await asyncFlowSharedLib.clearAllAwaitingSteps(
107
+ _izContext,
108
+ rbacPendingStepId
109
+ );
110
+
111
+ const originalRequestParams = additionalAttributes?.requestParams || {};
112
+
113
+ _izContext.logger.debug(
114
+ `[${process.env.iz_serviceTag}:<%- functionName %>] Retrieved originalRequestParams:`,
115
+ {
116
+ originalRequestParams
117
+ }
118
+ );
119
+
120
+ const rbacResults = Object.fromEntries(
121
+ Object.entries(collectedReturnValueByAwaitingStepId || {}).map(
122
+ ([stepId, attrs]) => {
123
+ const type = stepId.split('_').pop();
124
+ return [type, attrs];
125
+ }
126
+ )
127
+ );
128
+
129
+ const rbacCallbackResults = {};
130
+ const hasError = Object.entries(rbacResults).some(([type, result]) => {
131
+ if (result && result.error) {
132
+ errorsFound.push(result.error);
133
+ return true;
134
+ }
135
+ rbacCallbackResults[type] = result;
136
+ return false;
137
+ });
138
+
139
+ const isAllowed = Object.values(rbacCallbackResults).some(
140
+ item => item?.returnValue?.permission === true
141
+ );
142
+
143
+ if (!isAllowed) {
144
+ errorsFound.push('Permission denied');
145
+ }
146
+
147
+ _izContext.logger.debug(
148
+ `[${process.env.iz_serviceTag}:<%- functionName %>] Final rbacCallbackResults:`,
149
+ {
150
+ rbacCallbackResults,
151
+ isAllowed,
152
+ errorsFound
153
+ }
154
+ );
155
+
156
+ if (hasError || errorsFound.length > 0) {
157
+ const errorResult = {
158
+ errorsFound,
159
+ status: 'rejected',
160
+ requestParams: originalRequestParams
161
+ };
162
+
163
+ _izContext.logger.debug(
164
+ `[${process.env.iz_serviceTag}:<%- functionName %>] RBAC check failed, publishing rejected status:`,
165
+ errorResult
166
+ );
167
+
168
+ await sns.publishAsync(_izContext, {
169
+ TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
170
+ _izContext,
171
+ '<%- upperCaseFlowTag %>_Out',
172
+ process.env.iz_serviceTag
173
+ ),
174
+ Message: JSON.stringify(errorResult)
175
+ });
176
+
177
+ return errorResult;
178
+ }
179
+
180
+ //(<rbacCallbackMain>)
181
+ //(</rbacCallbackMain>)
182
+
183
+ return {
184
+ status: 'complete',
185
+ requestParams: originalRequestParams,
186
+ rbacCallbackResults
187
+ };
188
+ } catch (err) {
189
+ _izContext.logger.error(`[${process.env.iz_serviceTag}:<%- functionName %>] Error caught:`, {
190
+ error: err
191
+ });
192
+ throw err;
193
+ }
194
+ }
@@ -66,10 +66,10 @@ export default async function <%- typeof functionName !== 'undefined' ? function
66
66
  //(</additionalParams>)
67
67
  ) {
68
68
  try {
69
- _izContext.logger.debug('<%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag %> _izContext', _izContext);
70
- _izContext.logger.debug('<%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag %> requestParams', requestParams);
69
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag %>] _izContext:`, _izContext);
70
+ _izContext.logger.debug(`[${process.env.iz_serviceTag}:<%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag %>] requestParams:`, requestParams);
71
71
  _izContext.logger.debug(
72
- '<%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag %> callingFlowConfig',
72
+ `[${process.env.iz_serviceTag}:<%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag %>] callingFlowConfig:`,
73
73
  callingFlowConfig
74
74
  );
75
75
 
@@ -120,42 +120,34 @@ export default async function <%- typeof functionName !== 'undefined' ? function
120
120
 
121
121
  const resultPermissionCheck = await checkRbacPermission(
122
122
  _izContext,
123
- { flowTag: '<%- flow.flowTag %>', serviceTag: '<%- flow.serviceTag || (flow.objType ? flow.objType.serviceTag : "") %>' },
123
+ { flowTag: '<%- flow.flowTag %>', serviceTag: process.env.iz_serviceTag || '<%- flow.serviceTag || (flow.objType ? flow.objType.serviceTag : "") %>' },
124
124
  parameterGroups,
125
125
  {
126
126
  rbacObjType: {
127
- serviceTag: '<%- (flow.objType?.belongTo ? (Array.isArray(flow.objType.belongTo) ? flow.objType.belongTo[0]?.serviceTag : flow.objType.belongTo?.serviceTag) : null) || flow.serviceTag || (flow.objType ? flow.objType.serviceTag : "") %>'
127
+ serviceTag: '<%- (typeof rbacServiceTag !== "undefined" && rbacServiceTag) ? rbacServiceTag : ((flow.objType?.belongTo ? (Array.isArray(flow.objType.belongTo) ? flow.objType.belongTo[0]?.serviceTag : flow.objType.belongTo?.serviceTag) : null) || flow.serviceTag || (flow.objType ? flow.objType.serviceTag : "")) %>'
128
128
  },
129
129
  requestParams: typeof requestParams !== 'undefined' ? requestParams : {},
130
- nextFlowStepName: '<%- flow.flowTag %>RbacCallback'
130
+ nextFlowStepName: '<%- upperCaseFlowTag %>RbacCallback'
131
131
  }
132
132
  );
133
133
 
134
134
  _izContext.logger.debug(
135
- '[lib:auth:checkRbacPermission] resultPermissionCheck:',
135
+ `[${process.env.iz_serviceTag}:<%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag %>] checkRbacPermission result:`,
136
136
  resultPermissionCheck
137
137
  );
138
138
 
139
- if (resultPermissionCheck.permission === false) {
140
- //(<messageOutPutPermissionCheckFailed>)
141
- const message = {};
142
- //(</messageOutPutPermissionCheckFailed>)
143
-
144
- return await sns.publishAsync(_izContext, {
145
- Message: JSON.stringify(message),
146
- TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
147
- _izContext,
148
- '<%- flow.flowTag %>_Out'
149
- )
150
- });
151
- }
152
- <% } -%>
139
+ //(<rbacPublish_<%- flowTag %>)
140
+ //(</rbacPublish_<%- flowTag %>)
141
+
142
+ return resultPermissionCheck;
143
+ <% } else { -%>
153
144
 
154
145
  //(<endpointHook>)
155
146
  //(</endpointHook>)
147
+ <% } -%>
156
148
 
157
149
  } catch (err) {
158
- _izContext.logger.error('error WebSocketInvoke: ', err);
150
+ _izContext.logger.error(`[${process.env.iz_serviceTag}:<%- typeof functionName !== undefined ? functionName : upperCaseFlowTag %>] error:`, err);
159
151
  throw err;
160
152
  }
161
153
  }
@@ -52,7 +52,7 @@ export default async function <%= functionName %>(
52
52
  //(<hookCode>)
53
53
  //(</hookCode>)
54
54
  } catch (err) {
55
- _izContext.logger.error('error <%= functionName %>Main: ', err);
55
+ _izContext.logger.error(`[${process.env.iz_serviceTag}:<%= functionName %>] error:`, err);
56
56
  throw err;
57
57
  }
58
58
  }
@@ -6,5 +6,3 @@
6
6
  events:
7
7
  - websocket:
8
8
  route: <%= routeName %>
9
- # authorizer: \${self:custom.iz_authorizerAppLevel}
10
- # identifierResource: 'route.request.header.Auth'
@@ -2,7 +2,7 @@ import ejsLib from 'ejs';
2
2
  import { readFile } from 'node:fs/promises';
3
3
  import { rbacFlowTag } from './rbacFlowTag.js';
4
4
 
5
- const RBAC_FLOW_DEFINITIONS = [
5
+ const RBAC_CORE_FLOW_DEFINITIONS = [
6
6
  { flowTag: 'CreateTargetRole', event: ['ownTopic'] },
7
7
  { flowTag: 'ListTargetRole', event: ['lambdaSyncApi'] },
8
8
  { flowTag: 'DeleteTargetRole', event: ['ownTopic'] },
@@ -13,12 +13,33 @@ const RBAC_FLOW_DEFINITIONS = [
13
13
  { flowTag: 'ListUserInRoles', event: ['lambdaSyncApi'] },
14
14
  { flowTag: 'DeleteUserFromRole', event: ['ownTopic'] }
15
15
  ];
16
+
17
+ const LIMIT_FLOW_DEFINITIONS = [
18
+ { flowTag: 'CreateRoleLimit', event: ['ownTopic'] },
19
+ { flowTag: 'ListRoleLimits', event: ['lambdaSyncApi'] },
20
+ { flowTag: 'DeleteRoleLimit', event: ['ownTopic'] },
21
+ { flowTag: 'ReservedDynamicUsage', event: ['ownTopic'] },
22
+ { flowTag: 'ConfirmUsage', event: ['ownTopic'] },
23
+ { flowTag: 'CancelUsage', event: ['ownTopic'] }
24
+ ];
25
+
26
+ const RBAC_FLOW_DEFINITIONS = [
27
+ ...RBAC_CORE_FLOW_DEFINITIONS,
28
+ ...LIMIT_FLOW_DEFINITIONS
29
+ ];
30
+
16
31
  const TEMPLATE_URL = new URL('./templates/', import.meta.url);
17
32
 
18
- export const dynamicRbacFlowSchemaPaths = RBAC_FLOW_DEFINITIONS.map(
19
- ({ flowTag }) =>
20
- `app/src/schemas/FlowSchemas/generateCode/FlowRbac/${flowTag}.js`
21
- );
33
+ export const dynamicRbacFlowSchemaPaths = [
34
+ ...RBAC_CORE_FLOW_DEFINITIONS.map(
35
+ ({ flowTag }) =>
36
+ `app/src/schemas/FlowSchemas/generateCode/FlowRbac/${flowTag}.js`
37
+ ),
38
+ ...LIMIT_FLOW_DEFINITIONS.map(
39
+ ({ flowTag }) =>
40
+ `app/src/schemas/FlowSchemas/generateCode/FlowLimit/${flowTag}.js`
41
+ )
42
+ ];
22
43
 
23
44
  export function rbacFlowSchemaManagedPaths(objects = []) {
24
45
  if (!Array.isArray(objects)) {
@@ -78,8 +99,12 @@ function _hasRbacAddOn(object) {
78
99
  }
79
100
 
80
101
  async function _artifact(flowTag, flow) {
102
+ const isLimit = LIMIT_FLOW_DEFINITIONS.some(
103
+ (def) => def.flowTag === flowTag
104
+ );
105
+ const folder = isLimit ? 'FlowLimit' : 'FlowRbac';
81
106
  return {
82
- path: `app/src/schemas/FlowSchemas/generateCode/FlowRbac/${flowTag}.js`,
107
+ path: `app/src/schemas/FlowSchemas/generateCode/${folder}/${flowTag}.js`,
83
108
  content: ejsLib.render(
84
109
  await readFile(
85
110
  new URL('DynamicRbacFlowSchema.ejs', TEMPLATE_URL),
@@ -93,7 +118,7 @@ async function _artifact(flowTag, flow) {
93
118
  function _createSharedRbacFlow(flowTag, event) {
94
119
  return {
95
120
  flowTag,
96
- initiateBy: 'systemWithNoUser',
121
+ initiateBy: 'systemNoUser',
97
122
  statusType: 'none',
98
123
  event,
99
124
  outputTopic: true,
@@ -119,7 +144,7 @@ function _createUserRbacFlow(flowTag, serviceTag, objectType) {
119
144
  flowTag,
120
145
  objType: { serviceTag, objectType },
121
146
  event: ['ownTopic'],
122
- initiateBy: 'systemWithNoUser',
147
+ initiateBy: 'systemNoUser',
123
148
  handleObj: 'one',
124
149
  statusType: 'none',
125
150
  outputTopic: true,
@@ -10,6 +10,7 @@ import {
10
10
  import { rbacFlowTag } from './rbacFlowTag.js';
11
11
 
12
12
  const FLOW_RBAC_YAML_PATH = 'app/sls_yaml/generatedCode/source/flow-rbac.yml';
13
+ const FLOW_LIMITS_YAML_PATH = 'app/sls_yaml/generatedCode/source/flow-limits.yml';
13
14
  const CRUD_TEMPLATE_URL = new URL('../crud/templates/', import.meta.url);
14
15
  const RBAC_TEMPLATE_URL = new URL('./templates/', import.meta.url);
15
16
 
@@ -23,7 +24,8 @@ export async function emitRbacApplicationArtifacts(objects) {
23
24
  }
24
25
  const hasSelfRbac = objects.some(hasSelfRbacAddOn);
25
26
  const flowTags = [...new Set(rbacObjects.map(rbacFlowTag))];
26
- const handlers = await Promise.all([
27
+
28
+ const rbacHandlers = await Promise.all([
27
29
  ...(hasSelfRbac
28
30
  ? [
29
31
  createTargetRoleHandler(),
@@ -34,23 +36,47 @@ export async function emitRbacApplicationArtifacts(objects) {
34
36
  : []),
35
37
  ...flowTags.map(createUserRbacFlowHandler)
36
38
  ]);
37
- return [
38
- ...handlers.flatMap((handler) => handler.artifacts),
39
+
40
+ const limitHandlers = await Promise.all(
41
+ hasSelfRbac
42
+ ? [
43
+ ...LIMIT_LIST_DEFINITIONS.map(createLimitListHandler),
44
+ ...LIMIT_MUTATION_DEFINITIONS.map(createLimitMutationHandler),
45
+ ...ACCOUNT_LIMIT_HANDLERS.map(createAccountLimitHandler)
46
+ ]
47
+ : []
48
+ );
49
+
50
+ const artifacts = [
51
+ ...rbacHandlers.flatMap((handler) => handler.artifacts),
52
+ ...limitHandlers.flatMap((handler) => handler.artifacts),
39
53
  {
40
54
  path: FLOW_RBAC_YAML_PATH,
41
- content: handlers
55
+ content: rbacHandlers
42
56
  .flatMap((handler) => handler.functions)
43
57
  .map(renderFunctionYaml)
44
58
  .join('\n')
45
59
  }
46
60
  ];
61
+
62
+ if (hasSelfRbac) {
63
+ artifacts.push({
64
+ path: FLOW_LIMITS_YAML_PATH,
65
+ content: limitHandlers
66
+ .flatMap((handler) => handler.functions)
67
+ .map(renderFunctionYaml)
68
+ .join('\n')
69
+ });
70
+ }
71
+
72
+ return artifacts;
47
73
  }
48
74
 
49
75
  const LIST_DEFINITIONS = [
50
76
  {
51
77
  flowTag: 'ListTargetRole',
52
78
  tableName: 'TargetRoles',
53
- requestProperty: 'userId',
79
+ requestProperty: 'identifiersConcat',
54
80
  useContextUserId: true
55
81
  },
56
82
  {
@@ -64,6 +90,15 @@ const LIST_DEFINITIONS = [
64
90
  requestProperty: 'roleIdKey'
65
91
  }
66
92
  ];
93
+
94
+ const LIMIT_LIST_DEFINITIONS = [
95
+ {
96
+ flowTag: 'ListRoleLimits',
97
+ tableName: 'RoleLimit',
98
+ requestProperty: 'roleLimitId'
99
+ }
100
+ ];
101
+
67
102
  const MUTATION_DEFINITIONS = [
68
103
  {
69
104
  flowTag: 'CreateRolePermissions',
@@ -81,14 +116,36 @@ const MUTATION_DEFINITIONS = [
81
116
  flowTag: 'DeleteTargetRole',
82
117
  tableName: 'TargetRoles',
83
118
  method: 'deleteItem',
84
- fields: ['targetId', 'roleIdKey']
119
+ fields: ['identifiersConcat', 'roleIdKey']
85
120
  }
86
121
  ];
122
+
123
+ const LIMIT_MUTATION_DEFINITIONS = [
124
+ {
125
+ flowTag: 'CreateRoleLimit',
126
+ tableName: 'RoleLimit',
127
+ method: 'putItem',
128
+ fields: ['roleLimitId', 'limitType', 'limitValue', 'actionType']
129
+ },
130
+ {
131
+ flowTag: 'DeleteRoleLimit',
132
+ tableName: 'RoleLimit',
133
+ method: 'deleteItem',
134
+ fields: ['roleLimitId', 'limitType']
135
+ }
136
+ ];
137
+
87
138
  const USER_ROLE_MUTATIONS = [
88
139
  { flowTag: 'CreateUserRole', operation: 'Put' },
89
140
  { flowTag: 'DeleteUserFromRole', operation: 'Delete' }
90
141
  ];
91
142
 
143
+ const ACCOUNT_LIMIT_HANDLERS = [
144
+ 'ReservedDynamicUsage',
145
+ 'ConfirmUsage',
146
+ 'CancelUsage'
147
+ ];
148
+
92
149
  const STATIC_RBAC_APPLICATION_PATHS = [
93
150
  'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_Main.js',
94
151
  'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_HdrSqs.js',
@@ -118,6 +175,27 @@ const STATIC_RBAC_APPLICATION_PATHS = [
118
175
  FLOW_RBAC_YAML_PATH
119
176
  ];
120
177
 
178
+ const STATIC_LIMIT_APPLICATION_PATHS = [
179
+ ...LIMIT_LIST_DEFINITIONS.flatMap(({ flowTag }) => [
180
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_Main.js`,
181
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrSqs.js`,
182
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrApi.js`
183
+ ]),
184
+ ...LIMIT_MUTATION_DEFINITIONS.flatMap(({ flowTag }) => [
185
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_Main.js`,
186
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrSqs.js`,
187
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_WbsMain.js`,
188
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrWbs.js`
189
+ ]),
190
+ ...ACCOUNT_LIMIT_HANDLERS.flatMap((flowTag) => [
191
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_Main.js`,
192
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrSqs.js`,
193
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_WbsMain.js`,
194
+ `app/src/generatedCode/FlowLimit/${flowTag}/source/${flowTag}_HdrWbs.js`
195
+ ]),
196
+ FLOW_LIMITS_YAML_PATH
197
+ ];
198
+
121
199
  export function rbacApplicationManagedPaths(objects = []) {
122
200
  if (!Array.isArray(objects)) {
123
201
  throw new TypeError('objects must be an array');
@@ -131,7 +209,126 @@ export function rbacApplicationManagedPaths(objects = []) {
131
209
  `${sourcePath}/${flowTag}_HdrSqs.js`
132
210
  ];
133
211
  });
134
- return [...new Set([...STATIC_RBAC_APPLICATION_PATHS, ...sourcePaths])];
212
+ return [
213
+ ...new Set([
214
+ ...STATIC_RBAC_APPLICATION_PATHS,
215
+ ...STATIC_LIMIT_APPLICATION_PATHS,
216
+ ...sourcePaths
217
+ ])
218
+ ];
219
+ }
220
+
221
+ async function createAccountLimitHandler(flowTag) {
222
+ const sourcePath = `app/src/generatedCode/FlowLimit/${flowTag}/source`;
223
+ const handlerPath = `src/generatedCode/FlowLimit/${flowTag}/source`;
224
+ const webSocket = await createWebSocketEntry(
225
+ flowTag,
226
+ sourcePath,
227
+ handlerPath
228
+ );
229
+ return {
230
+ artifacts: [
231
+ {
232
+ path: `${sourcePath}/${flowTag}_Main.js`,
233
+ content: await renderRbacTemplate(`${flowTag}_Main.ejs`, { flowTag })
234
+ },
235
+ {
236
+ path: `${sourcePath}/${flowTag}_HdrSqs.js`,
237
+ content: await renderRbacTemplate('ListRbac_HdrSqs.ejs', { flowTag })
238
+ },
239
+ ...webSocket.artifacts
240
+ ],
241
+ functions: [
242
+ {
243
+ type: 'sqs',
244
+ functionName: `${flowTag}HdrSqs`,
245
+ handlerPath: `${handlerPath}/${flowTag}_HdrSqs.main`,
246
+ roleName: 'FlowRbacRole',
247
+ queueName: `${flowTag}HdrSqs`,
248
+ flowTag: flowTag,
249
+ flowStepName: ''
250
+ },
251
+ ...webSocket.functions
252
+ ]
253
+ };
254
+ }
255
+
256
+ async function createLimitListHandler(definition) {
257
+ const sourcePath = `app/src/generatedCode/FlowLimit/${definition.flowTag}/source`;
258
+ const handlerPath = `src/generatedCode/FlowLimit/${definition.flowTag}/source`;
259
+ return {
260
+ artifacts: [
261
+ {
262
+ path: `${sourcePath}/${definition.flowTag}_Main.js`,
263
+ content: await renderRbacTemplate('ListRbac_Main.ejs', {
264
+ ...definition,
265
+ useContextUserId: definition.useContextUserId ?? false
266
+ })
267
+ },
268
+ {
269
+ path: `${sourcePath}/${definition.flowTag}_HdrSqs.js`,
270
+ content: await renderRbacTemplate('ListRbac_HdrSqs.ejs', definition)
271
+ },
272
+ {
273
+ path: `${sourcePath}/${definition.flowTag}_HdrApi.js`,
274
+ content: await renderRbacTemplate('ListRbac_HdrApi.ejs', definition)
275
+ }
276
+ ],
277
+ functions: [
278
+ {
279
+ type: 'sqs',
280
+ functionName: `${definition.flowTag}HdrSqs`,
281
+ handlerPath: `${handlerPath}/${definition.flowTag}_HdrSqs.main`,
282
+ roleName: 'FlowRbacRole',
283
+ queueName: `${definition.flowTag}HdrSqs`,
284
+ flowTag: definition.flowTag,
285
+ flowStepName: ''
286
+ },
287
+ {
288
+ type: 'api',
289
+ functionName: `${definition.flowTag}HdrApi`,
290
+ handlerPath: `${handlerPath}/${definition.flowTag}_HdrApi.main`,
291
+ roleName: 'FlowRbacRole',
292
+ flowTag: definition.flowTag,
293
+ flowStepName: ''
294
+ }
295
+ ]
296
+ };
297
+ }
298
+
299
+ async function createLimitMutationHandler(definition) {
300
+ const sourcePath = `app/src/generatedCode/FlowLimit/${definition.flowTag}/source`;
301
+ const handlerPath = `src/generatedCode/FlowLimit/${definition.flowTag}/source`;
302
+ const webSocket = await createWebSocketEntry(
303
+ definition.flowTag,
304
+ sourcePath,
305
+ handlerPath
306
+ );
307
+ return {
308
+ artifacts: [
309
+ {
310
+ path: `${sourcePath}/${definition.flowTag}_Main.js`,
311
+ content: await renderRbacTemplate('RbacMutation_Main.ejs', definition)
312
+ },
313
+ {
314
+ path: `${sourcePath}/${definition.flowTag}_HdrSqs.js`,
315
+ content: await renderRbacTemplate('ListRbac_HdrSqs.ejs', definition)
316
+ },
317
+ ...webSocket.artifacts
318
+ ],
319
+ functions: [
320
+ {
321
+ type: 'sqs',
322
+ functionName: `${definition.flowTag}HdrSqs`,
323
+ handlerPath: `${handlerPath}/${definition.flowTag}_HdrSqs.main`,
324
+ roleName: 'FlowRbacRole',
325
+ queueName: `${definition.flowTag}HdrSqs`,
326
+ flowTag: definition.flowTag,
327
+ flowStepName: ''
328
+ },
329
+ ...webSocket.functions
330
+ ]
331
+ };
135
332
  }
136
333
 
137
334
  async function createTargetRoleHandler() {