cauthy-auth 0.24.3 → 0.26.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/dist/react.d.mts CHANGED
@@ -210,7 +210,7 @@ interface PublicSession {
210
210
  expiresAt: string;
211
211
  }
212
212
 
213
- type AuthField = 'email' | 'password' | 'newPassword' | 'name' | 'code';
213
+ type AuthField = 'email' | 'password' | 'newPassword' | 'name' | 'code' | 'organization';
214
214
 
215
215
  /** Whether this browser can use a passkey at all. */
216
216
  declare function canUsePasskeys(): boolean;
@@ -245,6 +245,11 @@ interface AuthMethods {
245
245
  }[];
246
246
  /** Whether people may create an account themselves. */
247
247
  signUp: boolean;
248
+ /** Set when the application's system makes an organization per sign-up: the form asks the company's name. */
249
+ organization?: {
250
+ ask: boolean;
251
+ required: boolean;
252
+ };
248
253
  magicLink: boolean;
249
254
  /** Whether to offer a passkey. */
250
255
  passkey: boolean;
@@ -592,21 +597,34 @@ interface AuthClient {
592
597
  }): Promise<AuthResult<'signed_in', {
593
598
  session: PublicSession;
594
599
  }>>;
595
- /** With address and password. `mfa_required`: ask for the code and call `signIn.mfa`. */
600
+ /**
601
+ * With address and password. `mfa_required`: ask for the code and call
602
+ * `signIn.mfa`. `method: 'email'` says the code was just mailed to the
603
+ * account's address (it has no factor of its own and the workspace, or
604
+ * the sign-in's risk, asked a second step): say so, and offer
605
+ * `mfaSendEmail` for another.
606
+ */
596
607
  email(form: {
597
608
  email: string;
598
609
  password: string;
599
610
  captchaToken?: string;
600
611
  }): Promise<AuthResult<'signed_in', {
601
612
  session: PublicSession;
602
- }> | AuthResult<'mfa_required'>>;
603
- /** The second step: the code of the authenticator app, or a recovery code. */
613
+ }> | AuthResult<'mfa_required', {
614
+ method?: 'email';
615
+ }>>;
616
+ /** The second step: the code of the authenticator app, the phone, the email, or a recovery code. */
604
617
  mfa(form: {
605
618
  code: string;
606
619
  }): Promise<AuthResult<'signed_in', {
607
620
  session: PublicSession;
608
621
  }>>;
609
- /** While the second step is asked for: whether the account has an authenticator app, the phone (masked) a code can be sent to, and phones that approve sign-ins. */
622
+ /**
623
+ * While the second step is asked for: whether the account has an
624
+ * authenticator app, the phone (masked) a code can be sent to, phones
625
+ * that approve sign-ins, and the address (masked) a code went to when
626
+ * the step is by email.
627
+ */
610
628
  mfaMethods(): Promise<AuthResult<'ok', {
611
629
  totp: boolean;
612
630
  phone: {
@@ -616,6 +634,13 @@ interface AuthClient {
616
634
  push: {
617
635
  devices: number;
618
636
  } | null;
637
+ email: {
638
+ to: string;
639
+ } | null;
640
+ }>>;
641
+ /** Mails the sign-in's code again, when its second step is by email; `mfa` takes it. A few per sign-in. */
642
+ mfaSendEmail(): Promise<AuthResult<'sent', {
643
+ sentTo: string;
619
644
  }>>;
620
645
  /**
621
646
  * Sends a push to the account's phones (the application's app, with
@@ -764,6 +789,7 @@ interface AuthClient {
764
789
  email: string;
765
790
  password: string;
766
791
  name?: string;
792
+ organization?: string;
767
793
  captchaToken?: string;
768
794
  }): Promise<AuthResult<'signed_in', {
769
795
  session: PublicSession;
@@ -782,9 +808,12 @@ interface AuthClient {
782
808
  password: string;
783
809
  }): Promise<AuthResult<'changed'>>;
784
810
  /** Confirms the address, with the token the mailed link opened the page with (`token`). */
811
+ /** Confirms the address a mailed link is for. The person is signed in from the link when their account asks no second step. */
785
812
  verifyEmail(form: {
786
813
  token: string;
787
- }): Promise<AuthResult<'verified'>>;
814
+ }): Promise<AuthResult<'verified'> | AuthResult<'signed_in', {
815
+ session: PublicSession;
816
+ }>>;
788
817
  signOut(): Promise<AuthResult<'signed_out'>>;
