@reventlessdev/reventless-aws 3.0.0-alpha.395 → 3.0.0-alpha.396

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/package.json +7 -7
  3. package/scripts/DeployApp.res +7 -1
  4. package/scripts/DeployApp.res.mjs +1 -1
  5. package/scripts/ProvisionAccounts.res +89 -4
  6. package/scripts/ProvisionAccounts.res.mjs +101 -5
  7. package/scripts/ProvisionIdentity.res +42 -18
  8. package/scripts/ProvisionIdentity.res.mjs +40 -26
  9. package/src/Platform.res +47 -10
  10. package/src/Platform.res.mjs +44 -10
  11. package/src/Platform_Stack.res +17 -0
  12. package/src/Platform_Stack.res.mjs +7 -1
  13. package/src/adapter/Auth/Auth_ActiveRoleTrigger.res +16 -7
  14. package/src/adapter/Auth/Auth_ActiveRoleTrigger.res.mjs +16 -3
  15. package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res +59 -9
  16. package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res.mjs +53 -6
  17. package/src/adapter/Auth/Auth_Cognito.res +13 -2
  18. package/src/adapter/Auth/Auth_Cognito.res.mjs +9 -2
  19. package/src/adapter/Auth/Auth_IdentityStore.res +52 -0
  20. package/src/adapter/Auth/Auth_IdentityStore.res.mjs +46 -0
  21. package/src/adapter/Auth/Auth_IdentityStore_Schema.res +39 -0
  22. package/src/adapter/Auth/Auth_IdentityStore_Schema.res.mjs +35 -0
  23. package/src/adapter/Identity/IdentityProvider_Cognito_Backend.res +251 -0
  24. package/src/adapter/Identity/IdentityProvider_Cognito_Backend.res.mjs +300 -0
  25. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +7 -4
  26. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +2 -2
  27. package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +80 -0
  28. package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res.mjs +53 -2
  29. package/src/components/AutomationSlice_Builder.res.mjs +1 -1
  30. package/src/components/OutboundTranslationSlice_Builder.res +2 -0
  31. package/src/components/OutboundTranslationSlice_Builder.res.mjs +1 -1
  32. package/src/plugin/runtime/PluginRuntime_Builder.res +23 -0
  33. package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +29 -0
  34. package/tests/Auth_ActiveRoleTrigger_OpsTest.res +40 -0
  35. package/tests/Auth_ActiveRoleTrigger_OpsTest.res.mjs +59 -8
  36. package/tests/Auth_CognitoTest.res +62 -0
  37. package/tests/Auth_CognitoTest.res.mjs +98 -0
  38. package/tests/Auth_IdentityStore_SchemaTest.res +35 -0
  39. package/tests/Auth_IdentityStore_SchemaTest.res.mjs +43 -0
  40. package/tests/IdentityProvider_Cognito_BackendTest.res +314 -0
  41. package/tests/IdentityProvider_Cognito_BackendTest.res.mjs +442 -0
  42. package/tests/ProvisionAccountsTest.res.mjs +1 -1
