@reventlessdev/reventless-aws 3.0.0-alpha.319 → 3.0.0-alpha.320
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/CHANGELOG.md +20 -0
- package/package.json +9 -5
- package/rescript.json +4 -0
- package/run-provision-identity.mjs +3 -0
- package/scripts/ProvisionIdentity.res +303 -0
- package/scripts/ProvisionIdentity.res.mjs +376 -0
- package/src/Platform.res +54 -30
- package/src/Platform.res.mjs +34 -32
- package/src/Platform_Stack.res +102 -19
- package/src/Platform_Stack.res.mjs +43 -7
- package/src/adapter/Auth/Auth_ActiveRolePoolAttachment.res +267 -32
- package/src/adapter/Auth/Auth_ActiveRolePoolAttachment.res.mjs +124 -14
- package/src/adapter/Auth/Auth_ActiveRoleStore.res +93 -5
- package/src/adapter/Auth/Auth_ActiveRoleStore.res.mjs +53 -4
- package/src/adapter/Auth/Auth_ActiveRoleStore_Ops.res +50 -4
- package/src/adapter/Auth/Auth_ActiveRoleStore_Ops.res.mjs +24 -3
- package/src/adapter/Auth/Auth_ActiveRoleStore_Schema.res +92 -0
- package/src/adapter/Auth/Auth_ActiveRoleStore_Schema.res.mjs +49 -0
- package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res +21 -7
- package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res.mjs +15 -7
- package/src/util/Util_AwsError.res +56 -0
- package/src/util/Util_AwsError.res.mjs +59 -0
- package/src/util/Util_ShellConfig.res +28 -0
- package/src/util/Util_ShellConfig.res.mjs +22 -0
- package/tests/Auth_ActiveRolePoolAttachmentTest.res +175 -0
- package/tests/Auth_ActiveRolePoolAttachmentTest.res.mjs +136 -0
- package/tests/Auth_ActiveRoleStoreTest.res +65 -0
- package/tests/Auth_ActiveRoleStoreTest.res.mjs +48 -0
- package/tests/Auth_ActiveRoleStore_SchemaTest.res +98 -0
- package/tests/Auth_ActiveRoleStore_SchemaTest.res.mjs +97 -0
- package/tests/AwsErrorFixtures.mjs +16 -0
- package/tests/ProvisionIdentityTest.res +109 -0
- package/tests/ProvisionIdentityTest.res.mjs +132 -0
- package/tests/Util_AwsErrorTest.res +127 -0
- package/tests/Util_AwsErrorTest.res.mjs +76 -0
- package/tests/Util_ShellConfigTest.res +51 -0
- package/tests/Util_ShellConfigTest.res.mjs +42 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
4
|
+
import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
|
|
5
|
+
import * as ProvisionIdentity$ReventlessAws from "../scripts/ProvisionIdentity.res.mjs";
|
|
6
|
+
|
|
7
|
+
globalThis.describe("ProvisionIdentity.parseArgs", () => {
|
|
8
|
+
globalThis.test("no arguments means adopt-or-create the default name", () => {
|
|
9
|
+
globalThis.expect(ProvisionIdentity$ReventlessAws.parseArgs([])).toEqual({
|
|
10
|
+
TAG: "Ok",
|
|
11
|
+
_0: {
|
|
12
|
+
poolName: ProvisionIdentity$ReventlessAws.defaultPoolName,
|
|
13
|
+
providerId: undefined,
|
|
14
|
+
help: false
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
globalThis.test("--provider-id names an existing pool", () => {
|
|
19
|
+
globalThis.expect(ProvisionIdentity$ReventlessAws.parseArgs([
|
|
20
|
+
"--provider-id",
|
|
21
|
+
"eu-west-1_AbCdEfGhI"
|
|
22
|
+
])).toEqual({
|
|
23
|
+
TAG: "Ok",
|
|
24
|
+
_0: {
|
|
25
|
+
poolName: ProvisionIdentity$ReventlessAws.defaultPoolName,
|
|
26
|
+
providerId: "eu-west-1_AbCdEfGhI",
|
|
27
|
+
help: false
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
globalThis.test("--name selects which pool to adopt by name", () => {
|
|
32
|
+
globalThis.expect(ProvisionIdentity$ReventlessAws.parseArgs([
|
|
33
|
+
"--name",
|
|
34
|
+
"examples-dev"
|
|
35
|
+
])).toEqual({
|
|
36
|
+
TAG: "Ok",
|
|
37
|
+
_0: {
|
|
38
|
+
poolName: "examples-dev",
|
|
39
|
+
providerId: undefined,
|
|
40
|
+
help: false
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
globalThis.test("both together are accepted, and the id wins at resolve time", () => {
|
|
45
|
+
globalThis.expect(ProvisionIdentity$ReventlessAws.parseArgs([
|
|
46
|
+
"--name",
|
|
47
|
+
"ignored",
|
|
48
|
+
"--provider-id",
|
|
49
|
+
"eu-west-1_x"
|
|
50
|
+
])).toEqual({
|
|
51
|
+
TAG: "Ok",
|
|
52
|
+
_0: {
|
|
53
|
+
poolName: "ignored",
|
|
54
|
+
providerId: "eu-west-1_x",
|
|
55
|
+
help: false
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
globalThis.test("a misspelled flag is refused, not ignored", () => {
|
|
60
|
+
globalThis.expect(ProvisionIdentity$ReventlessAws.parseArgs([
|
|
61
|
+
"--provider_id",
|
|
62
|
+
"eu-west-1_x"
|
|
63
|
+
])).toEqual({
|
|
64
|
+
TAG: "Error",
|
|
65
|
+
_0: `unknown argument "--provider_id"`
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
globalThis.test("a flag with no value is refused", () => {
|
|
69
|
+
globalThis.expect(ProvisionIdentity$ReventlessAws.parseArgs(["--provider-id"])).toEqual({
|
|
70
|
+
TAG: "Error",
|
|
71
|
+
_0: "--provider-id needs a value"
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
globalThis.test("--name with no value is refused too", () => {
|
|
75
|
+
globalThis.expect(ProvisionIdentity$ReventlessAws.parseArgs(["--name"])).toEqual({
|
|
76
|
+
TAG: "Error",
|
|
77
|
+
_0: "--name needs a value"
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
globalThis.test("--help and -h both ask for the usage text", () => {
|
|
81
|
+
globalThis.expect([
|
|
82
|
+
Stdlib_Result.map(ProvisionIdentity$ReventlessAws.parseArgs(["--help"]), a => a.help),
|
|
83
|
+
Stdlib_Result.map(ProvisionIdentity$ReventlessAws.parseArgs(["-h"]), a => a.help)
|
|
84
|
+
]).toEqual([
|
|
85
|
+
{
|
|
86
|
+
TAG: "Ok",
|
|
87
|
+
_0: true
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
TAG: "Ok",
|
|
91
|
+
_0: true
|
|
92
|
+
}
|
|
93
|
+
]);
|
|
94
|
+
});
|
|
95
|
+
globalThis.test("the first refusal is the one reported", () => {
|
|
96
|
+
globalThis.expect(ProvisionIdentity$ReventlessAws.parseArgs([
|
|
97
|
+
"--nope",
|
|
98
|
+
"--also-nope"
|
|
99
|
+
])).toEqual({
|
|
100
|
+
TAG: "Error",
|
|
101
|
+
_0: `unknown argument "--nope"`
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
globalThis.describe("ProvisionIdentity.poolSettings", () => {
|
|
107
|
+
let settings = ProvisionIdentity$ReventlessAws.poolSettings("MyIdentity");
|
|
108
|
+
globalThis.test("carries the name it was asked for", () => {
|
|
109
|
+
globalThis.expect(settings.PoolName).toBe("MyIdentity");
|
|
110
|
+
});
|
|
111
|
+
globalThis.test("matches what auto mode declares: email sign-in, no MFA, admin-only", () => {
|
|
112
|
+
globalThis.expect([
|
|
113
|
+
settings.UsernameAttributes,
|
|
114
|
+
settings.MfaConfiguration,
|
|
115
|
+
Stdlib_Option.flatMap(settings.AdminCreateUserConfig, c => c.AllowAdminCreateUserOnly)
|
|
116
|
+
]).toEqual([
|
|
117
|
+
["email"],
|
|
118
|
+
"OFF",
|
|
119
|
+
true
|
|
120
|
+
]);
|
|
121
|
+
});
|
|
122
|
+
globalThis.test("keeps the 12-character password policy", () => {
|
|
123
|
+
globalThis.expect(Stdlib_Option.flatMap(Stdlib_Option.flatMap(settings.Policies, p => p.PasswordPolicy), p => p.MinimumLength)).toEqual(12);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
let Provision;
|
|
128
|
+
|
|
129
|
+
export {
|
|
130
|
+
Provision,
|
|
131
|
+
}
|
|
132
|
+
/* Not a pure module */
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
open JestGlobals
|
|
2
|
+
|
|
3
|
+
// 🚨 These exist because the bug they cover shipped, and shipped precisely
|
|
4
|
+
// because the predicate lived inside a script that runs on import — nothing could
|
|
5
|
+
// reach it to assert anything.
|
|
6
|
+
//
|
|
7
|
+
// The fixtures below are the **real** shapes, captured from live calls rather
|
|
8
|
+
// than imagined. That is the whole point: the original guard tested the message
|
|
9
|
+
// for the error code, and the message never contains it.
|
|
10
|
+
|
|
11
|
+
module AwsError = Util_AwsError
|
|
12
|
+
|
|
13
|
+
@module("./AwsErrorFixtures.mjs")
|
|
14
|
+
external throwAwsError: (string, string) => unit = "throwAwsError"
|
|
15
|
+
|
|
16
|
+
/** The shape an AWS SDK v3 client actually throws, caught the way the real code
|
|
17
|
+
catches it.
|
|
18
|
+
|
|
19
|
+
🚨 **Thrown and caught, not constructed.** ReScript's `exn` for a JS error is
|
|
20
|
+
the wrapper its own `catch` builds — a bare `Error` value is a different thing
|
|
21
|
+
and `JsExn.fromException` does not recognise it. A fixture that returned one
|
|
22
|
+
would make every predicate here look broken while the code was fine, which is
|
|
23
|
+
exactly the wrong way round for a regression test. */
|
|
24
|
+
let awsError = (~name: string, ~message: string): exn =>
|
|
25
|
+
try {
|
|
26
|
+
throwAwsError(name, message)
|
|
27
|
+
Not_found
|
|
28
|
+
} catch {
|
|
29
|
+
| e => e
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe("Util_AwsError.isNotFound", () => {
|
|
33
|
+
// Captured from `DescribeTable` on a table that does not exist. Note the
|
|
34
|
+
// message: it does NOT contain "ResourceNotFoundException" anywhere, which is
|
|
35
|
+
// exactly why a message-only guard could never match it.
|
|
36
|
+
let dynamoNotFound = awsError(
|
|
37
|
+
~name="ResourceNotFoundException",
|
|
38
|
+
~message="Requested resource not found: Table: ReventlessNoSuchTable-probe not found",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
// Captured from `DescribeUserPool` on a pool that does not exist.
|
|
42
|
+
let cognitoNotFound = awsError(
|
|
43
|
+
~name="ResourceNotFoundException",
|
|
44
|
+
~message="User pool eu-west-1_zzzNoSuchPl does not exist.",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
testSync("a missing DynamoDB table is recognised from the name alone", () =>
|
|
48
|
+
expect(AwsError.isNotFound(dynamoNotFound))->toBe(true)
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
// The regression, stated as the property rather than as the fix: this is what
|
|
52
|
+
// the original guard tested, and it is false for the real error.
|
|
53
|
+
testSync("...and its message does not carry the code, which is why", () =>
|
|
54
|
+
expect(
|
|
55
|
+
AwsError.describe(dynamoNotFound)->String.includes(
|
|
56
|
+
"Requested resource not found",
|
|
57
|
+
),
|
|
58
|
+
)->toBe(true)
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
testSync("a missing Cognito pool is recognised too", () =>
|
|
62
|
+
expect(AwsError.isNotFound(cognitoNotFound))->toBe(true)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
// A wrapped or re-thrown error can lose its `name` while keeping the code in
|
|
66
|
+
// the text, so the fallback earns its place.
|
|
67
|
+
testSync("the code in the message alone still matches", () =>
|
|
68
|
+
expect(
|
|
69
|
+
AwsError.isNotFound(
|
|
70
|
+
awsError(~name="Error", ~message="ResourceNotFoundException: wrapped somewhere"),
|
|
71
|
+
),
|
|
72
|
+
)->toBe(true)
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
// 🚨 The direction that matters for safety. `describeTable` swallows this
|
|
76
|
+
// exception; a guard that said `true` here would report a table as absent when
|
|
77
|
+
// the call was actually refused, and the script would then try to create a
|
|
78
|
+
// table that already exists.
|
|
79
|
+
testSync("a permission failure is not an absence", () =>
|
|
80
|
+
expect(
|
|
81
|
+
AwsError.isNotFound(
|
|
82
|
+
awsError(
|
|
83
|
+
~name="AccessDeniedException",
|
|
84
|
+
~message="User is not authorized to perform: dynamodb:DescribeTable",
|
|
85
|
+
),
|
|
86
|
+
),
|
|
87
|
+
)->toBe(false)
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
testSync("a throttle is not an absence either", () =>
|
|
91
|
+
expect(
|
|
92
|
+
AwsError.isNotFound(
|
|
93
|
+
awsError(~name="ProvisionedThroughputExceededException", ~message="slow down"),
|
|
94
|
+
),
|
|
95
|
+
)->toBe(false)
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
testSync("something that is not a JS error at all is not an absence", () =>
|
|
99
|
+
expect(AwsError.isNotFound(Not_found))->toBe(false)
|
|
100
|
+
)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
// Without this the top of a CLI reports Node's own
|
|
104
|
+
// `UnhandledPromiseRejection ... "#<Object>"`, which names neither the failing
|
|
105
|
+
// call nor the reason.
|
|
106
|
+
describe("Util_AwsError.describe", () => {
|
|
107
|
+
testSync("names the code and the reason", () =>
|
|
108
|
+
expect(
|
|
109
|
+
AwsError.describe(awsError(~name="AccessDeniedException", ~message="not authorized")),
|
|
110
|
+
)->toBe("AccessDeniedException: not authorized")
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
testSync("a non-error value still produces a sentence", () =>
|
|
114
|
+
expect(AwsError.describe(Not_found))->toBe("an unexpected error escaped")
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
// Total on purpose: a describer that threw would replace one unreadable
|
|
118
|
+
// failure with another.
|
|
119
|
+
testSync("every shape yields something an operator can read", () =>
|
|
120
|
+
expect(
|
|
121
|
+
[
|
|
122
|
+
awsError(~name="X", ~message="y"),
|
|
123
|
+
Not_found,
|
|
124
|
+
]->Array.every(e => AwsError.describe(e)->String.length > 0),
|
|
125
|
+
)->toBe(true)
|
|
126
|
+
)
|
|
127
|
+
})
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
4
|
+
import * as AwsErrorFixturesMjs from "./AwsErrorFixtures.mjs";
|
|
5
|
+
import * as Util_AwsError$ReventlessAws from "../src/util/Util_AwsError.res.mjs";
|
|
6
|
+
|
|
7
|
+
function throwAwsError(prim0, prim1) {
|
|
8
|
+
AwsErrorFixturesMjs.throwAwsError(prim0, prim1);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function awsError(name, message) {
|
|
12
|
+
try {
|
|
13
|
+
AwsErrorFixturesMjs.throwAwsError(name, message);
|
|
14
|
+
return {
|
|
15
|
+
RE_EXN_ID: "Not_found"
|
|
16
|
+
};
|
|
17
|
+
} catch (raw_e) {
|
|
18
|
+
return Primitive_exceptions.internalToException(raw_e);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
globalThis.describe("Util_AwsError.isNotFound", () => {
|
|
23
|
+
let dynamoNotFound = awsError("ResourceNotFoundException", "Requested resource not found: Table: ReventlessNoSuchTable-probe not found");
|
|
24
|
+
let cognitoNotFound = awsError("ResourceNotFoundException", "User pool eu-west-1_zzzNoSuchPl does not exist.");
|
|
25
|
+
globalThis.test("a missing DynamoDB table is recognised from the name alone", () => {
|
|
26
|
+
globalThis.expect(Util_AwsError$ReventlessAws.isNotFound(dynamoNotFound)).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
globalThis.test("...and its message does not carry the code, which is why", () => {
|
|
29
|
+
globalThis.expect(Util_AwsError$ReventlessAws.describe(dynamoNotFound).includes("Requested resource not found")).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
globalThis.test("a missing Cognito pool is recognised too", () => {
|
|
32
|
+
globalThis.expect(Util_AwsError$ReventlessAws.isNotFound(cognitoNotFound)).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
globalThis.test("the code in the message alone still matches", () => {
|
|
35
|
+
globalThis.expect(Util_AwsError$ReventlessAws.isNotFound(awsError("Error", "ResourceNotFoundException: wrapped somewhere"))).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
globalThis.test("a permission failure is not an absence", () => {
|
|
38
|
+
globalThis.expect(Util_AwsError$ReventlessAws.isNotFound(awsError("AccessDeniedException", "User is not authorized to perform: dynamodb:DescribeTable"))).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
globalThis.test("a throttle is not an absence either", () => {
|
|
41
|
+
globalThis.expect(Util_AwsError$ReventlessAws.isNotFound(awsError("ProvisionedThroughputExceededException", "slow down"))).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
globalThis.test("something that is not a JS error at all is not an absence", () => {
|
|
44
|
+
globalThis.expect(Util_AwsError$ReventlessAws.isNotFound({
|
|
45
|
+
RE_EXN_ID: "Not_found"
|
|
46
|
+
})).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
globalThis.describe("Util_AwsError.describe", () => {
|
|
51
|
+
globalThis.test("names the code and the reason", () => {
|
|
52
|
+
globalThis.expect(Util_AwsError$ReventlessAws.describe(awsError("AccessDeniedException", "not authorized"))).toBe("AccessDeniedException: not authorized");
|
|
53
|
+
});
|
|
54
|
+
globalThis.test("a non-error value still produces a sentence", () => {
|
|
55
|
+
globalThis.expect(Util_AwsError$ReventlessAws.describe({
|
|
56
|
+
RE_EXN_ID: "Not_found"
|
|
57
|
+
})).toBe("an unexpected error escaped");
|
|
58
|
+
});
|
|
59
|
+
globalThis.test("every shape yields something an operator can read", () => {
|
|
60
|
+
globalThis.expect([
|
|
61
|
+
awsError("X", "y"),
|
|
62
|
+
{
|
|
63
|
+
RE_EXN_ID: "Not_found"
|
|
64
|
+
}
|
|
65
|
+
].every(e => Util_AwsError$ReventlessAws.describe(e).length > 0)).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
let AwsError;
|
|
70
|
+
|
|
71
|
+
export {
|
|
72
|
+
AwsError,
|
|
73
|
+
throwAwsError,
|
|
74
|
+
awsError,
|
|
75
|
+
}
|
|
76
|
+
/* Not a pure module */
|
|
@@ -224,3 +224,54 @@ describe("Util_ShellConfig.fields — shellConfig passthrough", () => {
|
|
|
224
224
|
}
|
|
225
225
|
})
|
|
226
226
|
})
|
|
227
|
+
|
|
228
|
+
// 🚨 The identity keys travel under both spellings through the rename. A shell
|
|
229
|
+
// reads config.json at runtime and CloudFront serves the previous bundle until
|
|
230
|
+
// someone invalidates it, so switching them in one deploy leaves a window where
|
|
231
|
+
// the served bundle and the served config disagree — and `cognitoClientId` is
|
|
232
|
+
// read into an option, so a bundle that cannot find its key does not error, it
|
|
233
|
+
// gets `None` and login silently stops working.
|
|
234
|
+
//
|
|
235
|
+
// These assert the property that removes that window, not the spelling.
|
|
236
|
+
describe("Util_ShellConfig.identityFields", () => {
|
|
237
|
+
let fields = Util_ShellConfig.identityFields(~providerId="eu-west-1_x", ~clientId="7cl13nt")
|
|
238
|
+
let get = key =>
|
|
239
|
+
fields->Array.find(((k, _)) => k == key)->Option.map(((_, v)) => v)
|
|
240
|
+
|
|
241
|
+
testSync("the new spelling is present", () =>
|
|
242
|
+
expect((get("identityProviderId"), get("identityProviderClientId")))->toEqual((
|
|
243
|
+
Some(JSON.Encode.string("eu-west-1_x")),
|
|
244
|
+
Some(JSON.Encode.string("7cl13nt")),
|
|
245
|
+
))
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
// Not "still" — deliberately. Every shipped shell reads these, and dropping
|
|
249
|
+
// them is a later release gated on the pinned bundle, not on this one.
|
|
250
|
+
testSync("the deprecated spelling is present too", () =>
|
|
251
|
+
expect((get("cognitoUserPoolId"), get("cognitoClientId")))->toEqual((
|
|
252
|
+
Some(JSON.Encode.string("eu-west-1_x")),
|
|
253
|
+
Some(JSON.Encode.string("7cl13nt")),
|
|
254
|
+
))
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
// The whole point: a bundle reading either name gets the same answer. Two keys
|
|
258
|
+
// carrying different values would be worse than one key, not better.
|
|
259
|
+
testSync("both spellings carry identical values", () =>
|
|
260
|
+
expect((
|
|
261
|
+
get("identityProviderId") == get("cognitoUserPoolId"),
|
|
262
|
+
get("identityProviderClientId") == get("cognitoClientId"),
|
|
263
|
+
))->toEqual((true, true))
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
// The client id is the load-bearing one — it is what the shell's auth provider
|
|
267
|
+
// branches on. The pool id is currently discarded by the shell, which is
|
|
268
|
+
// exactly why a `cognito*` sweep is dangerous: the safe one gives no warning.
|
|
269
|
+
testSync("nothing else sneaks into the identity field set", () =>
|
|
270
|
+
expect(fields->Array.map(((k, _)) => k)->Array.toSorted(String.compare))->toEqual([
|
|
271
|
+
"cognitoClientId",
|
|
272
|
+
"cognitoUserPoolId",
|
|
273
|
+
"identityProviderClientId",
|
|
274
|
+
"identityProviderId",
|
|
275
|
+
])
|
|
276
|
+
)
|
|
277
|
+
})
|
|
@@ -4,6 +4,8 @@ import * as JestGlobals from "@reventlessdev/rescript-jest/src/JestGlobals.res.m
|
|
|
4
4
|
import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
|
|
5
5
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
6
6
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
7
|
+
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
8
|
+
import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
|
|
7
9
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
8
10
|
import * as Util_ShellConfig$ReventlessAws from "../src/util/Util_ShellConfig.res.mjs";
|
|
9
11
|
import * as Platform_BakedManifest$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_BakedManifest.res.mjs";
|
|
@@ -252,6 +254,46 @@ globalThis.describe("Util_ShellConfig.fields — shellConfig passthrough", () =>
|
|
|
252
254
|
});
|
|
253
255
|
});
|
|
254
256
|
|
|
257
|
+
globalThis.describe("Util_ShellConfig.identityFields", () => {
|
|
258
|
+
let fields = Util_ShellConfig$ReventlessAws.identityFields("eu-west-1_x", "7cl13nt");
|
|
259
|
+
let get = key => Stdlib_Option.map(fields.find(param => param[0] === key), param => param[1]);
|
|
260
|
+
globalThis.test("the new spelling is present", () => {
|
|
261
|
+
globalThis.expect([
|
|
262
|
+
get("identityProviderId"),
|
|
263
|
+
get("identityProviderClientId")
|
|
264
|
+
]).toEqual([
|
|
265
|
+
"eu-west-1_x",
|
|
266
|
+
"7cl13nt"
|
|
267
|
+
]);
|
|
268
|
+
});
|
|
269
|
+
globalThis.test("the deprecated spelling is present too", () => {
|
|
270
|
+
globalThis.expect([
|
|
271
|
+
get("cognitoUserPoolId"),
|
|
272
|
+
get("cognitoClientId")
|
|
273
|
+
]).toEqual([
|
|
274
|
+
"eu-west-1_x",
|
|
275
|
+
"7cl13nt"
|
|
276
|
+
]);
|
|
277
|
+
});
|
|
278
|
+
globalThis.test("both spellings carry identical values", () => {
|
|
279
|
+
globalThis.expect([
|
|
280
|
+
Primitive_object.equal(get("identityProviderId"), get("cognitoUserPoolId")),
|
|
281
|
+
Primitive_object.equal(get("identityProviderClientId"), get("cognitoClientId"))
|
|
282
|
+
]).toEqual([
|
|
283
|
+
true,
|
|
284
|
+
true
|
|
285
|
+
]);
|
|
286
|
+
});
|
|
287
|
+
globalThis.test("nothing else sneaks into the identity field set", () => {
|
|
288
|
+
globalThis.expect(fields.map(param => param[0]).toSorted(Primitive_string.compare)).toEqual([
|
|
289
|
+
"cognitoClientId",
|
|
290
|
+
"cognitoUserPoolId",
|
|
291
|
+
"identityProviderClientId",
|
|
292
|
+
"identityProviderId"
|
|
293
|
+
]);
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
|
|
255
297
|
export {
|
|
256
298
|
computed,
|
|
257
299
|
get,
|