789
818
  /** The signed-in person's own account. */
790
819
  account: AccountClient;
@@ -826,12 +855,17 @@ interface AuthTexts {
826
855
  forgotPassword: string;
827
856
  noAccount: string;
828
857
  createAccount: string;
858
+ /** The label of the company's name, asked when the application's system makes an organization per sign-up. */
859
+ company: string;
829
860
  haveAccount: string;
830
861
  sendLink: string;
831
862
  linkSent: string;
832
863
  codeHelp: string;
833
864
  /** The second step when it is a phone only. */
834
865
  codeHelpPhone: string;
866
+ /** The second step by email (the account has no factor): "{to}" is the address, masked. */
867
+ codeHelpEmail: string;
868
+ sendEmailAgain: string;
835
869
  /** "{to}" is the phone, masked. */
836
870
  sendCodeSms: string;
837
871
  sendCodeWhatsapp: string;
package/dist/react.d.ts CHANGED
@@ -210,7 +210,7 @@ interface PublicSession {
210
210
  expiresAt: string;
211
211
  }
212
212
 
213
- type AuthField = 'email' | 'password' | 'newPassword' | 'name' | 'code';
213
+ type AuthField = 'email' | 'password' | 'newPassword' | 'name' | 'code' | 'organization';
214
214
 
215
215
  /** Whether this browser can use a passkey at all. */
216
216
  declare function canUsePasskeys(): boolean;
@@ -245,6 +245,11 @@ interface AuthMethods {
245
245
  }[];
246
246
  /** Whether people may create an account themselves. */
247
247
  signUp: boolean;
248
+ /** Set when the application's system makes an organization per sign-up: the form asks the company's name. */
249
+ organization?: {
250
+ ask: boolean;
251
+ required: boolean;
252
+ };
248
253
  magicLink: boolean;
249
254
  /** Whether to offer a passkey. */
250
255
  passkey: boolean;
@@ -592,21 +597,34 @@ interface AuthClient {
592
597
  }): Promise<AuthResult<'signed_in', {
593
598
  session: PublicSession;
594
599
  }>>;
595
- /** With address and password. `mfa_required`: ask for the code and call `signIn.mfa`. */
600
+ /**
601
+ * With address and password. `mfa_required`: ask for the code and call
602
+ * `signIn.mfa`. `method: 'email'` says the code was just mailed to the
603
+ * account's address (it has no factor of its own and the workspace, or
604
+ * the sign-in's risk, asked a second step): say so, and offer
605
+ * `mfaSendEmail` for another.
606
+ */
596
607
  email(form: {
597
608
  email: string;
598
609
  password: string;
599
610
  captchaToken?: string;
600
611
  }): Promise<AuthResult<'signed_in', {
601
612
  session: PublicSession;
602
- }> | AuthResult<'mfa_required'>>;
603
- /** The second step: the code of the authenticator app, or a recovery code. */
613
+ }> | AuthResult<'mfa_required', {
614
+ method?: 'email';
615
+ }>>;
616
+ /** The second step: the code of the authenticator app, the phone, the email, or a recovery code. */
604
617
  mfa(form: {
605
618
  code: string;
606
619
  }): Promise<AuthResult<'signed_in', {
607
620
  session: PublicSession;
608
621
  }>>;
