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.d.mts
CHANGED
|
@@ -260,6 +260,15 @@ interface AccountSession {
|
|
|
260
260
|
* The signed-in person's own account. What weakens it — the password, the
|
|
261
261
|
* second step, its recovery codes — asks for the current password again.
|
|
262
262
|
*/
|
|
263
|
+
/** A provider the account can also sign in with. */
|
|
264
|
+
interface LinkedIdentity {
|
|
265
|
+
provider: string;
|
|
266
|
+
/** The address the provider has for the person, when it said. */
|
|
267
|
+
email: string;
|
|
268
|
+
name: string;
|
|
269
|
+
/** When it was linked, in UTC (ISO 8601). */
|
|
270
|
+
linkedAt: string;
|
|
271
|
+
}
|
|
263
272
|
interface AccountClient {
|
|
264
273
|
/** The account, or null when nobody is signed in. */
|
|
265
274
|
get(): Promise<Account$1 | null>;
|
|
@@ -299,6 +308,34 @@ interface AccountClient {
|
|
|
299
308
|
recoveryCodes: string[];
|
|
300
309
|
}>>;
|
|
301
310
|
};
|
|
311
|
+
/**
|
|
312
|
+
* Asks to sign in with another address. Nothing changes yet: the new address
|
|
313
|
+
* is mailed a link to confirm it, and once it is confirmed the old one is
|
|
314
|
+
* told, with a link that undoes it. Both open Cauthy's own page.
|
|
315
|
+
*/
|
|
316
|
+
changeEmail(form: {
|
|
317
|
+
email: string;
|
|
318
|
+
password: string;
|
|
319
|
+
}): Promise<AuthResult<'sent', {
|
|
320
|
+
email: string;
|
|
321
|
+
}>>;
|
|
322
|
+
/** The providers (Google…) the account can also sign in with. */
|
|
323
|
+
identities(): Promise<LinkedIdentity[]>;
|
|
324
|
+
/**
|
|
325
|
+
* Sends the browser to the provider, to link it to the account; it comes back
|
|
326
|
+
* at `returnTo` with `?linked=<provider>`, or `?auth_error=<code>`.
|
|
327
|
+
*/
|
|
328
|
+
link(provider: string, options?: {
|
|
329
|
+
returnTo?: string;
|
|
330
|
+
}): void;
|
|
331
|
+
/** Where `link` sends the browser, for a plain link. */
|
|
332
|
+
linkUrl(provider: string, options?: {
|
|
333
|
+
returnTo?: string;
|
|
334
|
+
}): string;
|
|
335
|
+
/** The account stops signing in with that provider. Refused when it would be left with no way to sign in. */
|
|
336
|
+
unlink(provider: string): Promise<AuthResult<'unlinked', {
|
|
337
|
+
provider: string;
|
|
338
|
+
}>>;
|
|
302
339
|
/** Where the account is signed in. */
|
|
303
340
|
sessions(): Promise<AccountSession[]>;
|
|
304
341
|
/** Signs the account out everywhere, here too. */
|
|
@@ -395,6 +432,13 @@ interface AuthClientOptions {
|
|
|
395
432
|
/** Where the server mounted the routes. Default: `/api/auth`. */
|
|
396
433
|
basePath?: string;
|
|
397
434
|
fetch?: typeof fetch;
|
|
435
|
+
/**
|
|
436
|
+
* The language the person reads, for what Cauthy mails them (a sign-in
|
|
437
|
+
* link, a new password, a confirmation): a tag like `es` or `es-CO`, or a
|
|
438
|
+
* function that answers it when the person can change it. Default: the
|
|
439
|
+
* page's own (`<html lang>`), else the browser's.
|
|
440
|
+
*/
|
|
441
|
+
locale?: string | (() => string | undefined);
|
|
398
442
|
}
|
|
399
443
|
declare function createAuthClient(options?: AuthClientOptions): AuthClient;
|
|
400
444
|
|
|
@@ -448,6 +492,15 @@ interface AuthTexts {
|
|
|
448
492
|
sessions: string;
|
|
449
493
|
signOutEverywhere: string;
|
|
450
494
|
unknownDevice: string;
|
|
495
|
+
emailAddress: string;
|
|
496
|
+
newEmail: string;
|
|
497
|
+
changeEmail: string;
|
|
498
|
+
emailSent: string;
|
|
499
|
+
linkedAccounts: string;
|
|
500
|
+
noLinkedAccounts: string;
|
|
501
|
+
linkWith: string;
|
|
502
|
+
unlink: string;
|
|
503
|
+
linked: string;
|
|
451
504
|
/** By error code; one missing shows what the server said. */
|
|
452
505
|
errors: Record<string, string>;
|
|
453
506
|
}
|
|
@@ -576,4 +629,4 @@ declare function useSession(): SessionContext;
|
|
|
576
629
|
*/
|
|
577
630
|
declare function useAuth(): AuthClient & Pick<SessionContext, 'session' | 'status' | 'refresh'>;
|
|
578
631
|
|
|
579
|
-
export { Account, type AccountClient, type Account$1 as AccountDetails, type AccountProps, type AccountSession, type AuthClient, type AuthError, type AuthFormProps, type AuthMethods, type AuthResult, type AuthTexts, CauthyProvider, type CauthyProviderProps, ForgotPassword, type JsonValue, type PermissionOf, type Policy, type PublicSession, ResetPassword, type RoleOf, type SessionContext, type SessionOrganization, type SessionUser, SignIn, SignUp, VerifyEmail, can, createAuthClient, definePolicy, useAuth, useSession };
|
|
632
|
+
export { Account, type AccountClient, type Account$1 as AccountDetails, type AccountProps, type AccountSession, type AuthClient, type AuthError, type AuthFormProps, type AuthMethods, type AuthResult, type AuthTexts, CauthyProvider, type CauthyProviderProps, ForgotPassword, type JsonValue, type LinkedIdentity, type PermissionOf, type Policy, type PublicSession, ResetPassword, type RoleOf, type SessionContext, type SessionOrganization, type SessionUser, SignIn, SignUp, VerifyEmail, can, createAuthClient, definePolicy, useAuth, useSession };
|
package/dist/react.d.ts
CHANGED
|
@@ -260,6 +260,15 @@ interface AccountSession {
|
|
|
260
260
|
* The signed-in person's own account. What weakens it — the password, the
|
|
261
261
|
* second step, its recovery codes — asks for the current password again.
|
|
262
262
|
*/
|
|
263
|
+
/** A provider the account can also sign in with. */
|
|
264
|
+
interface LinkedIdentity {
|
|
265
|
+
provider: string;
|
|
266
|
+
/** The address the provider has for the person, when it said. */
|
|
267
|
+
email: string;
|
|
268
|
+
name: string;
|
|
269
|
+
/** When it was linked, in UTC (ISO 8601). */
|
|
270
|
+
linkedAt: string;
|
|
271
|
+
}
|
|
263
272
|
interface AccountClient {
|
|
264
273
|
/** The account, or null when nobody is signed in. */
|
|
265
274
|
get(): Promise<Account$1 | null>;
|
|
@@ -299,6 +308,34 @@ interface AccountClient {
|
|
|
299
308
|
recoveryCodes: string[];
|
|
300
309
|
}>>;
|
|
301
310
|
};
|
|
311
|
+
/**
|
|
312
|
+
* Asks to sign in with another address. Nothing changes yet: the new address
|
|
313
|
+
* is mailed a link to confirm it, and once it is confirmed the old one is
|
|
314
|
+
* told, with a link that undoes it. Both open Cauthy's own page.
|
|
315
|
+
*/
|
|
316
|
+
changeEmail(form: {
|
|
317
|
+
email: string;
|
|
318
|
+
password: string;
|
|
319
|
+
}): Promise<AuthResult<'sent', {
|
|
320
|
+
email: string;
|
|
321
|
+
}>>;
|
|
322
|
+
/** The providers (Google…) the account can also sign in with. */
|
|
323
|
+
identities(): Promise<LinkedIdentity[]>;
|
|
324
|
+
/**
|
|
325
|
+
* Sends the browser to the provider, to link it to the account; it comes back
|
|
326
|
+
* at `returnTo` with `?linked=<provider>`, or `?auth_error=<code>`.
|
|
327
|
+
*/
|
|
328
|
+
link(provider: string, options?: {
|
|
329
|
+
returnTo?: string;
|
|
330
|
+
}): void;
|
|
331
|
+
/** Where `link` sends the browser, for a plain link. */
|
|
332
|
+
linkUrl(provider: string, options?: {
|
|
333
|
+
returnTo?: string;
|
|
334
|
+
}): string;
|
|
335
|
+
/** The account stops signing in with that provider. Refused when it would be left with no way to sign in. */
|
|
336
|
+
unlink(provider: string): Promise<AuthResult<'unlinked', {
|
|
337
|
+
provider: string;
|
|
338
|
+
}>>;
|
|
302
339
|
/** Where the account is signed in. */
|
|
303
340
|
sessions(): Promise<AccountSession[]>;
|
|
304
341
|
/** Signs the account out everywhere, here too. */
|
|
@@ -395,6 +432,13 @@ interface AuthClientOptions {
|
|
|
395
432
|
/** Where the server mounted the routes. Default: `/api/auth`. */
|
|
396
433
|
basePath?: string;
|
|
397
434
|
fetch?: typeof fetch;
|
|
435
|
+
/**
|
|
436
|
+
* The language the person reads, for what Cauthy mails them (a sign-in
|
|
437
|
+
* link, a new password, a confirmation): a tag like `es` or `es-CO`, or a
|
|
438
|
+
* function that answers it when the person can change it. Default: the
|
|
439
|
+
* page's own (`<html lang>`), else the browser's.
|
|
440
|
+
*/
|
|
441
|
+
locale?: string | (() => string | undefined);
|
|
398
442
|
}
|
|
399
443
|
declare function createAuthClient(options?: AuthClientOptions): AuthClient;
|
|
400
444
|
|
|
@@ -448,6 +492,15 @@ interface AuthTexts {
|
|
|
448
492
|
sessions: string;
|
|
449
493
|
signOutEverywhere: string;
|
|
450
494
|
unknownDevice: string;
|
|
495
|
+
emailAddress: string;
|
|
496
|
+
newEmail: string;
|
|
497
|
+
changeEmail: string;
|
|
498
|
+
emailSent: string;
|
|
499
|
+
linkedAccounts: string;
|
|
500
|
+
noLinkedAccounts: string;
|
|
501
|
+
linkWith: string;
|
|
502
|
+
unlink: string;
|
|
503
|
+
linked: string;
|
|
451
504
|
/** By error code; one missing shows what the server said. */
|
|
452
505
|
errors: Record<string, string>;
|
|
453
506
|
}
|
|
@@ -576,4 +629,4 @@ declare function useSession(): SessionContext;
|
|
|
576
629
|
*/
|
|
577
630
|
declare function useAuth(): AuthClient & Pick<SessionContext, 'session' | 'status' | 'refresh'>;
|
|
578
631
|
|
|
579
|
-
export { Account, type AccountClient, type Account$1 as AccountDetails, type AccountProps, type AccountSession, type AuthClient, type AuthError, type AuthFormProps, type AuthMethods, type AuthResult, type AuthTexts, CauthyProvider, type CauthyProviderProps, ForgotPassword, type JsonValue, type PermissionOf, type Policy, type PublicSession, ResetPassword, type RoleOf, type SessionContext, type SessionOrganization, type SessionUser, SignIn, SignUp, VerifyEmail, can, createAuthClient, definePolicy, useAuth, useSession };
|
|
632
|
+
export { Account, type AccountClient, type Account$1 as AccountDetails, type AccountProps, type AccountSession, type AuthClient, type AuthError, type AuthFormProps, type AuthMethods, type AuthResult, type AuthTexts, CauthyProvider, type CauthyProviderProps, ForgotPassword, type JsonValue, type LinkedIdentity, type PermissionOf, type Policy, type PublicSession, ResetPassword, type RoleOf, type SessionContext, type SessionOrganization, type SessionUser, SignIn, SignUp, VerifyEmail, can, createAuthClient, definePolicy, useAuth, useSession };
|
package/dist/react.js
CHANGED
|
@@ -139,13 +139,17 @@ var UNAVAILABLE = { code: "unavailable", message: "Sign-in is unavailable right
|
|
|
139
139
|
function createAuthClient(options = {}) {
|
|
140
140
|
const base = (options.basePath ?? "/api/auth").replace(/\/+$/, "");
|
|
141
141
|
const doFetch = (...args) => (options.fetch ?? fetch)(...args);
|
|
142
|
+
const locale = () => {
|
|
143
|
+
const said = typeof options.locale === "function" ? options.locale() : options.locale;
|
|
144
|
+
return (said ?? (typeof document === "undefined" ? "" : document.documentElement?.lang) ?? "").trim();
|
|
145
|
+
};
|
|
142
146
|
async function post(path, form, bad) {
|
|
143
147
|
if (bad) return { ok: false, error: { code: bad.code, message: bad.message, field: bad.field } };
|
|
144
148
|
try {
|
|
145
149
|
const res = await doFetch(`${base}${path}`, {
|
|
146
150
|
method: "POST",
|
|
147
151
|
credentials: "same-origin",
|
|
148
|
-
headers: { "content-type": "application/json", accept: "application/json" },
|
|
152
|
+
headers: { "content-type": "application/json", accept: "application/json", ...locale() ? { "x-cauthy-locale": locale() } : {} },
|
|
149
153
|
body: JSON.stringify(form)
|
|
150
154
|
});
|
|
151
155
|
const body = await res.json().catch(() => null);
|
|
@@ -165,6 +169,7 @@ function createAuthClient(options = {}) {
|
|
|
165
169
|
return null;
|
|
166
170
|
}
|
|
167
171
|
}
|
|
172
|
+
const linkUrl = (provider, o = {}) => `${base}/me/identities/link/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ""}`;
|
|
168
173
|
const socialUrl = (provider, o = {}) => `${base}/sign-in/social/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ""}`;
|
|
169
174
|
const passkeyUrl = (o = {}) => {
|
|
170
175
|
const q = new URLSearchParams({ method: "passkey" });
|
|
@@ -211,6 +216,16 @@ function createAuthClient(options = {}) {
|
|
|
211
216
|
disable: (f) => post("/me/mfa/disable", { password: f.password }, null),
|
|
212
217
|
recoveryCodes: (f) => post("/me/mfa/recovery-codes", { password: f.password }, null)
|
|
213
218
|
},
|
|
219
|
+
changeEmail: (f) => post("/me/email", { email: f.email, password: f.password }, checkEmail(f.email)),
|
|
220
|
+
async identities() {
|
|
221
|
+
const body = await read("/me/identities");
|
|
222
|
+
return body && Array.isArray(body.identities) ? body.identities : [];
|
|
223
|
+
},
|
|
224
|
+
linkUrl,
|
|
225
|
+
link(provider, o) {
|
|
226
|
+
window.location.assign(linkUrl(provider, o));
|
|
227
|
+
},
|
|
228
|
+
unlink: (provider) => post("/me/identities/unlink", { provider }, null),
|
|
214
229
|
async sessions() {
|
|
215
230
|
const body = await read("/me/sessions");
|
|
216
231
|
return body && Array.isArray(body.sessions) ? body.sessions : [];
|
|
@@ -347,6 +362,15 @@ var TEXTS = {
|
|
|
347
362
|
sessions: "Where you are signed in",
|
|
348
363
|
signOutEverywhere: "Sign out everywhere",
|
|
349
364
|
unknownDevice: "Unknown device",
|
|
365
|
+
emailAddress: "Email address",
|
|
366
|
+
newEmail: "New email address",
|
|
367
|
+
changeEmail: "Change email",
|
|
368
|
+
emailSent: "We sent a link to {email}. Your address changes once you open it.",
|
|
369
|
+
linkedAccounts: "Linked accounts",
|
|
370
|
+
noLinkedAccounts: "No account is linked.",
|
|
371
|
+
linkWith: "Link",
|
|
372
|
+
unlink: "Unlink",
|
|
373
|
+
linked: "The account was linked.",
|
|
350
374
|
errors: {
|
|
351
375
|
required: "This is required.",
|
|
352
376
|
invalid_email: "That does not look like an email address.",
|
|
@@ -355,6 +379,11 @@ var TEXTS = {
|
|
|
355
379
|
unavailable: "Sign-in is unavailable right now. Try again in a moment.",
|
|
356
380
|
state_mismatch: "That sign-in could not be completed. Try again.",
|
|
357
381
|
cancelled: "The sign-in was cancelled.",
|
|
382
|
+
email_taken: "That address already has an account.",
|
|
383
|
+
email_unchanged: "That is already your address.",
|
|
384
|
+
last_sign_in_method: "Add a password or link another account first: it is your only way to sign in.",
|
|
385
|
+
identity_already_linked: "That account is linked to someone else.",
|
|
386
|
+
manual_linking_disabled: "Linking accounts is turned off for this workspace.",
|
|
358
387
|
invalid_token: "This link is not valid, or it has expired. Ask for a new one.",
|
|
359
388
|
invalid_code: "That code is not right, or it has expired.",
|
|
360
389
|
wrong_password: "The current password is not right.",
|
|
@@ -412,6 +441,15 @@ var TEXTS = {
|
|
|
412
441
|
sessions: "D\xF3nde tienes la sesi\xF3n abierta",
|
|
413
442
|
signOutEverywhere: "Cerrar sesi\xF3n en todas partes",
|
|
414
443
|
unknownDevice: "Dispositivo desconocido",
|
|
444
|
+
emailAddress: "Correo",
|
|
445
|
+
newEmail: "Correo nuevo",
|
|
446
|
+
changeEmail: "Cambiar el correo",
|
|
447
|
+
emailSent: "Enviamos un enlace a {email}. Tu correo cambia cuando lo abras.",
|
|
448
|
+
linkedAccounts: "Cuentas vinculadas",
|
|
449
|
+
noLinkedAccounts: "No hay cuentas vinculadas.",
|
|
450
|
+
linkWith: "Vincular",
|
|
451
|
+
unlink: "Desvincular",
|
|
452
|
+
linked: "La cuenta qued\xF3 vinculada.",
|
|
415
453
|
errors: {
|
|
416
454
|
required: "Este dato es obligatorio.",
|
|
417
455
|
invalid_email: "Eso no parece un correo.",
|
|
@@ -420,6 +458,11 @@ var TEXTS = {
|
|
|
420
458
|
unavailable: "No se puede entrar en este momento. Intenta de nuevo en un momento.",
|
|
421
459
|
state_mismatch: "No se pudo completar el ingreso. Intenta de nuevo.",
|
|
422
460
|
cancelled: "El ingreso se cancel\xF3.",
|
|
461
|
+
email_taken: "Ese correo ya tiene una cuenta.",
|
|
462
|
+
email_unchanged: "Ese ya es tu correo.",
|
|
463
|
+
last_sign_in_method: "Primero agrega una contrase\xF1a o vincula otra cuenta: es tu \xFAnica forma de entrar.",
|
|
464
|
+
identity_already_linked: "Esa cuenta est\xE1 vinculada a otra persona.",
|
|
465
|
+
manual_linking_disabled: "Vincular cuentas est\xE1 desactivado en este workspace.",
|
|
423
466
|
invalid_token: "Este enlace no es v\xE1lido o ya venci\xF3. Pide uno nuevo.",
|
|
424
467
|
invalid_code: "Ese c\xF3digo no es correcto o ya venci\xF3.",
|
|
425
468
|
wrong_password: "La contrase\xF1a actual no es correcta.",
|
|
@@ -779,7 +822,9 @@ function Account(props) {
|
|
|
779
822
|
const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleString());
|
|
780
823
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cx("account"), ...root, children: [
|
|
781
824
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProfilePart, { props, account, onSaved: setAccount }),
|
|
825
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmailPart, { props, account }),
|
|
782
826
|
account.hasPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PasswordPart, { props }),
|
|
827
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(LinkedPart, { props }),
|
|
783
828
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepPart, { props, account, onChanged: (mfaEnabled) => setAccount({ ...account, mfaEnabled }) }),
|
|
784
829
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: cx("section"), children: [
|
|
785
830
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: cx("heading"), children: t.passkeys }),
|
|
@@ -818,6 +863,65 @@ function ProfilePart({ props, account, onSaved }) {
|
|
|
818
863
|
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", className: f.cx("notice"), children: done })
|
|
819
864
|
] });
|
|
820
865
|
}
|
|
866
|
+
function EmailPart({ props, account }) {
|
|
867
|
+
const auth = useAuth();
|
|
868
|
+
const { f, done, setDone, run, general } = useSection(props);
|
|
869
|
+
const [email, setEmail] = (0, import_react.useState)("");
|
|
870
|
+
const [password, setPassword] = (0, import_react.useState)("");
|
|
871
|
+
const submit = async (e) => {
|
|
872
|
+
e.preventDefault();
|
|
873
|
+
const r = await run(() => auth.account.changeEmail({ email, password }));
|
|
874
|
+
if (!r.ok) return;
|
|
875
|
+
setPassword("");
|
|
876
|
+
setDone(f.t.emailSent.replace("{email}", r.email));
|
|
877
|
+
};
|
|
878
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: submit, noValidate: true, children: [
|
|
879
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: f.cx("heading"), children: f.t.emailAddress }),
|
|
880
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: account.email }),
|
|
881
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
|
|
882
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.newEmail, value: email, autoComplete: "email", required: true, onChange: setEmail }),
|
|
883
|
+
account.hasPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.changeEmail }),
|
|
885
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", className: f.cx("notice"), children: done })
|
|
886
|
+
] });
|
|
887
|
+
}
|
|
888
|
+
function LinkedPart({ props }) {
|
|
889
|
+
const auth = useAuth();
|
|
890
|
+
const { f, run, general } = useSection(props);
|
|
891
|
+
const [linked, setLinked] = (0, import_react.useState)(null);
|
|
892
|
+
const [offered, setOffered] = (0, import_react.useState)([]);
|
|
893
|
+
const [came, setCame] = (0, import_react.useState)(null);
|
|
894
|
+
(0, import_react.useEffect)(() => {
|
|
895
|
+
void auth.account.identities().then(setLinked);
|
|
896
|
+
void auth.methods().then((m) => setOffered(m.providers));
|
|
897
|
+
const back = typeof window === "undefined" ? null : new URLSearchParams(window.location.search);
|
|
898
|
+
if (back?.get("linked")) setCame(back.get("linked"));
|
|
899
|
+
else if (back?.get("auth_error")) f.setError({ code: back.get("auth_error"), message: "That account could not be linked. Try again." });
|
|
900
|
+
}, []);
|
|
901
|
+
if (linked === null) return null;
|
|
902
|
+
const name = (id) => offered.find((p) => p.id === id)?.name ?? id;
|
|
903
|
+
const unlink = async (provider) => {
|
|
904
|
+
const r = await run(() => auth.account.unlink(provider));
|
|
905
|
+
if (r.ok) setLinked(linked.filter((x) => x.provider !== provider));
|
|
906
|
+
};
|
|
907
|
+
const here = typeof window === "undefined" ? void 0 : window.location.pathname;
|
|
908
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
909
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: f.cx("heading"), children: f.t.linkedAccounts }),
|
|
910
|
+
came && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", className: f.cx("notice"), children: f.t.linked }),
|
|
911
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
|
|
912
|
+
linked.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: f.t.noLinkedAccounts }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: linked.map((x) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
913
|
+
name(x.provider),
|
|
914
|
+
x.email ? ` \xB7 ${x.email}` : "",
|
|
915
|
+
" ",
|
|
916
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void unlink(x.provider), children: f.t.unlink })
|
|
917
|
+
] }, x.provider)) }),
|
|
918
|
+
offered.filter((p) => !linked.some((x) => x.provider === p.id)).map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", className: f.cx("providerButton"), onClick: () => auth.account.link(p.id, { returnTo: here }), children: [
|
|
919
|
+
f.t.linkWith,
|
|
920
|
+
" ",
|
|
921
|
+
p.name
|
|
922
|
+
] }, p.id))
|
|
923
|
+
] });
|
|
924
|
+
}
|
|
821
925
|
function PasswordPart({ props }) {
|
|
822
926
|
const auth = useAuth();
|
|
823
927
|
const { f, done, setDone, run, general } = useSection(props);
|