@izara_project/izara-core-generate-service-code 1.0.85 → 1.0.87
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/compile/compileProject.js +1 -2
- package/src/compile/loadSchemas.js +29 -17
- package/src/emit/coreFunction/emitCoreFunctionArtifacts.js +2 -1
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +32 -14
- package/src/emit/crud/crudActionPlan.js +1 -1
- package/src/emit/crud/emitCrudApplicationArtifacts.js +10 -4
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +16 -8
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +12 -3
- package/src/emit/crud/templates/CreateLogicalLib.ejs +85 -20
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +48 -7
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +47 -6
- package/src/emit/crud/templates/UpdateLogicalLib.ejs +754 -353
- package/src/emit/function/functionYamlArtifact.js +4 -2
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +5 -5
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +70 -89
- package/src/emit/rbac/templates/CancelUsage_Main.ejs +14 -10
- package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +14 -10
- package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +56 -16
- package/src/emit/rbac/templates/DeleteTargetRole_Main.ejs +96 -0
- package/src/emit/rbac/templates/GetMyPermissions_Main.ejs +110 -0
- package/src/emit/rbac/templates/GetTargetRole_Main.ejs +62 -0
- package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +76 -34
- package/src/emit/rbac/templates/UpdateTargetRole_Main.ejs +107 -0
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +24 -21
- package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +12 -0
- package/src/emit/resource/emitResourceArtifacts.js +75 -8
- package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +4 -2
- package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +14 -18
- package/src/emit/system/templates/WebSocketComplete_Yaml.ejs +4 -2
- package/src/emit/systemText/emitSystemTextSchemas.js +5 -2
- package/src/generate.js +18 -12
- package/src/generateResources/IntTest/generateResources/generateResources.js +1 -1
- package/src/generateResources/IntTest/generateTests/generateTemplate.js +1 -1
- package/src/generateResources/IntTest/upload/uploadIntTest.js +8 -2
- package/test/createTargetRoleHandler.test.js +42 -15
- package/test/crudApplicationArtifacts.test.js +62 -3
- package/test/customFlowApplicationArtifacts.test.js +3 -5
- package/test/dynamicCrudFlowSchemas.test.js +5 -17
- package/test/dynamicRbacFlowSchemas.test.js +5 -5
- package/test/functionYamlArtifact.test.js +4 -2
- package/test/publicApi.test.js +18 -14
- package/test/resourceArtifacts.test.js +7 -3
|
@@ -138,6 +138,18 @@ Resources:
|
|
|
138
138
|
KeyType: RANGE
|
|
139
139
|
|
|
140
140
|
<% if (hasRbac) { %>
|
|
141
|
+
RolesTable:
|
|
142
|
+
Type: 'AWS::DynamoDB::Table'
|
|
143
|
+
Properties:
|
|
144
|
+
TableName: ${self:custom.iz_resourcePrefix}Roles
|
|
145
|
+
BillingMode: PAY_PER_REQUEST
|
|
146
|
+
AttributeDefinitions:
|
|
147
|
+
- AttributeName: roleIdKey
|
|
148
|
+
AttributeType: S
|
|
149
|
+
KeySchema:
|
|
150
|
+
- AttributeName: roleIdKey
|
|
151
|
+
KeyType: HASH
|
|
152
|
+
|
|
141
153
|
TargetRolesTable:
|
|
142
154
|
Type: 'AWS::DynamoDB::Table'
|
|
143
155
|
Properties:
|
|
@@ -221,22 +233,6 @@ Resources:
|
|
|
221
233
|
AttributeName: ttlTimestamp
|
|
222
234
|
Enabled: true
|
|
223
235
|
|
|
224
|
-
RoleLimitTable:
|
|
225
|
-
Type: 'AWS::DynamoDB::Table'
|
|
226
|
-
Properties:
|
|
227
|
-
TableName: ${self:custom.iz_resourcePrefix}RoleLimit
|
|
228
|
-
BillingMode: PAY_PER_REQUEST
|
|
229
|
-
AttributeDefinitions:
|
|
230
|
-
- AttributeName: roleLimitId
|
|
231
|
-
AttributeType: S
|
|
232
|
-
- AttributeName: limitType
|
|
233
|
-
AttributeType: S
|
|
234
|
-
KeySchema:
|
|
235
|
-
- AttributeName: roleLimitId
|
|
236
|
-
KeyType: HASH
|
|
237
|
-
- AttributeName: limitType
|
|
238
|
-
KeyType: RANGE
|
|
239
|
-
|
|
240
236
|
RunningTotalUsageTable:
|
|
241
237
|
Type: 'AWS::DynamoDB::Table'
|
|
242
238
|
Properties:
|
|
@@ -245,12 +241,12 @@ Resources:
|
|
|
245
241
|
AttributeDefinitions:
|
|
246
242
|
- AttributeName: identifiersConcat
|
|
247
243
|
AttributeType: S
|
|
248
|
-
- AttributeName:
|
|
244
|
+
- AttributeName: flowTypeConcat
|
|
249
245
|
AttributeType: S
|
|
250
246
|
KeySchema:
|
|
251
247
|
- AttributeName: identifiersConcat
|
|
252
248
|
KeyType: HASH
|
|
253
|
-
- AttributeName:
|
|
249
|
+
- AttributeName: flowTypeConcat
|
|
254
250
|
KeyType: RANGE
|
|
255
251
|
|
|
256
252
|
RunningTotalReservedUsageTable:
|
|
@@ -17,14 +17,17 @@ const RELATIONSHIP_ACTIONS = [
|
|
|
17
17
|
];
|
|
18
18
|
const RBAC_SHARED_FLOW_TAGS = [
|
|
19
19
|
'CreateTargetRole',
|
|
20
|
-
'
|
|
20
|
+
'UpdateTargetRole',
|
|
21
21
|
'DeleteTargetRole',
|
|
22
|
+
'GetTargetRole',
|
|
23
|
+
'ListTargetRole',
|
|
22
24
|
'CreateRolePermissions',
|
|
23
25
|
'ListRolePermissions',
|
|
24
26
|
'DeleteRolePermissions',
|
|
25
27
|
'CreateUserRole',
|
|
26
28
|
'ListUserInRoles',
|
|
27
|
-
'DeleteUserFromRole'
|
|
29
|
+
'DeleteUserFromRole',
|
|
30
|
+
'GetMyPermissions'
|
|
28
31
|
];
|
|
29
32
|
|
|
30
33
|
export function systemTextSchemaManagedPaths() {
|
package/src/generate.js
CHANGED
|
@@ -64,12 +64,10 @@ import {
|
|
|
64
64
|
|
|
65
65
|
export async function generate(rootPath, options = {}) {
|
|
66
66
|
const startedAt = Date.now();
|
|
67
|
-
|
|
68
|
-
logger?.info?.(`[INFO] [Generate] STATUS=STARTED | rootPath=${rootPath}`);
|
|
67
|
+
console.log(`[INFO] [Generate] STATUS=STARTED | rootPath=${rootPath}`);
|
|
69
68
|
try {
|
|
70
69
|
const project = compileProject({ ...options, rootPath });
|
|
71
70
|
const schemaLoadOptions = {
|
|
72
|
-
logger,
|
|
73
71
|
skipValidation: options.skipValidation
|
|
74
72
|
};
|
|
75
73
|
const [rawObjects, relationships, flows, notifications] = await Promise.all([
|
|
@@ -92,8 +90,10 @@ export async function generate(rootPath, options = {}) {
|
|
|
92
90
|
relationships,
|
|
93
91
|
schemaBucketName
|
|
94
92
|
);
|
|
95
|
-
|
|
96
|
-
`[DEBUG] [Generate] STATUS=SCHEMAS_LOADED |
|
|
93
|
+
console.log(
|
|
94
|
+
`[DEBUG] [Generate] STATUS=SCHEMAS_LOADED | ` +
|
|
95
|
+
`objects=${objects.length} ` +
|
|
96
|
+
`relationships=${relationships.length} flows=${flows.length}`
|
|
97
97
|
);
|
|
98
98
|
const groups = await _emitGroups({
|
|
99
99
|
project,
|
|
@@ -103,10 +103,14 @@ export async function generate(rootPath, options = {}) {
|
|
|
103
103
|
notifications,
|
|
104
104
|
objectGraphServiceTags,
|
|
105
105
|
relationshipGraphServiceTags,
|
|
106
|
-
logger
|
|
106
|
+
logger: options.logger
|
|
107
|
+
});
|
|
108
|
+
const scopeCounts = groups.map((group) => {
|
|
109
|
+
return `${group.scope}=${group.artifacts.length}`;
|
|
107
110
|
});
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
const emittedScopeSummary = scopeCounts.join(' ');
|
|
112
|
+
console.log(
|
|
113
|
+
`[DEBUG] [Generate] STATUS=ARTIFACTS_EMITTED | ${emittedScopeSummary}`
|
|
110
114
|
);
|
|
111
115
|
let files = [];
|
|
112
116
|
if (groups.length > 0) {
|
|
@@ -123,14 +127,16 @@ export async function generate(rootPath, options = {}) {
|
|
|
123
127
|
);
|
|
124
128
|
}
|
|
125
129
|
const durationMs = Date.now() - startedAt;
|
|
126
|
-
|
|
127
|
-
`[INFO] [Generate] STATUS=FINISHED |
|
|
130
|
+
console.log(
|
|
131
|
+
`[INFO] [Generate] STATUS=FINISHED | ` +
|
|
132
|
+
`files=${files.length} durationMs=${durationMs}`
|
|
128
133
|
);
|
|
129
134
|
|
|
130
135
|
return { project, durationMs, files };
|
|
131
136
|
} catch (error) {
|
|
132
|
-
|
|
133
|
-
`[ERROR] [Generate] STATUS=FAILED |
|
|
137
|
+
console.log(
|
|
138
|
+
`[ERROR] [Generate] STATUS=FAILED | ` +
|
|
139
|
+
`durationMs=${Date.now() - startedAt}`,
|
|
134
140
|
error
|
|
135
141
|
);
|
|
136
142
|
throw error;
|
|
@@ -103,7 +103,7 @@ async function generateCodeWithTemplate(_izContext, savePath, settings) {
|
|
|
103
103
|
|
|
104
104
|
return allCreateSource;
|
|
105
105
|
} catch (error) {
|
|
106
|
-
|
|
106
|
+
console.log(
|
|
107
107
|
'Error generating code with template propertyNode schema:',
|
|
108
108
|
error
|
|
109
109
|
);
|
|
@@ -17,10 +17,16 @@ import fs from 'fs';
|
|
|
17
17
|
import path from 'path';
|
|
18
18
|
|
|
19
19
|
import { s3 } from '@izara_project/izara-core-library-s3';
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
const consoleLogger = {
|
|
22
|
+
debug: console.log,
|
|
23
|
+
info: console.log,
|
|
24
|
+
warn: console.log,
|
|
25
|
+
error: console.error
|
|
26
|
+
};
|
|
21
27
|
|
|
22
28
|
const DEFAULT_BUCKET = 'integrationtest-config-us-east-2';
|
|
23
|
-
const _izContext = { Logger };
|
|
29
|
+
const _izContext = { logger: consoleLogger, Logger: consoleLogger };
|
|
24
30
|
|
|
25
31
|
function _getAllFiles(dirPath, filePaths = []) {
|
|
26
32
|
if (!fs.existsSync(dirPath)) {
|
|
@@ -9,21 +9,18 @@ import { generateCreateTargetRoleHandler } from '../src/emit/rbac/generateCreate
|
|
|
9
9
|
const roots = new Set();
|
|
10
10
|
const OWN_TOPIC_FLOWS = [
|
|
11
11
|
'CreateTargetRole',
|
|
12
|
+
'UpdateTargetRole',
|
|
12
13
|
'CreateRolePermissions',
|
|
13
14
|
'DeleteRolePermissions',
|
|
14
15
|
'DeleteTargetRole',
|
|
15
16
|
'CreateUserRole',
|
|
16
17
|
'DeleteUserFromRole',
|
|
17
|
-
'CreateRoleLimit',
|
|
18
|
-
'DeleteRoleLimit',
|
|
19
18
|
'ReservedDynamicUsage',
|
|
20
19
|
'ConfirmUsage',
|
|
21
20
|
'CancelUsage'
|
|
22
21
|
];
|
|
23
22
|
|
|
24
23
|
const LIMIT_FLOWS = [
|
|
25
|
-
'CreateRoleLimit',
|
|
26
|
-
'DeleteRoleLimit',
|
|
27
24
|
'ReservedDynamicUsage',
|
|
28
25
|
'ConfirmUsage',
|
|
29
26
|
'CancelUsage'
|
|
@@ -39,7 +36,7 @@ test('generates RBAC own-topic WebSocket entries alongside their SQS handlers',
|
|
|
39
36
|
const rootPath = await createProject(true);
|
|
40
37
|
const result = await generateCreateTargetRoleHandler(rootPath);
|
|
41
38
|
|
|
42
|
-
assert.equal(result.files.length,
|
|
39
|
+
assert.equal(result.files.length, 59);
|
|
43
40
|
assert.match(
|
|
44
41
|
await readFile(join(rootPath, result.files[0].path), 'utf8'),
|
|
45
42
|
/CreateTargetRole/
|
|
@@ -48,6 +45,46 @@ test('generates RBAC own-topic WebSocket entries alongside their SQS handlers',
|
|
|
48
45
|
await readFile(join(rootPath, result.files[0].path), 'utf8'),
|
|
49
46
|
/roleName = 'owner'/
|
|
50
47
|
);
|
|
48
|
+
assert.match(
|
|
49
|
+
await readFile(
|
|
50
|
+
join(
|
|
51
|
+
rootPath,
|
|
52
|
+
'app/src/generatedCode/FlowRbac/UpdateTargetRole/source/UpdateTargetRole_Main.js'
|
|
53
|
+
),
|
|
54
|
+
'utf8'
|
|
55
|
+
),
|
|
56
|
+
/Cannot modify system owner role/
|
|
57
|
+
);
|
|
58
|
+
assert.match(
|
|
59
|
+
await readFile(
|
|
60
|
+
join(
|
|
61
|
+
rootPath,
|
|
62
|
+
'app/src/generatedCode/FlowRbac/DeleteTargetRole/source/DeleteTargetRole_Main.js'
|
|
63
|
+
),
|
|
64
|
+
'utf8'
|
|
65
|
+
),
|
|
66
|
+
/Cannot delete system owner role/
|
|
67
|
+
);
|
|
68
|
+
assert.match(
|
|
69
|
+
await readFile(
|
|
70
|
+
join(
|
|
71
|
+
rootPath,
|
|
72
|
+
'app/src/generatedCode/FlowRbac/GetTargetRole/source/GetTargetRole_Main.js'
|
|
73
|
+
),
|
|
74
|
+
'utf8'
|
|
75
|
+
),
|
|
76
|
+
/GetTargetRole/
|
|
77
|
+
);
|
|
78
|
+
assert.match(
|
|
79
|
+
await readFile(
|
|
80
|
+
join(
|
|
81
|
+
rootPath,
|
|
82
|
+
'app/src/generatedCode/FlowRbac/GetMyPermissions/source/GetMyPermissions_Main.js'
|
|
83
|
+
),
|
|
84
|
+
'utf8'
|
|
85
|
+
),
|
|
86
|
+
/GetMyPermissions/
|
|
87
|
+
);
|
|
51
88
|
assert.match(
|
|
52
89
|
await readFile(join(rootPath, result.files[1].path), 'utf8'),
|
|
53
90
|
/CreateTargetRoleHdrSqs/
|
|
@@ -89,16 +126,6 @@ test('generates RBAC own-topic WebSocket entries alongside their SQS handlers',
|
|
|
89
126
|
),
|
|
90
127
|
/Math\.min\(maxIncrease, minDecrease\)/
|
|
91
128
|
);
|
|
92
|
-
assert.match(
|
|
93
|
-
await readFile(
|
|
94
|
-
join(
|
|
95
|
-
rootPath,
|
|
96
|
-
'app/src/generatedCode/FlowLimit/CreateRoleLimit/source/CreateRoleLimit_Main.js'
|
|
97
|
-
),
|
|
98
|
-
'utf8'
|
|
99
|
-
),
|
|
100
|
-
/actionType/
|
|
101
|
-
);
|
|
102
129
|
const rbacYaml = await readFile(
|
|
103
130
|
join(rootPath, 'app/sls_yaml/generatedCode/source/flow-rbac.yml'),
|
|
104
131
|
'utf8'
|
|
@@ -239,7 +239,7 @@ test('emits a single Complete RBAC handler for Update without Graph', async () =
|
|
|
239
239
|
);
|
|
240
240
|
});
|
|
241
241
|
|
|
242
|
-
test('emits
|
|
242
|
+
test('emits Complete handlers and inlines sync RBAC for Update with Graph', async () => {
|
|
243
243
|
const rootPath = await createRbacProject(false, true);
|
|
244
244
|
const result = await generateCrudApplicationArtifacts(rootPath, {
|
|
245
245
|
serviceTag: 'orders'
|
|
@@ -248,19 +248,25 @@ test('emits RbacCallback and Complete handlers for Update with Graph', async ()
|
|
|
248
248
|
.map((file) => file.path)
|
|
249
249
|
.filter((path) => path.includes('/FlowObjects/Update/source/'));
|
|
250
250
|
|
|
251
|
-
assert.ok(updatePaths.includes(
|
|
251
|
+
assert.ok(!updatePaths.includes(
|
|
252
252
|
'app/src/generatedCode/FlowObjects/Update/source/UpdateRbacCallback_Main.js'
|
|
253
253
|
));
|
|
254
254
|
assert.ok(updatePaths.includes(
|
|
255
255
|
'app/src/generatedCode/FlowObjects/Update/source/UpdateComplete_Main.js'
|
|
256
256
|
));
|
|
257
|
+
const updateMainContent = await readFile(
|
|
258
|
+
join(rootPath, 'app/src/generatedCode/FlowObjects/Update/source/Update_Main.js'),
|
|
259
|
+
'utf8'
|
|
260
|
+
);
|
|
261
|
+
assert.match(updateMainContent, /checkRbacPermission/);
|
|
262
|
+
assert.match(updateMainContent, /sync: true/);
|
|
257
263
|
execFileSync(
|
|
258
264
|
process.execPath,
|
|
259
265
|
[
|
|
260
266
|
'--check',
|
|
261
267
|
join(
|
|
262
268
|
rootPath,
|
|
263
|
-
'app/src/generatedCode/FlowObjects/Update/source/
|
|
269
|
+
'app/src/generatedCode/FlowObjects/Update/source/UpdateComplete_Main.js'
|
|
264
270
|
)
|
|
265
271
|
],
|
|
266
272
|
{ stdio: 'inherit' }
|
|
@@ -357,6 +363,59 @@ test('logs warning when ObjectSchema has invalid or non-CRUD generatedBy in crud
|
|
|
357
363
|
);
|
|
358
364
|
});
|
|
359
365
|
|
|
366
|
+
test('emits targetIdentifiers consistency check and fallback in Update_Main.js and Delete_Main.js', async () => {
|
|
367
|
+
const rootPath = await createProject(true);
|
|
368
|
+
await generateCrudApplicationArtifacts(rootPath, {
|
|
369
|
+
serviceTag: 'orders'
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
const updateMain = await readFile(
|
|
373
|
+
join(
|
|
374
|
+
rootPath,
|
|
375
|
+
'app/src/generatedCode/FlowObjects/Update/source/Update_Main.js'
|
|
376
|
+
),
|
|
377
|
+
'utf8'
|
|
378
|
+
);
|
|
379
|
+
assert.match(updateMain, /targetIdentifiers\.\$\{key\} must match objInstanceFull\.identifiers\.\$\{key\}/);
|
|
380
|
+
assert.match(updateMain, /if \(!objectSchema\.hasOwnProperty\('belongTo'\)\)/);
|
|
381
|
+
assert.doesNotMatch(updateMain, /requestParams\.targetIdentifiers\s*=/);
|
|
382
|
+
|
|
383
|
+
const deleteMain = await readFile(
|
|
384
|
+
join(
|
|
385
|
+
rootPath,
|
|
386
|
+
'app/src/generatedCode/FlowObjects/Delete/source/Delete_Main.js'
|
|
387
|
+
),
|
|
388
|
+
'utf8'
|
|
389
|
+
);
|
|
390
|
+
assert.match(deleteMain, /targetIdentifiers\.\$\{key\} must match identifiers\.\$\{key\}/);
|
|
391
|
+
assert.match(deleteMain, /if \(!objectSchema\.hasOwnProperty\('belongTo'\)\)/);
|
|
392
|
+
assert.doesNotMatch(deleteMain, /requestParams\.targetIdentifiers\s*=/);
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
test('emits targetIdentifiers passed directly to checkRbacPermission options in RBAC project', async () => {
|
|
396
|
+
const rootPath = await createRbacProject();
|
|
397
|
+
await generateCrudApplicationArtifacts(rootPath, {
|
|
398
|
+
serviceTag: 'orders'
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
const updateMain = await readFile(
|
|
402
|
+
join(
|
|
403
|
+
rootPath,
|
|
404
|
+
'app/src/generatedCode/FlowObjects/Update/source/Update_Main.js'
|
|
405
|
+
),
|
|
406
|
+
'utf8'
|
|
407
|
+
);
|
|
408
|
+
assert.match(updateMain, /checkRbacPermission\([\s\S]*targetIdentifiers,[\s\S]*rbacObjType/);
|
|
409
|
+
|
|
410
|
+
const deleteMain = await readFile(
|
|
411
|
+
join(
|
|
412
|
+
rootPath,
|
|
413
|
+
'app/src/generatedCode/FlowObjects/Delete/source/Delete_Main.js'
|
|
414
|
+
),
|
|
415
|
+
'utf8'
|
|
416
|
+
);
|
|
417
|
+
assert.match(deleteMain, /checkRbacPermission\([\s\S]*targetIdentifiers,[\s\S]*rbacObjType/);
|
|
418
|
+
});
|
|
360
419
|
|
|
361
420
|
async function createProject(withCrudObject) {
|
|
362
421
|
const rootPath = await mkdtemp(
|
|
@@ -895,7 +895,7 @@ test('registers SQS queue, SNS subscription, and SNS out topic for custom flowSc
|
|
|
895
895
|
);
|
|
896
896
|
});
|
|
897
897
|
|
|
898
|
-
test('
|
|
898
|
+
test('uses synchronous RBAC without obsolete callback SQS subscriptions in InitialSetupConfig', async () => {
|
|
899
899
|
const rootPath = await createProject();
|
|
900
900
|
await writeFile(
|
|
901
901
|
join(rootPath, 'app/src/schemas/ObjectSchemas/Member.js'),
|
|
@@ -920,10 +920,8 @@ test('renders RBAC Validator subscriptions in InitialSetupConfig when object has
|
|
|
920
920
|
),
|
|
921
921
|
'utf8'
|
|
922
922
|
);
|
|
923
|
-
assert.
|
|
924
|
-
assert.
|
|
925
|
-
assert.match(initialSetupConfigContent, /sqsEndpoint: 'UpdateRbacCallbackHdrSqs'/);
|
|
926
|
-
assert.match(initialSetupConfigContent, /sqsEndpoint: 'DeleteRbacCallbackHdrSqs'/);
|
|
923
|
+
assert.doesNotMatch(initialSetupConfigContent, /sqsEndpoint: 'UpdateRbacCallbackHdrSqs'/);
|
|
924
|
+
assert.doesNotMatch(initialSetupConfigContent, /sqsEndpoint: 'DeleteRbacCallbackHdrSqs'/);
|
|
927
925
|
});
|
|
928
926
|
|
|
929
927
|
test('deduplicates duplicate nextSteps topics across flowSteps in InitialSetupConfig', async () => {
|
|
@@ -142,7 +142,7 @@ test('generates a direct Complete step for RBAC-only Update flows', async () =>
|
|
|
142
142
|
assert.equal(update.flowSteps[1].properties.length, 0);
|
|
143
143
|
});
|
|
144
144
|
|
|
145
|
-
test('generates
|
|
145
|
+
test('generates CreateNodeCallback and Complete for Create when RBAC and Graph are present', async () => {
|
|
146
146
|
const rootPath = await createProject({
|
|
147
147
|
generatedBy: 'user',
|
|
148
148
|
});
|
|
@@ -160,13 +160,12 @@ test('generates RbacCallback and Complete for Create when RBAC and Graph are pre
|
|
|
160
160
|
const create = await readGeneratedFlow(rootPath, 'Create');
|
|
161
161
|
assert.deepEqual(create.flowSteps.map((step) => step.stepName), [
|
|
162
162
|
'Start',
|
|
163
|
-
'RbacCallback',
|
|
164
163
|
'CreateNodeCallback',
|
|
165
164
|
'Complete'
|
|
166
165
|
]);
|
|
167
166
|
});
|
|
168
167
|
|
|
169
|
-
test('uses
|
|
168
|
+
test('uses CreateNodeCallback step when Graph storage is present with sync RBAC', async () => {
|
|
170
169
|
const rootPath = await mkdtemp(
|
|
171
170
|
join(tmpdir(), 'generate-service-code-v2-crud-rbac-graph-')
|
|
172
171
|
);
|
|
@@ -186,11 +185,10 @@ test('uses the renamed RBAC callback step when Graph storage is present', async
|
|
|
186
185
|
const create = await readGeneratedFlow(rootPath, 'Create');
|
|
187
186
|
assert.deepEqual(create.flowSteps.map((step) => step.stepName), [
|
|
188
187
|
'Start',
|
|
189
|
-
'RbacCallback',
|
|
190
188
|
'CreateNodeCallback',
|
|
191
189
|
'Complete'
|
|
192
190
|
]);
|
|
193
|
-
assert.deepEqual(create.flowSteps[
|
|
191
|
+
assert.deepEqual(create.flowSteps[1].properties, [
|
|
194
192
|
'returnValue',
|
|
195
193
|
'parentFlowId',
|
|
196
194
|
'status',
|
|
@@ -199,7 +197,7 @@ test('uses the renamed RBAC callback step when Graph storage is present', async
|
|
|
199
197
|
]);
|
|
200
198
|
});
|
|
201
199
|
|
|
202
|
-
test('chains
|
|
200
|
+
test('chains Start and Complete for Update with RBAC and Graph', async () => {
|
|
203
201
|
const rootPath = await mkdtemp(
|
|
204
202
|
join(tmpdir(), 'generate-service-code-v2-crud-update-rbac-graph-')
|
|
205
203
|
);
|
|
@@ -219,19 +217,9 @@ test('chains RbacCallback and Complete for Update with RBAC and Graph', async ()
|
|
|
219
217
|
const update = await readGeneratedFlow(rootPath, 'Update');
|
|
220
218
|
assert.deepEqual(update.flowSteps.map((step) => step.stepName), [
|
|
221
219
|
'Start',
|
|
222
|
-
'RbacCallback',
|
|
223
220
|
'Complete'
|
|
224
221
|
]);
|
|
225
222
|
assert.deepEqual(update.flowSteps[0].nextSteps, [
|
|
226
|
-
{ targetType: 'ownTopic', stepName: 'RbacCallback' },
|
|
227
|
-
{
|
|
228
|
-
targetType: 'extTopic',
|
|
229
|
-
serviceTag: 'Rbac',
|
|
230
|
-
topicName: 'ValidatorRbac_In',
|
|
231
|
-
toStepNames: ['RbacCallback']
|
|
232
|
-
}
|
|
233
|
-
]);
|
|
234
|
-
assert.deepEqual(update.flowSteps[1].nextSteps, [
|
|
235
223
|
{ targetType: 'ownTopic', stepName: 'Complete' },
|
|
236
224
|
{
|
|
237
225
|
targetType: 'extTopic',
|
|
@@ -240,7 +228,7 @@ test('chains RbacCallback and Complete for Update with RBAC and Graph', async ()
|
|
|
240
228
|
toStepNames: ['Complete']
|
|
241
229
|
}
|
|
242
230
|
]);
|
|
243
|
-
assert.deepEqual(update.flowSteps[
|
|
231
|
+
assert.deepEqual(update.flowSteps[1].properties, [
|
|
244
232
|
'returnValue',
|
|
245
233
|
'parentFlowId',
|
|
246
234
|
'status',
|
|
@@ -10,20 +10,20 @@ import { generateDynamicRbacFlowSchemas } from '../src/emit/rbac/generateDynamic
|
|
|
10
10
|
const projectRoots = new Set();
|
|
11
11
|
const STATIC_RBAC_ACTIONS = [
|
|
12
12
|
'CreateTargetRole',
|
|
13
|
-
'
|
|
13
|
+
'UpdateTargetRole',
|
|
14
14
|
'DeleteTargetRole',
|
|
15
|
+
'GetTargetRole',
|
|
16
|
+
'ListTargetRole',
|
|
15
17
|
'CreateRolePermissions',
|
|
16
18
|
'ListRolePermissions',
|
|
17
19
|
'DeleteRolePermissions',
|
|
18
20
|
'CreateUserRole',
|
|
19
21
|
'ListUserInRoles',
|
|
20
|
-
'DeleteUserFromRole'
|
|
22
|
+
'DeleteUserFromRole',
|
|
23
|
+
'GetMyPermissions'
|
|
21
24
|
];
|
|
22
25
|
|
|
23
26
|
const STATIC_LIMIT_ACTIONS = [
|
|
24
|
-
'CreateRoleLimit',
|
|
25
|
-
'ListRoleLimits',
|
|
26
|
-
'DeleteRoleLimit',
|
|
27
27
|
'ReservedDynamicUsage',
|
|
28
28
|
'ConfirmUsage',
|
|
29
29
|
'CancelUsage'
|
|
@@ -83,12 +83,14 @@ test('filters all SQS functions by their calling flow', () => {
|
|
|
83
83
|
/#<#CreateCompleteHdrSqsFilterPatterns#>[\s\S]*filterPatterns:[\s\S]*\$\{self:custom\.iz_resourcePrefix\}CreateCompleteHdrSqs/
|
|
84
84
|
);
|
|
85
85
|
assert.match(completion, /#<#\/CreateCompleteHdrSqsFilterPatterns#>/);
|
|
86
|
-
assert.match(completion, /exists: false/);
|
|
86
|
+
assert.match(completion, /callingFlow:\s*\n\s*- exists: false/);
|
|
87
|
+
assert.match(completion, /MessageAttributes:\s*\n\s*- exists: false/);
|
|
87
88
|
assert.match(
|
|
88
89
|
ordinary,
|
|
89
90
|
/#<#CreateHdrSqsFilterPatterns#>[\s\S]*filterPatterns:[\s\S]*\$\{self:custom\.iz_resourcePrefix\}CreateHdrSqs/
|
|
90
91
|
);
|
|
91
92
|
assert.match(ordinary, /#<#\/CreateHdrSqsFilterPatterns#>/);
|
|
92
|
-
assert.match(ordinary, /exists: false/);
|
|
93
|
+
assert.match(ordinary, /callingFlow:\s*\n\s*- exists: false/);
|
|
94
|
+
assert.match(ordinary, /MessageAttributes:\s*\n\s*- exists: false/);
|
|
93
95
|
});
|
|
94
96
|
|
package/test/publicApi.test.js
CHANGED
|
@@ -57,24 +57,28 @@ test('generate commits schemas, application artifacts, and resources in one publ
|
|
|
57
57
|
);
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
test('generate logs its lifecycle through
|
|
60
|
+
test('generate logs its lifecycle through console.log', async () => {
|
|
61
61
|
const rootPath = await createCrudProject();
|
|
62
62
|
const messages = [];
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
])
|
|
68
|
-
);
|
|
63
|
+
const originalLog = console.log;
|
|
64
|
+
console.log = (...args) => {
|
|
65
|
+
messages.push(args.join(' '));
|
|
66
|
+
};
|
|
69
67
|
|
|
70
|
-
|
|
68
|
+
try {
|
|
69
|
+
await generate(rootPath);
|
|
71
70
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
assert.match(messages[0], /STATUS=STARTED/);
|
|
72
|
+
assert.ok(messages.some((message) => {
|
|
73
|
+
return /STATUS=SCHEMAS_LOADED/.test(message);
|
|
74
|
+
}));
|
|
75
|
+
assert.ok(messages.some((message) => {
|
|
76
|
+
return /STATUS=ARTIFACTS_EMITTED/.test(message);
|
|
77
|
+
}));
|
|
78
|
+
assert.match(messages.at(-1), /STATUS=FINISHED/);
|
|
79
|
+
} finally {
|
|
80
|
+
console.log = originalLog;
|
|
81
|
+
}
|
|
78
82
|
});
|
|
79
83
|
|
|
80
84
|
test('generate commits RBAC WebSocket entries for own-topic mutation flows', async () => {
|
|
@@ -76,8 +76,9 @@ test('emits queues, topics, tables, and IAM roles from schema data', async () =>
|
|
|
76
76
|
assert.match(dynamoYaml, /OrdersTable:/);
|
|
77
77
|
assert.match(dynamoYaml, /#<#OrdersTableSetting#>/);
|
|
78
78
|
assert.match(dynamoYaml, /#<#\/OrdersTableSetting#>/);
|
|
79
|
+
assert.match(dynamoYaml, /RolesTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+TableName: \${self:custom\.iz_resourcePrefix}Roles/);
|
|
79
80
|
assert.match(dynamoYaml, /TargetRolesTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+AttributeName: identifiersConcat/);
|
|
80
|
-
assert.
|
|
81
|
+
assert.doesNotMatch(dynamoYaml, /RoleLimitTable:/);
|
|
81
82
|
assert.match(dynamoYaml, /RunningTotalUsageTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+TableName: \${self:custom\.iz_resourcePrefix}RunningTotalUsage/);
|
|
82
83
|
assert.match(dynamoYaml, /RunningTotalReservedUsageTable:\s+Type: 'AWS::DynamoDB::Table'[\s\S]+TableName: \${self:custom\.iz_resourcePrefix}RunningTotalReservedUsage/);
|
|
83
84
|
const iam = await readFile(
|
|
@@ -108,9 +109,9 @@ test('emits queues, topics, tables, and IAM roles from schema data', async () =>
|
|
|
108
109
|
roleBlock(iam, 'FlowRbacRole'),
|
|
109
110
|
/RolePermissions|ProcessCreateTargetRoleHdrSqs/
|
|
110
111
|
);
|
|
111
|
-
assert.
|
|
112
|
+
assert.doesNotMatch(roleBlock(iam, 'FlowRbacRole'), /RoleLimit/);
|
|
112
113
|
assert.match(roleBlock(iam, 'FlowRbacRole'), /RunningTotalUsage/);
|
|
113
|
-
assert.
|
|
114
|
+
assert.doesNotMatch(roleBlock(iam, 'FlowObjectsRole'), /RoleLimit/);
|
|
114
115
|
// Per-object RBAC flow queue (e.g. ValidatorRbacHdrSqs from Order with rbac add-on)
|
|
115
116
|
assert.match(roleBlock(iam, 'FlowRbacRole'), /ValidatorRbacHdrSqs/);
|
|
116
117
|
|
|
@@ -365,6 +366,9 @@ test('emits CreateNodeCallbackHdrSqs in FlowObjectsRole when object has graph an
|
|
|
365
366
|
const role = roleBlock(iam, 'FlowObjectsRole');
|
|
366
367
|
assert.match(role, /CreateNodeCallbackHdrSqs/);
|
|
367
368
|
assert.match(role, /CreateNodeCallbackHdrSqsDLQ/);
|
|
369
|
+
assert.match(role, /RolePermissions/);
|
|
370
|
+
assert.match(role, /ValidatorRbac_In/);
|
|
371
|
+
assert.match(role, /Rbac_\$\{self:custom\.iz_stage\}_ValidatorRbac_In/);
|
|
368
372
|
});
|
|
369
373
|
|
|
370
374
|
function roleBlock(iam, roleName) {
|