@@ -0,0 +1,442 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
4
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
+ import * as Pulumi from "@pulumi/pulumi";
6
+ import * as Auth_UserId$ReventlessCore from "@reventlessdev/reventless-core/src/adapter/Auth/Auth_UserId.res.mjs";
7
+ import * as IdentityProvider_Cognito_Backend$ReventlessAws from "../src/adapter/Identity/IdentityProvider_Cognito_Backend.res.mjs";
8
+ import * as AutomationSliceRuntime_Builder_Single$ReventlessAws from "../src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res.mjs";
9
+
10
+ function awsError(code) {
11
+ let e = new Error(code + `: from the fake pool`);
12
+ e.name = code;
13
+ return e;
14
+ }
15
+
16
+ function fakeOps(pool, failOn) {
17
+ let record = step => {
18
+ pool.calls.push(step);
19
+ if (failOn === undefined) {
20
+ return;
21
+ }
22
+ if (failOn[0] !== step) {
23
+ return;
24
+ }
25
+ throw awsError(failOn[1]);
26
+ };
27
+ return {
28
+ createUser: async (username, param) => {
29
+ record("createUser");
30
+ if (username in pool.users) {
31
+ throw awsError("UsernameExistsException");
32
+ }
33
+ let sub = `sub-` + username;
34
+ pool.users[username] = [
35
+ sub,
36
+ []
37
+ ];
38
+ return sub;
39
+ },
40
+ subOf: async username => {
41
+ record("subOf");
42
+ let match = pool.users[username];
43
+ if (match !== undefined) {
44
+ return match[0];
45
+ }
46
+ throw awsError("UserNotFoundException");
47
+ },
48
+ setPassword: async (param, param$1) => record("setPassword"),
49
+ addToGroup: async (username, group) => {
50
+ record("addToGroup");
51
+ let match = pool.users[username];
52
+ if (match !== undefined) {
53
+ pool.users[username] = [
54
+ match[0],
55
+ match[1].concat([group])
56
+ ];
57
+ return;
58
+ }
59
+ throw awsError("UserNotFoundException");
60
+ },
61
+ removeFromGroup: async (username, group) => {
62
+ record("removeFromGroup");
63
+ let match = pool.users[username];
64
+ if (match !== undefined) {
65
+ pool.users[username] = [
66
+ match[0],
67
+ match[1].filter(g => g !== group)
68
+ ];
69
+ return;
70
+ }
71
+ throw awsError("UserNotFoundException");
72
+ },
73
+ deleteUser: async username => {
74
+ record("deleteUser");
75
+ if (!(username in pool.users)) {
76
+ throw awsError("UserNotFoundException");
77
+ }
78
+ return Stdlib_Dict.$$delete(pool.users, username);
79
+ },
80
+ putUserId: async (sub, userId) => {
81
+ record("putUserId");
82
+ pool.rows[sub] = userId;
83
+ },
84
+ deleteUserId: async sub => {
85
+ record("deleteUserId");
86
+ return Stdlib_Dict.$$delete(pool.rows, sub);
87
+ }
88
+ };
89
+ }
90
+
91
+ function emptyPool() {
92
+ return {
93
+ users: {},
94
+ rows: {},
95
+ calls: []
96
+ };
97
+ }
98
+
99
+ function email(address) {
100
+ return {
101
+ TAG: "ToEmail",
102
+ _0: address
103
+ };
104
+ }
105
+
106
+ globalThis.describe("IdentityProvider_Cognito_Backend", () => {
107
+ globalThis.test("creates the principal, sets its password and groups, and mints its id", async () => {
108
+ let pool_users = {};
109
+ let pool_rows = {};
110
+ let pool_calls = [];
111
+ let pool = {
112
+ users: pool_users,
113
+ rows: pool_rows,
114
+ calls: pool_calls
115
+ };
116
+ let provider = IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, undefined), true);
117
+ let answer = await provider.createPrincipal({
118
+ TAG: "ToEmail",
119
+ _0: "new@example.com"
120
+ }, {
121
+ TAG: "Password",
122
+ _0: "pw"
123
+ }, ["Shopper"]);
124
+ globalThis.expect(answer).toEqual({
125
+ TAG: "Ok",
126
+ _0: {
127
+ providerId: "new@example.com"
128
+ }
129
+ });
130
+ globalThis.expect(pool_users["new@example.com"]).toEqual([
131
+ "sub-new@example.com",
132
+ ["Shopper"]
133
+ ]);
134
+ globalThis.expect(Stdlib_Option.map(pool_rows["sub-new@example.com"], Auth_UserId$ReventlessCore.isMinted)).toEqual(true);
135
+ });
136
+ globalThis.test("an existing account is a Conflict, not an outage", async () => {
137
+ let pool_users = {};
138
+ let pool_rows = {};
139
+ let pool_calls = [];
140
+ let pool = {
141
+ users: pool_users,
142
+ rows: pool_rows,
143
+ calls: pool_calls
144
+ };
145
+ let provider = IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, undefined), true);
146
+ let create = () => provider.createPrincipal({
147
+ TAG: "ToEmail",
148
+ _0: "twice@example.com"
149
+ }, "NoCredential", []);
150
+ await create();
151
+ globalThis.expect(await create()).toEqual({
152
+ TAG: "Error",
153
+ _0: "Conflict"
154
+ });
155
+ });
156
+ globalThis.test("a later step failing undoes the account, so a retry starts clean", async () => {
157
+ let pool_users = {};
158
+ let pool_rows = {};
159
+ let pool_calls = [];
160
+ let pool = {
161
+ users: pool_users,
162
+ rows: pool_rows,
163
+ calls: pool_calls
164
+ };
165
+ let failing = IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, [
166
+ "addToGroup",
167
+ "TooManyRequestsException"
168
+ ]), true);
169
+ let first = await failing.createPrincipal({
170
+ TAG: "ToEmail",
171
+ _0: "retry@example.com"
172
+ }, {
173
+ TAG: "Password",
174
+ _0: "pw"
175
+ }, ["Shopper"]);
176
+ let tmp;
177
+ if (first.TAG === "Ok") {
178
+ tmp = false;
179
+ } else {
180
+ let tmp$1 = first._0;
181
+ tmp = typeof tmp$1 !== "object" ? false : tmp$1.TAG === "Unavailable";
182
+ }
183
+ globalThis.expect(tmp).toBe(true);
184
+ globalThis.expect("retry@example.com" in pool_users).toBe(false);
185
+ globalThis.expect(Object.keys(pool_rows)).toEqual([]);
186
+ let healthy = IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, undefined), true);
187
+ let second = await healthy.createPrincipal({
188
+ TAG: "ToEmail",
189
+ _0: "retry@example.com"
190
+ }, {
191
+ TAG: "Password",
192
+ _0: "pw"
193
+ }, ["Shopper"]);
194
+ globalThis.expect(second).toEqual({
195
+ TAG: "Ok",
196
+ _0: {
197
+ providerId: "retry@example.com"
198
+ }
199
+ });
200
+ });
201
+ globalThis.test("a password the pool's policy rejects is Refused, and undone", async () => {
202
+ let pool_users = {};
203
+ let pool_rows = {};
204
+ let pool_calls = [];
205
+ let pool = {
206
+ users: pool_users,
207
+ rows: pool_rows,
208
+ calls: pool_calls
209
+ };
210
+ let provider = IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, [
211
+ "setPassword",
212
+ "InvalidPasswordException"
213
+ ]), true);
214
+ let answer = await provider.createPrincipal({
215
+ TAG: "ToEmail",
216
+ _0: "weak@example.com"
217
+ }, {
218
+ TAG: "Password",
219
+ _0: "1"
220
+ }, []);
221
+ let tmp;
222
+ if (answer.TAG === "Ok") {
223
+ tmp = false;
224
+ } else {
225
+ let tmp$1 = answer._0;
226
+ tmp = typeof tmp$1 !== "object" ? false : tmp$1.TAG !== "Unavailable";
227
+ }
228
+ globalThis.expect(tmp).toBe(true);
229
+ globalThis.expect("weak@example.com" in pool_users).toBe(false);
230
+ });
231
+ globalThis.test("NoCredential sets no password", async () => {
232
+ let pool_users = {};
233
+ let pool_rows = {};
234
+ let pool_calls = [];
235
+ let pool = {
236
+ users: pool_users,
237
+ rows: pool_rows,
238
+ calls: pool_calls
239
+ };
240
+ let provider = IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, undefined), true);
241
+ await provider.createPrincipal({
242
+ TAG: "ToEmail",
243
+ _0: "later@example.com"
244
+ }, "NoCredential", []);
245
+ globalThis.expect(pool_calls.includes("setPassword")).toBe(false);
246
+ });
247
+ globalThis.test("without a store, no id is minted", async () => {
248
+ let pool_users = {};
249
+ let pool_rows = {};
250
+ let pool_calls = [];
251
+ let pool = {
252
+ users: pool_users,
253
+ rows: pool_rows,
254
+ calls: pool_calls
255
+ };
256
+ let provider = IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, undefined), false);
257
+ await provider.createPrincipal({
258
+ TAG: "ToEmail",
259
+ _0: "old@example.com"
260
+ }, "NoCredential", []);
261
+ globalThis.expect(pool_calls.includes("putUserId")).toBe(false);
262
+ globalThis.expect("old@example.com" in pool_users).toBe(true);
263
+ });
264
+ globalThis.test("a push address is refused before the pool is asked", async () => {
265
+ let pool_users = {};
266
+ let pool_rows = {};
267
+ let pool_calls = [];
268
+ let pool = {
269
+ users: pool_users,
270
+ rows: pool_rows,
271
+ calls: pool_calls
272
+ };
273
+ let provider = IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, undefined), true);
274
+ let answer = await provider.createPrincipal({
275
+ TAG: "ToPush",
276
+ _0: {
277
+ TAG: "Fcm",
278
+ registrationToken: "tok"
279
+ }
280
+ }, "NoCredential", []);
281
+ let tmp;
282
+ if (answer.TAG === "Ok") {
283
+ tmp = false;
284
+ } else {
285
+ let tmp$1 = answer._0;
286
+ tmp = typeof tmp$1 !== "object" ? false : tmp$1.TAG !== "Unavailable";
287
+ }
288
+ globalThis.expect(tmp).toBe(true);
289
+ globalThis.expect(pool_calls).toEqual([]);
290
+ });
291
+ globalThis.test("groups change on the pool, and an unknown principal is Refused", async () => {
292
+ let pool_users = {};
293
+ let pool_rows = {};
294
+ let pool_calls = [];
295
+ let pool = {
296
+ users: pool_users,
297
+ rows: pool_rows,
298
+ calls: pool_calls
299
+ };
300
+ let provider = IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, undefined), true);
301
+ let principal = {
302
+ providerId: "grp@example.com"
303
+ };
304
+ await provider.createPrincipal({
305
+ TAG: "ToEmail",
306
+ _0: "grp@example.com"
307
+ }, "NoCredential", ["Shopper"]);
308
+ globalThis.expect(await provider.addToGroup(principal, "Reviewer")).toEqual({
309
+ TAG: "Ok",
310
+ _0: undefined
311
+ });
312
+ globalThis.expect(await provider.removeFromGroup(principal, "Shopper")).toEqual({
313
+ TAG: "Ok",
314
+ _0: undefined
315
+ });
316
+ globalThis.expect(pool_users["grp@example.com"]).toEqual([
317
+ "sub-grp@example.com",
318
+ ["Reviewer"]
319
+ ]);
320
+ let match = await provider.addToGroup({
321
+ providerId: "ghost"
322
+ }, "Shopper");
323
+ let tmp;
324
+ if (match.TAG === "Ok") {
325
+ tmp = false;
326
+ } else {
327
+ let tmp$1 = match._0;
328
+ tmp = typeof tmp$1 !== "object" ? false : tmp$1.TAG !== "Unavailable";
329
+ }
330
+ globalThis.expect(tmp).toBe(true);
331
+ });
332
+ globalThis.test("deleting removes the account and its row, and a second delete is Ok", async () => {
333
+ let pool_users = {};
334
+ let pool_rows = {};
335
+ let pool_calls = [];
336
+ let pool = {
337
+ users: pool_users,
338
+ rows: pool_rows,
339
+ calls: pool_calls
340
+ };
341
+ let provider = IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, undefined), true);
342
+ let principal = {
343
+ providerId: "gone@example.com"
344
+ };
345
+ await provider.createPrincipal({
346
+ TAG: "ToEmail",
347
+ _0: "gone@example.com"
348
+ }, "NoCredential", []);
349
+ globalThis.expect(await provider.deletePrincipal(principal)).toEqual({
350
+ TAG: "Ok",
351
+ _0: undefined
352
+ });
353
+ globalThis.expect("gone@example.com" in pool_users).toBe(false);
354
+ globalThis.expect("sub-gone@example.com" in pool_rows).toBe(false);
355
+ globalThis.expect(await provider.deletePrincipal(principal)).toEqual({
356
+ TAG: "Ok",
357
+ _0: undefined
358
+ });
359
+ });
360
+ globalThis.test("an outage while deleting is retried, not reported as done", async () => {
361
+ let pool_users = {};
362
+ let pool_rows = {};
363
+ let pool_calls = [];
364
+ let pool = {
365
+ users: pool_users,
366
+ rows: pool_rows,
367
+ calls: pool_calls
368
+ };
369
+ await IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, undefined), true).createPrincipal({
370
+ TAG: "ToEmail",
371
+ _0: "busy@example.com"
372
+ }, "NoCredential", []);
373
+ let failing = IdentityProvider_Cognito_Backend$ReventlessAws.withOps(fakeOps(pool, [
374
+ "deleteUser",
375
+ "TooManyRequestsException"
376
+ ]), true);
377
+ let match = await failing.deletePrincipal({
378
+ providerId: "busy@example.com"
379
+ });
380
+ let tmp;
381
+ if (match.TAG === "Ok") {
382
+ tmp = false;
383
+ } else {
384
+ let tmp$1 = match._0;
385
+ tmp = typeof tmp$1 !== "object" ? false : tmp$1.TAG === "Unavailable";
386
+ }
387
+ globalThis.expect(tmp).toBe(true);
388
+ globalThis.expect("busy@example.com" in pool_users).toBe(true);
389
+ });
390
+ globalThis.test("no pool configured answers Unavailable with no operations", () => {
391
+ globalThis.expect(IdentityProvider_Cognito_Backend$ReventlessAws.provider("", "").operations).toEqual([]);
392
+ });
393
+ globalThis.test("a configured pool publishes all four operations", () => {
394
+ globalThis.expect(IdentityProvider_Cognito_Backend$ReventlessAws.provider("eu-west-1_X", "t").operations).toEqual([
395
+ "CreatePrincipal",
396
+ "AddToGroup",
397
+ "RemoveFromGroup",
398
+ "DeletePrincipal"
399
+ ]);
400
+ });
401
+ });
402
+
403
+ globalThis.describe("AutomationSliceRuntime_Builder_Single.declaresIdentityProvider", () => {
404
+ let info = needs => ({
405
+ specModulePath: "",
406
+ bodyModulePath: "",
407
+ callbackType: "outbound",
408
+ queryDbTableName: Pulumi.output(""),
409
+ queryDbResources: [],
410
+ context: undefined,
411
+ sourceTopics: {},
412
+ consumesDcbLog: true,
413
+ commandTargetName: undefined,
414
+ schedule: undefined,
415
+ schedulesResources: [],
416
+ capabilityNeeds: needs
417
+ });
418
+ globalThis.test("only a slice declaring the need earns the grant", () => {
419
+ globalThis.expect(AutomationSliceRuntime_Builder_Single$ReventlessAws.declaresIdentityProvider([
420
+ info(["Messaging"]),
421
+ info([])
422
+ ])).toBe(false);
423
+ globalThis.expect(AutomationSliceRuntime_Builder_Single$ReventlessAws.declaresIdentityProvider([
424
+ info(["Messaging"]),
425
+ info(["IdentityProvider"])
426
+ ])).toBe(true);
427
+ });
428
+ });
429
+
430
+ let Backend;
431
+
432
+ let IP;
433
+
434
+ export {
435
+ Backend,
436
+ IP,
437
+ awsError,
438
+ fakeOps,
439
+ emptyPool,
440
+ email,
441
+ }
442
+ /* Not a pure module */
@@ -162,7 +162,7 @@ globalThis.describe("ProvisionAccounts.provision", () => {
162
162
  TAG: "Error",
163
163
  _0: "pool signs in on email"
164
164
  });
165
- let outcome = await ProvisionAccounts$ReventlessAws.provision(file, "eu-west-1_Refuses", refuse);
165
+ let outcome = await ProvisionAccounts$ReventlessAws.provision(file, "eu-west-1_Refuses", undefined, refuse);
166
166
  let after = Nodefs.readFileSync(file, "utf8");
167
167
  Nodefs.rmSync(dir, {
168
168
  recursive: true,