cauthy-auth 0.30.0 → 0.31.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.
Files changed (46) hide show
  1. package/README.md +10 -3
  2. package/dist/{cauthy-BXgsZ-Um.d.mts → cauthy-2jtP2LVQ.d.mts} +1 -1
  3. package/dist/{cauthy-CHENs452.d.ts → cauthy-CKfvvv_i.d.ts} +1 -1
  4. package/dist/cli.js +8 -5
  5. package/dist/client.d.mts +47 -6
  6. package/dist/client.d.ts +47 -6
  7. package/dist/client.js +16 -2
  8. package/dist/client.js.map +1 -1
  9. package/dist/client.mjs +16 -2
  10. package/dist/client.mjs.map +1 -1
  11. package/dist/express.d.mts +2 -2
  12. package/dist/express.d.ts +2 -2
  13. package/dist/fastify.d.mts +2 -2
  14. package/dist/fastify.d.ts +2 -2
  15. package/dist/hono.d.mts +2 -2
  16. package/dist/hono.d.ts +2 -2
  17. package/dist/index.d.mts +2 -2
  18. package/dist/index.d.ts +2 -2
  19. package/dist/index.js +64 -21
  20. package/dist/index.js.map +1 -1
  21. package/dist/index.mjs +64 -21
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/next.d.mts +2 -2
  24. package/dist/next.d.ts +2 -2
  25. package/dist/react.d.mts +61 -5
  26. package/dist/react.d.ts +61 -5
  27. package/dist/react.js +183 -46
  28. package/dist/react.js.map +1 -1
  29. package/dist/react.mjs +182 -46
  30. package/dist/react.mjs.map +1 -1
  31. package/dist/styles.css +8 -0
  32. package/dist/svelte.d.mts +2 -2
  33. package/dist/svelte.d.ts +2 -2
  34. package/dist/svelte.js +16 -2
  35. package/dist/svelte.js.map +1 -1
  36. package/dist/svelte.mjs +16 -2
  37. package/dist/svelte.mjs.map +1 -1
  38. package/dist/{system-0mHrdAgO.d.mts → system-BrrJsrFW.d.mts} +14 -0
  39. package/dist/{system-BIYbS7h2.d.ts → system-BvvoNs2y.d.ts} +14 -0
  40. package/dist/vue.d.mts +2 -2
  41. package/dist/vue.d.ts +2 -2
  42. package/dist/vue.js +16 -2
  43. package/dist/vue.js.map +1 -1
  44. package/dist/vue.mjs +16 -2
  45. package/dist/vue.mjs.map +1 -1
  46. package/package.json +1 -1
package/dist/react.js CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  // src/react.tsx
22
22
  var react_exports = {};
23
23
  __export(react_exports, {
24
+ AcceptInvite: () => AcceptInvite,
24
25
  Account: () => Account,
25
26
  CauthyProvider: () => CauthyProvider,
26
27
  ForgotPassword: () => ForgotPassword,
@@ -411,11 +412,11 @@ function createAuthClient(options = {}) {
411
412
  if (res.ok) {
412
413
  const m = await res.json();
413
414
  if (m.password) policy = passwordPolicyOf(m.password);
414
- return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, ...policy ? { password: policy } : {}, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true, sso: m.sso === true };
415
+ return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, ...policy ? { password: policy } : {}, passwordSignIn: m.passwordSignIn !== false, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true, sso: m.sso === true };
415
416
  }
416
417
  } catch {
417
418
  }
418
- return { providers: [], signUp: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false, sso: false };
419
+ return { providers: [], signUp: true, passwordSignIn: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false, sso: false };
419
420
  }
