@izara_project/izara-core-generate-service-code 1.0.84 → 1.0.85
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/emit/coreFunction/emitCoreFunctionArtifacts.js +5 -0
- package/src/emit/coreFunction/templates/InitialSetupConfig.ejs +13 -4
- package/src/emit/crud/crudActionPlan.js +3 -1
- package/src/emit/crud/emitCrudApplicationArtifacts.js +37 -4
- package/src/emit/crud/emitDynamicCrudFlowSchemas.js +126 -21
- package/src/emit/crud/templates/CreateConfirmComplete_Main.ejs +54 -0
- package/src/emit/crud/templates/CreateEndpoint_Main.ejs +248 -181
- package/src/emit/crud/templates/CreateLogicalLib.ejs +1155 -293
- package/src/emit/crud/templates/CreateNodeCallback_Main.ejs +221 -0
- package/src/emit/crud/templates/FlowEndpointRbacCallback_Main.ejs +20 -120
- package/src/emit/crud/templates/FlowEndpoint_HdrWbs.ejs +76 -14
- package/src/emit/crud/templates/FlowMain_Wbs.ejs +31 -35
- package/src/emit/rbac/templates/CancelUsage_Main.ejs +82 -22
- package/src/emit/rbac/templates/ConfirmUsage_Main.ejs +130 -14
- package/src/emit/rbac/templates/CreateTargetRole_Main.ejs +29 -10
- package/src/emit/rbac/templates/ReservedDynamicUsage_Main.ejs +30 -11
- package/src/emit/rbac/templates/UserRbacFlow_Main.ejs +28 -3
- package/src/emit/rbac/templates/UserRoleMutation_Main.ejs +10 -7
- package/src/emit/resource/emitResourceArtifacts.js +9 -0
- package/src/emit/resource/templates/GeneratedLambdaRoleServiceConfig.ejs +3 -1
- package/src/emit/resource/templates/SystemDynamoDB_Yaml.ejs +2 -0
- package/src/emit/shared/templates/FlowHandler_HdrSqs.ejs +1 -1
- package/src/emit/system/templates/WebSocketConnect_Yaml.ejs +0 -1
- package/test/dynamicCrudFlowSchemas.test.js +16 -2
- package/test/resourceArtifacts.test.js +21 -0
|
@@ -22,35 +22,68 @@ import { consts, NoRetryError } from '@izara_project/izara-core-library-core';
|
|
|
22
22
|
|
|
23
23
|
export default async function CancelUsage(_izContext, requestParams) {
|
|
24
24
|
try {
|
|
25
|
+
let runningTotalReservedId =
|
|
26
|
+
requestParams?.runningTotalReservedId ||
|
|
27
|
+
requestParams?.reservedId ||
|
|
28
|
+
requestParams?.runningTotalReservedUsageId;
|
|
29
|
+
|
|
30
|
+
const usedTimestampId =
|
|
31
|
+
requestParams?.usedTimestampId ||
|
|
32
|
+
requestParams?.uniqueIdentify;
|
|
33
|
+
|
|
25
34
|
const submittedByUserId =
|
|
26
|
-
requestParams
|
|
35
|
+
requestParams?.submittedByUserId ||
|
|
27
36
|
_izContext.correlationIds?.get(consts.SUBMITTED_BY_USER_ID);
|
|
28
|
-
const
|
|
37
|
+
const flowTypeConcat =
|
|
38
|
+
requestParams?.flowTypeConcat ||
|
|
39
|
+
requestParams?.limitTag;
|
|
29
40
|
|
|
30
|
-
const targetIdentifiers = requestParams
|
|
31
|
-
let identifiersConcat = requestParams
|
|
41
|
+
const targetIdentifiers = requestParams?.targetIdentifiers;
|
|
42
|
+
let identifiersConcat = requestParams?.identifiersConcat;
|
|
32
43
|
if (!identifiersConcat && targetIdentifiers && typeof targetIdentifiers === 'object') {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
if (targetIdentifiers.identifierConcat) {
|
|
45
|
+
identifiersConcat = targetIdentifiers.identifierConcat;
|
|
46
|
+
} else {
|
|
47
|
+
const sortedKeys = Object.keys(targetIdentifiers).sort();
|
|
48
|
+
const parts = [];
|
|
49
|
+
for (const key of sortedKeys) {
|
|
50
|
+
const value = targetIdentifiers[key];
|
|
51
|
+
if (
|
|
52
|
+
key !== 'submittedByUserId' &&
|
|
53
|
+
key !== 'identifierConcat' &&
|
|
54
|
+
value !== undefined &&
|
|
55
|
+
value !== null
|
|
56
|
+
) {
|
|
57
|
+
parts.push(`${key}#${value}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (parts.length > 0) {
|
|
61
|
+
identifiersConcat = parts.join('|');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
36
64
|
}
|
|
37
65
|
if (!identifiersConcat) {
|
|
38
66
|
identifiersConcat = submittedByUserId;
|
|
39
67
|
}
|
|
40
68
|
|
|
41
|
-
if (!
|
|
69
|
+
if (!runningTotalReservedId) {
|
|
70
|
+
if (identifiersConcat && flowTypeConcat) {
|
|
71
|
+
runningTotalReservedId = `${identifiersConcat}_${flowTypeConcat}`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!runningTotalReservedId || !usedTimestampId) {
|
|
42
76
|
throw new NoRetryError(
|
|
43
|
-
'identifiersConcat
|
|
77
|
+
'runningTotalReservedId (or identifiersConcat + flowTypeConcat) and usedTimestampId (or uniqueIdentify) are required.'
|
|
44
78
|
);
|
|
45
79
|
}
|
|
46
80
|
|
|
47
|
-
const runningTotalReservedId = `${identifiersConcat}_${limitTag}`;
|
|
48
81
|
const reservedRecord = await dynamodbSharedLib.getItem(
|
|
49
82
|
_izContext,
|
|
50
83
|
dynamodbSharedLib.tableName(_izContext, 'RunningTotalReservedUsage'),
|
|
51
84
|
{
|
|
52
85
|
runningTotalReservedId,
|
|
53
|
-
usedTimestampId
|
|
86
|
+
usedTimestampId
|
|
54
87
|
}
|
|
55
88
|
);
|
|
56
89
|
|
|
@@ -61,36 +94,63 @@ export default async function CancelUsage(_izContext, requestParams) {
|
|
|
61
94
|
dynamodbSharedLib.tableName(_izContext, 'RunningTotalReservedUsage'),
|
|
62
95
|
{
|
|
63
96
|
runningTotalReservedId,
|
|
64
|
-
usedTimestampId
|
|
97
|
+
usedTimestampId
|
|
65
98
|
},
|
|
66
99
|
{
|
|
67
100
|
runningTotalUsageStatus: 'cancelled'
|
|
68
101
|
}
|
|
69
102
|
);
|
|
70
103
|
|
|
71
|
-
if (usageCount > 0) {
|
|
104
|
+
if (usageCount > 0 && identifiersConcat && flowTypeConcat) {
|
|
72
105
|
const usageRecord = await dynamodbSharedLib.getItem(
|
|
73
106
|
_izContext,
|
|
74
107
|
dynamodbSharedLib.tableName(_izContext, 'RunningTotalUsage'),
|
|
75
|
-
{ identifiersConcat,
|
|
108
|
+
{ identifiersConcat, flowTypeConcat }
|
|
76
109
|
);
|
|
77
110
|
if (usageRecord) {
|
|
78
|
-
const
|
|
79
|
-
|
|
111
|
+
const currentTotal = usageRecord.totalCount || 0;
|
|
112
|
+
const newTotal = Math.max(0, currentTotal - usageCount);
|
|
113
|
+
const queryElementsWhenUpdate = {
|
|
114
|
+
additionalAttributes: { currentUuid: usageRecord.updateUuid },
|
|
115
|
+
logicalElements: [
|
|
116
|
+
{
|
|
117
|
+
type: 'logical',
|
|
118
|
+
comparison: 'equals',
|
|
119
|
+
lhsAttribute: 'updateUuid',
|
|
120
|
+
rhsReference: 'currentUuid'
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
returnValues: 'ALL_NEW'
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const updateAttributes = [
|
|
127
|
+
{ attributeName: 'totalCount', action: 'set', value: newTotal },
|
|
128
|
+
{ attributeName: 'updateUuid', action: 'set', value: _izContext.uniqueRequestId || `${Date.now()}` }
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
await dynamodbSharedLib.updateItem(
|
|
80
132
|
_izContext,
|
|
81
133
|
dynamodbSharedLib.tableName(_izContext, 'RunningTotalUsage'),
|
|
134
|
+
{ identifiersConcat, flowTypeConcat },
|
|
135
|
+
updateAttributes,
|
|
136
|
+
queryElementsWhenUpdate,
|
|
82
137
|
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
totalCount: newTotal,
|
|
86
|
-
updateUuid: _izContext.uniqueRequestId || `${Date.now()}`
|
|
138
|
+
complexAttributes: true,
|
|
139
|
+
errorOnConditionalExpNotPass: false
|
|
87
140
|
}
|
|
88
|
-
);
|
|
141
|
+
).catch(() => null);
|
|
89
142
|
}
|
|
90
143
|
}
|
|
91
144
|
|
|
92
145
|
await sns.publishMessage(_izContext, {
|
|
93
|
-
message: {
|
|
146
|
+
message: {
|
|
147
|
+
returnResult: {
|
|
148
|
+
status: true,
|
|
149
|
+
uniqueIdentify: usedTimestampId,
|
|
150
|
+
usedTimestampId,
|
|
151
|
+
runningTotalReservedId
|
|
152
|
+
}
|
|
153
|
+
},
|
|
94
154
|
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
95
155
|
_izContext,
|
|
96
156
|
'CancelUsage_Out'
|
|
@@ -22,43 +22,159 @@ import { consts, NoRetryError } from '@izara_project/izara-core-library-core';
|
|
|
22
22
|
|
|
23
23
|
export default async function ConfirmUsage(_izContext, requestParams) {
|
|
24
24
|
try {
|
|
25
|
+
let runningTotalReservedId =
|
|
26
|
+
requestParams?.runningTotalReservedId ||
|
|
27
|
+
requestParams?.reservedId ||
|
|
28
|
+
requestParams?.runningTotalReservedUsageId;
|
|
29
|
+
|
|
30
|
+
const usedTimestampId =
|
|
31
|
+
requestParams?.usedTimestampId ||
|
|
32
|
+
requestParams?.uniqueIdentify;
|
|
33
|
+
|
|
25
34
|
const submittedByUserId =
|
|
26
|
-
requestParams
|
|
35
|
+
requestParams?.submittedByUserId ||
|
|
27
36
|
_izContext.correlationIds?.get(consts.SUBMITTED_BY_USER_ID);
|
|
28
|
-
const
|
|
37
|
+
const flowTypeConcat =
|
|
38
|
+
requestParams?.flowTypeConcat ||
|
|
39
|
+
requestParams?.limitTag;
|
|
29
40
|
|
|
30
|
-
const targetIdentifiers = requestParams
|
|
31
|
-
let identifiersConcat = requestParams
|
|
41
|
+
const targetIdentifiers = requestParams?.targetIdentifiers;
|
|
42
|
+
let identifiersConcat = requestParams?.identifiersConcat;
|
|
32
43
|
if (!identifiersConcat && targetIdentifiers && typeof targetIdentifiers === 'object') {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
if (targetIdentifiers.identifierConcat) {
|
|
45
|
+
identifiersConcat = targetIdentifiers.identifierConcat;
|
|
46
|
+
} else {
|
|
47
|
+
const sortedKeys = Object.keys(targetIdentifiers).sort();
|
|
48
|
+
const parts = [];
|
|
49
|
+
for (const key of sortedKeys) {
|
|
50
|
+
const value = targetIdentifiers[key];
|
|
51
|
+
if (
|
|
52
|
+
key !== 'submittedByUserId' &&
|
|
53
|
+
key !== 'identifierConcat' &&
|
|
54
|
+
value !== undefined &&
|
|
55
|
+
value !== null
|
|
56
|
+
) {
|
|
57
|
+
parts.push(`${key}#${value}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (parts.length > 0) {
|
|
61
|
+
identifiersConcat = parts.join('|');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
36
64
|
}
|
|
37
65
|
if (!identifiersConcat) {
|
|
38
66
|
identifiersConcat = submittedByUserId;
|
|
39
67
|
}
|
|
40
68
|
|
|
41
|
-
if (!
|
|
69
|
+
if (!runningTotalReservedId) {
|
|
70
|
+
if (identifiersConcat && flowTypeConcat) {
|
|
71
|
+
runningTotalReservedId = `${identifiersConcat}_${flowTypeConcat}`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!runningTotalReservedId || !usedTimestampId) {
|
|
42
76
|
throw new NoRetryError(
|
|
43
|
-
'identifiersConcat
|
|
77
|
+
'runningTotalReservedId (or identifiersConcat + flowTypeConcat) and usedTimestampId (or uniqueIdentify) are required.'
|
|
44
78
|
);
|
|
45
79
|
}
|
|
46
80
|
|
|
47
|
-
const
|
|
81
|
+
const reservedTable = dynamodbSharedLib.tableName(
|
|
82
|
+
_izContext,
|
|
83
|
+
'RunningTotalReservedUsage'
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const reservedRecord = await dynamodbSharedLib
|
|
87
|
+
.getItem(_izContext, reservedTable, {
|
|
88
|
+
runningTotalReservedId,
|
|
89
|
+
usedTimestampId
|
|
90
|
+
})
|
|
91
|
+
.catch(() => null);
|
|
92
|
+
|
|
93
|
+
let usageCount = 1;
|
|
94
|
+
if (reservedRecord && typeof reservedRecord.usageCount === 'number') {
|
|
95
|
+
usageCount = reservedRecord.usageCount;
|
|
96
|
+
}
|
|
97
|
+
|
|
48
98
|
await dynamodbSharedLib.updateItem(
|
|
49
99
|
_izContext,
|
|
50
|
-
|
|
100
|
+
reservedTable,
|
|
51
101
|
{
|
|
52
102
|
runningTotalReservedId,
|
|
53
|
-
usedTimestampId
|
|
103
|
+
usedTimestampId
|
|
54
104
|
},
|
|
55
105
|
{
|
|
56
|
-
runningTotalUsageStatus: 'confirmed'
|
|
106
|
+
runningTotalUsageStatus: 'confirmed',
|
|
107
|
+
confirmedAt: new Date().toISOString()
|
|
57
108
|
}
|
|
58
109
|
);
|
|
59
110
|
|
|
111
|
+
if (identifiersConcat && flowTypeConcat) {
|
|
112
|
+
const usageTable = dynamodbSharedLib.tableName(
|
|
113
|
+
_izContext,
|
|
114
|
+
'RunningTotalUsage'
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const usageRecord = await dynamodbSharedLib
|
|
118
|
+
.getItem(_izContext, usageTable, {
|
|
119
|
+
identifiersConcat,
|
|
120
|
+
flowTypeConcat
|
|
121
|
+
})
|
|
122
|
+
.catch(() => null);
|
|
123
|
+
|
|
124
|
+
let currentTotal = 0;
|
|
125
|
+
let queryElementsWhenUpdate = {};
|
|
126
|
+
|
|
127
|
+
if (usageRecord && typeof usageRecord.totalCount === 'number') {
|
|
128
|
+
currentTotal = usageRecord.totalCount;
|
|
129
|
+
queryElementsWhenUpdate = {
|
|
130
|
+
additionalAttributes: { currentUuid: usageRecord.updateUuid },
|
|
131
|
+
logicalElements: [
|
|
132
|
+
{
|
|
133
|
+
type: 'logical',
|
|
134
|
+
comparison: 'equals',
|
|
135
|
+
lhsAttribute: 'updateUuid',
|
|
136
|
+
rhsReference: 'currentUuid'
|
|
137
|
+
}
|
|
138
|
+
],
|
|
139
|
+
returnValues: 'ALL_NEW'
|
|
140
|
+
};
|
|
141
|
+
} else {
|
|
142
|
+
queryElementsWhenUpdate = {
|
|
143
|
+
logicalElements: dynamodbSharedLib.generateNotExistLogicalElements({
|
|
144
|
+
identifiersConcat,
|
|
145
|
+
flowTypeConcat
|
|
146
|
+
}),
|
|
147
|
+
returnValues: 'ALL_NEW'
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const updateAttributes = [
|
|
152
|
+
{ attributeName: 'totalCount', action: 'set', value: currentTotal + usageCount },
|
|
153
|
+
{ attributeName: 'updateUuid', action: 'set', value: _izContext.uniqueRequestId || `${Date.now()}` }
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
await dynamodbSharedLib.updateItem(
|
|
157
|
+
_izContext,
|
|
158
|
+
usageTable,
|
|
159
|
+
{ identifiersConcat, flowTypeConcat },
|
|
160
|
+
updateAttributes,
|
|
161
|
+
queryElementsWhenUpdate,
|
|
162
|
+
{
|
|
163
|
+
complexAttributes: true,
|
|
164
|
+
errorOnConditionalExpNotPass: false
|
|
165
|
+
}
|
|
166
|
+
).catch(() => null);
|
|
167
|
+
}
|
|
168
|
+
|
|
60
169
|
await sns.publishMessage(_izContext, {
|
|
61
|
-
message: {
|
|
170
|
+
message: {
|
|
171
|
+
returnResult: {
|
|
172
|
+
status: true,
|
|
173
|
+
uniqueIdentify: usedTimestampId,
|
|
174
|
+
usedTimestampId,
|
|
175
|
+
runningTotalReservedId
|
|
176
|
+
}
|
|
177
|
+
},
|
|
62
178
|
TopicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
63
179
|
_izContext,
|
|
64
180
|
'ConfirmUsage_Out'
|
|
@@ -30,9 +30,26 @@ export default async function CreateTargetRole(_izContext, requestParams) {
|
|
|
30
30
|
const targetIdentifiers = requestParams.targetIdentifiers;
|
|
31
31
|
let identifiersConcat = requestParams.identifiersConcat;
|
|
32
32
|
if (!identifiersConcat && targetIdentifiers && typeof targetIdentifiers === 'object') {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
if (targetIdentifiers.identifierConcat) {
|
|
34
|
+
identifiersConcat = targetIdentifiers.identifierConcat;
|
|
35
|
+
} else {
|
|
36
|
+
const sortedKeys = Object.keys(targetIdentifiers).sort();
|
|
37
|
+
const parts = [];
|
|
38
|
+
for (const key of sortedKeys) {
|
|
39
|
+
const value = targetIdentifiers[key];
|
|
40
|
+
if (
|
|
41
|
+
key !== 'submittedByUserId' &&
|
|
42
|
+
key !== 'identifierConcat' &&
|
|
43
|
+
value !== undefined &&
|
|
44
|
+
value !== null
|
|
45
|
+
) {
|
|
46
|
+
parts.push(`${key}#${value}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (parts.length > 0) {
|
|
50
|
+
identifiersConcat = parts.join('|');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
36
53
|
}
|
|
37
54
|
if (!identifiersConcat) {
|
|
38
55
|
identifiersConcat = submittedByUserId;
|
|
@@ -57,20 +74,22 @@ export default async function CreateTargetRole(_izContext, requestParams) {
|
|
|
57
74
|
try {
|
|
58
75
|
await dynamodbSharedLib.transactWriteItems(_izContext, [
|
|
59
76
|
{
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
action: 'put',
|
|
78
|
+
params: {
|
|
79
|
+
tableName: dynamodbSharedLib.tableName(_izContext, 'RoleUsers'),
|
|
80
|
+
attributes: { roleIdKey, submittedByUserId }
|
|
63
81
|
}
|
|
64
82
|
},
|
|
65
83
|
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
84
|
+
action: 'put',
|
|
85
|
+
params: {
|
|
86
|
+
tableName: dynamodbSharedLib.tableName(_izContext, 'UserRoles'),
|
|
87
|
+
attributes: { submittedByUserId, roleIdKey }
|
|
69
88
|
}
|
|
70
89
|
}
|
|
71
90
|
]);
|
|
72
91
|
} catch (assignError) {
|
|
73
|
-
_izContext.logger.debug(`[${process.env.iz_serviceTag}:CreateTargetRole] UserRoles transactWrite ignored
|
|
92
|
+
_izContext.logger.debug(`[${process.env.iz_serviceTag}:CreateTargetRole] UserRoles transactWrite ignored:`, assignError);
|
|
74
93
|
}
|
|
75
94
|
}
|
|
76
95
|
|
|
@@ -25,8 +25,10 @@ export default async function ReservedDynamicUsage(_izContext, requestParams) {
|
|
|
25
25
|
const submittedByUserId =
|
|
26
26
|
requestParams.submittedByUserId ||
|
|
27
27
|
_izContext.correlationIds?.get(consts.SUBMITTED_BY_USER_ID);
|
|
28
|
+
const flowTypeConcat =
|
|
29
|
+
requestParams.flowTypeConcat ||
|
|
30
|
+
requestParams.limitTag;
|
|
28
31
|
const {
|
|
29
|
-
limitTag,
|
|
30
32
|
value = 1,
|
|
31
33
|
usedTimestamp = new Date().toISOString(),
|
|
32
34
|
roleLimitId
|
|
@@ -35,9 +37,26 @@ export default async function ReservedDynamicUsage(_izContext, requestParams) {
|
|
|
35
37
|
const targetIdentifiers = requestParams.targetIdentifiers;
|
|
36
38
|
let identifiersConcat = requestParams.identifiersConcat;
|
|
37
39
|
if (!identifiersConcat && targetIdentifiers && typeof targetIdentifiers === 'object') {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
if (targetIdentifiers.identifierConcat) {
|
|
41
|
+
identifiersConcat = targetIdentifiers.identifierConcat;
|
|
42
|
+
} else {
|
|
43
|
+
const sortedKeys = Object.keys(targetIdentifiers).sort();
|
|
44
|
+
const parts = [];
|
|
45
|
+
for (const key of sortedKeys) {
|
|
46
|
+
const value = targetIdentifiers[key];
|
|
47
|
+
if (
|
|
48
|
+
key !== 'submittedByUserId' &&
|
|
49
|
+
key !== 'identifierConcat' &&
|
|
50
|
+
value !== undefined &&
|
|
51
|
+
value !== null
|
|
52
|
+
) {
|
|
53
|
+
parts.push(`${key}#${value}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (parts.length > 0) {
|
|
57
|
+
identifiersConcat = parts.join('|');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
41
60
|
}
|
|
42
61
|
if (!identifiersConcat) {
|
|
43
62
|
identifiersConcat = submittedByUserId;
|
|
@@ -46,14 +65,14 @@ export default async function ReservedDynamicUsage(_izContext, requestParams) {
|
|
|
46
65
|
if (!identifiersConcat) {
|
|
47
66
|
throw new NoRetryError('Identifier not found.');
|
|
48
67
|
}
|
|
49
|
-
if (!
|
|
50
|
-
throw new NoRetryError('limitTag is required.');
|
|
68
|
+
if (!flowTypeConcat) {
|
|
69
|
+
throw new NoRetryError('flowTypeConcat (or limitTag) is required.');
|
|
51
70
|
}
|
|
52
71
|
|
|
53
72
|
const uniqueIdentify = `${usedTimestamp}_${_izContext.uniqueRequestId || Date.now()}`;
|
|
54
73
|
const roleLimitKeys = Array.isArray(requestParams.roleLimitIds)
|
|
55
74
|
? requestParams.roleLimitIds
|
|
56
|
-
: [roleLimitId || `${identifiersConcat}_${
|
|
75
|
+
: [roleLimitId || `${identifiersConcat}_${flowTypeConcat}`];
|
|
57
76
|
|
|
58
77
|
let maxLimit = Infinity;
|
|
59
78
|
const limitRecords = [];
|
|
@@ -93,7 +112,7 @@ export default async function ReservedDynamicUsage(_izContext, requestParams) {
|
|
|
93
112
|
const usageRecord = await dynamodbSharedLib.getItem(
|
|
94
113
|
_izContext,
|
|
95
114
|
dynamodbSharedLib.tableName(_izContext, 'RunningTotalUsage'),
|
|
96
|
-
{ identifiersConcat,
|
|
115
|
+
{ identifiersConcat, flowTypeConcat }
|
|
97
116
|
);
|
|
98
117
|
const currentTotal = usageRecord?.totalCount || 0;
|
|
99
118
|
|
|
@@ -106,7 +125,7 @@ export default async function ReservedDynamicUsage(_izContext, requestParams) {
|
|
|
106
125
|
_izContext,
|
|
107
126
|
dynamodbSharedLib.tableName(_izContext, 'RunningTotalReservedUsage'),
|
|
108
127
|
{
|
|
109
|
-
runningTotalReservedId: `${identifiersConcat}_${
|
|
128
|
+
runningTotalReservedId: `${identifiersConcat}_${flowTypeConcat}`,
|
|
110
129
|
usedTimestampId: uniqueIdentify,
|
|
111
130
|
usageCount: value,
|
|
112
131
|
runningTotalUsageStatus: 'reserved',
|
|
@@ -119,7 +138,7 @@ export default async function ReservedDynamicUsage(_izContext, requestParams) {
|
|
|
119
138
|
dynamodbSharedLib.tableName(_izContext, 'RunningTotalUsage'),
|
|
120
139
|
{
|
|
121
140
|
identifiersConcat,
|
|
122
|
-
|
|
141
|
+
flowTypeConcat,
|
|
123
142
|
totalCount: currentTotal + value,
|
|
124
143
|
updateUuid: _izContext.uniqueRequestId || `${Date.now()}`
|
|
125
144
|
}
|
|
@@ -129,7 +148,7 @@ export default async function ReservedDynamicUsage(_izContext, requestParams) {
|
|
|
129
148
|
const returnResult = {
|
|
130
149
|
passStatus,
|
|
131
150
|
uniqueIdentify,
|
|
132
|
-
|
|
151
|
+
flowTypeConcat,
|
|
133
152
|
identifiersConcat
|
|
134
153
|
};
|
|
135
154
|
|
|
@@ -92,12 +92,37 @@ async function _setL2Cache(_izContext, submittedByUserId, cacheSubKey, value) {
|
|
|
92
92
|
export default async function <%- flowTag %>(_izContext, requestParams = {}) {
|
|
93
93
|
const submittedByUserId =
|
|
94
94
|
requestParams.submittedByUserId ||
|
|
95
|
+
requestParams.targetIdentifiers?.submittedByUserId ||
|
|
95
96
|
_izContext.correlationIds.get(consts.SUBMITTED_BY_USER_ID);
|
|
96
97
|
|
|
97
98
|
const targetIdentifiers = requestParams.targetIdentifiers;
|
|
98
|
-
let targetId =
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
let targetId = '';
|
|
100
|
+
if (targetIdentifiers) {
|
|
101
|
+
if (typeof targetIdentifiers === 'string') {
|
|
102
|
+
targetId = targetIdentifiers;
|
|
103
|
+
} else if (typeof targetIdentifiers === 'object') {
|
|
104
|
+
if (targetIdentifiers.identifierConcat) {
|
|
105
|
+
targetId = targetIdentifiers.identifierConcat;
|
|
106
|
+
} else {
|
|
107
|
+
const sortedKeys = Object.keys(targetIdentifiers).sort();
|
|
108
|
+
const parts = [];
|
|
109
|
+
for (const key of sortedKeys) {
|
|
110
|
+
const value = targetIdentifiers[key];
|
|
111
|
+
if (
|
|
112
|
+
key !== 'submittedByUserId' &&
|
|
113
|
+
key !== 'identifierConcat' &&
|
|
114
|
+
value !== undefined &&
|
|
115
|
+
value !== null
|
|
116
|
+
) {
|
|
117
|
+
parts.push(`${key}#${value}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (parts.length > 0) {
|
|
121
|
+
targetId = parts.join('|');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
101
126
|
|
|
102
127
|
if (!submittedByUserId || !targetIdentifiers) {
|
|
103
128
|
throw new Error('Missing required request parameters: submittedByUserId or targetIdentifiers');
|
|
@@ -16,7 +16,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
<%
|
|
19
|
-
const
|
|
19
|
+
const action = operation === 'Put' ? 'put' : 'delete';
|
|
20
|
+
const propName = operation === 'Put' ? 'attributes' : 'keyValues';
|
|
20
21
|
const roleUsersKey = operation === 'Put' ? 'userId, roleIdKey' : 'roleIdKey, userId';
|
|
21
22
|
-%> import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
22
23
|
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
@@ -27,15 +28,17 @@ export default async function <%- flowTag %>(_izContext, requestParams) {
|
|
|
27
28
|
const { roleIdKey, userId } = requestParams;
|
|
28
29
|
await dynamodbSharedLib.transactWriteItems(_izContext, [
|
|
29
30
|
{
|
|
30
|
-
<%-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
action: '<%- action %>',
|
|
32
|
+
params: {
|
|
33
|
+
tableName: dynamodbSharedLib.tableName(_izContext, 'RoleUsers'),
|
|
34
|
+
<%- propName %>: { <%- roleUsersKey %> }
|
|
33
35
|
}
|
|
34
36
|
},
|
|
35
37
|
{
|
|
36
|
-
<%-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
action: '<%- action %>',
|
|
39
|
+
params: {
|
|
40
|
+
tableName: dynamodbSharedLib.tableName(_izContext, 'UserRoles'),
|
|
41
|
+
<%- propName %>: { userId, roleIdKey }
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
44
|
]);
|
|
@@ -215,6 +215,9 @@ function createResourceState({ objects, relationships, flows }) {
|
|
|
215
215
|
if (crud) {
|
|
216
216
|
for (const action of ['Create', 'Update', 'Delete']) {
|
|
217
217
|
const plan = crudActionPlans[action];
|
|
218
|
+
if (plan.hasCreateNodeCallback) {
|
|
219
|
+
crudSqsQueues.push(`${action}NodeCallbackHdrSqs`);
|
|
220
|
+
}
|
|
218
221
|
if (plan.hasComplete) {
|
|
219
222
|
crudSqsQueues.push(`${action}CompleteHdrSqs`);
|
|
220
223
|
}
|
|
@@ -474,6 +477,9 @@ function createResourceState({ objects, relationships, flows }) {
|
|
|
474
477
|
flow.initiateBy === 'systemWithUser'))) &&
|
|
475
478
|
upperFirst(flow.flowTag) === topic
|
|
476
479
|
) ||
|
|
480
|
+
(objects.length > 0 &&
|
|
481
|
+
topic !== 'Get' &&
|
|
482
|
+
CRUD_ACTIONS.includes(topic)) ||
|
|
477
483
|
(relationships.length > 0 &&
|
|
478
484
|
topic !== 'GetRelationship' &&
|
|
479
485
|
RELATIONSHIP_ACTIONS.includes(topic))
|
|
@@ -832,6 +838,9 @@ function roleQueueNames(state, roleName) {
|
|
|
832
838
|
if (!plan.outputTopic) return [];
|
|
833
839
|
return [
|
|
834
840
|
`${action}HdrSqs`,
|
|
841
|
+
...(plan.hasCreateNodeCallback
|
|
842
|
+
? [`${action}NodeCallbackHdrSqs`]
|
|
843
|
+
: []),
|
|
835
844
|
...(plan.hasRbacCallback
|
|
836
845
|
? [`${action}RbacCallbackHdrSqs`]
|
|
837
846
|
: []),
|
|
@@ -56,7 +56,9 @@ export function generatedLambdaRole() {
|
|
|
56
56
|
Effect: 'Allow',
|
|
57
57
|
Action: ['sns:Publish'],
|
|
58
58
|
Resource: [
|
|
59
|
-
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', 'Rbac')}
|
|
59
|
+
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', 'Rbac')}`,
|
|
60
|
+
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ConfirmUsage_In', 'Rbac')}`,
|
|
61
|
+
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'CancelUsage_In', 'Rbac')}`<% (rbacValidatorServiceTags || []).forEach(function(tag) { %>,
|
|
60
62
|
`arn:aws:sns:${process.env.iz_region}:${process.env.iz_accountId}:${snsSharedLib.snsTopicNameByFlowSchema(_izContext, 'ValidatorRbac_In', '<%= tag %>')}`<% }); %>
|
|
61
63
|
]
|
|
62
64
|
}<% } %>
|
|
@@ -88,7 +88,7 @@ export const main = middleware.wrap(async (event, context) => {
|
|
|
88
88
|
|
|
89
89
|
// add argument (to invoke lambda) to passOnProperties[]
|
|
90
90
|
passOnProperties.push(record.body.Message);
|
|
91
|
-
<% if (typeof usePassBack === 'undefined' ? functionName.endsWith('Complete') : usePassBack) { %>
|
|
91
|
+
<% if (typeof usePassBack === 'undefined' ? (functionName.endsWith('Complete') || functionName.endsWith('CompleteMain') || functionName.includes('Callback')) : usePassBack) { %>
|
|
92
92
|
passOnProperties.push(
|
|
93
93
|
callingFlowSharedLib.addPassBackPropertiesToPassOnProperties(
|
|
94
94
|
record.body.Message
|
|
@@ -9,7 +9,6 @@ WebSocketConnect:
|
|
|
9
9
|
authorizer:
|
|
10
10
|
arn: arn:aws:lambda:${self:custom.iz_region}:${self:custom.iz_accountId}:function:UserAccount${self:custom.iz_stage}UserIdentityAuthorizer
|
|
11
11
|
identitySource:
|
|
12
|
-
- 'route.request.header.Authorization'
|
|
13
12
|
- 'route.request.querystring.access_token'
|
|
14
13
|
#<#/WebSocketConnectAuthorizer#>
|
|
15
14
|
- websocket:
|
|
@@ -161,6 +161,7 @@ test('generates RbacCallback and Complete for Create when RBAC and Graph are pre
|
|
|
161
161
|
assert.deepEqual(create.flowSteps.map((step) => step.stepName), [
|
|
162
162
|
'Start',
|
|
163
163
|
'RbacCallback',
|
|
164
|
+
'CreateNodeCallback',
|
|
164
165
|
'Complete'
|
|
165
166
|
]);
|
|
166
167
|
});
|
|
@@ -186,6 +187,7 @@ test('uses the renamed RBAC callback step when Graph storage is present', async
|
|
|
186
187
|
assert.deepEqual(create.flowSteps.map((step) => step.stepName), [
|
|
187
188
|
'Start',
|
|
188
189
|
'RbacCallback',
|
|
190
|
+
'CreateNodeCallback',
|
|
189
191
|
'Complete'
|
|
190
192
|
]);
|
|
191
193
|
assert.deepEqual(create.flowSteps[2].properties, [
|
|
@@ -221,10 +223,22 @@ test('chains RbacCallback and Complete for Update with RBAC and Graph', async ()
|
|
|
221
223
|
'Complete'
|
|
222
224
|
]);
|
|
223
225
|
assert.deepEqual(update.flowSteps[0].nextSteps, [
|
|
224
|
-
{ targetType: 'ownTopic', stepName: 'RbacCallback' }
|
|
226
|
+
{ targetType: 'ownTopic', stepName: 'RbacCallback' },
|
|
227
|
+
{
|
|
228
|
+
targetType: 'extTopic',
|
|
229
|
+
serviceTag: 'Rbac',
|
|
230
|
+
topicName: 'ValidatorRbac_In',
|
|
231
|
+
toStepNames: ['RbacCallback']
|
|
232
|
+
}
|
|
225
233
|
]);
|
|
226
234
|
assert.deepEqual(update.flowSteps[1].nextSteps, [
|
|
227
|
-
{ targetType: 'ownTopic', stepName: 'Complete' }
|
|
235
|
+
{ targetType: 'ownTopic', stepName: 'Complete' },
|
|
236
|
+
{
|
|
237
|
+
targetType: 'extTopic',
|
|
238
|
+
serviceTag: 'GraphHandler',
|
|
239
|
+
topicName: 'UpdateNode_In',
|
|
240
|
+
toStepNames: ['Complete']
|
|
241
|
+
}
|
|
228
242
|
]);
|
|
229
243
|
assert.deepEqual(update.flowSteps[2].properties, [
|
|
230
244
|
'returnValue',
|