@izara_project/izara-core-generate-service-code 1.0.85 → 1.0.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +1 -0
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +15 -4
- package/src/emit/crud/emitCrudApplicationArtifacts.js +10 -4
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +10 -4
- package/src/emit/crud/templates/DeleteEndpoint_Main.ejs +36 -4
- package/src/emit/crud/templates/UpdateEndpoint_Main.ejs +35 -3
- package/src/emit/crud/templates/UpdateLogicalLib.ejs +754 -353
- package/src/emit/rbac/emitDynamicRbacFlowSchemas.js +5 -2
- package/src/emit/rbac/emitRbacApplicationArtifacts.js +102 -6
- package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +34 -4
- package/src/emit/rbac/templates/DeleteTargetRole_Main.ejs +96 -0
- package/src/emit/rbac/templates/GetMyPermissions_Main.ejs +106 -0
- package/src/emit/rbac/templates/GetTargetRole_Main.ejs +62 -0
- package/src/emit/rbac/templates/UpdateTargetRole_Main.ejs +107 -0
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +12 -12
- package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +12 -0
- package/src/emit/resource/emitResourceArtifacts.js +43 -2
- package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.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 -1
- package/test/crudApplicationArtifacts.test.js +53 -0
- package/test/dynamicRbacFlowSchemas.test.js +5 -2
- package/test/publicApi.test.js +18 -14
- package/test/resourceArtifacts.test.js +3 -0
|
@@ -4,14 +4,17 @@ import { rbacFlowTag } from './rbacFlowTag.js';
|
|
|
4
4
|
|
|
5
5
|
const RBAC_CORE_FLOW_DEFINITIONS = [
|
|
6
6
|
{ flowTag: 'CreateTargetRole', event: ['ownTopic'] },
|
|
7
|
-
{ flowTag: '
|
|
7
|
+
{ flowTag: 'UpdateTargetRole', event: ['ownTopic'] },
|
|
8
8
|
{ flowTag: 'DeleteTargetRole', event: ['ownTopic'] },
|
|
9
|
+
{ flowTag: 'GetTargetRole', event: ['lambdaSyncApi'] },
|
|
10
|
+
{ flowTag: 'ListTargetRole', event: ['lambdaSyncApi'] },
|
|
9
11
|
{ flowTag: 'CreateRolePermissions', event: ['ownTopic'] },
|
|
10
12
|
{ flowTag: 'ListRolePermissions', event: ['lambdaSyncApi'] },
|
|
11
13
|
{ flowTag: 'DeleteRolePermissions', event: ['ownTopic'] },
|
|
12
14
|
{ flowTag: 'CreateUserRole', event: ['ownTopic'] },
|
|
13
15
|
{ flowTag: 'ListUserInRoles', event: ['lambdaSyncApi'] },
|
|
14
|
-
{ flowTag: 'DeleteUserFromRole', event: ['ownTopic'] }
|
|
16
|
+
{ flowTag: 'DeleteUserFromRole', event: ['ownTopic'] },
|
|
17
|
+
{ flowTag: 'GetMyPermissions', event: ['lambdaSyncApi'] }
|
|
15
18
|
];
|
|
16
19
|
|
|
17
20
|
const LIMIT_FLOW_DEFINITIONS = [
|
|
@@ -29,6 +29,19 @@ export async function emitRbacApplicationArtifacts(objects) {
|
|
|
29
29
|
...(hasSelfRbac
|
|
30
30
|
? [
|
|
31
31
|
createTargetRoleHandler(),
|
|
32
|
+
createCustomRbacOwnTopicHandler(
|
|
33
|
+
'UpdateTargetRole',
|
|
34
|
+
'UpdateTargetRole_Main.ejs'
|
|
35
|
+
),
|
|
36
|
+
createCustomRbacOwnTopicHandler(
|
|
37
|
+
'DeleteTargetRole',
|
|
38
|
+
'DeleteTargetRole_Main.ejs'
|
|
39
|
+
),
|
|
40
|
+
createCustomRbacApiHandler('GetTargetRole', 'GetTargetRole_Main.ejs'),
|
|
41
|
+
createCustomRbacApiHandler(
|
|
42
|
+
'GetMyPermissions',
|
|
43
|
+
'GetMyPermissions_Main.ejs'
|
|
44
|
+
),
|
|
32
45
|
...LIST_DEFINITIONS.map(createListHandler),
|
|
33
46
|
...MUTATION_DEFINITIONS.map(createMutationHandler),
|
|
34
47
|
...USER_ROLE_MUTATIONS.map(createUserRoleMutationHandler)
|
|
@@ -111,12 +124,6 @@ const MUTATION_DEFINITIONS = [
|
|
|
111
124
|
tableName: 'RolePermissions',
|
|
112
125
|
method: 'deleteItem',
|
|
113
126
|
fields: ['roleIdKey', 'flowTypeConcat']
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
flowTag: 'DeleteTargetRole',
|
|
117
|
-
tableName: 'TargetRoles',
|
|
118
|
-
method: 'deleteItem',
|
|
119
|
-
fields: ['identifiersConcat', 'roleIdKey']
|
|
120
127
|
}
|
|
121
128
|
];
|
|
122
129
|
|
|
@@ -151,6 +158,20 @@ const STATIC_RBAC_APPLICATION_PATHS = [
|
|
|
151
158
|
'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_HdrSqs.js',
|
|
152
159
|
'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_WbsMain.js',
|
|
153
160
|
'app/src/generatedCode/FlowRbac/CreateTargetRole/source/CreateTargetRole_HdrWbs.js',
|
|
161
|
+
'app/src/generatedCode/FlowRbac/UpdateTargetRole/source/UpdateTargetRole_Main.js',
|
|
162
|
+
'app/src/generatedCode/FlowRbac/UpdateTargetRole/source/UpdateTargetRole_HdrSqs.js',
|
|
163
|
+
'app/src/generatedCode/FlowRbac/UpdateTargetRole/source/UpdateTargetRole_WbsMain.js',
|
|
164
|
+
'app/src/generatedCode/FlowRbac/UpdateTargetRole/source/UpdateTargetRole_HdrWbs.js',
|
|
165
|
+
'app/src/generatedCode/FlowRbac/DeleteTargetRole/source/DeleteTargetRole_Main.js',
|
|
166
|
+
'app/src/generatedCode/FlowRbac/DeleteTargetRole/source/DeleteTargetRole_HdrSqs.js',
|
|
167
|
+
'app/src/generatedCode/FlowRbac/DeleteTargetRole/source/DeleteTargetRole_WbsMain.js',
|
|
168
|
+
'app/src/generatedCode/FlowRbac/DeleteTargetRole/source/DeleteTargetRole_HdrWbs.js',
|
|
169
|
+
'app/src/generatedCode/FlowRbac/GetTargetRole/source/GetTargetRole_Main.js',
|
|
170
|
+
'app/src/generatedCode/FlowRbac/GetTargetRole/source/GetTargetRole_HdrSqs.js',
|
|
171
|
+
'app/src/generatedCode/FlowRbac/GetTargetRole/source/GetTargetRole_HdrApi.js',
|
|
172
|
+
'app/src/generatedCode/FlowRbac/GetMyPermissions/source/GetMyPermissions_Main.js',
|
|
173
|
+
'app/src/generatedCode/FlowRbac/GetMyPermissions/source/GetMyPermissions_HdrSqs.js',
|
|
174
|
+
'app/src/generatedCode/FlowRbac/GetMyPermissions/source/GetMyPermissions_HdrApi.js',
|
|
154
175
|
'app/src/generatedCode/FlowRbac/ValidatorRbac/source/ValidatorRbac_Main.js',
|
|
155
176
|
'app/src/generatedCode/FlowRbac/ValidatorRbac/source/ValidatorRbac_HdrSqs.js',
|
|
156
177
|
'app/src/generatedCode/FlowRbac/ValidatorRbac/source/ValidatorRbac_WbsMain.js',
|
|
@@ -331,6 +352,81 @@ async function createLimitMutationHandler(definition) {
|
|
|
331
352
|
};
|
|
332
353
|
}
|
|
333
354
|
|
|
355
|
+
async function createCustomRbacOwnTopicHandler(flowTag, mainTemplateName) {
|
|
356
|
+
const sourcePath = `app/src/generatedCode/FlowRbac/${flowTag}/source`;
|
|
357
|
+
const handlerPath = `src/generatedCode/FlowRbac/${flowTag}/source`;
|
|
358
|
+
const webSocket = await createWebSocketEntry(
|
|
359
|
+
flowTag,
|
|
360
|
+
sourcePath,
|
|
361
|
+
handlerPath
|
|
362
|
+
);
|
|
363
|
+
return {
|
|
364
|
+
artifacts: [
|
|
365
|
+
{
|
|
366
|
+
path: `${sourcePath}/${flowTag}_Main.js`,
|
|
367
|
+
content: await renderRbacTemplate(mainTemplateName, { flowTag })
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
path: `${sourcePath}/${flowTag}_HdrSqs.js`,
|
|
371
|
+
content: await renderRbacTemplate('ListRbac_HdrSqs.ejs', { flowTag })
|
|
372
|
+
},
|
|
373
|
+
...webSocket.artifacts
|
|
374
|
+
],
|
|
375
|
+
functions: [
|
|
376
|
+
{
|
|
377
|
+
type: 'sqs',
|
|
378
|
+
functionName: `${flowTag}HdrSqs`,
|
|
379
|
+
handlerPath: `${handlerPath}/${flowTag}_HdrSqs.main`,
|
|
380
|
+
roleName: 'FlowRbacRole',
|
|
381
|
+
queueName: `${flowTag}HdrSqs`,
|
|
382
|
+
flowTag: flowTag,
|
|
383
|
+
flowStepName: ''
|
|
384
|
+
},
|
|
385
|
+
...webSocket.functions
|
|
386
|
+
]
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
async function createCustomRbacApiHandler(flowTag, mainTemplateName) {
|
|
391
|
+
const sourcePath = `app/src/generatedCode/FlowRbac/${flowTag}/source`;
|
|
392
|
+
const handlerPath = `src/generatedCode/FlowRbac/${flowTag}/source`;
|
|
393
|
+
return {
|
|
394
|
+
artifacts: [
|
|
395
|
+
{
|
|
396
|
+
path: `${sourcePath}/${flowTag}_Main.js`,
|
|
397
|
+
content: await renderRbacTemplate(mainTemplateName, { flowTag })
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
path: `${sourcePath}/${flowTag}_HdrSqs.js`,
|
|
401
|
+
content: await renderRbacTemplate('ListRbac_HdrSqs.ejs', { flowTag })
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
path: `${sourcePath}/${flowTag}_HdrApi.js`,
|
|
405
|
+
content: await renderRbacTemplate('ListRbac_HdrApi.ejs', { flowTag })
|
|
406
|
+
}
|
|
407
|
+
],
|
|
408
|
+
functions: [
|
|
409
|
+
{
|
|
410
|
+
type: 'sqs',
|
|
411
|
+
functionName: `${flowTag}HdrSqs`,
|
|
412
|
+
handlerPath: `${handlerPath}/${flowTag}_HdrSqs.main`,
|
|
413
|
+
roleName: 'FlowRbacRole',
|
|
414
|
+
queueName: `${flowTag}HdrSqs`,
|
|
415
|
+
flowTag: flowTag,
|
|
416
|
+
flowStepName: ''
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
type: 'api',
|
|
420
|
+
functionName: `${flowTag}HdrApi`,
|
|
421
|
+
handlerPath: `${handlerPath}/${flowTag}_HdrApi.main`,
|
|
422
|
+
roleName: 'FlowRbacRole',
|
|
423
|
+
flowTag: flowTag,
|
|
424
|
+
flowStepName: ''
|
|
425
|
+
}
|
|
426
|
+
]
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
|
|
334
430
|
async function createTargetRoleHandler() {
|
|
335
431
|
const sourcePath = 'app/src/generatedCode/FlowRbac/CreateTargetRole/source';
|
|
336
432
|
const webSocket = await createWebSocketEntry(
|
|
@@ -55,7 +55,12 @@ export default async function CreateTargetRole(_izContext, requestParams) {
|
|
|
55
55
|
identifiersConcat = submittedByUserId;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
const {
|
|
58
|
+
const {
|
|
59
|
+
roleName = 'owner',
|
|
60
|
+
roleId: inputRoleId,
|
|
61
|
+
permissions = [],
|
|
62
|
+
assignUserIds = []
|
|
63
|
+
} = requestParams;
|
|
59
64
|
const roleId = inputRoleId || roleName || identifierUuid();
|
|
60
65
|
const roleIdKey = `${identifiersConcat}_${roleId}`;
|
|
61
66
|
|
|
@@ -70,21 +75,46 @@ export default async function CreateTargetRole(_izContext, requestParams) {
|
|
|
70
75
|
}
|
|
71
76
|
);
|
|
72
77
|
|
|
73
|
-
if (
|
|
78
|
+
if (Array.isArray(permissions) && permissions.length > 0) {
|
|
79
|
+
const rolePermissionsTable = dynamodbSharedLib.tableName(_izContext, 'RolePermissions');
|
|
80
|
+
for (const perm of permissions) {
|
|
81
|
+
const flowTypeConcat = typeof perm === 'string' ? perm : perm.flowTypeConcat;
|
|
82
|
+
if (flowTypeConcat) {
|
|
83
|
+
const permission =
|
|
84
|
+
typeof perm === 'object' && perm.permission !== undefined
|
|
85
|
+
? perm.permission
|
|
86
|
+
: true;
|
|
87
|
+
const parameterGroups = (typeof perm === 'object' && perm.parameterGroups) || {};
|
|
88
|
+
await dynamodbSharedLib.putItem(_izContext, rolePermissionsTable, {
|
|
89
|
+
roleIdKey,
|
|
90
|
+
flowTypeConcat,
|
|
91
|
+
permission,
|
|
92
|
+
parameterGroups
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const usersToAssign =
|
|
99
|
+
Array.isArray(assignUserIds) && assignUserIds.length > 0
|
|
100
|
+
? assignUserIds
|
|
101
|
+
: (roleName === 'owner' && submittedByUserId ? [submittedByUserId] : []);
|
|
102
|
+
|
|
103
|
+
for (const userId of usersToAssign) {
|
|
74
104
|
try {
|
|
75
105
|
await dynamodbSharedLib.transactWriteItems(_izContext, [
|
|
76
106
|
{
|
|
77
107
|
action: 'put',
|
|
78
108
|
params: {
|
|
79
109
|
tableName: dynamodbSharedLib.tableName(_izContext, 'RoleUsers'),
|
|
80
|
-
attributes: { roleIdKey, submittedByUserId }
|
|
110
|
+
attributes: { roleIdKey, userId, submittedByUserId }
|
|
81
111
|
}
|
|
82
112
|
},
|
|
83
113
|
{
|
|
84
114
|
action: 'put',
|
|
85
115
|
params: {
|
|
86
116
|
tableName: dynamodbSharedLib.tableName(_izContext, 'UserRoles'),
|
|
87
|
-
attributes: {
|
|
117
|
+
attributes: { userId, roleIdKey, submittedByUserId }
|
|
88
118
|
}
|
|
89
119
|
}
|
|
90
120
|
]);
|
|
@@ -0,0 +1,96 @@
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
19
|
+
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
20
|
+
import { sns } from '@izara_project/izara-core-library-external-request';
|
|
21
|
+
import { NoRetryError } from '@izara_project/izara-core-library-core';
|
|
22
|
+
|
|
23
|
+
export default async function DeleteTargetRole(_izContext, requestParams) {
|
|
24
|
+
try {
|
|
25
|
+
const { identifiersConcat, roleIdKey } = requestParams;
|
|
26
|
+
if (!roleIdKey) {
|
|
27
|
+
throw new NoRetryError('roleIdKey is required');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (roleIdKey.endsWith('_owner')) {
|
|
31
|
+
throw new NoRetryError('Cannot delete system owner role');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const targetRolesTable = dynamodbSharedLib.tableName(_izContext, 'TargetRoles');
|
|
35
|
+
const rolePermissionsTable = dynamodbSharedLib.tableName(_izContext, 'RolePermissions');
|
|
36
|
+
const roleUsersTable = dynamodbSharedLib.tableName(_izContext, 'RoleUsers');
|
|
37
|
+
const userRolesTable = dynamodbSharedLib.tableName(_izContext, 'UserRoles');
|
|
38
|
+
|
|
39
|
+
// 1. Delete from TargetRoles
|
|
40
|
+
await dynamodbSharedLib.deleteItem(
|
|
41
|
+
_izContext,
|
|
42
|
+
targetRolesTable,
|
|
43
|
+
{ identifiersConcat, roleIdKey }
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// 2. Cascade delete all permissions for this roleIdKey
|
|
47
|
+
const permsResult = await dynamodbSharedLib.query(_izContext, rolePermissionsTable, {
|
|
48
|
+
roleIdKey
|
|
49
|
+
});
|
|
50
|
+
for (const perm of (permsResult?.Items || [])) {
|
|
51
|
+
await dynamodbSharedLib.deleteItem(_izContext, rolePermissionsTable, {
|
|
52
|
+
roleIdKey,
|
|
53
|
+
flowTypeConcat: perm.flowTypeConcat
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 3. Cascade delete user assignments in RoleUsers and UserRoles
|
|
58
|
+
const usersResult = await dynamodbSharedLib.query(_izContext, roleUsersTable, {
|
|
59
|
+
roleIdKey
|
|
60
|
+
});
|
|
61
|
+
for (const userItem of (usersResult?.Items || [])) {
|
|
62
|
+
const userId = userItem.userId;
|
|
63
|
+
try {
|
|
64
|
+
await dynamodbSharedLib.transactWriteItems(_izContext, [
|
|
65
|
+
{
|
|
66
|
+
action: 'delete',
|
|
67
|
+
params: {
|
|
68
|
+
tableName: roleUsersTable,
|
|
69
|
+
keyValues: { roleIdKey, userId }
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
action: 'delete',
|
|
74
|
+
params: {
|
|
75
|
+
tableName: userRolesTable,
|
|
76
|
+
keyValues: { userId, roleIdKey }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
]);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:DeleteTargetRole] Cascade user cleanup ignored:`, err);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
await sns.publishMessage(_izContext, {
|
|
86
|
+
message: { returnResult: { identifiersConcat, roleIdKey, status: 'deleted' } },
|
|
87
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
88
|
+
_izContext,
|
|
89
|
+
'DeleteTargetRole_Out'
|
|
90
|
+
)
|
|
91
|
+
});
|
|
92
|
+
} catch (error) {
|
|
93
|
+
_izContext.logger.error(`[${process.env.iz_serviceTag}:DeleteTargetRole] error:`, error);
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
19
|
+
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
20
|
+
import { sns } from '@izara_project/izara-core-library-external-request';
|
|
21
|
+
import { consts, NoRetryError } from '@izara_project/izara-core-library-core';
|
|
22
|
+
|
|
23
|
+
export default async function GetMyPermissions(_izContext, requestParams) {
|
|
24
|
+
try {
|
|
25
|
+
const submittedByUserId =
|
|
26
|
+
requestParams.submittedByUserId ||
|
|
27
|
+
_izContext.correlationIds?.get(consts.SUBMITTED_BY_USER_ID);
|
|
28
|
+
|
|
29
|
+
if (!submittedByUserId) {
|
|
30
|
+
throw new NoRetryError('User identity not found in context.');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const targetIdentifiers = requestParams.targetIdentifiers;
|
|
34
|
+
let identifiersConcat = requestParams.identifiersConcat;
|
|
35
|
+
if (!identifiersConcat && targetIdentifiers && typeof targetIdentifiers === 'object') {
|
|
36
|
+
if (targetIdentifiers.identifierConcat) {
|
|
37
|
+
identifiersConcat = targetIdentifiers.identifierConcat;
|
|
38
|
+
} else {
|
|
39
|
+
const sortedKeys = Object.keys(targetIdentifiers).sort();
|
|
40
|
+
const parts = [];
|
|
41
|
+
for (const key of sortedKeys) {
|
|
42
|
+
const value = targetIdentifiers[key];
|
|
43
|
+
if (
|
|
44
|
+
key !== 'submittedByUserId' &&
|
|
45
|
+
key !== 'identifierConcat' &&
|
|
46
|
+
value !== undefined &&
|
|
47
|
+
value !== null
|
|
48
|
+
) {
|
|
49
|
+
parts.push(`${key}#${value}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (parts.length > 0) {
|
|
53
|
+
identifiersConcat = parts.join('|');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const userRolesTable = dynamodbSharedLib.tableName(_izContext, 'UserRoles');
|
|
59
|
+
const rolePermissionsTable = dynamodbSharedLib.tableName(_izContext, 'RolePermissions');
|
|
60
|
+
|
|
61
|
+
const userRolesResult = await dynamodbSharedLib.query(_izContext, userRolesTable, {
|
|
62
|
+
userId: submittedByUserId
|
|
63
|
+
});
|
|
64
|
+
const userRoleItems = userRolesResult?.Items || [];
|
|
65
|
+
|
|
66
|
+
const matchingRoles = identifiersConcat
|
|
67
|
+
? userRoleItems.filter((item) => item.roleIdKey?.startsWith(identifiersConcat))
|
|
68
|
+
: userRoleItems;
|
|
69
|
+
|
|
70
|
+
const permissionsMap = {};
|
|
71
|
+
const rolesList = [];
|
|
72
|
+
|
|
73
|
+
for (const roleItem of matchingRoles) {
|
|
74
|
+
rolesList.push(roleItem.roleIdKey);
|
|
75
|
+
const permsResult = await dynamodbSharedLib.query(_izContext, rolePermissionsTable, {
|
|
76
|
+
roleIdKey: roleItem.roleIdKey
|
|
77
|
+
});
|
|
78
|
+
for (const p of (permsResult?.Items || [])) {
|
|
79
|
+
if (p.permission === true) {
|
|
80
|
+
permissionsMap[p.flowTypeConcat] = true;
|
|
81
|
+
} else if (permissionsMap[p.flowTypeConcat] === undefined) {
|
|
82
|
+
permissionsMap[p.flowTypeConcat] = false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const result = {
|
|
88
|
+
userId: submittedByUserId,
|
|
89
|
+
identifiersConcat: identifiersConcat || null,
|
|
90
|
+
roles: rolesList,
|
|
91
|
+
permissions: permissionsMap
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
await sns.publishMessage(_izContext, {
|
|
95
|
+
message: { returnResult: result },
|
|
96
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
97
|
+
_izContext,
|
|
98
|
+
'GetMyPermissions_Out'
|
|
99
|
+
)
|
|
100
|
+
});
|
|
101
|
+
return result;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
_izContext.logger.error(`[${process.env.iz_serviceTag}:GetMyPermissions] error:`, error);
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
19
|
+
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
20
|
+
import { sns } from '@izara_project/izara-core-library-external-request';
|
|
21
|
+
import { NoRetryError } from '@izara_project/izara-core-library-core';
|
|
22
|
+
|
|
23
|
+
export default async function GetTargetRole(_izContext, requestParams) {
|
|
24
|
+
try {
|
|
25
|
+
const { identifiersConcat, roleIdKey } = requestParams;
|
|
26
|
+
if (!roleIdKey) {
|
|
27
|
+
throw new NoRetryError('roleIdKey is required');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const targetRolesTable = dynamodbSharedLib.tableName(_izContext, 'TargetRoles');
|
|
31
|
+
const rolePermissionsTable = dynamodbSharedLib.tableName(_izContext, 'RolePermissions');
|
|
32
|
+
const roleUsersTable = dynamodbSharedLib.tableName(_izContext, 'RoleUsers');
|
|
33
|
+
|
|
34
|
+
const role = identifiersConcat
|
|
35
|
+
? await dynamodbSharedLib.getItem(_izContext, targetRolesTable, { identifiersConcat, roleIdKey })
|
|
36
|
+
: null;
|
|
37
|
+
|
|
38
|
+
const [permsResult, usersResult] = await Promise.all([
|
|
39
|
+
dynamodbSharedLib.query(_izContext, rolePermissionsTable, { roleIdKey }),
|
|
40
|
+
dynamodbSharedLib.query(_izContext, roleUsersTable, { roleIdKey })
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
const result = {
|
|
44
|
+
role,
|
|
45
|
+
roleIdKey,
|
|
46
|
+
permissions: permsResult?.Items || [],
|
|
47
|
+
users: usersResult?.Items || []
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
await sns.publishMessage(_izContext, {
|
|
51
|
+
message: { returnResult: result },
|
|
52
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
53
|
+
_izContext,
|
|
54
|
+
'GetTargetRole_Out'
|
|
55
|
+
)
|
|
56
|
+
});
|
|
57
|
+
return result;
|
|
58
|
+
} catch (error) {
|
|
59
|
+
_izContext.logger.error(`[${process.env.iz_serviceTag}:GetTargetRole] error:`, error);
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
19
|
+
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
20
|
+
import { sns } from '@izara_project/izara-core-library-external-request';
|
|
21
|
+
import { consts, NoRetryError } from '@izara_project/izara-core-library-core';
|
|
22
|
+
|
|
23
|
+
export default async function UpdateTargetRole(_izContext, requestParams) {
|
|
24
|
+
try {
|
|
25
|
+
const submittedByUserId =
|
|
26
|
+
requestParams.submittedByUserId ||
|
|
27
|
+
_izContext.correlationIds?.get(consts.SUBMITTED_BY_USER_ID);
|
|
28
|
+
|
|
29
|
+
const {
|
|
30
|
+
identifiersConcat,
|
|
31
|
+
roleIdKey,
|
|
32
|
+
roleName,
|
|
33
|
+
permissions
|
|
34
|
+
} = requestParams;
|
|
35
|
+
|
|
36
|
+
if (!roleIdKey) {
|
|
37
|
+
throw new NoRetryError('roleIdKey is required');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (roleIdKey.endsWith('_owner')) {
|
|
41
|
+
throw new NoRetryError('Cannot modify system owner role');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const targetRolesTable = dynamodbSharedLib.tableName(_izContext, 'TargetRoles');
|
|
45
|
+
const rolePermissionsTable = dynamodbSharedLib.tableName(_izContext, 'RolePermissions');
|
|
46
|
+
|
|
47
|
+
if (roleName && identifiersConcat) {
|
|
48
|
+
const existingRole = await dynamodbSharedLib.getItem(_izContext, targetRolesTable, {
|
|
49
|
+
identifiersConcat,
|
|
50
|
+
roleIdKey
|
|
51
|
+
});
|
|
52
|
+
if (existingRole) {
|
|
53
|
+
await dynamodbSharedLib.putItem(_izContext, targetRolesTable, {
|
|
54
|
+
...existingRole,
|
|
55
|
+
roleName
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (Array.isArray(permissions)) {
|
|
61
|
+
const currentPermsQuery = await dynamodbSharedLib.query(_izContext, rolePermissionsTable, {
|
|
62
|
+
roleIdKey
|
|
63
|
+
});
|
|
64
|
+
const currentPerms = currentPermsQuery?.Items || [];
|
|
65
|
+
const currentFlowMap = new Map(currentPerms.map((p) => [p.flowTypeConcat, p]));
|
|
66
|
+
|
|
67
|
+
const newFlowSet = new Set();
|
|
68
|
+
for (const perm of permissions) {
|
|
69
|
+
const flowTypeConcat = typeof perm === 'string' ? perm : perm.flowTypeConcat;
|
|
70
|
+
if (flowTypeConcat) {
|
|
71
|
+
newFlowSet.add(flowTypeConcat);
|
|
72
|
+
const permission =
|
|
73
|
+
typeof perm === 'object' && perm.permission !== undefined
|
|
74
|
+
? perm.permission
|
|
75
|
+
: true;
|
|
76
|
+
const parameterGroups = (typeof perm === 'object' && perm.parameterGroups) || {};
|
|
77
|
+
await dynamodbSharedLib.putItem(_izContext, rolePermissionsTable, {
|
|
78
|
+
roleIdKey,
|
|
79
|
+
flowTypeConcat,
|
|
80
|
+
permission,
|
|
81
|
+
parameterGroups
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
for (const [oldFlow] of currentFlowMap.entries()) {
|
|
87
|
+
if (!newFlowSet.has(oldFlow)) {
|
|
88
|
+
await dynamodbSharedLib.deleteItem(_izContext, rolePermissionsTable, {
|
|
89
|
+
roleIdKey,
|
|
90
|
+
flowTypeConcat: oldFlow
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
await sns.publishMessage(_izContext, {
|
|
97
|
+
message: { returnResult: { roleIdKey, status: 'updated' } },
|
|
98
|
+
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
99
|
+
_izContext,
|
|
100
|
+
'UpdateTargetRole_Out'
|
|
101
|
+
)
|
|
102
|
+
});
|
|
103
|
+
} catch (error) {
|
|
104
|
+
_izContext.logger.error(`[${process.env.iz_serviceTag}:UpdateTargetRole] error:`, error);
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
}
|