609
- /** While the second step is asked for: whether the account has an authenticator app, the phone (masked) a code can be sent to, and phones that approve sign-ins. */
622
+ /**
623
+ * While the second step is asked for: whether the account has an
624
+ * authenticator app, the phone (masked) a code can be sent to, phones
625
+ * that approve sign-ins, and the address (masked) a code went to when
626
+ * the step is by email.
627
+ */
610
628
  mfaMethods(): Promise<AuthResult<'ok', {
611
629
  totp: boolean;
612
630
  phone: {
@@ -616,6 +634,13 @@ interface AuthClient {
616
634
  push: {
617
635
  devices: number;
618
636
  } | null;
637
+ email: {
638
+ to: string;
639
+ } | null;
640
+ }>>;
641
+ /** Mails the sign-in's code again, when its second step is by email; `mfa` takes it. A few per sign-in. */
642
+ mfaSendEmail(): Promise<AuthResult<'sent', {
643
+ sentTo: string;
619
644
  }>>;
620
645
  /**
621
646
  * Sends a push to the account's phones (the application's app, with
@@ -764,6 +789,7 @@ interface AuthClient {
764
789
  email: string;
765
790
  password: string;
766
791
  name?: string;
792
+ organization?: string;
767
793
  captchaToken?: string;
768
794
  }): Promise<AuthResult<'signed_in', {
769
795
  session: PublicSession;
@@ -782,9 +808,12 @@ interface AuthClient {
782
808
  password: string;
783
809
  }): Promise<AuthResult<'changed'>>;
784
810
  /** Confirms the address, with the token the mailed link opened the page with (`token`). */
811
+ /** Confirms the address a mailed link is for. The person is signed in from the link when their account asks no second step. */
785
812
  verifyEmail(form: {
786
813
  token: string;
787
- }): Promise<AuthResult<'verified'>>;
814
+ }): Promise<AuthResult<'verified'> | AuthResult<'signed_in', {
815
+ session: PublicSession;
816
+ }>>;
788
817
  signOut(): Promise<AuthResult<'signed_out'>>;
789
818
  /** The signed-in person's own account. */
790
819
  account: AccountClient;