420
421
  async function ceremony(begin, finish, form, run, more = {}) {
421
422
  const begun = await post(begin, form, null);
@@ -562,6 +563,20 @@ function createAuthClient(options = {}) {
562
563
  forgotPassword: (f) => post("/forgot-password", { email: f.email }, checkEmail(f.email), f.captchaToken),
563
564
  resetPassword: (f) => post("/reset-password", { token: f.token, password: f.password }, checkNewPassword(f.password, policy)),
564
565
  verifyEmail: (f) => post("/verify-email", { token: f.token }, null),
566
+ async invitation(token) {
567
+ const bad = { ok: false, error: { code: "invalid_token", message: "This invitation is not valid, or it has expired." } };
568
+ if (typeof token !== "string" || token.trim() === "") return bad;
569
+ try {
570
+ const res = await doFetch(`${base}/invitation?token=${encodeURIComponent(token.trim())}`, { credentials: "same-origin", headers: { accept: "application/json" } });
571
+ const body = await res.json().catch(() => null);
572
+ if (res.ok && body?.invitation) return { ok: true, status: "ok", invitation: body.invitation };
573
+ const e = body?.error;
574
+ return { ok: false, error: e && typeof e.code === "string" ? { code: e.code, message: String(e.message ?? "") } : UNAVAILABLE };
575
+ } catch {
576
+ return { ok: false, error: UNAVAILABLE };
577
+ }
578
+ },
579
+ acceptInvitation: (token, password) => post("/invitation/accept", { token, password }, checkNewPassword(password, policy)),
565
580
  signOut: () => post("/sign-out", {}, null),
566
581
  organizations: {
567
582
  async list(system) {
@@ -798,6 +813,13 @@ var TEXTS = {
798
813
  passwordChanged: "Your password was changed. You can sign in with it now.",
799
814
  confirming: "Confirming your address\u2026",
800
815
  emailConfirmed: "Your address is confirmed. You can sign in now.",
816
+ invitedTo: "You've been invited to {workspace}",
817
+ invitedToOrganization: "You've been invited to {organization} on {workspace}",
818
+ invitedAs: "You will sign in as {email}.",
819
+ choosePassword: "Choose a password",
820
+ acceptInvite: "Accept and sign in",
821
+ openingInvitation: "Opening your invitation\u2026",
822
+ invitationInvalid: "This invitation is not valid: it was already used, or it has expired. Ask whoever invited you to send it again.",
801
823
  profile: "Profile",
802
824
  save: "Save",
803
825
  saved: "Saved.",
@@ -912,7 +934,9 @@ var TEXTS = {
912
934
  invalid_assertion: "Your company's answer could not be checked. Try again.",
913
935
  provisioning_disabled: "Your company's sign-in worked, but this workspace has no account for you. Ask its admin to add you.",
914
936
  connection_inactive: "Your company's sign-in is turned off for this workspace.",
915
- invalid_grant: "That sign-in expired. Try again."
937
+ invalid_grant: "That sign-in expired. Try again.",
938
+ password_disabled: "This workspace does not sign in with a password. Use one of the other ways.",
939
+ passkeys_disabled: "Passkeys are turned off for this workspace."
916
940
  }
917
941
  },
918
942
  es: {
@@ -965,6 +989,13 @@ var TEXTS = {
965
989
  passwordChanged: "Tu contrase\xF1a se cambi\xF3. Ya puedes entrar con ella.",
966
990
  confirming: "Confirmando tu correo\u2026",
967
991
  emailConfirmed: "Tu correo qued\xF3 confirmado. Ya puedes entrar.",
992
+ invitedTo: "Te invitaron a {workspace}",
993
+ invitedToOrganization: "Te invitaron a {organization} en {workspace}",
994
+ invitedAs: "Vas a entrar como {email}.",
995
+ choosePassword: "Elige una contrase\xF1a",
996
+ acceptInvite: "Aceptar y entrar",
997
+ openingInvitation: "Abriendo tu invitaci\xF3n\u2026",
998
+ invitationInvalid: "Esta invitaci\xF3n no es v\xE1lida: ya se us\xF3 o venci\xF3. P\xEDdele a quien te invit\xF3 que te la env\xEDe de nuevo.",
968
999
  profile: "Perfil",
969
1000
  save: "Guardar",
970
1001
  saved: "Guardado.",
@@ -1079,7 +1110,9 @@ var TEXTS = {
1079
1110
  invalid_assertion: "No se pudo verificar la respuesta de tu empresa. Intenta de nuevo.",
1080
1111
  provisioning_disabled: "El ingreso con tu empresa funcion\xF3, pero este workspace no tiene una cuenta para ti. P\xEDdele a su admin que te agregue.",
1081
1112
  connection_inactive: "El inicio de sesi\xF3n de tu empresa est\xE1 apagado en este workspace.",
1082
- invalid_grant: "Ese ingreso venci\xF3. Intenta de nuevo."
1113
+ invalid_grant: "Ese ingreso venci\xF3. Intenta de nuevo.",
1114
+ password_disabled: "En este workspace no se entra con contrase\xF1a. Usa una de las otras formas.",
1115
+ passkeys_disabled: "Las llaves de acceso est\xE1n desactivadas en este workspace."
1083
1116
  }
1084
1117
  }
1085
1118
  };
@@ -1274,23 +1307,16 @@ function useMailedToken(name, open) {
1274
1307
  open(takeToken(name));
1275
1308
  }, []);
1276
1309
  }
1277
- function SignIn(props) {
1278
- const auth = useAuth();
1279
- const f = useForm(props);
1280
- const [methods, setMethods] = (0, import_react.useState)(null);
1281
- const [email, setEmail] = (0, import_react.useState)("");
1282
- const [password, setPassword] = (0, import_react.useState)("");
1310
+ function SecondStepForm(p) {
1311
+ const { f, auth } = p;
1283
1312
  const [code, setCode] = (0, import_react.useState)("");
1284
- const [step, setStep] = (0, import_react.useState)("password");
1285
- const challenge = useChallenge(methods?.captchaSiteKey, props.locale);
1286
1313
  const [phoneWay, setPhoneWay] = (0, import_react.useState)(null);
1287
1314
  const [phoneSent, setPhoneSent] = (0, import_react.useState)("");
1288
1315
  (0, import_react.useEffect)(() => {
1289
- if (step !== "code") return;
1290
1316
  void auth.signIn.mfaMethods().then((r) => {
1291
1317
  if (r.ok) setPhoneWay({ totp: r.totp, phone: r.phone, push: r.push, email: r.email });
1292
1318
  });
1293
- }, [step]);
1319
+ }, []);
1294
1320
  const sendEmail = async () => {
1295
1321
  f.setBusy(true);
1296
1322
  f.setError(null);
@@ -1326,6 +1352,55 @@ function SignIn(props) {
1326
1352
  if (!r.ok) return f.setError(r.error);
1327
1353
  setPhoneSent(r.sentTo);
1328
1354
  };
1355
+ const submit = async (e) => {
1356
+ e.preventDefault();
1357
+ f.setBusy(true);
1358
+ f.setError(null);
1359
+ const r = await auth.signIn.mfa({ code });
1360
+ f.setBusy(false);
1361
+ if (!r.ok) return f.setError(r.error);
1362
+ f.done();
1363
+ };
1364
+ const general = f.error && !f.error.field ? f.error : null;
1365
+ const to = phoneWay?.phone?.number ?? "";
1366
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1367
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: phoneSent ? f.t.codeSent.replace("{to}", phoneSent) : phoneWay?.email ? f.t.codeHelpEmail.replace("{to}", phoneWay.email.to) : phoneWay?.phone && !phoneWay.totp ? f.t.codeHelpPhone : f.t.codeHelp }),
1368
+ general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
1369
+ phoneWay?.email && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendEmail(), children: f.t.sendEmailAgain }),
1370
+ pushNumber > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("notice"), role: "status", "aria-live": "polite", children: [
1371
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
1372
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 48, fontWeight: 700, margin: "4px 0", textAlign: "center" }, children: pushNumber }),
1373
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushWaiting })
1374
+ ] }) : phoneWay?.push && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("button"), onClick: () => void sendPush(), children: f.t.pushSend }),
1375
+ phoneWay?.phone && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendCode(), children: (phoneWay.phone.channel === "whatsapp" ? f.t.sendCodeWhatsapp : f.t.sendCodeSms).replace("{to}", to) }),
1376
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
1377
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
1378
+ ] });
1379
+ }
1380
+ function ProviderButtons(p) {
1381
+ const { f } = p;
1382
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: p.providers.map((provider) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", className: f.cx("providerButton"), onClick: () => p.onPick(provider.id), children: [
1383
+ provider.iconUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: provider.iconUrl, alt: "", width: 18, height: 18, className: f.cx("providerIcon") }),
1384
+ f.t.continueWith,
1385
+ " ",
1386
+ provider.name
1387
+ ] }, provider.id)) });
1388
+ }
1389
+ function signInOffers(methods) {
1390
+ const password = methods?.passwordSignIn !== false;
1391
+ return { password, email: password || methods?.magicLink === true || methods?.sso === true, passkey: methods?.passkey === true };
1392
+ }
1393
+ function SignIn(props) {
1394
+ const auth = useAuth();
1395
+ const f = useForm(props);
1396
+ const [methods, setMethods] = (0, import_react.useState)(null);
1397
+ const [email, setEmail] = (0, import_react.useState)("");
1398
+ const [password, setPassword] = (0, import_react.useState)("");
1399
+ const [code, setCode] = (0, import_react.useState)("");
1400
+ const [step, setStep] = (0, import_react.useState)("password");
1401
+ const challenge = useChallenge(methods?.captchaSiteKey, props.locale);
1402
+ const offers = signInOffers(methods);
1403
+ const passwordOn = offers.password;
1329
1404
  const autofill = (0, import_react.useRef)(null);
1330
1405
  const [offer, setOffer] = (0, import_react.useState)(0);
1331
1406
  const [company, setCompany] = (0, import_react.useState)(null);
@@ -1377,10 +1452,18 @@ function SignIn(props) {
1377
1452
  const submit = async (e) => {
1378
1453
  e.preventDefault();
1379
1454
  autofill.current?.abort();
1455
+ if (step === "password" && company?.enforced) {
1456
+ f.setError(null);
1457
+ return toCompany();
1458
+ }
1459
+ if (step === "password" && !passwordOn) {
1460
+ if (company) return toCompany();
1461
+ if (methods?.magicLink) return sendLink();
1462
+ return;
1463
+ }
1380
1464
  f.setBusy(true);
1381
1465
  f.setError(null);
1382
- if (step === "password" && company?.enforced) return toCompany();
1383
- const r = step === "code" ? await auth.signIn.mfa({ code }) : step === "sent" ? await auth.signIn.emailCode({ code }) : await auth.signIn.email({ email, password, captchaToken: challenge.token });
1466
+ const r = step === "sent" ? await auth.signIn.emailCode({ code }) : await auth.signIn.email({ email, password, captchaToken: challenge.token });
1384
1467
  f.setBusy(false);
1385
1468
  if (step === "password") challenge.renew();
1386
1469
  if (!r.ok && r.error.code === "sso_required") return toCompany();
@@ -1414,6 +1497,7 @@ function SignIn(props) {
1414
1497
  setStep("sent");
1415
1498
  };
1416
1499
  const general = f.error && !f.error.field ? f.error : null;
1500
+ const asksEmail = offers.email;
1417
1501
  if (step === "opening") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("form"), ...f.root, "aria-busy": "true" });
1418
1502
  if (step === "sent") {
1419
1503
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
@@ -1424,39 +1508,20 @@ function SignIn(props) {
1424
1508
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
1425
1509
  ] });
