@izara_project/izara-core-generate-service-code 1.0.55 → 1.0.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/codeGenerators/app/initial_setup/InitialSetupGenerator.js +223 -123
- package/src/codeGenerators/app/initial_setup/templates/InitialSetup_LambdaRole.ejs +6 -6
- package/src/codeGenerators/app/sls_yaml/FindDataYamlGenerator.js +1 -1
- package/src/codeGenerators/app/sls_yaml/FunctionYamlGenerator.js +299 -197
- package/src/codeGenerators/app/sls_yaml/RoleNameConfigGenerator.js +84 -60
- package/src/codeGenerators/app/sls_yaml/SharedResourceYamlGenerator.js +304 -271
- package/src/codeGenerators/app/sls_yaml/__tests__/SharedResourceYamlGenerator.test.js +91 -32
- package/src/codeGenerators/app/sls_yaml/templates/SharedResource_Yaml.ejs +2 -2
- package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/EndpointsGenerator.js +1 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/FlowRbac_Main.ejs +252 -0
- package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/RelationshipFlowGenerator.js +1 -1
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowClassifier.js +3 -2
- package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowMainFunctionBase.js +12 -5
- package/src/codeGenerators/app/src/generatedCode/libs/templates/Consts.ejs +23 -23
- package/src/codeGenerators/resource/sls_yaml/DynamoDBGenerator.js +1 -1
- package/src/codeGenerators/resource/sls_yaml/FlowOutGenerator.js +4 -6
- package/src/codeGenerators/resource/sls_yaml/FlowResourceYamlGenerator.js +26 -10
- package/src/codeGenerators/resource/sls_yaml/templates/SystemDynamoDB_Yaml.ejs +64 -0
- package/src/generate.js +1 -1
- package/src/generateCode.js +7 -7
- package/src/generateSchema.js +1 -1
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/FlowSchemaGenerator.js +0 -1
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/RbacFlowSchemaGenerator.js +16 -2
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/DynamicFlowSchemaTemplate.ejs +12 -12
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/DynamicRbacFlowSchemaTemplate.ejs +1 -0
- package/src/schemaGenerators/app/src/schemas/FlowSchemas/templates/UserRbacFlowSchemaTemplate.ejs +22 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/.gitkeep +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/templates/FlowEndpointBeforeLogical_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/templates/crud/CreateEndpoint_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/templates/crud/DeleteEndpoint_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/templates/crud/GetEndpoint_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowEndpoints → FlowObjects}/templates/crud/UpdateEndpoint_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessChangeRelationshipComplete_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessChangeRelationship_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessCreateRelationshipComplete_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessCreateRelationship_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessDeleteRelationshipComplete_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessDeleteRelationship_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessGetRelationshipComplete_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessGetRelationship_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessMoveRelationshipComplete_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessMoveRelationship_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessUpdateRelationshipComplete_Main.ejs +0 -0
- /package/src/codeGenerators/app/src/generatedCode/Flow/{FlowRelationshipEndpoints → FlowRelationships}/templates/relationship/ProcessUpdateRelationship_Main.ejs +0 -0
|
@@ -34,7 +34,10 @@ describe('generateSharedResourceYaml', () => {
|
|
|
34
34
|
'Resources:',
|
|
35
35
|
' AwaitingStepTable:',
|
|
36
36
|
' Properties:',
|
|
37
|
-
' TableName: ${self:custom.iz_resourcePrefix}AwaitingStep'
|
|
37
|
+
' TableName: ${self:custom.iz_resourcePrefix}AwaitingStep',
|
|
38
|
+
' WebSocketTaskTable:',
|
|
39
|
+
' Properties:',
|
|
40
|
+
' TableName: ${self:custom.iz_resourcePrefix}WebSocketTask'
|
|
38
41
|
].join('\n'),
|
|
39
42
|
'utf8'
|
|
40
43
|
);
|
|
@@ -58,7 +61,13 @@ describe('generateSharedResourceYaml', () => {
|
|
|
58
61
|
' QueueName: ${self:custom.iz_resourcePrefix}ReservationsSqsDLQ',
|
|
59
62
|
' InReservations:',
|
|
60
63
|
' Properties:',
|
|
61
|
-
' TopicName: ${self:custom.iz_serviceTag}_${self:custom.iz_stage}
|
|
64
|
+
' TopicName: ${self:custom.iz_serviceTag}_${self:custom.iz_stage}_ReservationsComplete_In',
|
|
65
|
+
' InReservationsMain:',
|
|
66
|
+
' Properties:',
|
|
67
|
+
' TopicName: ${self:custom.iz_serviceTag}_${self:custom.iz_stage}_Reservations_In',
|
|
68
|
+
' InCreateRolePermissions:',
|
|
69
|
+
' Properties:',
|
|
70
|
+
' TopicName: ${self:custom.iz_serviceTag}_${self:custom.iz_stage}_CreateRolePermissions_In'
|
|
62
71
|
].join('\n'),
|
|
63
72
|
'utf8'
|
|
64
73
|
);
|
|
@@ -92,85 +101,135 @@ describe('generateSharedResourceYaml', () => {
|
|
|
92
101
|
),
|
|
93
102
|
[
|
|
94
103
|
'ReservationsCompleteSqs:',
|
|
104
|
+
' role: WebSocketMainRole',
|
|
95
105
|
' events:',
|
|
96
106
|
' - sqs:',
|
|
97
107
|
' arn: arn:aws:sqs:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}ReservationsCompleteSqs'
|
|
98
108
|
].join('\n'),
|
|
99
109
|
'utf8'
|
|
100
110
|
);
|
|
111
|
+
|
|
112
|
+
await fs.writeFile(
|
|
113
|
+
path.join(
|
|
114
|
+
tmpDir,
|
|
115
|
+
'app',
|
|
116
|
+
'sls_yaml',
|
|
117
|
+
'generatedCode',
|
|
118
|
+
'source',
|
|
119
|
+
'role-name-config.yml'
|
|
120
|
+
),
|
|
121
|
+
[
|
|
122
|
+
'# for createIamRole',
|
|
123
|
+
'- arn:aws:iam::${self:custom.iz_accountId}:role/${self:custom.iz_resourcePrefix}FlowObjectsRole',
|
|
124
|
+
'- arn:aws:iam::${self:custom.iz_accountId}:role/${self:custom.iz_resourcePrefix}ProcFindDataRole',
|
|
125
|
+
'- arn:aws:iam::${self:custom.iz_accountId}:role/${self:custom.iz_resourcePrefix}RegisterRole',
|
|
126
|
+
'- arn:aws:iam::${self:custom.iz_accountId}:role/${self:custom.iz_resourcePrefix}ReservationsRole',
|
|
127
|
+
'- arn:aws:iam::${self:custom.iz_accountId}:role/${self:custom.iz_resourcePrefix}WebSocketMainRole'
|
|
128
|
+
].join('\n'),
|
|
129
|
+
'utf8'
|
|
130
|
+
);
|
|
101
131
|
});
|
|
102
132
|
|
|
103
|
-
it('registers
|
|
133
|
+
it('registers scoped IAM statements and avoids broad defaults', async () => {
|
|
104
134
|
await generateSharedResourceYaml(
|
|
105
135
|
{ objects: [{ objectType: 'Foo' }], flows: [] },
|
|
106
136
|
{ outputPath: tmpDir }
|
|
107
137
|
);
|
|
108
138
|
|
|
109
139
|
const grouped = policyRegistry.toGroupedByRole();
|
|
140
|
+
const resources = grouped.FlowObjectsRole.statements.flatMap(
|
|
141
|
+
statement => statement.resource
|
|
142
|
+
);
|
|
143
|
+
const actions = grouped.FlowObjectsRole.statements.flatMap(
|
|
144
|
+
statement => statement.action
|
|
145
|
+
);
|
|
146
|
+
|
|
110
147
|
expect(Object.keys(grouped).sort()).toEqual(
|
|
111
148
|
expect.arrayContaining([
|
|
112
|
-
'
|
|
149
|
+
'FlowObjectsRole',
|
|
113
150
|
'ProcFindDataRole',
|
|
114
|
-
'RegisterRole'
|
|
151
|
+
'RegisterRole',
|
|
152
|
+
'ReservationsRole',
|
|
153
|
+
'WebSocketMainRole'
|
|
115
154
|
])
|
|
116
155
|
);
|
|
117
|
-
|
|
118
|
-
const resources = grouped.PerActionEndpointRole.statements.flatMap(
|
|
119
|
-
statement => statement.resource
|
|
120
|
-
);
|
|
121
|
-
|
|
122
156
|
expect(resources).toContain(
|
|
123
157
|
'arn:aws:s3:::${self:custom.iz_serviceSchemaBucketName}/perServiceSchemas/*'
|
|
124
158
|
);
|
|
125
159
|
expect(resources).toContain(
|
|
126
160
|
'arn:aws:dynamodb:${self:custom.iz_region}:${self:custom.iz_accountId}:table/${self:custom.iz_resourcePrefix}AwaitingStep'
|
|
127
161
|
);
|
|
128
|
-
|
|
129
|
-
|
|
162
|
+
const reservationResources = grouped.ReservationsRole.statements.flatMap(
|
|
163
|
+
statement => statement.resource
|
|
130
164
|
);
|
|
131
|
-
|
|
132
|
-
|
|
165
|
+
const reservationActions = grouped.ReservationsRole.statements.flatMap(
|
|
166
|
+
statement => statement.action
|
|
133
167
|
);
|
|
134
|
-
|
|
168
|
+
|
|
169
|
+
expect(reservationResources).toContain(
|
|
135
170
|
'arn:aws:sns:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_serviceTag}_${self:custom.iz_stage}_Reservations_Out'
|
|
136
171
|
);
|
|
172
|
+
expect(reservationResources).not.toContain(
|
|
173
|
+
'arn:aws:sns:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_serviceTag}_${self:custom.iz_stage}_ReservationsComplete_In'
|
|
174
|
+
);
|
|
137
175
|
expect(resources).not.toContain(
|
|
138
|
-
'arn:aws:
|
|
176
|
+
'arn:aws:sns:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_serviceTag}_${self:custom.iz_stage}_CreateRolePermissions_In'
|
|
139
177
|
);
|
|
178
|
+
expect(reservationActions).toContain('sns:Publish');
|
|
179
|
+
expect(reservationActions).not.toContain('sns:Subscribe');
|
|
140
180
|
expect(resources).not.toContain(
|
|
141
|
-
'arn:aws:
|
|
181
|
+
'arn:aws:dynamodb:${self:custom.iz_region}:${self:custom.iz_accountId}:table/${self:custom.iz_resourcePrefix}*'
|
|
142
182
|
);
|
|
143
183
|
});
|
|
144
184
|
|
|
145
|
-
it('adds WebSocket permissions only for WebSocketMainRole
|
|
185
|
+
it('adds WebSocket permissions only for WebSocketMainRole', async () => {
|
|
146
186
|
await generateSharedResourceYaml(
|
|
147
187
|
{ flows: [{ flowTag: 'dummy', event: ['ownTopic'] }] },
|
|
148
188
|
{ outputPath: tmpDir }
|
|
149
189
|
);
|
|
150
190
|
|
|
151
191
|
const grouped = policyRegistry.toGroupedByRole();
|
|
152
|
-
expect(Object.keys(grouped)).toContain('WebSocketMainRole');
|
|
153
192
|
const wsActions = grouped.WebSocketMainRole.statements.flatMap(
|
|
154
193
|
statement => statement.action
|
|
155
194
|
);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
);
|
|
195
|
+
|
|
196
|
+
expect(wsActions).toContain('execute-api:ManageConnections');
|
|
197
|
+
expect(wsActions).not.toContain('execute-api:Invoke');
|
|
198
|
+
|
|
199
|
+
for (const [roleName, roleData] of Object.entries(grouped)) {
|
|
200
|
+
if (roleName === 'WebSocketMainRole') continue;
|
|
201
|
+
const actions = roleData.statements.flatMap(statement => statement.action);
|
|
202
|
+
expect(actions).not.toContain('execute-api:ManageConnections');
|
|
203
|
+
expect(actions).not.toContain('execute-api:Invoke');
|
|
204
|
+
}
|
|
159
205
|
});
|
|
160
206
|
|
|
161
|
-
it('
|
|
207
|
+
it('only emits roles present in role-name-config', async () => {
|
|
208
|
+
policyRegistry.add(
|
|
209
|
+
'UnexpectedRole',
|
|
210
|
+
'sns:Publish',
|
|
211
|
+
'arn:aws:sns:${self:custom.iz_region}:${self:custom.iz_accountId}:unexpected'
|
|
212
|
+
);
|
|
213
|
+
|
|
162
214
|
await generateSharedResourceYaml(
|
|
163
|
-
{
|
|
215
|
+
{ objects: [{ objectType: 'Foo' }], flows: [] },
|
|
164
216
|
{ outputPath: tmpDir }
|
|
165
217
|
);
|
|
166
218
|
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
219
|
+
const content = await fs.readFile(
|
|
220
|
+
path.join(
|
|
221
|
+
tmpDir,
|
|
222
|
+
'app',
|
|
223
|
+
'sls_yaml',
|
|
224
|
+
'generatedCode',
|
|
225
|
+
'source',
|
|
226
|
+
'generate-shared-resource.yml'
|
|
227
|
+
),
|
|
228
|
+
'utf8'
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
expect(content).toContain('FlowObjectsRole:');
|
|
232
|
+
expect(content).toContain('WebSocketMainRole:');
|
|
233
|
+
expect(content).not.toContain('UnexpectedRole:');
|
|
175
234
|
});
|
|
176
235
|
});
|
|
@@ -40,7 +40,7 @@ export async function generateEndpointsFlow(allSchemas, options) {
|
|
|
40
40
|
for (const action of CRUD_ACTIONS) {
|
|
41
41
|
const isAsync = CRUD_ASYNC_ACTIONS.includes(action);
|
|
42
42
|
const upperAction = upperFirst(action);
|
|
43
|
-
const flowOutputDir = path.join(baseOutputDir, '
|
|
43
|
+
const flowOutputDir = path.join(baseOutputDir, 'FlowObjects', upperAction, 'source');
|
|
44
44
|
await fs.mkdir(flowOutputDir, { recursive: true });
|
|
45
45
|
|
|
46
46
|
const mainFileName = processMainFileName(action);
|
package/src/codeGenerators/app/src/generatedCode/Flow/FlowRbac/templates/rbac/FlowRbac_Main.ejs
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2020 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
|
|
16
|
+
<http: //www.gnu.org/licenses />.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
20
|
+
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
21
|
+
import sqsSharedLib from '@izara_project/izara-core-library-sqs';
|
|
22
|
+
import asyncFlowSharedLib from '@izara_project/izara-core-library-asynchronous-flow';
|
|
23
|
+
import callingFlowSharedLib from '@izara_project/izara-core-library-calling-flow';
|
|
24
|
+
import lambdaSharedLib from '@izara_project/izara-core-library-lambda';
|
|
25
|
+
|
|
26
|
+
//(<optionalImport>)
|
|
27
|
+
import { coreConsts } from '@izara_project/izara-core-library-core';
|
|
28
|
+
import { getObjectSchema } from '@izara_project/izara-core-library-service-schemas';
|
|
29
|
+
import {
|
|
30
|
+
lambda,
|
|
31
|
+
sns,
|
|
32
|
+
sqs
|
|
33
|
+
} from '@izara_project/izara-core-library-external-request';
|
|
34
|
+
import { NoRetryError } from '@izara_project/izara-core-library-core';
|
|
35
|
+
import { utils } from '@izara_project/izara-core-library-service-schemas';
|
|
36
|
+
|
|
37
|
+
const { createFlowTypeConcat } = utils;
|
|
38
|
+
//(</optionalImport>)
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
*
|
|
43
|
+
* description of function.
|
|
44
|
+
* @param {Object} _izContext
|
|
45
|
+
* @param {CorrelationIds} _izContext.correlationIds - property of _izContext
|
|
46
|
+
* @param {Logger} _izContext.logger - property of _izContext
|
|
47
|
+
* @param {Object} requestParams - request params
|
|
48
|
+
* @param {Object} requestParams.identifiers - identifiers for get data
|
|
49
|
+
* @param {Object} requestParams.additionalRequest - additionalRequest
|
|
50
|
+
*
|
|
51
|
+
*
|
|
52
|
+
* @returns {object} description of return value
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
export default async function ProcessUserRbacFlow(
|
|
56
|
+
_izContext,
|
|
57
|
+
requestParams,
|
|
58
|
+
callingFlowConfig = {}
|
|
59
|
+
//(<additionalParams>)
|
|
60
|
+
//(</additionalParams>)
|
|
61
|
+
) {
|
|
62
|
+
try {
|
|
63
|
+
_izContext.logger.debug('ProcessUserRbacFlow _izContext', _izContext);
|
|
64
|
+
_izContext.logger.debug('ProcessUserRbacFlow requestParams', requestParams);
|
|
65
|
+
_izContext.logger.debug(
|
|
66
|
+
'ProcessUserRbacFlow callingFlowConfig',
|
|
67
|
+
callingFlowConfig
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const userId = _izContext.correlationIds.get(coreConsts.BASE_USER_ID);
|
|
71
|
+
const targetId = _izContext.correlationIds.get(coreConsts.TARGET_ID);
|
|
72
|
+
|
|
73
|
+
if (!userId && !targetId) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
'Missing required request parameters: userId or targetId'
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const { flowTypeConcat, inputParameterGroups } = requestParams;
|
|
80
|
+
if (!flowTypeConcat) {
|
|
81
|
+
throw new Error('Missing flowTypeConcat in requestParams');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_izContext.logger.debug('userId', userId);
|
|
85
|
+
_izContext.logger.debug('targetId', targetId);
|
|
86
|
+
_izContext.logger.debug('flowTypeConcat', flowTypeConcat);
|
|
87
|
+
|
|
88
|
+
const tableUserRoles = dynamodbSharedLib.tableName(_izContext, 'UserRoles');
|
|
89
|
+
|
|
90
|
+
const resultUserRoles = await dynamodbSharedLib.query(
|
|
91
|
+
_izContext,
|
|
92
|
+
tableUserRoles,
|
|
93
|
+
{
|
|
94
|
+
userId
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
if (!resultUserRoles.Items) {
|
|
99
|
+
resultUserRoles.Items = [];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let targetUserRoles = resultUserRoles.Items;
|
|
103
|
+
|
|
104
|
+
targetUserRoles = targetUserRoles.filter(
|
|
105
|
+
r => r.roleIdKey && r.roleIdKey.startsWith(targetId + '_')
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
const tableRolePermission = dynamodbSharedLib.tableName(
|
|
109
|
+
_izContext,
|
|
110
|
+
'RolePermissions'
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const chunkSize = 10;
|
|
114
|
+
const rbacRolePermissions = [];
|
|
115
|
+
|
|
116
|
+
for (let i = 0; i < targetUserRoles.length; i += chunkSize) {
|
|
117
|
+
const chunk = targetUserRoles.slice(i, i + chunkSize);
|
|
118
|
+
const promises = chunk.map(userRole =>
|
|
119
|
+
dynamodbSharedLib
|
|
120
|
+
.getItem(_izContext, tableRolePermission, {
|
|
121
|
+
roleIdKey: userRole.roleIdKey,
|
|
122
|
+
flowTypeConcat: flowTypeConcat
|
|
123
|
+
})
|
|
124
|
+
.catch(err => {
|
|
125
|
+
_izContext.logger.error(
|
|
126
|
+
`Error fetching permission for role ${userRole.roleIdKey}:`,
|
|
127
|
+
err
|
|
128
|
+
);
|
|
129
|
+
return null;
|
|
130
|
+
})
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
const results = await Promise.all(promises);
|
|
134
|
+
rbacRolePermissions.push(...results);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let isPermission = false;
|
|
138
|
+
let roleIdKey = '';
|
|
139
|
+
|
|
140
|
+
for (let i = 0; i < rbacRolePermissions.length; i++) {
|
|
141
|
+
const rbacRolePermission = rbacRolePermissions[i];
|
|
142
|
+
const userRole = targetUserRoles[i];
|
|
143
|
+
|
|
144
|
+
if (rbacRolePermission && rbacRolePermission.permission === true) {
|
|
145
|
+
const dbParameterGroups = rbacRolePermission.parameterGroups;
|
|
146
|
+
let isParamValid = true;
|
|
147
|
+
|
|
148
|
+
if (
|
|
149
|
+
dbParameterGroups &&
|
|
150
|
+
typeof dbParameterGroups === 'object' &&
|
|
151
|
+
!Array.isArray(dbParameterGroups)
|
|
152
|
+
) {
|
|
153
|
+
const entries = Object.entries(dbParameterGroups);
|
|
154
|
+
if (entries.length > 0) {
|
|
155
|
+
let any_parameterGroup_match = false;
|
|
156
|
+
|
|
157
|
+
for (const [groupName, parameterGroup] of entries) {
|
|
158
|
+
if (!Array.isArray(parameterGroup)) {
|
|
159
|
+
_izContext.logger.debug(
|
|
160
|
+
`Skipping non-array parameterGroup: ${groupName}`
|
|
161
|
+
);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
_izContext.logger.debug(
|
|
166
|
+
`Checking parameterGroup [${groupName}]:`,
|
|
167
|
+
parameterGroup
|
|
168
|
+
);
|
|
169
|
+
let parameterGroupMatch = true;
|
|
170
|
+
|
|
171
|
+
for (const check_parameter of parameterGroup) {
|
|
172
|
+
let tempRequestParams = inputParameterGroups || {};
|
|
173
|
+
|
|
174
|
+
if (
|
|
175
|
+
!check_parameter.parameterNames ||
|
|
176
|
+
!Array.isArray(check_parameter.parameterNames)
|
|
177
|
+
) {
|
|
178
|
+
parameterGroupMatch = false;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
for (const parameterName of check_parameter.parameterNames) {
|
|
183
|
+
if (
|
|
184
|
+
!tempRequestParams ||
|
|
185
|
+
typeof tempRequestParams !== 'object' ||
|
|
186
|
+
!(parameterName in tempRequestParams)
|
|
187
|
+
) {
|
|
188
|
+
parameterGroupMatch = false;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
tempRequestParams = tempRequestParams[parameterName];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!parameterGroupMatch) break;
|
|
195
|
+
|
|
196
|
+
if (
|
|
197
|
+
!check_parameter.parameterValues ||
|
|
198
|
+
!Array.isArray(check_parameter.parameterValues)
|
|
199
|
+
) {
|
|
200
|
+
parameterGroupMatch = false;
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const valueMatched =
|
|
205
|
+
check_parameter.parameterValues.includes(tempRequestParams);
|
|
206
|
+
|
|
207
|
+
if (!valueMatched) {
|
|
208
|
+
parameterGroupMatch = false;
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (parameterGroupMatch) {
|
|
214
|
+
_izContext.logger.debug(
|
|
215
|
+
`✅ parameterGroup [${groupName}] matched`
|
|
216
|
+
);
|
|
217
|
+
any_parameterGroup_match = true;
|
|
218
|
+
break;
|
|
219
|
+
} else {
|
|
220
|
+
_izContext.logger.debug(
|
|
221
|
+
`❌ parameterGroup [${groupName}] did not match`
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
isParamValid = any_parameterGroup_match;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (isParamValid) {
|
|
231
|
+
isPermission = true;
|
|
232
|
+
roleIdKey = rbacRolePermission.roleIdKey;
|
|
233
|
+
_izContext.logger.debug(
|
|
234
|
+
'### matched rbacRolePermission ###',
|
|
235
|
+
rbacRolePermission
|
|
236
|
+
);
|
|
237
|
+
break;
|
|
238
|
+
} else {
|
|
239
|
+
_izContext.logger.debug(
|
|
240
|
+
'### rbacRolePermission parameterGroups check failed ###',
|
|
241
|
+
{ roleIdKey: userRole.roleIdKey }
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return { permission: isPermission, roleIdKey };
|
|
248
|
+
} catch (err) {
|
|
249
|
+
_izContext.logger.error('error ProcessUserRbacFlow: ', err);
|
|
250
|
+
throw err;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -37,7 +37,7 @@ export async function generateRelationshipFlows(allSchemas, options) {
|
|
|
37
37
|
const upperFlowTag = upperFirst(flowTag);
|
|
38
38
|
const processFunction = processFunctionName(flowTag);
|
|
39
39
|
|
|
40
|
-
const flowOutputDir = path.join(baseOutputDir, '
|
|
40
|
+
const flowOutputDir = path.join(baseOutputDir, 'FlowRelationships', upperFlowTag, 'source');
|
|
41
41
|
await fs.mkdir(flowOutputDir, { recursive: true });
|
|
42
42
|
|
|
43
43
|
// 1. Generate Action Step (In) Main Function
|
|
@@ -42,8 +42,9 @@ export function isRelationshipFlow(flowTag) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export function getFlowOutputSubDir(flowTag) {
|
|
45
|
-
if (isCrudFlow(flowTag)) return '
|
|
45
|
+
if (isCrudFlow(flowTag)) return 'FlowObjects';
|
|
46
46
|
if (isRbacFlow(flowTag)) return 'FlowRbac';
|
|
47
|
-
if (isRelationshipFlow(flowTag)) return '
|
|
47
|
+
if (isRelationshipFlow(flowTag)) return 'FlowRelationships';
|
|
48
|
+
if (String(flowTag || '').toLowerCase().endsWith('rbacflow')) return 'FlowRbac';
|
|
48
49
|
return 'FlowSchemas';
|
|
49
50
|
}
|
package/src/codeGenerators/app/src/generatedCode/Flow/_shared/shared/flowMainFunctionBase.js
CHANGED
|
@@ -53,16 +53,23 @@ export async function generateFlowMainFunction(allSchemas, options) {
|
|
|
53
53
|
let templateName = 'FlowEndpoint_Main.ejs';
|
|
54
54
|
if (['Create', 'Update', 'Delete', 'Get'].includes(flowTag)) {
|
|
55
55
|
templateName = `${flowTag}Endpoint_Main.ejs`;
|
|
56
|
+
} else if (String(flowTag || '').toLowerCase().endsWith('rbacflow')) {
|
|
57
|
+
templateName = 'FlowRbac_Main.ejs';
|
|
56
58
|
} else if (isOwnTopic) {
|
|
57
59
|
// Non-CRUD flow with ownTopic: WebSocket entry that fetches flowSchema and publishes to SNS In topic
|
|
58
60
|
templateName = 'FlowMain_Wbs.ejs';
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
// crud templates live under
|
|
63
|
+
// crud templates live under FlowObjects (the only output child that uses them);
|
|
62
64
|
// shared endpoint templates (FlowEndpoint_Main, FlowMain_Wbs) live under _internal/_shared/endpoint
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
let templateBaseDir;
|
|
66
|
+
if (templateName === 'FlowRbac_Main.ejs') {
|
|
67
|
+
templateBaseDir = path.join(__dirname, '..', '..', 'FlowRbac', 'templates', 'rbac');
|
|
68
|
+
} else if (templateName.startsWith('crud/') || ['CreateEndpoint_Main.ejs', 'UpdateEndpoint_Main.ejs', 'DeleteEndpoint_Main.ejs', 'GetEndpoint_Main.ejs'].includes(templateName)) {
|
|
69
|
+
templateBaseDir = path.join(__dirname, '..', '..', 'FlowObjects', 'templates', 'crud');
|
|
70
|
+
} else {
|
|
71
|
+
templateBaseDir = path.join(__dirname, '..', '..', 'FlowSchemas', 'templates', 'endpoint');
|
|
72
|
+
}
|
|
66
73
|
const mainTemplateStr = await fs.readFile(
|
|
67
74
|
path.join(templateBaseDir, templateName),
|
|
68
75
|
'utf-8'
|
|
@@ -130,7 +137,7 @@ export async function generateFlowMainFunction(allSchemas, options) {
|
|
|
130
137
|
const beforeLogicalConfigs = generateCode.filter(c => c.codeHookTag === 'beforeLogical');
|
|
131
138
|
if (isCrud && beforeLogicalConfigs.length > 0) {
|
|
132
139
|
const beforeLogicalTemplateStr = await fs.readFile(
|
|
133
|
-
path.join(__dirname, '..', '..', '
|
|
140
|
+
path.join(__dirname, '..', '..', 'FlowObjects', 'templates', 'FlowEndpointBeforeLogical_Main.ejs'),
|
|
134
141
|
'utf-8'
|
|
135
142
|
);
|
|
136
143
|
|
|
@@ -166,12 +166,12 @@ const FUNCTION_NAME = {
|
|
|
166
166
|
outTranslateIds: 'processTranslateIdsComplete',
|
|
167
167
|
findData: 'findData',
|
|
168
168
|
processLogical: 'processLogical',
|
|
169
|
-
updateNodeComplete: '
|
|
170
|
-
createObjectComplete: '
|
|
171
|
-
getNodeComplete: '
|
|
169
|
+
updateNodeComplete: 'updateComplete',
|
|
170
|
+
createObjectComplete: 'createComplete',
|
|
171
|
+
getNodeComplete: 'getComplete',
|
|
172
172
|
paginateProcessLogical: 'paginateProcessLogical',
|
|
173
173
|
deleteNode: 'deleteNode',
|
|
174
|
-
deleteNodeComplete: '
|
|
174
|
+
deleteNodeComplete: 'deleteComplete',
|
|
175
175
|
createObjectS3: 'createObjectS3',
|
|
176
176
|
createObjectS3Complete: 'webSocketTaskComplete',
|
|
177
177
|
processAfterUploadS3: 'processAfterUploadS3',
|
|
@@ -203,12 +203,12 @@ const SHORT_FUNCTION_NAME = functionName => {
|
|
|
203
203
|
[FUNCTION_NAME.deleteRelComplete]: 'deleteRelComp',
|
|
204
204
|
[FUNCTION_NAME.findData]: 'findData',
|
|
205
205
|
[FUNCTION_NAME.processLogical]: 'processLogical',
|
|
206
|
-
[FUNCTION_NAME.updateNodeComplete]: '
|
|
207
|
-
[FUNCTION_NAME.createObjectComplete]: '
|
|
208
|
-
[FUNCTION_NAME.getNodeComplete]: '
|
|
206
|
+
[FUNCTION_NAME.updateNodeComplete]: 'updateComp',
|
|
207
|
+
[FUNCTION_NAME.createObjectComplete]: 'createComp',
|
|
208
|
+
[FUNCTION_NAME.getNodeComplete]: 'getComp',
|
|
209
209
|
[FUNCTION_NAME.paginateProcessLogical]: 'paginateProLogical',
|
|
210
210
|
[FUNCTION_NAME.deleteNode]: 'deleteNode',
|
|
211
|
-
[FUNCTION_NAME.deleteNodeComplete]: '
|
|
211
|
+
[FUNCTION_NAME.deleteNodeComplete]: 'deleteComp',
|
|
212
212
|
[FUNCTION_NAME.createObjectS3Complete]: 'webSocketTaskComp',
|
|
213
213
|
[FUNCTION_NAME.getRel]: 'getRel',
|
|
214
214
|
[FUNCTION_NAME.getRelComplete]: 'getRelComp',
|
|
@@ -238,7 +238,7 @@ const SOURCE_GENERATE_IAM_ROLE = {
|
|
|
238
238
|
ProcessFindDataRole: 'ProcFindData',
|
|
239
239
|
ObjectCompleteRole: 'ObjectCom',
|
|
240
240
|
NodeCompleteRole: 'NodeCom',
|
|
241
|
-
|
|
241
|
+
FlowRelationshipRole: 'Relationship',
|
|
242
242
|
RelationshipCompleteRole: 'RelationshipCom',
|
|
243
243
|
FlowSchemaUploadS3Role: 'FlowSchemaUploadS3',
|
|
244
244
|
FlowSchemaOwnTopic: 'FlowSchemaOwnTopic',
|
|
@@ -320,27 +320,27 @@ const TOPIC_NAME_GENERATE_CODE = {
|
|
|
320
320
|
createRelComplete: 'CreateRelationshipComplete',
|
|
321
321
|
deleteRelComplete: 'DeleteRelationshipComplete',
|
|
322
322
|
getRelComplete: 'GetRelationshipComplete',
|
|
323
|
-
outUpdateRelComplete: '
|
|
324
|
-
outCreateRelComplete: '
|
|
325
|
-
outDeleteRelComplete: '
|
|
326
|
-
outGetRelComplete: '
|
|
327
|
-
updateNodeComplete: '
|
|
328
|
-
outUpdateNodeComplete: '
|
|
329
|
-
createNodeComplete: '
|
|
330
|
-
outCreateNodeComplete: '
|
|
331
|
-
deleteNodeComplete: '
|
|
332
|
-
outDeleteNodeComplete: '
|
|
333
|
-
getNodeComplete: '
|
|
334
|
-
outGetNodeComplete: '
|
|
323
|
+
outUpdateRelComplete: 'UpdateRelationship_Out',
|
|
324
|
+
outCreateRelComplete: 'CreateRelationship_Out',
|
|
325
|
+
outDeleteRelComplete: 'DeleteRelationship_Out',
|
|
326
|
+
outGetRelComplete: 'GetRelationship_Out',
|
|
327
|
+
updateNodeComplete: 'UpdateComplete',
|
|
328
|
+
outUpdateNodeComplete: 'Update_Out',
|
|
329
|
+
createNodeComplete: 'CreateComplete',
|
|
330
|
+
outCreateNodeComplete: 'Create_Out',
|
|
331
|
+
deleteNodeComplete: 'DeleteComplete',
|
|
332
|
+
outDeleteNodeComplete: 'Delete_Out',
|
|
333
|
+
getNodeComplete: 'GetComplete',
|
|
334
|
+
outGetNodeComplete: 'Get_Out',
|
|
335
335
|
reservedLimitComplete: 'ReservedLimitComplete',
|
|
336
336
|
createPreSignUrl: 'CreatePreSignUrl',
|
|
337
337
|
flowSchemaOwnTopicComplete: 'FlowSchemaOwnTopicComplete',
|
|
338
338
|
flowSchemaOwnTopicEndpointComplete: 'FlowSchemaOwnTopicEndpointComplete',
|
|
339
339
|
createRecordComplete: 'CreateRecordComplete',
|
|
340
340
|
changeRelationshipComplete: 'ChangeRelationshipComplete',
|
|
341
|
-
outChangeRelationshipComplete: '
|
|
341
|
+
outChangeRelationshipComplete: 'ChangeRelationship_Out',
|
|
342
342
|
moveRelationshipComplete: 'MoveRelationshipComplete',
|
|
343
|
-
outMoveRelationshipComplete: '
|
|
343
|
+
outMoveRelationshipComplete: 'MoveRelationship_Out'
|
|
344
344
|
};
|
|
345
345
|
|
|
346
346
|
const GRAPH_HANDLER_SERVICE_NAME = {
|
|
@@ -80,7 +80,7 @@ export async function generateDynamoDBTables(allSchemas, options) {
|
|
|
80
80
|
const systemYamlTpl = await fs.readFile(systemYamlTplPath, 'utf-8');
|
|
81
81
|
const systemYamlContent = ejs.render(systemYamlTpl, {});
|
|
82
82
|
await fs.writeFile(yamlOutputPath, `${systemYamlContent}\n`, 'utf-8');
|
|
83
|
-
generatedCount +=
|
|
83
|
+
generatedCount += 12; // 12 system tables
|
|
84
84
|
|
|
85
85
|
for (const [tableName, keys] of tables.entries()) {
|
|
86
86
|
const yamlContent = ejs.render(yamlTpl, {
|
|
@@ -28,7 +28,7 @@ export async function generateFlowOut(allSchemas, options) {
|
|
|
28
28
|
|
|
29
29
|
let generatedCount = 0;
|
|
30
30
|
const yamlOutputPath = path.join(resourceYamlDir, 'generated-sns-out.yml');
|
|
31
|
-
await fs.writeFile(yamlOutputPath, '', 'utf-8');
|
|
31
|
+
await fs.writeFile(yamlOutputPath, 'Resources:\n', 'utf-8'); // ponytail: simplest one-line fix
|
|
32
32
|
|
|
33
33
|
const generatedTopics = new Set();
|
|
34
34
|
|
|
@@ -48,11 +48,9 @@ export async function generateFlowOut(allSchemas, options) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
const systemTopics = [
|
|
51
|
-
'
|
|
52
|
-
'
|
|
53
|
-
'
|
|
54
|
-
'ProcessLogicalComplete',
|
|
55
|
-
'FindDataComplete',
|
|
51
|
+
'ProcessLogical',
|
|
52
|
+
'PaginateProcessLogical',
|
|
53
|
+
'FindData',
|
|
56
54
|
'Create',
|
|
57
55
|
'Update',
|
|
58
56
|
'Delete',
|