@@ -826,12 +855,17 @@ interface AuthTexts {
826
855
  forgotPassword: string;
827
856
  noAccount: string;
828
857
  createAccount: string;
858
+ /** The label of the company's name, asked when the application's system makes an organization per sign-up. */
859
+ company: string;
829
860
  haveAccount: string;
830
861
  sendLink: string;
831
862
  linkSent: string;
832
863
  codeHelp: string;
833
864
  /** The second step when it is a phone only. */
834
865
  codeHelpPhone: string;
866
+ /** The second step by email (the account has no factor): "{to}" is the address, masked. */
867
+ codeHelpEmail: string;
868
+ sendEmailAgain: string;
835
869
  /** "{to}" is the phone, masked. */
836
870
  sendCodeSms: string;
837
871
  sendCodeWhatsapp: string;
package/dist/react.js CHANGED
@@ -211,6 +211,13 @@ function checkName(value) {
211
211
  if (typeof value !== "string" || value.trim().length > MAX_NAME) return { field: "name", code: "too_long", message: `Use at most ${MAX_NAME} characters.` };
212
212
  return null;
213
213
  }
214
+ var MAX_ORGANIZATION = 120;
215
+ function checkOrganization(value, required = false) {
216
+ const v = typeof value === "string" ? value.trim() : "";
217
+ if (v === "") return required ? { field: "organization", code: "required", message: "Enter your company's name." } : null;
218
+ if (v.length > MAX_ORGANIZATION) return { field: "organization", code: "too_long", message: `Use at most ${MAX_ORGANIZATION} characters.` };
219
+ return null;
220
+ }
214
221
  function checkCode(value) {
215
222
  const v = typeof value === "string" ? value.trim() : "";
216
223
  if (v === "") return { field: "code", code: "required", message: "Enter the code." };
@@ -317,6 +324,7 @@ function createAuthClient(options = {}) {
317
324
  mfa: (f) => post("/sign-in/mfa", { code: f.code }, checkCode(f.code)),
318
325
  mfaMethods: () => post("/sign-in/mfa/methods", {}, null),
319
326
  mfaSendCode: () => post("/sign-in/mfa/send", {}, null),
327
+ mfaSendEmail: () => post("/sign-in/mfa/email", {}, null),
320
328
  mfaPush: () => post("/sign-in/mfa/push", {}, null),
321
329
  async mfaPushWait(o = {}) {
322
330
  const status = await new Promise((resolve) => {
@@ -433,7 +441,12 @@ function createAuthClient(options = {}) {
433
441
  }
434
442
  },
435
443
  signUp: {
436
- email: (f) => post("/sign-up/email", { email: f.email, password: f.password, name: f.name }, firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password)), f.captchaToken)
444
+ email: (f) => post(
445
+ "/sign-up/email",
446
+ { email: f.email, password: f.password, name: f.name, organization: f.organization },
447
+ firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password), checkOrganization(f.organization)),
448
+ f.captchaToken
449
+ )
437
450
  },
438
451
  forgotPassword: (f) => post("/forgot-password", { email: f.email }, checkEmail(f.email), f.captchaToken),
439
452
  resetPassword: (f) => post("/reset-password", { token: f.token, password: f.password }, checkNewPassword(f.password)),
@@ -593,6 +606,7 @@ var TEXTS = {
593
606
  email: "Email",
594
607
  password: "Password",
595
608
  name: "Name",
609
+ company: "Your company's name",
596
610
  code: "Code",
597
611
  signIn: "Sign in",
598
612
  signUp: "Create account",
@@ -607,6 +621,8 @@ var TEXTS = {
607
621
  codeHelp: "Enter the code from your authenticator app, or a recovery code.",
608
622
  verify: "Verify",
609
623
  codeHelpPhone: "We send a code to your phone. Ask for it, then type it here, or use a recovery code.",
624
+ codeHelpEmail: "We sent a code to {to}. Type it here.",
625
+ sendEmailAgain: "Send the code again",
610
626
  sendCodeSms: "Send a code by SMS to {to}",
611
627
  sendCodeWhatsapp: "Send a code by WhatsApp to {to}",
612
628
  codeSent: "We sent a code to {to}. Type it here.",
@@ -621,7 +637,7 @@ var TEXTS = {
621
637
  removePhone: "Remove phone",
622
638
  bySms: "SMS",
623
639
  byWhatsapp: "WhatsApp",
624
- checkEmail: "Almost there: open the link we sent to confirm your address, then sign in.",
640
+ checkEmail: "Almost there: open the link we sent to confirm your address \u2014 it signs you in.",
625
641
  backToSignIn: "Back to sign in",
626
642
  emailMeALink: "Email me a sign-in link",
627
643
  usePasskey: "Sign in with a passkey",
@@ -742,6 +758,7 @@ var TEXTS = {
742
758
  email: "Correo",
743
759
  password: "Contrase\xF1a",
744
760
  name: "Nombre",
761
+ company: "Nombre de tu empresa",
745
762
  code: "C\xF3digo",
746
763
  signIn: "Entrar",
747
764
  signUp: "Crear cuenta",
@@ -756,6 +773,8 @@ var TEXTS = {
756
773
  codeHelp: "Escribe el c\xF3digo de tu aplicaci\xF3n de autenticaci\xF3n, o un c\xF3digo de recuperaci\xF3n.",
757
774
  verify: "Verificar",
758
775
  codeHelpPhone: "Te enviamos un c\xF3digo a tu tel\xE9fono. P\xEDdelo y escr\xEDbelo aqu\xED, o usa un c\xF3digo de recuperaci\xF3n.",
776
+ codeHelpEmail: "Te enviamos un c\xF3digo a {to}. Escr\xEDbelo aqu\xED.",
777
+ sendEmailAgain: "Enviar el c\xF3digo de nuevo",
759
778
  sendCodeSms: "Enviar un c\xF3digo por SMS a {to}",
760
779
  sendCodeWhatsapp: "Enviar un c\xF3digo por WhatsApp a {to}",
761
780
  codeSent: "Te enviamos un c\xF3digo a {to}. Escr\xEDbelo aqu\xED.",
@@ -770,7 +789,7 @@ var TEXTS = {
770
789
  removePhone: "Quitar tel\xE9fono",
771
790
  bySms: "SMS",
772
791
  byWhatsapp: "WhatsApp",
773
- checkEmail: "Ya casi: abre el enlace que te enviamos para confirmar tu correo y luego entra.",
792
+ checkEmail: "Casi listo: abre el enlace que te enviamos para confirmar tu correo; te deja adentro.",
774
793
  backToSignIn: "Volver a entrar",
775
794
  emailMeALink: "Env\xEDame un enlace para entrar",
776
795
  usePasskey: "Entrar con una llave de acceso",
@@ -1074,9 +1093,17 @@ function SignIn(props) {
1074
1093
  (0, import_react.useEffect)(() => {
1075
1094
  if (step !== "code") return;
1076
1095
  void auth.signIn.mfaMethods().then((r) => {
1077
- if (r.ok) setPhoneWay({ totp: r.totp, phone: r.phone, push: r.push });
1096
+ if (r.ok) setPhoneWay({ totp: r.totp, phone: r.phone, push: r.push, email: r.email });
1078
1097
  });
1079
1098
  }, [step]);
1099
+ const sendEmail = async () => {
1100
+ f.setBusy(true);
1101
+ f.setError(null);
1102
+ const r = await auth.signIn.mfaSendEmail();
1103
+ f.setBusy(false);
1104
+ if (!r.ok) return f.setError(r.error);
1105
+ setPhoneSent(r.sentTo);
1106
+ };
1080
1107
  const [pushNumber, setPushNumber] = (0, import_react.useState)(0);
1081
1108
  const pushWait = (0, import_react.useRef)(null);
1082
1109
  (0, import_react.useEffect)(() => () => pushWait.current?.abort(), []);
@@ -1205,8 +1232,9 @@ function SignIn(props) {
1205
1232
  if (step === "code") {
1206
1233
  const to = phoneWay?.phone?.number ?? "";
1207
1234
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1208
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: phoneSent ? f.t.codeSent.replace("{to}", phoneSent) : phoneWay?.phone && !phoneWay.totp ? f.t.codeHelpPhone : f.t.codeHelp }),
1235
+ /* @__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 }),
1209
1236
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
1237
+ 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 }),
1210
1238
  pushNumber > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("notice"), role: "status", "aria-live": "polite", children: [
1211
1239
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
1212
1240
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 48, fontWeight: 700, margin: "4px 0", textAlign: "center" }, children: pushNumber }),
@@ -1281,15 +1309,17 @@ function SignUp(props) {
1281
1309
  const auth = useAuth();
1282
1310
  const f = useForm(props);
1283
1311
  const [name, setName] = (0, import_react.useState)("");
1312
+ const [organization, setOrganization] = (0, import_react.useState)("");
1284
1313
  const [email, setEmail] = (0, import_react.useState)("");
1285
1314
  const [password, setPassword] = (0, import_react.useState)("");
1286
1315
  const [sent, setSent] = (0, import_react.useState)(false);
1287
- const challenge = useChallenge(useMethods(auth)?.captchaSiteKey, props.locale);
1316
+ const methods = useMethods(auth);
1317
+ const challenge = useChallenge(methods?.captchaSiteKey, props.locale);
1288
1318
  const submit = async (e) => {
1289
1319
  e.preventDefault();
1290
1320
  f.setBusy(true);
1291
1321
  f.setError(null);
1292
- const r = auth.session?.user.isAnonymous === true ? await auth.account.upgrade({ name, email, password }) : await auth.signUp.email({ name, email, password, captchaToken: challenge.token });
1322
+ const r = auth.session?.user.isAnonymous === true ? await auth.account.upgrade({ name, email, password }) : await auth.signUp.email({ name, email, password, ...methods?.organization?.ask ? { organization } : {}, captchaToken: challenge.token });
1293
1323
  f.setBusy(false);
1294
1324
  challenge.renew();
1295
1325
  if (!r.ok) return f.setError(r.error);
@@ -1305,6 +1335,7 @@ function SignUp(props) {
1305
1335
  }
1306
1336
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1307
1337
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
1338
+ 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 }),
1308
1339
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
1309
1340
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
1310
1341
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.password, value: password, autoComplete: "new-password", required: true, onChange: setPassword }),
@@ -1397,6 +1428,7 @@ function VerifyEmail(props) {
1397
1428
  return setState("failed");
1398
1429
  }
1399
1430
  void auth.verifyEmail({ token }).then((r) => {
1431
+ if (r.ok && r.status === "signed_in") return f.done();
1400
1432
  if (r.ok) return setState("confirmed");
1401
1433
  f.setError(r.error);
1402
1434
  setState("failed");