1426
1510
  }
1427
- if (step === "code") {
1428
- const to = phoneWay?.phone?.number ?? "";
1429
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1430
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: phoneSent ? f.t.codeSent.replace("{to}", phoneSent) : phoneWay?.email ? f.t.codeHelpEmail.replace("{to}", phoneWay.email.to) : phoneWay?.phone && !phoneWay.totp ? f.t.codeHelpPhone : f.t.codeHelp }),
1431
- general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
1432
- phoneWay?.email && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendEmail(), children: f.t.sendEmailAgain }),
1433
- pushNumber > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("notice"), role: "status", "aria-live": "polite", children: [
1434
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
1435
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 48, fontWeight: 700, margin: "4px 0", textAlign: "center" }, children: pushNumber }),
1436
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushWaiting })
1437
- ] }) : phoneWay?.push && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("button"), onClick: () => void sendPush(), children: f.t.pushSend }),
1438
- phoneWay?.phone && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendCode(), children: (phoneWay.phone.channel === "whatsapp" ? f.t.sendCodeWhatsapp : f.t.sendCodeSms).replace("{to}", to) }),
1439
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
1440
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
1441
- ] });
1442
- }
1511
+ if (step === "code") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepForm, { f, auth });
1443
1512
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1444
1513
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
1445
- (methods?.providers ?? []).map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", className: f.cx("providerButton"), onClick: () => auth.signIn.social(p.id, { returnTo: props.returnTo }), children: [
1446
- f.t.continueWith,
1447
- " ",
1448
- p.name
1449
- ] }, p.id)),
1450
- methods?.passkey && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void usePasskey(), children: f.t.usePasskey }),
1451
- ((methods?.providers.length ?? 0) > 0 || methods?.passkey) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("separator"), children: f.t.orWithEmail }),
1452
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: methods?.passkeyHere ? "username webauthn" : "username", required: true, onChange: setEmail }),
1514
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers: methods?.providers ?? [], onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
1515
+ offers.passkey && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void usePasskey(), children: f.t.usePasskey }),
1516
+ asksEmail && ((methods?.providers.length ?? 0) > 0 || offers.passkey) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("separator"), children: f.t.orWithEmail }),
1517
+ asksEmail && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: methods?.passkeyHere ? "username webauthn" : "username", required: true, onChange: setEmail }),
1453
1518
  company && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", disabled: f.busy, className: f.cx(company.enforced ? "button" : "providerButton"), onClick: toCompany, children: [
