@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
|
@@ -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(
|
|
70
|
-
_izContext.logger.debug(
|
|
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
|
-
|
|
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: '<%-
|
|
130
|
+
nextFlowStepName: '<%- upperCaseFlowTag %>RbacCallback'
|
|
131
131
|
}
|
|
132
132
|
);
|
|
133
133
|
|
|
134
134
|
_izContext.logger.debug(
|
|
135
|
-
'
|
|
135
|
+
`[${process.env.iz_serviceTag}:<%- typeof functionName !== 'undefined' ? functionName : upperCaseFlowTag %>] checkRbacPermission result:`,
|
|
136
136
|
resultPermissionCheck
|
|
137
137
|
);
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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(
|
|
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(
|
|
55
|
+
_izContext.logger.error(`[${process.env.iz_serviceTag}:<%= functionName %>] error:`, err);
|
|
56
56
|
throw err;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -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
|
|
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 =
|
|
19
|
-
(
|
|
20
|
-
|
|
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
|
|
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: '
|
|
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: '
|
|
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
|
-
|
|
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
|
-
|
|
38
|
-
|
|
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:
|
|
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: '
|
|
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: ['
|
|
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 [
|
|
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() {
|