@dloizides/auth-web 1.22.0 → 1.23.0
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 +14 -0
- package/dist/index.d.mts +73 -10
- package/dist/index.d.ts +73 -10
- package/dist/index.js +571 -112
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +565 -113
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -306,7 +306,8 @@ var DEFAULT_RESET_PASSWORD_LABELS = {
|
|
|
306
306
|
errorWeakPassword: "Use at least 8 characters with an uppercase letter, a lowercase letter and a digit.",
|
|
307
307
|
errorMismatch: "The passwords do not match.",
|
|
308
308
|
errorTokenInvalid: "This reset link is invalid or has expired. Request a new one.",
|
|
309
|
-
errorNetwork: "Something went wrong. Please try again."
|
|
309
|
+
errorNetwork: "Something went wrong. Please try again.",
|
|
310
|
+
errorRateLimited: "Too many attempts. Wait a minute and try again."
|
|
310
311
|
};
|
|
311
312
|
|
|
312
313
|
// src/components/labels/accountSettingsLabels.ts
|
|
@@ -343,6 +344,8 @@ var DEFAULT_REGISTER_LABELS = {
|
|
|
343
344
|
submitHint: "Creates your account",
|
|
344
345
|
submitting: "Creating account...",
|
|
345
346
|
fullName: field("Your name", "Enter your full name"),
|
|
347
|
+
checkEmailTitle: "Check your email",
|
|
348
|
+
checkEmailBody: "If this address can be used, a link to finish signing up is on its way.",
|
|
346
349
|
fields: {
|
|
347
350
|
firstName: field("First name", "Enter your first name"),
|
|
348
351
|
lastName: field("Last name", "Enter your last name"),
|
|
@@ -355,6 +358,19 @@ var DEFAULT_REGISTER_LABELS = {
|
|
|
355
358
|
};
|
|
356
359
|
|
|
357
360
|
// src/components/labels/verifyEmailLabels.ts
|
|
361
|
+
var DEFAULT_VERIFY_NEW_PASSWORD_LABELS = {
|
|
362
|
+
...DEFAULT_RESET_PASSWORD_LABELS,
|
|
363
|
+
title: "Set a new password",
|
|
364
|
+
description: "To finish signing in, choose a new password for your account.",
|
|
365
|
+
submit: "Save and sign in",
|
|
366
|
+
submitting: "Saving..."
|
|
367
|
+
};
|
|
368
|
+
var DEFAULT_VERIFY_SIGN_IN_LABELS = {
|
|
369
|
+
title: "Your email is verified",
|
|
370
|
+
body: "We could not sign you in automatically. Please sign in with your password.",
|
|
371
|
+
action: "Sign in",
|
|
372
|
+
actionHint: "Go to the sign in page"
|
|
373
|
+
};
|
|
358
374
|
var DEFAULT_VERIFY_EMAIL_LABELS = {
|
|
359
375
|
loadingTitle: "Verifying your email...",
|
|
360
376
|
loadingHint: "Please wait while we verify your address.",
|
|
@@ -376,7 +392,10 @@ var DEFAULT_VERIFY_EMAIL_LABELS = {
|
|
|
376
392
|
resendMissingEmail: "Enter your email address.",
|
|
377
393
|
resendSubmit: "Send link",
|
|
378
394
|
resendSubmitHint: "Sends a new verification email",
|
|
379
|
-
resendConfirmation: "If that address has an account, a new verification link is on its way."
|
|
395
|
+
resendConfirmation: "If that address has an account, a new verification link is on its way.",
|
|
396
|
+
errorRateLimited: "Too many attempts. Wait a minute and try again.",
|
|
397
|
+
newPassword: DEFAULT_VERIFY_NEW_PASSWORD_LABELS,
|
|
398
|
+
signIn: DEFAULT_VERIFY_SIGN_IN_LABELS
|
|
380
399
|
};
|
|
381
400
|
|
|
382
401
|
// src/components/testIds.ts
|
|
@@ -475,6 +494,8 @@ var AuthTestIds = {
|
|
|
475
494
|
verifyEmailSuccess: "auth-verify-email-success",
|
|
476
495
|
verifyEmailContinue: "auth-verify-email-continue",
|
|
477
496
|
verifyEmailError: "auth-verify-email-error",
|
|
497
|
+
verifyEmailSignIn: "auth-verify-email-sign-in",
|
|
498
|
+
verifyEmailSignInContinue: "auth-verify-email-sign-in-continue",
|
|
478
499
|
verifyEmailResendCta: "auth-verify-email-resend-cta",
|
|
479
500
|
verifyEmailResendForm: "auth-verify-email-resend-form",
|
|
480
501
|
verifyEmailResendEmail: "auth-verify-email-resend-email",
|
|
@@ -576,6 +597,12 @@ function useAuthStyles(theme) {
|
|
|
576
597
|
marginTop: spacing.xs,
|
|
577
598
|
color: colors.danger
|
|
578
599
|
},
|
|
600
|
+
errorBody: {
|
|
601
|
+
fontSize: typography.body,
|
|
602
|
+
marginTop: spacing.xs,
|
|
603
|
+
marginBottom: spacing.md,
|
|
604
|
+
color: colors.danger
|
|
605
|
+
},
|
|
579
606
|
successText: {
|
|
580
607
|
fontSize: typography.body,
|
|
581
608
|
lineHeight: typography.body * 1.4,
|
|
@@ -1269,8 +1296,107 @@ var ResetPasswordError = /* @__PURE__ */ ((ResetPasswordError2) => {
|
|
|
1269
1296
|
ResetPasswordError2["Mismatch"] = "mismatch";
|
|
1270
1297
|
ResetPasswordError2["TokenInvalid"] = "tokenInvalid";
|
|
1271
1298
|
ResetPasswordError2["Network"] = "network";
|
|
1299
|
+
ResetPasswordError2["RateLimited"] = "rateLimited";
|
|
1272
1300
|
return ResetPasswordError2;
|
|
1273
1301
|
})(ResetPasswordError || {});
|
|
1302
|
+
function errorMessage(errorKey, labels) {
|
|
1303
|
+
switch (errorKey) {
|
|
1304
|
+
case "empty" /* Empty */:
|
|
1305
|
+
return labels.errorEmpty;
|
|
1306
|
+
case "weakPassword" /* WeakPassword */:
|
|
1307
|
+
return labels.errorWeakPassword;
|
|
1308
|
+
case "mismatch" /* Mismatch */:
|
|
1309
|
+
return labels.errorMismatch;
|
|
1310
|
+
case "tokenInvalid" /* TokenInvalid */:
|
|
1311
|
+
return labels.errorTokenInvalid;
|
|
1312
|
+
case "network" /* Network */:
|
|
1313
|
+
return labels.errorNetwork;
|
|
1314
|
+
case "rateLimited" /* RateLimited */:
|
|
1315
|
+
return labels.errorRateLimited ?? labels.errorNetwork;
|
|
1316
|
+
default:
|
|
1317
|
+
return null;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
function ResetPasswordFields({
|
|
1321
|
+
form,
|
|
1322
|
+
labels,
|
|
1323
|
+
styles: styles3,
|
|
1324
|
+
theme,
|
|
1325
|
+
testIdPrefix,
|
|
1326
|
+
newPasswordRef,
|
|
1327
|
+
onSubmitEditing
|
|
1328
|
+
}) {
|
|
1329
|
+
const message = errorMessage(form.errorKey, labels);
|
|
1330
|
+
const submitButtonStyle = form.isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
1331
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1332
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
|
|
1333
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.description }),
|
|
1334
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
1335
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.newPasswordLabel }),
|
|
1336
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1337
|
+
reactNative.TextInput,
|
|
1338
|
+
{
|
|
1339
|
+
ref: newPasswordRef,
|
|
1340
|
+
secureTextEntry: true,
|
|
1341
|
+
accessibilityHint: labels.newPasswordPlaceholder,
|
|
1342
|
+
accessibilityLabel: labels.newPasswordLabel,
|
|
1343
|
+
autoCapitalize: "none",
|
|
1344
|
+
autoCorrect: false,
|
|
1345
|
+
editable: !form.isSubmitting,
|
|
1346
|
+
placeholder: labels.newPasswordPlaceholder,
|
|
1347
|
+
placeholderTextColor: theme.colors.textSecondary,
|
|
1348
|
+
style: styles3.input,
|
|
1349
|
+
testID: withTestIdPrefix(AuthTestIds.resetPasswordNewInput, testIdPrefix),
|
|
1350
|
+
value: form.newPassword,
|
|
1351
|
+
onChangeText: form.setNewPassword,
|
|
1352
|
+
onSubmitEditing
|
|
1353
|
+
}
|
|
1354
|
+
)
|
|
1355
|
+
] }),
|
|
1356
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
1357
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.confirmPasswordLabel }),
|
|
1358
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1359
|
+
reactNative.TextInput,
|
|
1360
|
+
{
|
|
1361
|
+
secureTextEntry: true,
|
|
1362
|
+
accessibilityHint: labels.confirmPasswordPlaceholder,
|
|
1363
|
+
accessibilityLabel: labels.confirmPasswordLabel,
|
|
1364
|
+
autoCapitalize: "none",
|
|
1365
|
+
autoCorrect: false,
|
|
1366
|
+
editable: !form.isSubmitting,
|
|
1367
|
+
placeholder: labels.confirmPasswordPlaceholder,
|
|
1368
|
+
placeholderTextColor: theme.colors.textSecondary,
|
|
1369
|
+
style: styles3.input,
|
|
1370
|
+
testID: withTestIdPrefix(AuthTestIds.resetPasswordConfirmInput, testIdPrefix),
|
|
1371
|
+
value: form.confirmPassword,
|
|
1372
|
+
onChangeText: form.setConfirmPassword,
|
|
1373
|
+
onSubmitEditing
|
|
1374
|
+
}
|
|
1375
|
+
)
|
|
1376
|
+
] }),
|
|
1377
|
+
message !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1378
|
+
reactNative.Text,
|
|
1379
|
+
{
|
|
1380
|
+
style: styles3.errorText,
|
|
1381
|
+
testID: withTestIdPrefix(AuthTestIds.resetPasswordError, testIdPrefix),
|
|
1382
|
+
children: message
|
|
1383
|
+
}
|
|
1384
|
+
) : null,
|
|
1385
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1386
|
+
reactNative.TouchableOpacity,
|
|
1387
|
+
{
|
|
1388
|
+
accessibilityHint: labels.submit,
|
|
1389
|
+
accessibilityLabel: form.isSubmitting ? labels.submitting : labels.submit,
|
|
1390
|
+
accessibilityRole: "button",
|
|
1391
|
+
disabled: form.isSubmitting,
|
|
1392
|
+
style: submitButtonStyle,
|
|
1393
|
+
testID: withTestIdPrefix(AuthTestIds.resetPasswordSubmitButton, testIdPrefix),
|
|
1394
|
+
onPress: form.submit,
|
|
1395
|
+
children: form.isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.submit })
|
|
1396
|
+
}
|
|
1397
|
+
)
|
|
1398
|
+
] });
|
|
1399
|
+
}
|
|
1274
1400
|
|
|
1275
1401
|
// src/password/PasswordPolicyError.ts
|
|
1276
1402
|
var PasswordPolicyError = /* @__PURE__ */ ((PasswordPolicyError2) => {
|
|
@@ -1409,22 +1535,6 @@ function useResetPasswordForm({
|
|
|
1409
1535
|
submit
|
|
1410
1536
|
};
|
|
1411
1537
|
}
|
|
1412
|
-
function errorMessage(errorKey, labels) {
|
|
1413
|
-
switch (errorKey) {
|
|
1414
|
-
case "empty" /* Empty */:
|
|
1415
|
-
return labels.errorEmpty;
|
|
1416
|
-
case "weakPassword" /* WeakPassword */:
|
|
1417
|
-
return labels.errorWeakPassword;
|
|
1418
|
-
case "mismatch" /* Mismatch */:
|
|
1419
|
-
return labels.errorMismatch;
|
|
1420
|
-
case "tokenInvalid" /* TokenInvalid */:
|
|
1421
|
-
return labels.errorTokenInvalid;
|
|
1422
|
-
case "network" /* Network */:
|
|
1423
|
-
return labels.errorNetwork;
|
|
1424
|
-
default:
|
|
1425
|
-
return null;
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
1538
|
function ResetPasswordForm({
|
|
1429
1539
|
client,
|
|
1430
1540
|
token,
|
|
@@ -1440,78 +1550,21 @@ function ResetPasswordForm({
|
|
|
1440
1550
|
[labelsProp]
|
|
1441
1551
|
);
|
|
1442
1552
|
const form = useResetPasswordForm({ client, token, onSuccess });
|
|
1443
|
-
|
|
1444
|
-
const submitButtonStyle = form.isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
|
|
1445
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1553
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1446
1554
|
reactNative.View,
|
|
1447
1555
|
{
|
|
1448
1556
|
style: styles3.card,
|
|
1449
1557
|
testID: withTestIdPrefix(AuthTestIds.resetPasswordForm, testIdPrefix),
|
|
1450
|
-
children:
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
accessibilityLabel: labels.newPasswordLabel,
|
|
1461
|
-
autoCapitalize: "none",
|
|
1462
|
-
autoCorrect: false,
|
|
1463
|
-
editable: !form.isSubmitting,
|
|
1464
|
-
placeholder: labels.newPasswordPlaceholder,
|
|
1465
|
-
placeholderTextColor: theme.colors.textSecondary,
|
|
1466
|
-
style: styles3.input,
|
|
1467
|
-
testID: withTestIdPrefix(AuthTestIds.resetPasswordNewInput, testIdPrefix),
|
|
1468
|
-
value: form.newPassword,
|
|
1469
|
-
onChangeText: form.setNewPassword
|
|
1470
|
-
}
|
|
1471
|
-
)
|
|
1472
|
-
] }),
|
|
1473
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
|
|
1474
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.label, children: labels.confirmPasswordLabel }),
|
|
1475
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1476
|
-
reactNative.TextInput,
|
|
1477
|
-
{
|
|
1478
|
-
secureTextEntry: true,
|
|
1479
|
-
accessibilityHint: labels.confirmPasswordPlaceholder,
|
|
1480
|
-
accessibilityLabel: labels.confirmPasswordLabel,
|
|
1481
|
-
autoCapitalize: "none",
|
|
1482
|
-
autoCorrect: false,
|
|
1483
|
-
editable: !form.isSubmitting,
|
|
1484
|
-
placeholder: labels.confirmPasswordPlaceholder,
|
|
1485
|
-
placeholderTextColor: theme.colors.textSecondary,
|
|
1486
|
-
style: styles3.input,
|
|
1487
|
-
testID: withTestIdPrefix(AuthTestIds.resetPasswordConfirmInput, testIdPrefix),
|
|
1488
|
-
value: form.confirmPassword,
|
|
1489
|
-
onChangeText: form.setConfirmPassword
|
|
1490
|
-
}
|
|
1491
|
-
)
|
|
1492
|
-
] }),
|
|
1493
|
-
message !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1494
|
-
reactNative.Text,
|
|
1495
|
-
{
|
|
1496
|
-
style: styles3.errorText,
|
|
1497
|
-
testID: withTestIdPrefix(AuthTestIds.resetPasswordError, testIdPrefix),
|
|
1498
|
-
children: message
|
|
1499
|
-
}
|
|
1500
|
-
) : null,
|
|
1501
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1502
|
-
reactNative.TouchableOpacity,
|
|
1503
|
-
{
|
|
1504
|
-
accessibilityHint: labels.submit,
|
|
1505
|
-
accessibilityLabel: form.isSubmitting ? labels.submitting : labels.submit,
|
|
1506
|
-
accessibilityRole: "button",
|
|
1507
|
-
disabled: form.isSubmitting,
|
|
1508
|
-
style: submitButtonStyle,
|
|
1509
|
-
testID: withTestIdPrefix(AuthTestIds.resetPasswordSubmitButton, testIdPrefix),
|
|
1510
|
-
onPress: form.submit,
|
|
1511
|
-
children: form.isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.submit })
|
|
1512
|
-
}
|
|
1513
|
-
)
|
|
1514
|
-
]
|
|
1558
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1559
|
+
ResetPasswordFields,
|
|
1560
|
+
{
|
|
1561
|
+
form,
|
|
1562
|
+
labels,
|
|
1563
|
+
styles: styles3,
|
|
1564
|
+
testIdPrefix,
|
|
1565
|
+
theme
|
|
1566
|
+
}
|
|
1567
|
+
)
|
|
1515
1568
|
}
|
|
1516
1569
|
) });
|
|
1517
1570
|
}
|
|
@@ -4140,7 +4193,8 @@ var RegisterTestIds = {
|
|
|
4140
4193
|
confirmPasswordInput: "register-confirm-password-input",
|
|
4141
4194
|
tenantNameInput: "register-tenant-name-input",
|
|
4142
4195
|
submitButton: "register-submit-button",
|
|
4143
|
-
websiteInput: "register-website"
|
|
4196
|
+
websiteInput: "register-website",
|
|
4197
|
+
checkEmail: "register-check-email"
|
|
4144
4198
|
};
|
|
4145
4199
|
var FIELDS = [
|
|
4146
4200
|
{ key: "firstName", testId: RegisterTestIds.firstNameInput, autoComplete: "name" },
|
|
@@ -4262,6 +4316,14 @@ function routeRegisterOutcome(outcome, handlers) {
|
|
|
4262
4316
|
}
|
|
4263
4317
|
}
|
|
4264
4318
|
|
|
4319
|
+
// src/hooks/registerAccepted.ts
|
|
4320
|
+
function isRegisterAccepted(result) {
|
|
4321
|
+
if (typeof result !== "object" || result === null) {
|
|
4322
|
+
return false;
|
|
4323
|
+
}
|
|
4324
|
+
return result.accepted === true;
|
|
4325
|
+
}
|
|
4326
|
+
|
|
4265
4327
|
// src/hooks/registerErrors.ts
|
|
4266
4328
|
var MIN_PASSWORD_LENGTH = 8;
|
|
4267
4329
|
var WHITESPACE_REGEX = /\s/;
|
|
@@ -4414,6 +4476,42 @@ function expandCompactRegisterValues(values) {
|
|
|
4414
4476
|
};
|
|
4415
4477
|
}
|
|
4416
4478
|
|
|
4479
|
+
// src/hooks/newIdempotencyKey.ts
|
|
4480
|
+
var HEX_RADIX = 16;
|
|
4481
|
+
var HEX_BYTE_LENGTH = 2;
|
|
4482
|
+
var KEY_BYTES = 16;
|
|
4483
|
+
var fallbackSequence = 0;
|
|
4484
|
+
function newIdempotencyKey() {
|
|
4485
|
+
const cryptoApi = globalThis.crypto;
|
|
4486
|
+
if (typeof cryptoApi?.randomUUID === "function") {
|
|
4487
|
+
return cryptoApi.randomUUID();
|
|
4488
|
+
}
|
|
4489
|
+
if (typeof cryptoApi?.getRandomValues === "function") {
|
|
4490
|
+
const bytes = cryptoApi.getRandomValues(new Uint8Array(KEY_BYTES));
|
|
4491
|
+
return Array.from(bytes, (byte) => byte.toString(HEX_RADIX).padStart(HEX_BYTE_LENGTH, "0")).join("");
|
|
4492
|
+
}
|
|
4493
|
+
fallbackSequence += 1;
|
|
4494
|
+
return `${Date.now().toString(HEX_RADIX)}-${String(fallbackSequence)}`;
|
|
4495
|
+
}
|
|
4496
|
+
|
|
4497
|
+
// src/hooks/useRegisterSubmitMeta.ts
|
|
4498
|
+
function useRegisterSubmitMeta() {
|
|
4499
|
+
const openedAt = react.useRef(Date.now());
|
|
4500
|
+
const key = react.useRef(null);
|
|
4501
|
+
return react.useMemo(
|
|
4502
|
+
() => ({
|
|
4503
|
+
next: () => {
|
|
4504
|
+
key.current ?? (key.current = newIdempotencyKey());
|
|
4505
|
+
return { idempotencyKey: key.current, formElapsedMs: Date.now() - openedAt.current };
|
|
4506
|
+
},
|
|
4507
|
+
resetKey: () => {
|
|
4508
|
+
key.current = null;
|
|
4509
|
+
}
|
|
4510
|
+
}),
|
|
4511
|
+
[]
|
|
4512
|
+
);
|
|
4513
|
+
}
|
|
4514
|
+
|
|
4417
4515
|
// src/hooks/useRegisterForm.ts
|
|
4418
4516
|
var EMPTY_VALUES = {
|
|
4419
4517
|
firstName: "",
|
|
@@ -4425,6 +4523,9 @@ var EMPTY_VALUES = {
|
|
|
4425
4523
|
tenantName: "",
|
|
4426
4524
|
website: ""
|
|
4427
4525
|
};
|
|
4526
|
+
function withoutPasswords(values) {
|
|
4527
|
+
return { ...values, password: "", confirmPassword: "" };
|
|
4528
|
+
}
|
|
4428
4529
|
function toSubmitValues(values) {
|
|
4429
4530
|
return {
|
|
4430
4531
|
firstName: values.firstName,
|
|
@@ -4440,15 +4541,18 @@ function useRegisterForm({
|
|
|
4440
4541
|
onSubmit,
|
|
4441
4542
|
passwordPolicy = isRegisterPasswordStrong,
|
|
4442
4543
|
onSubmitAttempt,
|
|
4443
|
-
compact = false
|
|
4544
|
+
compact = false,
|
|
4545
|
+
sharedRegistration = false
|
|
4444
4546
|
}) {
|
|
4445
4547
|
const [state, setState] = react.useState(EMPTY_VALUES);
|
|
4446
4548
|
const [isSubmitting, setIsSubmitting] = react.useState(false);
|
|
4447
4549
|
const [error, setError] = react.useState(null);
|
|
4448
4550
|
const inFlight = react.useRef(false);
|
|
4551
|
+
const submitMeta = useRegisterSubmitMeta();
|
|
4449
4552
|
const setField = react.useCallback((field2, value) => {
|
|
4553
|
+
submitMeta.resetKey();
|
|
4450
4554
|
setState((prev) => ({ ...prev, [field2]: value }));
|
|
4451
|
-
}, []);
|
|
4555
|
+
}, [submitMeta]);
|
|
4452
4556
|
const submit = react.useCallback(async () => {
|
|
4453
4557
|
if (inFlight.current) {
|
|
4454
4558
|
return { ok: false, error: "inFlight" /* InFlight */ };
|
|
@@ -4465,7 +4569,11 @@ function useRegisterForm({
|
|
|
4465
4569
|
setError(null);
|
|
4466
4570
|
setIsSubmitting(true);
|
|
4467
4571
|
try {
|
|
4468
|
-
const
|
|
4572
|
+
const values = toSubmitValues(trimmed);
|
|
4573
|
+
const result = await (sharedRegistration ? onSubmit(values, submitMeta.next()) : onSubmit(values));
|
|
4574
|
+
if (sharedRegistration && isRegisterAccepted(result)) {
|
|
4575
|
+
setState(withoutPasswords);
|
|
4576
|
+
}
|
|
4469
4577
|
return { ok: true, result };
|
|
4470
4578
|
} catch (caught) {
|
|
4471
4579
|
const code = mapRegisterErrorCode(caught);
|
|
@@ -4475,10 +4583,10 @@ function useRegisterForm({
|
|
|
4475
4583
|
inFlight.current = false;
|
|
4476
4584
|
setIsSubmitting(false);
|
|
4477
4585
|
}
|
|
4478
|
-
}, [compact, onSubmit, onSubmitAttempt, passwordPolicy, state]);
|
|
4586
|
+
}, [compact, onSubmit, onSubmitAttempt, passwordPolicy, sharedRegistration, state, submitMeta]);
|
|
4479
4587
|
return { state, setField, submit, isSubmitting, error };
|
|
4480
4588
|
}
|
|
4481
|
-
function
|
|
4589
|
+
function RegisterFormCore({
|
|
4482
4590
|
onSubmit,
|
|
4483
4591
|
onSuccess,
|
|
4484
4592
|
onError,
|
|
@@ -4488,7 +4596,8 @@ function RegisterForm({
|
|
|
4488
4596
|
theme: themeProp,
|
|
4489
4597
|
footer,
|
|
4490
4598
|
testIdPrefix,
|
|
4491
|
-
compact = false
|
|
4599
|
+
compact = false,
|
|
4600
|
+
sharedRegistration
|
|
4492
4601
|
}) {
|
|
4493
4602
|
const theme = useAuthTheme(themeProp);
|
|
4494
4603
|
const styles3 = useAuthStyles(theme);
|
|
@@ -4500,7 +4609,8 @@ function RegisterForm({
|
|
|
4500
4609
|
onSubmit,
|
|
4501
4610
|
onSubmitAttempt,
|
|
4502
4611
|
passwordPolicy,
|
|
4503
|
-
compact
|
|
4612
|
+
compact,
|
|
4613
|
+
sharedRegistration
|
|
4504
4614
|
});
|
|
4505
4615
|
const handlePress = react.useCallback(async () => {
|
|
4506
4616
|
routeRegisterOutcome(await submit(), { onSuccess, onError });
|
|
@@ -4538,6 +4648,9 @@ function RegisterForm({
|
|
|
4538
4648
|
footer
|
|
4539
4649
|
] }) });
|
|
4540
4650
|
}
|
|
4651
|
+
function RegisterForm(props) {
|
|
4652
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RegisterFormCore, { ...props, sharedRegistration: false });
|
|
4653
|
+
}
|
|
4541
4654
|
async function lazyFetchHttpClient(request) {
|
|
4542
4655
|
const fetchImpl = typeof fetch === "function" ? fetch.bind(globalThis) : void 0;
|
|
4543
4656
|
if (fetchImpl === void 0) {
|
|
@@ -4673,6 +4786,11 @@ function createBffChangePasswordClient(options = {}) {
|
|
|
4673
4786
|
}
|
|
4674
4787
|
};
|
|
4675
4788
|
}
|
|
4789
|
+
function useFocusOnMount(ref) {
|
|
4790
|
+
react.useEffect(() => {
|
|
4791
|
+
ref.current?.focus();
|
|
4792
|
+
}, [ref]);
|
|
4793
|
+
}
|
|
4676
4794
|
function useResendVerification({ client, verifyUrlTemplate }) {
|
|
4677
4795
|
const [email, setEmail] = react.useState("");
|
|
4678
4796
|
const [missingEmail, setMissingEmail] = react.useState(false);
|
|
@@ -4692,6 +4810,11 @@ function useResendVerification({ client, verifyUrlTemplate }) {
|
|
|
4692
4810
|
}, [client, email, verifyUrlTemplate]);
|
|
4693
4811
|
return { email, setEmail, missingEmail, submitting, confirmed, submit };
|
|
4694
4812
|
}
|
|
4813
|
+
function ResendConfirmation({ style, testID, text }) {
|
|
4814
|
+
const ref = react.useRef(null);
|
|
4815
|
+
useFocusOnMount(ref);
|
|
4816
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { ref, accessible: true, accessibilityLiveRegion: "polite", focusable: true, testID, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style, children: text }) });
|
|
4817
|
+
}
|
|
4695
4818
|
function VerifyEmailResendForm({
|
|
4696
4819
|
client,
|
|
4697
4820
|
labels,
|
|
@@ -4703,7 +4826,7 @@ function VerifyEmailResendForm({
|
|
|
4703
4826
|
const resend = useResendVerification({ client, verifyUrlTemplate });
|
|
4704
4827
|
const id = (base) => withTestIdPrefix(base, testIdPrefix);
|
|
4705
4828
|
if (resend.confirmed) {
|
|
4706
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4829
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ResendConfirmation, { style: styles3.successText, testID: id(AuthTestIds.verifyEmailResendConfirmation), text: labels.resendConfirmation });
|
|
4707
4830
|
}
|
|
4708
4831
|
const submit = () => {
|
|
4709
4832
|
void resend.submit();
|
|
@@ -4732,7 +4855,7 @@ function VerifyEmailResendForm({
|
|
|
4732
4855
|
}
|
|
4733
4856
|
)
|
|
4734
4857
|
] }),
|
|
4735
|
-
resend.missingEmail ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.
|
|
4858
|
+
resend.missingEmail ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorBody, children: labels.resendMissingEmail }) : null,
|
|
4736
4859
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4737
4860
|
reactNative.TouchableOpacity,
|
|
4738
4861
|
{
|
|
@@ -4756,19 +4879,155 @@ var VerifyEmailErrorCode = /* @__PURE__ */ ((VerifyEmailErrorCode2) => {
|
|
|
4756
4879
|
VerifyEmailErrorCode2["TokenUsed"] = "TOKEN_USED";
|
|
4757
4880
|
VerifyEmailErrorCode2["KeycloakUpdateFailed"] = "KEYCLOAK_UPDATE_FAILED";
|
|
4758
4881
|
VerifyEmailErrorCode2["MissingToken"] = "MISSING_TOKEN";
|
|
4882
|
+
VerifyEmailErrorCode2["NewPasswordRequired"] = "NEW_PASSWORD_REQUIRED";
|
|
4883
|
+
VerifyEmailErrorCode2["WeakPassword"] = "WEAK_PASSWORD";
|
|
4884
|
+
VerifyEmailErrorCode2["RateLimited"] = "RATE_LIMITED";
|
|
4885
|
+
VerifyEmailErrorCode2["SignInFailed"] = "SIGN_IN_FAILED";
|
|
4759
4886
|
VerifyEmailErrorCode2["Generic"] = "GENERIC";
|
|
4760
4887
|
return VerifyEmailErrorCode2;
|
|
4761
4888
|
})(VerifyEmailErrorCode || {});
|
|
4762
4889
|
|
|
4890
|
+
// src/verify/useVerifyNewPasswordForm.ts
|
|
4891
|
+
var GENERIC_FAILURE = { success: false, errorCode: "GENERIC" /* Generic */ };
|
|
4892
|
+
var DEAD_LINK_CODES = [
|
|
4893
|
+
"TOKEN_INVALID" /* TokenInvalid */,
|
|
4894
|
+
"TOKEN_EXPIRED" /* TokenExpired */,
|
|
4895
|
+
"TOKEN_USED" /* TokenUsed */,
|
|
4896
|
+
"SIGN_IN_FAILED" /* SignInFailed */
|
|
4897
|
+
];
|
|
4898
|
+
function retryableError(code) {
|
|
4899
|
+
if (DEAD_LINK_CODES.includes(code)) {
|
|
4900
|
+
return null;
|
|
4901
|
+
}
|
|
4902
|
+
if (code === "WEAK_PASSWORD" /* WeakPassword */) {
|
|
4903
|
+
return "weakPassword" /* WeakPassword */;
|
|
4904
|
+
}
|
|
4905
|
+
return code === "RATE_LIMITED" /* RateLimited */ ? "rateLimited" /* RateLimited */ : "network" /* Network */;
|
|
4906
|
+
}
|
|
4907
|
+
function useVerifyNewPasswordForm({
|
|
4908
|
+
client,
|
|
4909
|
+
token,
|
|
4910
|
+
onSettled
|
|
4911
|
+
}) {
|
|
4912
|
+
const { state, setters } = useFormState();
|
|
4913
|
+
const [isSubmitting, setIsSubmitting] = react.useState(false);
|
|
4914
|
+
const inFlight = react.useRef(false);
|
|
4915
|
+
const send = react.useMemo(
|
|
4916
|
+
() => async (newPassword) => {
|
|
4917
|
+
if (inFlight.current) {
|
|
4918
|
+
return;
|
|
4919
|
+
}
|
|
4920
|
+
inFlight.current = true;
|
|
4921
|
+
setIsSubmitting(true);
|
|
4922
|
+
const result = await (client.setNewPassword?.(token, newPassword) ?? Promise.resolve(GENERIC_FAILURE)).catch(
|
|
4923
|
+
() => GENERIC_FAILURE
|
|
4924
|
+
);
|
|
4925
|
+
inFlight.current = false;
|
|
4926
|
+
setIsSubmitting(false);
|
|
4927
|
+
const formError = result.success ? null : retryableError(result.errorCode);
|
|
4928
|
+
if (formError === null) {
|
|
4929
|
+
onSettled(result);
|
|
4930
|
+
return;
|
|
4931
|
+
}
|
|
4932
|
+
setters.setErrorKey(formError);
|
|
4933
|
+
},
|
|
4934
|
+
[client, onSettled, setters, token]
|
|
4935
|
+
);
|
|
4936
|
+
return {
|
|
4937
|
+
...state,
|
|
4938
|
+
setNewPassword: setters.setNewPassword,
|
|
4939
|
+
setConfirmPassword: setters.setConfirmPassword,
|
|
4940
|
+
isSubmitting,
|
|
4941
|
+
submit: () => runSubmit({
|
|
4942
|
+
newPassword: state.newPassword,
|
|
4943
|
+
confirmPassword: state.confirmPassword,
|
|
4944
|
+
token,
|
|
4945
|
+
setErrorKey: setters.setErrorKey,
|
|
4946
|
+
setHasInvalidToken: setters.setHasInvalidToken,
|
|
4947
|
+
mutate: (request) => {
|
|
4948
|
+
void send(request.newPassword);
|
|
4949
|
+
}
|
|
4950
|
+
})
|
|
4951
|
+
};
|
|
4952
|
+
}
|
|
4953
|
+
function VerifyNewPasswordStep({
|
|
4954
|
+
client,
|
|
4955
|
+
token,
|
|
4956
|
+
labels: labelsProp,
|
|
4957
|
+
styles: styles3,
|
|
4958
|
+
theme,
|
|
4959
|
+
testIdPrefix,
|
|
4960
|
+
onSettled
|
|
4961
|
+
}) {
|
|
4962
|
+
const labels = react.useMemo(
|
|
4963
|
+
() => ({ ...DEFAULT_VERIFY_NEW_PASSWORD_LABELS, ...labelsProp }),
|
|
4964
|
+
[labelsProp]
|
|
4965
|
+
);
|
|
4966
|
+
const form = useVerifyNewPasswordForm({ client, token, onSettled });
|
|
4967
|
+
const handleSubmitEditing = useSubmitOnEnter(form.submit);
|
|
4968
|
+
const newPasswordRef = react.useRef(null);
|
|
4969
|
+
useFocusOnMount(newPasswordRef);
|
|
4970
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { testID: withTestIdPrefix(AuthTestIds.resetPasswordForm, testIdPrefix), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4971
|
+
ResetPasswordFields,
|
|
4972
|
+
{
|
|
4973
|
+
form,
|
|
4974
|
+
labels,
|
|
4975
|
+
newPasswordRef,
|
|
4976
|
+
styles: styles3,
|
|
4977
|
+
testIdPrefix,
|
|
4978
|
+
theme,
|
|
4979
|
+
onSubmitEditing: handleSubmitEditing
|
|
4980
|
+
}
|
|
4981
|
+
) });
|
|
4982
|
+
}
|
|
4983
|
+
function VerifySignInPrompt({
|
|
4984
|
+
labels: labelsProp,
|
|
4985
|
+
styles: styles3,
|
|
4986
|
+
testID,
|
|
4987
|
+
actionTestID,
|
|
4988
|
+
onContinue
|
|
4989
|
+
}) {
|
|
4990
|
+
const labels = react.useMemo(() => ({ ...DEFAULT_VERIFY_SIGN_IN_LABELS, ...labelsProp }), [labelsProp]);
|
|
4991
|
+
const actionRef = react.useRef(null);
|
|
4992
|
+
useFocusOnMount(actionRef);
|
|
4993
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID, children: [
|
|
4994
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.title }),
|
|
4995
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.body }),
|
|
4996
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4997
|
+
reactNative.TouchableOpacity,
|
|
4998
|
+
{
|
|
4999
|
+
ref: actionRef,
|
|
5000
|
+
accessibilityHint: labels.actionHint,
|
|
5001
|
+
accessibilityLabel: labels.action,
|
|
5002
|
+
accessibilityRole: "button",
|
|
5003
|
+
style: styles3.primaryButton,
|
|
5004
|
+
testID: actionTestID,
|
|
5005
|
+
onPress: onContinue,
|
|
5006
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.action })
|
|
5007
|
+
}
|
|
5008
|
+
)
|
|
5009
|
+
] });
|
|
5010
|
+
}
|
|
5011
|
+
|
|
4763
5012
|
// src/verify/VerifyEmailPhase.ts
|
|
4764
5013
|
var VerifyEmailPhase = /* @__PURE__ */ ((VerifyEmailPhase2) => {
|
|
4765
5014
|
VerifyEmailPhase2["Loading"] = "loading";
|
|
4766
5015
|
VerifyEmailPhase2["Success"] = "success";
|
|
4767
5016
|
VerifyEmailPhase2["Failure"] = "failure";
|
|
5017
|
+
VerifyEmailPhase2["NewPasswordRequired"] = "newPasswordRequired";
|
|
4768
5018
|
return VerifyEmailPhase2;
|
|
4769
5019
|
})(VerifyEmailPhase || {});
|
|
4770
5020
|
|
|
4771
|
-
// src/verify/
|
|
5021
|
+
// src/verify/resolveVerifyView.ts
|
|
5022
|
+
function resolveVerifyView(verify, passwordOutcome) {
|
|
5023
|
+
if (passwordOutcome === null) {
|
|
5024
|
+
return verify;
|
|
5025
|
+
}
|
|
5026
|
+
if (passwordOutcome.success) {
|
|
5027
|
+
return { phase: "success" /* Success */, errorCode: "GENERIC" /* Generic */ };
|
|
5028
|
+
}
|
|
5029
|
+
return { phase: "failure" /* Failure */, errorCode: passwordOutcome.errorCode };
|
|
5030
|
+
}
|
|
4772
5031
|
var LOADING = {
|
|
4773
5032
|
phase: "loading" /* Loading */,
|
|
4774
5033
|
errorCode: "GENERIC" /* Generic */
|
|
@@ -4777,6 +5036,10 @@ var SUCCESS = {
|
|
|
4777
5036
|
phase: "success" /* Success */,
|
|
4778
5037
|
errorCode: "GENERIC" /* Generic */
|
|
4779
5038
|
};
|
|
5039
|
+
var NEW_PASSWORD_REQUIRED = {
|
|
5040
|
+
phase: "newPasswordRequired" /* NewPasswordRequired */,
|
|
5041
|
+
errorCode: "GENERIC" /* Generic */
|
|
5042
|
+
};
|
|
4780
5043
|
var REJECTED = { success: false, errorCode: "GENERIC" /* Generic */ };
|
|
4781
5044
|
function failure(errorCode) {
|
|
4782
5045
|
return { phase: "failure" /* Failure */, errorCode };
|
|
@@ -4802,6 +5065,10 @@ function useVerifyEmail({ client, token, onVerified, onFailed }) {
|
|
|
4802
5065
|
latest.current.onVerified?.();
|
|
4803
5066
|
return;
|
|
4804
5067
|
}
|
|
5068
|
+
if (result.errorCode === "NEW_PASSWORD_REQUIRED" /* NewPasswordRequired */) {
|
|
5069
|
+
setState(NEW_PASSWORD_REQUIRED);
|
|
5070
|
+
return;
|
|
5071
|
+
}
|
|
4805
5072
|
setState(failure(result.errorCode));
|
|
4806
5073
|
latest.current.onFailed?.(result.errorCode);
|
|
4807
5074
|
};
|
|
@@ -4827,8 +5094,31 @@ function verifyEmailErrorText(code, labels) {
|
|
|
4827
5094
|
if (code === "MISSING_TOKEN" /* MissingToken */) {
|
|
4828
5095
|
return labels.missingToken;
|
|
4829
5096
|
}
|
|
5097
|
+
if (code === "SIGN_IN_FAILED" /* SignInFailed */) {
|
|
5098
|
+
return labels.signIn?.body ?? DEFAULT_VERIFY_SIGN_IN_LABELS.body;
|
|
5099
|
+
}
|
|
5100
|
+
if (code === "RATE_LIMITED" /* RateLimited */) {
|
|
5101
|
+
return labels.errorRateLimited ?? labels.errorGeneric;
|
|
5102
|
+
}
|
|
4830
5103
|
return labels.errorGeneric;
|
|
4831
5104
|
}
|
|
5105
|
+
function ResendCta({ label, hint, style, textStyle, testID, onPress }) {
|
|
5106
|
+
const ref = react.useRef(null);
|
|
5107
|
+
useFocusOnMount(ref);
|
|
5108
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5109
|
+
reactNative.TouchableOpacity,
|
|
5110
|
+
{
|
|
5111
|
+
ref,
|
|
5112
|
+
accessibilityHint: hint,
|
|
5113
|
+
accessibilityLabel: label,
|
|
5114
|
+
accessibilityRole: "button",
|
|
5115
|
+
style,
|
|
5116
|
+
testID,
|
|
5117
|
+
onPress,
|
|
5118
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: textStyle, children: label })
|
|
5119
|
+
}
|
|
5120
|
+
);
|
|
5121
|
+
}
|
|
4832
5122
|
function VerifyEmailScreen({
|
|
4833
5123
|
client,
|
|
4834
5124
|
token,
|
|
@@ -4846,7 +5136,20 @@ function VerifyEmailScreen({
|
|
|
4846
5136
|
() => ({ ...DEFAULT_VERIFY_EMAIL_LABELS, ...labelsProp }),
|
|
4847
5137
|
[labelsProp]
|
|
4848
5138
|
);
|
|
4849
|
-
const
|
|
5139
|
+
const verify = useVerifyEmail({ client, token, onVerified, onFailed });
|
|
5140
|
+
const [passwordOutcome, setPasswordOutcome] = react.useState(null);
|
|
5141
|
+
const { phase, errorCode } = resolveVerifyView(verify, passwordOutcome);
|
|
5142
|
+
const settlePassword = react.useCallback(
|
|
5143
|
+
(result) => {
|
|
5144
|
+
setPasswordOutcome(result);
|
|
5145
|
+
if (result.success) {
|
|
5146
|
+
onVerified?.();
|
|
5147
|
+
return;
|
|
5148
|
+
}
|
|
5149
|
+
onFailed?.(result.errorCode);
|
|
5150
|
+
},
|
|
5151
|
+
[onFailed, onVerified]
|
|
5152
|
+
);
|
|
4850
5153
|
const [resendOpen, setResendOpen] = react.useState(false);
|
|
4851
5154
|
const openResend = react.useCallback(() => setResendOpen(true), []);
|
|
4852
5155
|
const id = (base) => withTestIdPrefix(base, testIdPrefix);
|
|
@@ -4856,6 +5159,18 @@ function VerifyEmailScreen({
|
|
|
4856
5159
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.loadingTitle }),
|
|
4857
5160
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.loadingHint })
|
|
4858
5161
|
] }) : null,
|
|
5162
|
+
phase === "newPasswordRequired" /* NewPasswordRequired */ ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5163
|
+
VerifyNewPasswordStep,
|
|
5164
|
+
{
|
|
5165
|
+
client,
|
|
5166
|
+
labels: labels.newPassword,
|
|
5167
|
+
styles: styles3,
|
|
5168
|
+
testIdPrefix,
|
|
5169
|
+
theme,
|
|
5170
|
+
token,
|
|
5171
|
+
onSettled: settlePassword
|
|
5172
|
+
}
|
|
5173
|
+
) : null,
|
|
4859
5174
|
phase === "success" /* Success */ ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID: id(AuthTestIds.verifyEmailSuccess), children: [
|
|
4860
5175
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.successTitle }),
|
|
4861
5176
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.successBody }),
|
|
@@ -4872,9 +5187,19 @@ function VerifyEmailScreen({
|
|
|
4872
5187
|
}
|
|
4873
5188
|
)
|
|
4874
5189
|
] }) : null,
|
|
4875
|
-
phase === "failure" /* Failure */ ? /* @__PURE__ */ jsxRuntime.
|
|
5190
|
+
phase === "failure" /* Failure */ && errorCode === "SIGN_IN_FAILED" /* SignInFailed */ ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5191
|
+
VerifySignInPrompt,
|
|
5192
|
+
{
|
|
5193
|
+
actionTestID: id(AuthTestIds.verifyEmailSignInContinue),
|
|
5194
|
+
labels: labels.signIn,
|
|
5195
|
+
styles: styles3,
|
|
5196
|
+
testID: id(AuthTestIds.verifyEmailSignIn),
|
|
5197
|
+
onContinue
|
|
5198
|
+
}
|
|
5199
|
+
) : null,
|
|
5200
|
+
phase === "failure" /* Failure */ && errorCode !== "SIGN_IN_FAILED" /* SignInFailed */ ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { testID: id(AuthTestIds.verifyEmailError), children: [
|
|
4876
5201
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.errorTitle }),
|
|
4877
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.
|
|
5202
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorBody, children: verifyEmailErrorText(errorCode, labels) }),
|
|
4878
5203
|
resendOpen ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4879
5204
|
VerifyEmailResendForm,
|
|
4880
5205
|
{
|
|
@@ -4886,15 +5211,14 @@ function VerifyEmailScreen({
|
|
|
4886
5211
|
verifyUrlTemplate
|
|
4887
5212
|
}
|
|
4888
5213
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4889
|
-
|
|
5214
|
+
ResendCta,
|
|
4890
5215
|
{
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
accessibilityRole: "button",
|
|
5216
|
+
hint: labels.resendCtaHint,
|
|
5217
|
+
label: labels.resendCta,
|
|
4894
5218
|
style: styles3.primaryButton,
|
|
4895
5219
|
testID: id(AuthTestIds.verifyEmailResendCta),
|
|
4896
|
-
|
|
4897
|
-
|
|
5220
|
+
textStyle: styles3.primaryButtonText,
|
|
5221
|
+
onPress: openResend
|
|
4898
5222
|
}
|
|
4899
5223
|
)
|
|
4900
5224
|
] }) : null
|
|
@@ -4911,7 +5235,10 @@ var SERVER_ERROR_CODES2 = [
|
|
|
4911
5235
|
"TOKEN_USED" /* TokenUsed */,
|
|
4912
5236
|
"KEYCLOAK_UPDATE_FAILED" /* KeycloakUpdateFailed */
|
|
4913
5237
|
];
|
|
4914
|
-
var
|
|
5238
|
+
var GENERIC_FAILURE2 = { success: false, errorCode: "GENERIC" /* Generic */ };
|
|
5239
|
+
var INVALID_TOKEN = { success: false, errorCode: "TOKEN_INVALID" /* TokenInvalid */ };
|
|
5240
|
+
var HTTP_BAD_REQUEST3 = 400;
|
|
5241
|
+
var TOKEN_FIELD = "token";
|
|
4915
5242
|
async function lazyFetchHttpClient3(request) {
|
|
4916
5243
|
const fetchImpl = typeof fetch === "function" ? fetch.bind(globalThis) : void 0;
|
|
4917
5244
|
if (fetchImpl === void 0) {
|
|
@@ -4925,14 +5252,23 @@ function isServerErrorCode(value) {
|
|
|
4925
5252
|
function isRecord3(value) {
|
|
4926
5253
|
return typeof value === "object" && value !== null;
|
|
4927
5254
|
}
|
|
4928
|
-
function
|
|
5255
|
+
function isTokenValidationRejection(status, body) {
|
|
5256
|
+
if (status !== HTTP_BAD_REQUEST3 || !isRecord3(body.errors)) {
|
|
5257
|
+
return false;
|
|
5258
|
+
}
|
|
5259
|
+
return Object.keys(body.errors).some((field2) => field2.toLowerCase() === TOKEN_FIELD);
|
|
5260
|
+
}
|
|
5261
|
+
function decodeVerifyResponse(status, body) {
|
|
4929
5262
|
if (!isRecord3(body)) {
|
|
4930
|
-
return
|
|
5263
|
+
return GENERIC_FAILURE2;
|
|
4931
5264
|
}
|
|
4932
5265
|
if (body.success === true) {
|
|
4933
5266
|
return { success: true };
|
|
4934
5267
|
}
|
|
4935
|
-
|
|
5268
|
+
if (isServerErrorCode(body.errorCode)) {
|
|
5269
|
+
return { success: false, errorCode: body.errorCode };
|
|
5270
|
+
}
|
|
5271
|
+
return isTokenValidationRejection(status, body) ? INVALID_TOKEN : GENERIC_FAILURE2;
|
|
4936
5272
|
}
|
|
4937
5273
|
function createBffVerifyEmailClient(options = {}) {
|
|
4938
5274
|
const http = options.http ?? lazyFetchHttpClient3;
|
|
@@ -4948,9 +5284,9 @@ function createBffVerifyEmailClient(options = {}) {
|
|
|
4948
5284
|
verifyEmail: async (token) => {
|
|
4949
5285
|
try {
|
|
4950
5286
|
const response = await post(VERIFY_EMAIL_ENDPOINT, { token });
|
|
4951
|
-
return decodeVerifyResponse(response.data);
|
|
5287
|
+
return decodeVerifyResponse(response.status, response.data);
|
|
4952
5288
|
} catch {
|
|
4953
|
-
return
|
|
5289
|
+
return GENERIC_FAILURE2;
|
|
4954
5290
|
}
|
|
4955
5291
|
},
|
|
4956
5292
|
resendVerification: async (email, verifyUrlTemplate) => {
|
|
@@ -4990,6 +5326,122 @@ function readVerifyToken(raw) {
|
|
|
4990
5326
|
return typeof first === "string" ? first : "";
|
|
4991
5327
|
}
|
|
4992
5328
|
|
|
5329
|
+
// src/verify/sharedRegistrationClient.ts
|
|
5330
|
+
var REGISTER_ENDPOINT = "/bff/register";
|
|
5331
|
+
var VERIFY_AND_LOGIN_ENDPOINT = "/bff/verify-and-login";
|
|
5332
|
+
var HTTP_ACCEPTED = 202;
|
|
5333
|
+
var HTTP_UNAUTHORIZED2 = 401;
|
|
5334
|
+
var HTTP_TOO_MANY_REQUESTS2 = 429;
|
|
5335
|
+
var NO_MESSAGE = "";
|
|
5336
|
+
var GENERIC_FAILURE3 = { success: false, errorCode: "GENERIC" /* Generic */ };
|
|
5337
|
+
function decodeVerifyAndLogin(response) {
|
|
5338
|
+
if (response.ok) {
|
|
5339
|
+
return { success: true };
|
|
5340
|
+
}
|
|
5341
|
+
if (response.status === HTTP_TOO_MANY_REQUESTS2) {
|
|
5342
|
+
return { success: false, errorCode: "RATE_LIMITED" /* RateLimited */ };
|
|
5343
|
+
}
|
|
5344
|
+
if (response.status === HTTP_UNAUTHORIZED2) {
|
|
5345
|
+
return { success: false, errorCode: "SIGN_IN_FAILED" /* SignInFailed */ };
|
|
5346
|
+
}
|
|
5347
|
+
const body = isRecord3(response.data) ? response.data : {};
|
|
5348
|
+
if (body.errorCode === "NEW_PASSWORD_REQUIRED" /* NewPasswordRequired */ || body.errorCode === "WEAK_PASSWORD" /* WeakPassword */) {
|
|
5349
|
+
return { success: false, errorCode: body.errorCode };
|
|
5350
|
+
}
|
|
5351
|
+
return decodeVerifyResponse(response.status, response.data);
|
|
5352
|
+
}
|
|
5353
|
+
function registerFailure(response) {
|
|
5354
|
+
const body = isRecord3(response.data) ? response.data : {};
|
|
5355
|
+
const errorCode = body.errorCode ?? body.code;
|
|
5356
|
+
const message = `Registration failed with status ${String(response.status)}`;
|
|
5357
|
+
return Object.assign(new Error(message), { status: response.status, errorCode });
|
|
5358
|
+
}
|
|
5359
|
+
function createSharedRegistrationClient(options = {}) {
|
|
5360
|
+
const http = options.http ?? lazyFetchHttpClient3;
|
|
5361
|
+
const baseUrl = options.baseUrl ?? "";
|
|
5362
|
+
const post = (path, body, headers = {}) => http({
|
|
5363
|
+
url: `${baseUrl}${path}`,
|
|
5364
|
+
method: "POST",
|
|
5365
|
+
headers: { "Content-Type": "application/json", "X-BFF-Csrf": "1", ...headers },
|
|
5366
|
+
body: JSON.stringify(body),
|
|
5367
|
+
credentials: "include"
|
|
5368
|
+
});
|
|
5369
|
+
const verifyAndLogin = async (body) => {
|
|
5370
|
+
try {
|
|
5371
|
+
return decodeVerifyAndLogin(await post(VERIFY_AND_LOGIN_ENDPOINT, body));
|
|
5372
|
+
} catch {
|
|
5373
|
+
return GENERIC_FAILURE3;
|
|
5374
|
+
}
|
|
5375
|
+
};
|
|
5376
|
+
const verifyEmailClient = createBffVerifyEmailClient(options);
|
|
5377
|
+
return {
|
|
5378
|
+
register: async (request, meta) => {
|
|
5379
|
+
const body = meta === void 0 ? request : { ...request, formElapsedMs: meta.formElapsedMs };
|
|
5380
|
+
const headers = meta === void 0 ? {} : { "Idempotency-Key": meta.idempotencyKey };
|
|
5381
|
+
const response = await post(REGISTER_ENDPOINT, body, headers).catch(() => {
|
|
5382
|
+
throw new Error(NO_MESSAGE);
|
|
5383
|
+
});
|
|
5384
|
+
if (!response.ok) {
|
|
5385
|
+
throw registerFailure(response);
|
|
5386
|
+
}
|
|
5387
|
+
return { accepted: response.status === HTTP_ACCEPTED, body: response.data };
|
|
5388
|
+
},
|
|
5389
|
+
verifyEmail: (token) => verifyAndLogin({ token }),
|
|
5390
|
+
setNewPassword: (token, newPassword) => verifyAndLogin({ token, newPassword }),
|
|
5391
|
+
resendVerification: (email, verifyUrlTemplate) => verifyEmailClient.resendVerification(email, verifyUrlTemplate)
|
|
5392
|
+
};
|
|
5393
|
+
}
|
|
5394
|
+
function RegisterCheckEmail({
|
|
5395
|
+
labels,
|
|
5396
|
+
styles: styles3,
|
|
5397
|
+
footer,
|
|
5398
|
+
testIdPrefix
|
|
5399
|
+
}) {
|
|
5400
|
+
const headingRef = react.useRef(null);
|
|
5401
|
+
useFocusOnMount(headingRef);
|
|
5402
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5403
|
+
reactNative.View,
|
|
5404
|
+
{
|
|
5405
|
+
accessibilityLiveRegion: "polite",
|
|
5406
|
+
style: styles3.card,
|
|
5407
|
+
testID: withTestIdPrefix(RegisterTestIds.checkEmail, testIdPrefix),
|
|
5408
|
+
children: [
|
|
5409
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { ref: headingRef, accessible: true, focusable: true, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: styles3.title, children: labels.checkEmailTitle }) }),
|
|
5410
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.checkEmailBody }),
|
|
5411
|
+
footer
|
|
5412
|
+
]
|
|
5413
|
+
}
|
|
5414
|
+
) });
|
|
5415
|
+
}
|
|
5416
|
+
function SharedRegisterForm({
|
|
5417
|
+
onSuccess,
|
|
5418
|
+
onAccepted,
|
|
5419
|
+
...formProps
|
|
5420
|
+
}) {
|
|
5421
|
+
const { footer, labels: labelsProp, testIdPrefix, theme: themeProp } = formProps;
|
|
5422
|
+
const styles3 = useAuthStyles(useAuthTheme(themeProp));
|
|
5423
|
+
const labels = react.useMemo(
|
|
5424
|
+
() => ({ ...DEFAULT_REGISTER_LABELS, ...labelsProp }),
|
|
5425
|
+
[labelsProp]
|
|
5426
|
+
);
|
|
5427
|
+
const [accepted, setAccepted] = react.useState(false);
|
|
5428
|
+
const handleResult = react.useCallback(
|
|
5429
|
+
(result) => {
|
|
5430
|
+
if (!isRegisterAccepted(result)) {
|
|
5431
|
+
onSuccess(result);
|
|
5432
|
+
return;
|
|
5433
|
+
}
|
|
5434
|
+
setAccepted(true);
|
|
5435
|
+
onAccepted?.(result);
|
|
5436
|
+
},
|
|
5437
|
+
[onAccepted, onSuccess]
|
|
5438
|
+
);
|
|
5439
|
+
if (accepted) {
|
|
5440
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RegisterCheckEmail, { footer, labels, styles: styles3, testIdPrefix });
|
|
5441
|
+
}
|
|
5442
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RegisterFormCore, { ...formProps, sharedRegistration: true, onSuccess: handleResult });
|
|
5443
|
+
}
|
|
5444
|
+
|
|
4993
5445
|
Object.defineProperty(exports, "BffAuthClient", {
|
|
4994
5446
|
enumerable: true,
|
|
4995
5447
|
get: function () { return authClient.BffAuthClient; }
|
|
@@ -5024,6 +5476,8 @@ exports.DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS = DEFAULT_PREFERRED_METHOD_SETT
|
|
|
5024
5476
|
exports.DEFAULT_REGISTER_LABELS = DEFAULT_REGISTER_LABELS;
|
|
5025
5477
|
exports.DEFAULT_RESET_PASSWORD_LABELS = DEFAULT_RESET_PASSWORD_LABELS;
|
|
5026
5478
|
exports.DEFAULT_VERIFY_EMAIL_LABELS = DEFAULT_VERIFY_EMAIL_LABELS;
|
|
5479
|
+
exports.DEFAULT_VERIFY_NEW_PASSWORD_LABELS = DEFAULT_VERIFY_NEW_PASSWORD_LABELS;
|
|
5480
|
+
exports.DEFAULT_VERIFY_SIGN_IN_LABELS = DEFAULT_VERIFY_SIGN_IN_LABELS;
|
|
5027
5481
|
exports.DEVICE_PIN_ALLOWED_DIGITS = DEVICE_PIN_ALLOWED_DIGITS;
|
|
5028
5482
|
exports.DEVICE_PIN_DEFAULT_DIGITS = DEVICE_PIN_DEFAULT_DIGITS;
|
|
5029
5483
|
exports.DemoCredentialsHint = DemoCredentialsHint;
|
|
@@ -5052,12 +5506,15 @@ exports.PinForm = PinForm;
|
|
|
5052
5506
|
exports.PreferredMethodHint = PreferredMethodHint;
|
|
5053
5507
|
exports.PreferredMethodSettingsCard = PreferredMethodSettingsCard;
|
|
5054
5508
|
exports.PrefillIntent = PrefillIntent;
|
|
5509
|
+
exports.REGISTER_ENDPOINT = REGISTER_ENDPOINT;
|
|
5055
5510
|
exports.RESEND_VERIFICATION_ENDPOINT = RESEND_VERIFICATION_ENDPOINT;
|
|
5056
5511
|
exports.RegisterErrorCode = RegisterErrorCode;
|
|
5057
5512
|
exports.RegisterForm = RegisterForm;
|
|
5058
5513
|
exports.RegisterTestIds = RegisterTestIds;
|
|
5059
5514
|
exports.ResetPasswordError = ResetPasswordError;
|
|
5060
5515
|
exports.ResetPasswordForm = ResetPasswordForm;
|
|
5516
|
+
exports.SharedRegisterForm = SharedRegisterForm;
|
|
5517
|
+
exports.VERIFY_AND_LOGIN_ENDPOINT = VERIFY_AND_LOGIN_ENDPOINT;
|
|
5061
5518
|
exports.VERIFY_EMAIL_ENDPOINT = VERIFY_EMAIL_ENDPOINT;
|
|
5062
5519
|
exports.VERIFY_TOKEN_PLACEHOLDER = VERIFY_TOKEN_PLACEHOLDER;
|
|
5063
5520
|
exports.VerifyEmailErrorCode = VerifyEmailErrorCode;
|
|
@@ -5071,10 +5528,12 @@ exports.createBffAuthClient = createBffAuthClient;
|
|
|
5071
5528
|
exports.createBffChangePasswordClient = createBffChangePasswordClient;
|
|
5072
5529
|
exports.createBffVerifyEmailClient = createBffVerifyEmailClient;
|
|
5073
5530
|
exports.createPreferencesClient = createPreferencesClient;
|
|
5531
|
+
exports.createSharedRegistrationClient = createSharedRegistrationClient;
|
|
5074
5532
|
exports.defaultAuthTheme = defaultAuthTheme;
|
|
5075
5533
|
exports.deriveUsernameFromEmail = deriveUsernameFromEmail;
|
|
5076
5534
|
exports.isAllowedPinDigits = isAllowedPinDigits;
|
|
5077
5535
|
exports.isPasswordValid = isPasswordValid;
|
|
5536
|
+
exports.isRegisterAccepted = isRegisterAccepted;
|
|
5078
5537
|
exports.isRegisterPasswordStrong = isRegisterPasswordStrong;
|
|
5079
5538
|
exports.isValidForgotPasswordEmail = isValidForgotPasswordEmail;
|
|
5080
5539
|
exports.performBffLogout = performBffLogout;
|