1454
1519
  f.t.continueWith,
1455
1520
  " ",
1456
1521
  company.name
1457
1522
  ] }),
1458
1523
  company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: f.t.ssoOnly }),
1459
- !company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1524
+ !company?.enforced && passwordOn && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1460
1525
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1461
1526
  Field,
1462
1527
  {
@@ -1474,6 +1539,7 @@ function SignIn(props) {
1474
1539
  challenge.node,
1475
1540
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signIn })
1476
1541
  ] }),
1542
+ !company?.enforced && !passwordOn && methods?.magicLink && challenge.node,
1477
1543
  methods?.magicLink && !company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendLink(), children: f.t.emailMeALink }),
1478
1544
  methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: f.cx("footer"), children: [
1479
1545
  f.t.noAccount,
@@ -1533,14 +1599,30 @@ function SignUp(props) {
1533
1599
  f.done();
1534
1600
  };
1535
1601
  const general = f.error && !f.error.field ? f.error : null;
1602
+ const passwordOn = methods?.passwordSignIn !== false;
1603
+ const providers = auth.session?.user.isAnonymous === true || methods?.organization?.required ? [] : methods?.providers ?? [];
1536
1604
  if (sent) {
1537
1605
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
1538
1606
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: f.t.checkEmail }),
1539
1607
  props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href: props.links.signIn, children: f.t.backToSignIn })
