cauthy-auth 0.8.0 → 0.10.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/client.d.mts +45 -1
- package/dist/client.d.ts +45 -1
- package/dist/client.js +16 -1
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +16 -1
- package/dist/client.mjs.map +1 -1
- package/dist/index.js +53 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +53 -3
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +54 -1
- package/dist/react.d.ts +54 -1
- package/dist/react.js +105 -1
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +105 -1
- package/dist/react.mjs.map +1 -1
- package/dist/svelte.js +16 -1
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +16 -1
- package/dist/svelte.mjs.map +1 -1
- package/dist/vue.js +16 -1
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +16 -1
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react.mjs
CHANGED
|
@@ -105,13 +105,17 @@ var UNAVAILABLE = { code: "unavailable", message: "Sign-in is unavailable right
|
|
|
105
105
|
function createAuthClient(options = {}) {
|
|
106
106
|
const base = (options.basePath ?? "/api/auth").replace(/\/+$/, "");
|
|
107
107
|
const doFetch = (...args) => (options.fetch ?? fetch)(...args);
|
|
108
|
+
const locale = () => {
|
|
109
|
+
const said = typeof options.locale === "function" ? options.locale() : options.locale;
|
|
110
|
+
return (said ?? (typeof document === "undefined" ? "" : document.documentElement?.lang) ?? "").trim();
|
|
111
|
+
};
|
|
108
112
|
async function post(path, form, bad) {
|
|
109
113
|
if (bad) return { ok: false, error: { code: bad.code, message: bad.message, field: bad.field } };
|
|
110
114
|
try {
|
|
111
115
|
const res = await doFetch(`${base}${path}`, {
|
|
112
116
|
method: "POST",
|
|
113
117
|
credentials: "same-origin",
|
|
114
|
-
headers: { "content-type": "application/json", accept: "application/json" },
|
|
118
|
+
headers: { "content-type": "application/json", accept: "application/json", ...locale() ? { "x-cauthy-locale": locale() } : {} },
|
|
115
119
|
body: JSON.stringify(form)
|
|
116
120
|
});
|
|
117
121
|
const body = await res.json().catch(() => null);
|
|
@@ -131,6 +135,7 @@ function createAuthClient(options = {}) {
|
|
|
131
135
|
return null;
|
|
132
136
|
}
|
|
133
137
|
}
|
|
138
|
+
const linkUrl = (provider, o = {}) => `${base}/me/identities/link/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ""}`;
|
|
134
139
|
const socialUrl = (provider, o = {}) => `${base}/sign-in/social/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ""}`;
|
|
135
140
|
const passkeyUrl = (o = {}) => {
|
|
136
141
|
const q = new URLSearchParams({ method: "passkey" });
|
|
@@ -177,6 +182,16 @@ function createAuthClient(options = {}) {
|
|
|
177
182
|
disable: (f) => post("/me/mfa/disable", { password: f.password }, null),
|
|
178
183
|
recoveryCodes: (f) => post("/me/mfa/recovery-codes", { password: f.password }, null)
|
|
179
184
|
},
|
|
185
|
+
changeEmail: (f) => post("/me/email", { email: f.email, password: f.password }, checkEmail(f.email)),
|
|
186
|
+
async identities() {
|
|
187
|
+
const body = await read("/me/identities");
|
|
188
|
+
return body && Array.isArray(body.identities) ? body.identities : [];
|
|
189
|
+
},
|
|
190
|
+
linkUrl,
|
|
191
|
+
link(provider, o) {
|
|
192
|
+
window.location.assign(linkUrl(provider, o));
|
|
193
|
+
},
|
|
194
|
+
unlink: (provider) => post("/me/identities/unlink", { provider }, null),
|
|
180
195
|
async sessions() {
|
|
181
196
|
const body = await read("/me/sessions");
|
|
182
197
|
return body && Array.isArray(body.sessions) ? body.sessions : [];
|
|
@@ -313,6 +328,15 @@ var TEXTS = {
|
|
|
313
328
|
sessions: "Where you are signed in",
|
|
314
329
|
signOutEverywhere: "Sign out everywhere",
|
|
315
330
|
unknownDevice: "Unknown device",
|
|
331
|
+
emailAddress: "Email address",
|
|
332
|
+
newEmail: "New email address",
|
|
333
|
+
changeEmail: "Change email",
|
|
334
|
+
emailSent: "We sent a link to {email}. Your address changes once you open it.",
|
|
335
|
+
linkedAccounts: "Linked accounts",
|
|
336
|
+
noLinkedAccounts: "No account is linked.",
|
|
337
|
+
linkWith: "Link",
|
|
338
|
+
unlink: "Unlink",
|
|
339
|
+
linked: "The account was linked.",
|
|
316
340
|
errors: {
|
|
317
341
|
required: "This is required.",
|
|
318
342
|
invalid_email: "That does not look like an email address.",
|
|
@@ -321,6 +345,11 @@ var TEXTS = {
|
|
|
321
345
|
unavailable: "Sign-in is unavailable right now. Try again in a moment.",
|
|
322
346
|
state_mismatch: "That sign-in could not be completed. Try again.",
|
|
323
347
|
cancelled: "The sign-in was cancelled.",
|
|
348
|
+
email_taken: "That address already has an account.",
|
|
349
|
+
email_unchanged: "That is already your address.",
|
|
350
|
+
last_sign_in_method: "Add a password or link another account first: it is your only way to sign in.",
|
|
351
|
+
identity_already_linked: "That account is linked to someone else.",
|
|
352
|
+
manual_linking_disabled: "Linking accounts is turned off for this workspace.",
|
|
324
353
|
invalid_token: "This link is not valid, or it has expired. Ask for a new one.",
|
|
325
354
|
invalid_code: "That code is not right, or it has expired.",
|
|
326
355
|
wrong_password: "The current password is not right.",
|
|
@@ -378,6 +407,15 @@ var TEXTS = {
|
|
|
378
407
|
sessions: "D\xF3nde tienes la sesi\xF3n abierta",
|
|
379
408
|
signOutEverywhere: "Cerrar sesi\xF3n en todas partes",
|
|
380
409
|
unknownDevice: "Dispositivo desconocido",
|
|
410
|
+
emailAddress: "Correo",
|
|
411
|
+
newEmail: "Correo nuevo",
|
|
412
|
+
changeEmail: "Cambiar el correo",
|
|
413
|
+
emailSent: "Enviamos un enlace a {email}. Tu correo cambia cuando lo abras.",
|
|
414
|
+
linkedAccounts: "Cuentas vinculadas",
|
|
415
|
+
noLinkedAccounts: "No hay cuentas vinculadas.",
|
|
416
|
+
linkWith: "Vincular",
|
|
417
|
+
unlink: "Desvincular",
|
|
418
|
+
linked: "La cuenta qued\xF3 vinculada.",
|
|
381
419
|
errors: {
|
|
382
420
|
required: "Este dato es obligatorio.",
|
|
383
421
|
invalid_email: "Eso no parece un correo.",
|
|
@@ -386,6 +424,11 @@ var TEXTS = {
|
|
|
386
424
|
unavailable: "No se puede entrar en este momento. Intenta de nuevo en un momento.",
|
|
387
425
|
state_mismatch: "No se pudo completar el ingreso. Intenta de nuevo.",
|
|
388
426
|
cancelled: "El ingreso se cancel\xF3.",
|
|
427
|
+
email_taken: "Ese correo ya tiene una cuenta.",
|
|
428
|
+
email_unchanged: "Ese ya es tu correo.",
|
|
429
|
+
last_sign_in_method: "Primero agrega una contrase\xF1a o vincula otra cuenta: es tu \xFAnica forma de entrar.",
|
|
430
|
+
identity_already_linked: "Esa cuenta est\xE1 vinculada a otra persona.",
|
|
431
|
+
manual_linking_disabled: "Vincular cuentas est\xE1 desactivado en este workspace.",
|
|
389
432
|
invalid_token: "Este enlace no es v\xE1lido o ya venci\xF3. Pide uno nuevo.",
|
|
390
433
|
invalid_code: "Ese c\xF3digo no es correcto o ya venci\xF3.",
|
|
391
434
|
wrong_password: "La contrase\xF1a actual no es correcta.",
|
|
@@ -745,7 +788,9 @@ function Account(props) {
|
|
|
745
788
|
const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleString());
|
|
746
789
|
return /* @__PURE__ */ jsxs("div", { className: cx("account"), ...root, children: [
|
|
747
790
|
/* @__PURE__ */ jsx(ProfilePart, { props, account, onSaved: setAccount }),
|
|
791
|
+
/* @__PURE__ */ jsx(EmailPart, { props, account }),
|
|
748
792
|
account.hasPassword && /* @__PURE__ */ jsx(PasswordPart, { props }),
|
|
793
|
+
/* @__PURE__ */ jsx(LinkedPart, { props }),
|
|
749
794
|
/* @__PURE__ */ jsx(SecondStepPart, { props, account, onChanged: (mfaEnabled) => setAccount({ ...account, mfaEnabled }) }),
|
|
750
795
|
/* @__PURE__ */ jsxs("section", { className: cx("section"), children: [
|
|
751
796
|
/* @__PURE__ */ jsx("h2", { className: cx("heading"), children: t.passkeys }),
|
|
@@ -784,6 +829,65 @@ function ProfilePart({ props, account, onSaved }) {
|
|
|
784
829
|
done && /* @__PURE__ */ jsx("p", { role: "status", className: f.cx("notice"), children: done })
|
|
785
830
|
] });
|
|
786
831
|
}
|
|
832
|
+
function EmailPart({ props, account }) {
|
|
833
|
+
const auth = useAuth();
|
|
834
|
+
const { f, done, setDone, run, general } = useSection(props);
|
|
835
|
+
const [email, setEmail] = useState("");
|
|
836
|
+
const [password, setPassword] = useState("");
|
|
837
|
+
const submit = async (e) => {
|
|
838
|
+
e.preventDefault();
|
|
839
|
+
const r = await run(() => auth.account.changeEmail({ email, password }));
|
|
840
|
+
if (!r.ok) return;
|
|
841
|
+
setPassword("");
|
|
842
|
+
setDone(f.t.emailSent.replace("{email}", r.email));
|
|
843
|
+
};
|
|
844
|
+
return /* @__PURE__ */ jsxs("form", { className: f.cx("section"), onSubmit: submit, noValidate: true, children: [
|
|
845
|
+
/* @__PURE__ */ jsx("h2", { className: f.cx("heading"), children: f.t.emailAddress }),
|
|
846
|
+
/* @__PURE__ */ jsx("p", { className: f.cx("notice"), children: account.email }),
|
|
847
|
+
general && /* @__PURE__ */ jsx("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
|
|
848
|
+
/* @__PURE__ */ jsx(Field, { f, name: "email", type: "email", label: f.t.newEmail, value: email, autoComplete: "email", required: true, onChange: setEmail }),
|
|
849
|
+
account.hasPassword && /* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
850
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.changeEmail }),
|
|
851
|
+
done && /* @__PURE__ */ jsx("p", { role: "status", className: f.cx("notice"), children: done })
|
|
852
|
+
] });
|
|
853
|
+
}
|
|
854
|
+
function LinkedPart({ props }) {
|
|
855
|
+
const auth = useAuth();
|
|
856
|
+
const { f, run, general } = useSection(props);
|
|
857
|
+
const [linked, setLinked] = useState(null);
|
|
858
|
+
const [offered, setOffered] = useState([]);
|
|
859
|
+
const [came, setCame] = useState(null);
|
|
860
|
+
useEffect(() => {
|
|
861
|
+
void auth.account.identities().then(setLinked);
|
|
862
|
+
void auth.methods().then((m) => setOffered(m.providers));
|
|
863
|
+
const back = typeof window === "undefined" ? null : new URLSearchParams(window.location.search);
|
|
864
|
+
if (back?.get("linked")) setCame(back.get("linked"));
|
|
865
|
+
else if (back?.get("auth_error")) f.setError({ code: back.get("auth_error"), message: "That account could not be linked. Try again." });
|
|
866
|
+
}, []);
|
|
867
|
+
if (linked === null) return null;
|
|
868
|
+
const name = (id) => offered.find((p) => p.id === id)?.name ?? id;
|
|
869
|
+
const unlink = async (provider) => {
|
|
870
|
+
const r = await run(() => auth.account.unlink(provider));
|
|
871
|
+
if (r.ok) setLinked(linked.filter((x) => x.provider !== provider));
|
|
872
|
+
};
|
|
873
|
+
const here = typeof window === "undefined" ? void 0 : window.location.pathname;
|
|
874
|
+
return /* @__PURE__ */ jsxs("section", { className: f.cx("section"), children: [
|
|
875
|
+
/* @__PURE__ */ jsx("h2", { className: f.cx("heading"), children: f.t.linkedAccounts }),
|
|
876
|
+
came && /* @__PURE__ */ jsx("p", { role: "status", className: f.cx("notice"), children: f.t.linked }),
|
|
877
|
+
general && /* @__PURE__ */ jsx("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
|
|
878
|
+
linked.length === 0 ? /* @__PURE__ */ jsx("p", { className: f.cx("notice"), children: f.t.noLinkedAccounts }) : /* @__PURE__ */ jsx("ul", { className: f.cx("sessions"), children: linked.map((x) => /* @__PURE__ */ jsxs("li", { className: f.cx("session"), children: [
|
|
879
|
+
name(x.provider),
|
|
880
|
+
x.email ? ` \xB7 ${x.email}` : "",
|
|
881
|
+
" ",
|
|
882
|
+
/* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void unlink(x.provider), children: f.t.unlink })
|
|
883
|
+
] }, x.provider)) }),
|
|
884
|
+
offered.filter((p) => !linked.some((x) => x.provider === p.id)).map((p) => /* @__PURE__ */ jsxs(f.Button, { type: "button", className: f.cx("providerButton"), onClick: () => auth.account.link(p.id, { returnTo: here }), children: [
|
|
885
|
+
f.t.linkWith,
|
|
886
|
+
" ",
|
|
887
|
+
p.name
|
|
888
|
+
] }, p.id))
|
|
889
|
+
] });
|
|
890
|
+
}
|
|
787
891
|
function PasswordPart({ props }) {
|
|
788
892
|
const auth = useAuth();
|
|
789
893
|
const { f, done, setDone, run, general } = useSection(props);
|