1540
1608
  ] });
1541
1609
  }
1610
+ const footer = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: f.cx("footer"), children: [
1611
+ f.t.haveAccount,
1612
+ " ",
1613
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href: props.links.signIn, children: f.t.signIn })
1614
+ ] });
1615
+ if (!passwordOn) {
1616
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
1617
+ general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
1618
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers, onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
1619
+ footer
1620
+ ] });
1621
+ }
1542
1622
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1543
1623
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
1624
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers, onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
1625
+ providers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("separator"), children: f.t.orWithEmail }),
1544
1626
  methods?.organization?.ask && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "organization", type: "text", label: f.t.company, value: organization, autoComplete: "organization", required: methods.organization.required, onChange: setOrganization }),
1545
1627
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
1546
1628
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
@@ -1566,11 +1648,7 @@ function SignUp(props) {
1566
1648
  ] }, p.key)),
1567
1649
  challenge.node,
1568
1650
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signUp }),
1569
- props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: f.cx("footer"), children: [
1570
- f.t.haveAccount,
1571
- " ",
1572
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href: props.links.signIn, children: f.t.signIn })
1573
- ] })
1651
+ footer
1574
1652
  ] });
1575
1653
  }
1576
1654
  function ForgotPassword(props) {
@@ -1667,6 +1745,62 @@ function VerifyEmail(props) {
1667
1745
  state !== "confirming" && props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href: props.links.signIn, children: f.t.backToSignIn })
1668
1746
  ] });
1669
1747
  }
1748
+ function AcceptInvite(props) {
1749
+ const auth = useAuth();
1750
+ const f = useForm(props);
1751
+ const [token, setToken] = (0, import_react.useState)("");
1752
+ const [invitation, setInvitation] = (0, import_react.useState)(null);
1753
+ const [state, setState] = (0, import_react.useState)("opening");
1754
+ const [password, setPassword] = (0, import_react.useState)("");
1755
+ usePasswordPolicy(f, useMethods(auth));
1756
+ useMailedToken("token", (t) => {
1757
+ if (!t) return setState("invalid");
1758
+ setToken(t);
1759
+ void auth.invitation(t).then((r) => {
1760
+ if (r.ok) {
1761
+ setInvitation(r.invitation);
1762
+ return setState("ready");
1763
+ }
1764
+ if (r.error.code !== "invalid_token") f.setError(r.error);
1765
+ setState("invalid");
1766
+ });
1767
+ });
1768
+ const submit = async (e) => {
1769
+ e.preventDefault();
1770
+ f.setBusy(true);
1771
+ f.setError(null);
1772
+ const r = await auth.acceptInvitation(token, password);
1773
+ f.setBusy(false);
1774
+ if (!r.ok) {
1775
+ if (r.error.code === "invalid_token") return setState("invalid");
1776
+ return f.setError(r.error);
1777
+ }
1778
+ if (r.status === "mfa_required") return setState("code");
1779
+ f.done();
1780
+ };
1781
+ const general = f.error && !f.error.field ? f.error : null;
1782
+ const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href: props.links.signIn, children: f.t.backToSignIn });
1783
+ if (state === "opening") {
1784
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("form"), ...f.root, "aria-busy": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: f.t.openingInvitation }) });
1785
+ }
1786
+ if (state === "invalid") {
1787
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
1788
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: general ? f.say(general) : f.t.invitationInvalid }),
1789
+ back
1790
+ ] });
1791
+ }
1792
+ if (state === "code") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepForm, { f, auth });
1793
+ const workspace = invitation?.workspace ?? "";
1794
+ const heading = invitation?.organization ? f.t.invitedToOrganization.replace("{organization}", invitation.organization).replace("{workspace}", workspace) : f.t.invitedTo.replace("{workspace}", workspace);
1795
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1796
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: f.cx("heading"), children: heading }),
1797
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: f.t.invitedAs.replace("{email}", invitation?.email ?? "") }),
1798
+ general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
1799
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "email", name: "username", autoComplete: "username", value: invitation?.email ?? "", readOnly: true, hidden: true }),
1800
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.choosePassword, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
1801
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.acceptInvite })
1802
+ ] });
1803
+ }
1670
1804
  function useSection(props) {
1671
1805
  const f = useForm({ ...props, unstyled: true });
1672
1806
  const [done, setDone] = (0, import_react.useState)(null);
@@ -2314,6 +2448,8 @@ function useAuth() {
2314
2448
  googleOneTap: (o) => then(client.signIn.googleOneTap(o))
2315
2449
  },
2316
2450
  signUp: { email: (f) => then(client.signUp.email(f)) },
2451
+ // The invited person is signed in once they accept.
2452
+ acceptInvitation: (token, password) => then(client.acceptInvitation(token, password)),
2317
2453
  signOut: () => then(client.signOut()),
2318
2454
  account: {
2319
2455
  ...client.account,
@@ -2332,6 +2468,7 @@ function useAuth() {
2332
2468
  }
2333
2469
  // Annotate the CommonJS export names for ESM import in node:
2334
2470
  0 && (module.exports = {
2471
+ AcceptInvite,
2335
2472
  Account,
2336
2473
  CauthyProvider,
2337
2474
  ForgotPassword,