cauthy-auth 0.19.0 → 0.22.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/{cauthy-Bn3iv50y.d.ts → cauthy-DGAy45G2.d.ts} +1 -1
- package/dist/{cauthy-C29HCvag.d.mts → cauthy-XkIbG5gE.d.mts} +1 -1
- package/dist/client.d.mts +157 -2
- package/dist/client.d.ts +157 -2
- package/dist/client.js +37 -2
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +37 -2
- package/dist/client.mjs.map +1 -1
- package/dist/express.d.mts +2 -2
- package/dist/express.d.ts +2 -2
- package/dist/fastify.d.mts +2 -2
- package/dist/fastify.d.ts +2 -2
- package/dist/hono.d.mts +2 -2
- package/dist/hono.d.ts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +181 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +181 -6
- package/dist/index.mjs.map +1 -1
- package/dist/next.d.mts +2 -2
- package/dist/next.d.ts +2 -2
- package/dist/react.d.mts +192 -1
- package/dist/react.d.ts +192 -1
- package/dist/react.js +279 -23
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +278 -23
- package/dist/react.mjs.map +1 -1
- package/dist/svelte.d.mts +3 -3
- package/dist/svelte.d.ts +3 -3
- package/dist/svelte.js +37 -2
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +37 -2
- package/dist/svelte.mjs.map +1 -1
- package/dist/{system-ZD_Wa8Bm.d.mts → system-BxMsSIu1.d.mts} +2 -0
- package/dist/{system-DhRr_WxR.d.ts → system-DTIeDXDP.d.ts} +2 -0
- package/dist/vue.d.mts +3 -3
- package/dist/vue.d.ts +3 -3
- package/dist/vue.js +37 -2
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +37 -2
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react.mjs
CHANGED
|
@@ -229,8 +229,14 @@ function createAuthClient(options = {}) {
|
|
|
229
229
|
return null;
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
|
+
const upgradeUrl = (provider, o = {}) => `${base}/me/upgrade/social/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ""}`;
|
|
232
233
|
const linkUrl = (provider, o = {}) => `${base}/me/identities/link/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ""}`;
|
|
233
234
|
const socialUrl = (provider, o = {}) => `${base}/sign-in/social/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ""}`;
|
|
235
|
+
const ssoUrl = (target, o = {}) => {
|
|
236
|
+
const q = new URLSearchParams("connection" in target ? { connection: target.connection } : { email: target.email.trim() });
|
|
237
|
+
if (o.returnTo) q.set("return_to", o.returnTo);
|
|
238
|
+
return `${base}/sign-in/sso?${q}`;
|
|
239
|
+
};
|
|
234
240
|
const passkeyUrl = (o = {}) => {
|
|
235
241
|
const q = new URLSearchParams({ method: "passkey" });
|
|
236
242
|
if (o.returnTo) q.set("return_to", o.returnTo);
|
|
@@ -242,11 +248,11 @@ function createAuthClient(options = {}) {
|
|
|
242
248
|
const res = await doFetch(`${base}/methods`, { credentials: "same-origin", headers: { accept: "application/json" } });
|
|
243
249
|
if (res.ok) {
|
|
244
250
|
const m = await res.json();
|
|
245
|
-
return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true };
|
|
251
|
+
return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true, sso: m.sso === true };
|
|
246
252
|
}
|
|
247
253
|
} catch {
|
|
248
254
|
}
|
|
249
|
-
return { providers: [], signUp: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false };
|
|
255
|
+
return { providers: [], signUp: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false, sso: false };
|
|
250
256
|
}
|
|
251
257
|
async function ceremony(begin, finish, form, run, more = {}) {
|
|
252
258
|
const begun = await post(begin, form, null);
|
|
@@ -261,6 +267,7 @@ function createAuthClient(options = {}) {
|
|
|
261
267
|
}
|
|
262
268
|
return {
|
|
263
269
|
signIn: {
|
|
270
|
+
anonymously: (f = {}) => post("/sign-in/anonymous", {}, null, f.captchaToken),
|
|
264
271
|
email: (f) => post("/sign-in/email", { email: f.email, password: f.password }, firstProblem(checkEmail(f.email), checkPassword(f.password)), f.captchaToken),
|
|
265
272
|
mfa: (f) => post("/sign-in/mfa", { code: f.code }, checkCode(f.code)),
|
|
266
273
|
mfaMethods: () => post("/sign-in/mfa/methods", {}, null),
|
|
@@ -344,6 +351,11 @@ function createAuthClient(options = {}) {
|
|
|
344
351
|
socialUrl,
|
|
345
352
|
social(provider, o) {
|
|
346
353
|
window.location.assign(socialUrl(provider, o));
|
|
354
|
+
},
|
|
355
|
+
ssoDiscover: (f) => post("/sign-in/sso/discover", { email: f.email.trim() }, checkEmail(f.email)),
|
|
356
|
+
ssoUrl,
|
|
357
|
+
sso(target, o) {
|
|
358
|
+
window.location.assign(ssoUrl(target, o));
|
|
347
359
|
}
|
|
348
360
|
},
|
|
349
361
|
signUp: {
|
|
@@ -353,6 +365,24 @@ function createAuthClient(options = {}) {
|
|
|
353
365
|
resetPassword: (f) => post("/reset-password", { token: f.token, password: f.password }, checkNewPassword(f.password)),
|
|
354
366
|
verifyEmail: (f) => post("/verify-email", { token: f.token }, null),
|
|
355
367
|
signOut: () => post("/sign-out", {}, null),
|
|
368
|
+
organizations: {
|
|
369
|
+
async list(system) {
|
|
370
|
+
const body = await read(`/me/organizations${system ? `?system=${encodeURIComponent(system)}` : ""}`);
|
|
371
|
+
return body && Array.isArray(body.organizations) ? body.organizations : [];
|
|
372
|
+
},
|
|
373
|
+
async members(id) {
|
|
374
|
+
const body = await read(`/me/organizations/members?id=${encodeURIComponent(id)}`);
|
|
375
|
+
return body && Array.isArray(body.members) ? body.members : null;
|
|
376
|
+
},
|
|
377
|
+
async roles(id) {
|
|
378
|
+
const body = await read(`/me/organizations/roles?id=${encodeURIComponent(id)}`);
|
|
379
|
+
return body && Array.isArray(body.roles) ? body.roles : null;
|
|
380
|
+
},
|
|
381
|
+
add: (id, f) => post("/me/organizations/members/add", { organizationId: id, email: f.email, role: f.role, name: f.name ?? "", locale: f.locale ?? "" }, checkEmail(f.email)),
|
|
382
|
+
setRole: (id, userId, role) => post("/me/organizations/members/role", { organizationId: id, userId, role }, null),
|
|
383
|
+
remove: (id, userId) => post("/me/organizations/members/remove", { organizationId: id, userId }, null),
|
|
384
|
+
inviteAgain: (id, userId, f = {}) => post("/me/organizations/members/invite", { organizationId: id, userId, locale: f.locale ?? "" }, null)
|
|
385
|
+
},
|
|
356
386
|
account: {
|
|
357
387
|
async get() {
|
|
358
388
|
const body = await read("/me");
|
|
@@ -391,6 +421,11 @@ function createAuthClient(options = {}) {
|
|
|
391
421
|
return body && Array.isArray(body.sessions) ? body.sessions : [];
|
|
392
422
|
},
|
|
393
423
|
signOutEverywhere: () => post("/me/sessions/end", {}, null),
|
|
424
|
+
upgrade: (f) => post("/me/upgrade", { email: f.email, password: f.password, name: f.name ?? "" }, firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password))),
|
|
425
|
+
upgradeUrl,
|
|
426
|
+
upgradeWith(provider, o) {
|
|
427
|
+
window.location.assign(upgradeUrl(provider, o));
|
|
428
|
+
},
|
|
394
429
|
async agents() {
|
|
395
430
|
const body = await read("/me/agents");
|
|
396
431
|
return body && Array.isArray(body.agents) ? body.agents : [];
|
|
@@ -564,7 +599,30 @@ var TEXTS = {
|
|
|
564
599
|
linkWith: "Link",
|
|
565
600
|
unlink: "Unlink",
|
|
566
601
|
linked: "The account was linked.",
|
|
602
|
+
ssoOnly: "Your company signs you in to this account.",
|
|
603
|
+
members: "Members",
|
|
604
|
+
membersHidden: "Your role here does not let you see the members.",
|
|
605
|
+
organizationMissing: "You do not belong to this organization.",
|
|
606
|
+
memberYou: "you",
|
|
607
|
+
memberInvited: "invited",
|
|
608
|
+
memberManager: "manages members",
|
|
609
|
+
memberRole: "Role",
|
|
610
|
+
memberAdd: "Add member",
|
|
611
|
+
memberAdded: "{email} is a member now.",
|
|
612
|
+
memberRemove: "Remove",
|
|
613
|
+
memberRemoveConfirm: "Remove {who}?",
|
|
614
|
+
memberLeave: "Leave",
|
|
615
|
+
memberLeaveConfirm: "Leave {org}? You will need an invitation to come back.",
|
|
616
|
+
memberInviteAgain: "Send the invitation again",
|
|
617
|
+
memberInvitationSent: "The invitation is on its way.",
|
|
618
|
+
yes: "Yes",
|
|
619
|
+
cancel: "Cancel",
|
|
567
620
|
errors: {
|
|
621
|
+
not_allowed: "Your role in this organization does not allow that.",
|
|
622
|
+
last_manager: "Somebody else must manage the members first: give that role to another member.",
|
|
623
|
+
already_member: "That person already belongs to the organization. Change their role instead.",
|
|
624
|
+
unknown_role: "Choose one of the roles offered.",
|
|
625
|
+
user_not_active: "That account is disabled.",
|
|
568
626
|
required: "This is required.",
|
|
569
627
|
invalid_email: "That does not look like an email address.",
|
|
570
628
|
too_short: "Use at least 8 characters.",
|
|
@@ -592,7 +650,15 @@ var TEXTS = {
|
|
|
592
650
|
captcha_failed: "The check that you are not a bot did not pass. Try it again.",
|
|
593
651
|
passkey_failed: "The passkey could not be used. Try again, or sign in another way.",
|
|
594
652
|
passkey_exists: "This device already has a passkey for your account.",
|
|
595
|
-
passkey_unavailable: "Passkeys cannot be used here."
|
|
653
|
+
passkey_unavailable: "Passkeys cannot be used here.",
|
|
654
|
+
sso_required: "This address signs in through its company.",
|
|
655
|
+
sso_not_found: "No company sign-in answers for this address.",
|
|
656
|
+
sso_failed: "The sign-in with your company could not be completed. Try again.",
|
|
657
|
+
sso_unavailable: "Your company's sign-in cannot be reached right now. Try again in a moment.",
|
|
658
|
+
invalid_assertion: "Your company's answer could not be checked. Try again.",
|
|
659
|
+
provisioning_disabled: "Your company's sign-in worked, but this workspace has no account for you. Ask its admin to add you.",
|
|
660
|
+
connection_inactive: "Your company's sign-in is turned off for this workspace.",
|
|
661
|
+
invalid_grant: "That sign-in expired. Try again."
|
|
596
662
|
}
|
|
597
663
|
},
|
|
598
664
|
es: {
|
|
@@ -679,7 +745,30 @@ var TEXTS = {
|
|
|
679
745
|
linkWith: "Vincular",
|
|
680
746
|
unlink: "Desvincular",
|
|
681
747
|
linked: "La cuenta qued\xF3 vinculada.",
|
|
748
|
+
ssoOnly: "A esta cuenta entras con el inicio de sesi\xF3n de tu empresa.",
|
|
749
|
+
members: "Miembros",
|
|
750
|
+
membersHidden: "Tu rol aqu\xED no te deja ver los miembros.",
|
|
751
|
+
organizationMissing: "No perteneces a esta organizaci\xF3n.",
|
|
752
|
+
memberYou: "t\xFA",
|
|
753
|
+
memberInvited: "invitado",
|
|
754
|
+
memberManager: "administra los miembros",
|
|
755
|
+
memberRole: "Rol",
|
|
756
|
+
memberAdd: "Agregar miembro",
|
|
757
|
+
memberAdded: "{email} ya es miembro.",
|
|
758
|
+
memberRemove: "Quitar",
|
|
759
|
+
memberRemoveConfirm: "\xBFQuitar a {who}?",
|
|
760
|
+
memberLeave: "Salir",
|
|
761
|
+
memberLeaveConfirm: "\xBFSalir de {org}? Necesitar\xE1s una invitaci\xF3n para volver.",
|
|
762
|
+
memberInviteAgain: "Enviar la invitaci\xF3n de nuevo",
|
|
763
|
+
memberInvitationSent: "La invitaci\xF3n va en camino.",
|
|
764
|
+
yes: "S\xED",
|
|
765
|
+
cancel: "Cancelar",
|
|
682
766
|
errors: {
|
|
767
|
+
not_allowed: "Tu rol en esta organizaci\xF3n no permite eso.",
|
|
768
|
+
last_manager: "Primero alguien m\xE1s debe administrar los miembros: dale ese rol a otro miembro.",
|
|
769
|
+
already_member: "Esa persona ya pertenece a la organizaci\xF3n. Cambia su rol.",
|
|
770
|
+
unknown_role: "Escoge uno de los roles ofrecidos.",
|
|
771
|
+
user_not_active: "Esa cuenta est\xE1 desactivada.",
|
|
683
772
|
required: "Este dato es obligatorio.",
|
|
684
773
|
invalid_email: "Eso no parece un correo.",
|
|
685
774
|
too_short: "Usa al menos 8 caracteres.",
|
|
@@ -707,7 +796,15 @@ var TEXTS = {
|
|
|
707
796
|
captcha_failed: "La verificaci\xF3n de que no eres un robot no pas\xF3. Int\xE9ntalo de nuevo.",
|
|
708
797
|
passkey_failed: "No se pudo usar la llave de acceso. Intenta de nuevo o entra de otra forma.",
|
|
709
798
|
passkey_exists: "Este dispositivo ya tiene una llave de acceso de tu cuenta.",
|
|
710
|
-
passkey_unavailable: "Aqu\xED no se pueden usar llaves de acceso."
|
|
799
|
+
passkey_unavailable: "Aqu\xED no se pueden usar llaves de acceso.",
|
|
800
|
+
sso_required: "Este correo entra con el inicio de sesi\xF3n de su empresa.",
|
|
801
|
+
sso_not_found: "Ninguna empresa usa inicio de sesi\xF3n propio con este correo.",
|
|
802
|
+
sso_failed: "No se pudo completar el ingreso con tu empresa. Intenta de nuevo.",
|
|
803
|
+
sso_unavailable: "Ahora no se puede llegar al inicio de sesi\xF3n de tu empresa. Intenta en un momento.",
|
|
804
|
+
invalid_assertion: "No se pudo verificar la respuesta de tu empresa. Intenta de nuevo.",
|
|
805
|
+
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.",
|
|
806
|
+
connection_inactive: "El inicio de sesi\xF3n de tu empresa est\xE1 apagado en este workspace.",
|
|
807
|
+
invalid_grant: "Ese ingreso venci\xF3. Intenta de nuevo."
|
|
711
808
|
}
|
|
712
809
|
}
|
|
713
810
|
};
|
|
@@ -900,6 +997,25 @@ function SignIn(props) {
|
|
|
900
997
|
};
|
|
901
998
|
const autofill = useRef(null);
|
|
902
999
|
const [offer, setOffer] = useState(0);
|
|
1000
|
+
const [company, setCompany] = useState(null);
|
|
1001
|
+
useEffect(() => {
|
|
1002
|
+
if (!methods?.sso || checkEmail(email) !== null) return setCompany(null);
|
|
1003
|
+
let current = true;
|
|
1004
|
+
const t = setTimeout(() => {
|
|
1005
|
+
void auth.signIn.ssoDiscover({ email }).then((r) => {
|
|
1006
|
+
if (current) setCompany(r.ok && r.status === "found" ? r.connection : null);
|
|
1007
|
+
});
|
|
1008
|
+
}, 350);
|
|
1009
|
+
return () => {
|
|
1010
|
+
current = false;
|
|
1011
|
+
clearTimeout(t);
|
|
1012
|
+
};
|
|
1013
|
+
}, [email, methods]);
|
|
1014
|
+
const toCompany = () => {
|
|
1015
|
+
autofill.current?.abort();
|
|
1016
|
+
f.setBusy(true);
|
|
1017
|
+
auth.signIn.sso({ email }, { returnTo: props.returnTo });
|
|
1018
|
+
};
|
|
903
1019
|
useEffect(() => {
|
|
904
1020
|
void auth.methods().then(setMethods);
|
|
905
1021
|
const back = returnedError();
|
|
@@ -932,9 +1048,11 @@ function SignIn(props) {
|
|
|
932
1048
|
autofill.current?.abort();
|
|
933
1049
|
f.setBusy(true);
|
|
934
1050
|
f.setError(null);
|
|
1051
|
+
if (step === "password" && company?.enforced) return toCompany();
|
|
935
1052
|
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 });
|
|
936
1053
|
f.setBusy(false);
|
|
937
1054
|
if (step === "password") challenge.renew();
|
|
1055
|
+
if (!r.ok && r.error.code === "sso_required") return toCompany();
|
|
938
1056
|
if (!r.ok) {
|
|
939
1057
|
setOffer((n) => n + 1);
|
|
940
1058
|
return f.setError(r.error);
|
|
@@ -960,6 +1078,7 @@ function SignIn(props) {
|
|
|
960
1078
|
const r = await auth.signIn.magicLink({ email, captchaToken: challenge.token, create: props.createAccounts, returnTo: props.returnTo });
|
|
961
1079
|
f.setBusy(false);
|
|
962
1080
|
challenge.renew();
|
|
1081
|
+
if (!r.ok && r.error.code === "sso_required") return toCompany();
|
|
963
1082
|
if (!r.ok) return f.setError(r.error);
|
|
964
1083
|
setStep("sent");
|
|
965
1084
|
};
|
|
@@ -994,23 +1113,31 @@ function SignIn(props) {
|
|
|
994
1113
|
methods?.passkey && /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void usePasskey(), children: f.t.usePasskey }),
|
|
995
1114
|
((methods?.providers.length ?? 0) > 0 || methods?.passkey) && /* @__PURE__ */ jsx("p", { className: f.cx("separator"), children: f.t.orWithEmail }),
|
|
996
1115
|
/* @__PURE__ */ jsx(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: methods?.passkeyHere ? "username webauthn" : "username", required: true, onChange: setEmail }),
|
|
997
|
-
/* @__PURE__ */
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1116
|
+
company && /* @__PURE__ */ jsxs(f.Button, { type: "button", disabled: f.busy, className: f.cx(company.enforced ? "button" : "providerButton"), onClick: toCompany, children: [
|
|
1117
|
+
f.t.continueWith,
|
|
1118
|
+
" ",
|
|
1119
|
+
company.name
|
|
1120
|
+
] }),
|
|
1121
|
+
company?.enforced && /* @__PURE__ */ jsx("p", { className: f.cx("notice"), children: f.t.ssoOnly }),
|
|
1122
|
+
!company?.enforced && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1123
|
+
/* @__PURE__ */ jsx(
|
|
1124
|
+
Field,
|
|
1125
|
+
{
|
|
1126
|
+
f,
|
|
1127
|
+
name: "password",
|
|
1128
|
+
type: "password",
|
|
1129
|
+
label: f.t.password,
|
|
1130
|
+
value: password,
|
|
1131
|
+
autoComplete: "current-password",
|
|
1132
|
+
required: true,
|
|
1133
|
+
onChange: setPassword,
|
|
1134
|
+
aside: props.links?.forgotPassword ? /* @__PURE__ */ jsx("a", { className: f.cx("link"), href: props.links.forgotPassword, children: f.t.forgotPassword }) : void 0
|
|
1135
|
+
}
|
|
1136
|
+
),
|
|
1137
|
+
challenge.node,
|
|
1138
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signIn })
|
|
1139
|
+
] }),
|
|
1140
|
+
methods?.magicLink && !company?.enforced && /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendLink(), children: f.t.emailMeALink }),
|
|
1014
1141
|
methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ jsxs("p", { className: f.cx("footer"), children: [
|
|
1015
1142
|
f.t.noAccount,
|
|
1016
1143
|
" ",
|
|
@@ -1045,7 +1172,7 @@ function SignUp(props) {
|
|
|
1045
1172
|
e.preventDefault();
|
|
1046
1173
|
f.setBusy(true);
|
|
1047
1174
|
f.setError(null);
|
|
1048
|
-
const r = await auth.signUp.email({ name, email, password, captchaToken: challenge.token });
|
|
1175
|
+
const r = auth.session?.user.isAnonymous === true ? await auth.account.upgrade({ name, email, password }) : await auth.signUp.email({ name, email, password, captchaToken: challenge.token });
|
|
1049
1176
|
f.setBusy(false);
|
|
1050
1177
|
challenge.renew();
|
|
1051
1178
|
if (!r.ok) return f.setError(r.error);
|
|
@@ -1215,6 +1342,130 @@ function Account(props) {
|
|
|
1215
1342
|
] })
|
|
1216
1343
|
] });
|
|
1217
1344
|
}
|
|
1345
|
+
function OrganizationMembers(props) {
|
|
1346
|
+
const auth = useAuth();
|
|
1347
|
+
const { root } = useForm(props);
|
|
1348
|
+
const { f, done, setDone, run } = useSection(props);
|
|
1349
|
+
const problem = f.error && f.error.field !== "email" ? f.error : null;
|
|
1350
|
+
const [seat, setSeat] = useState(void 0);
|
|
1351
|
+
const [members, setMembers] = useState(null);
|
|
1352
|
+
const [roles, setRoles] = useState([]);
|
|
1353
|
+
const [email, setEmail] = useState("");
|
|
1354
|
+
const [role, setRole] = useState("");
|
|
1355
|
+
const [asking, setAsking] = useState(null);
|
|
1356
|
+
const id = props.organizationId;
|
|
1357
|
+
const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleDateString());
|
|
1358
|
+
const load = async () => {
|
|
1359
|
+
const [list, people, choices] = await Promise.all([auth.organizations.list(), auth.organizations.members(id), auth.organizations.roles(id)]);
|
|
1360
|
+
setSeat(list.find((o) => o.id === id) ?? null);
|
|
1361
|
+
setMembers(people);
|
|
1362
|
+
setRoles(choices ?? []);
|
|
1363
|
+
if (choices && choices.length > 0 && !choices.some((c) => c.role === role)) setRole(choices[0].role);
|
|
1364
|
+
};
|
|
1365
|
+
useEffect(() => {
|
|
1366
|
+
void load();
|
|
1367
|
+
}, [id]);
|
|
1368
|
+
if (seat === void 0) return /* @__PURE__ */ jsx("div", { className: f.cx("account"), ...root, "aria-busy": "true" });
|
|
1369
|
+
if (seat === null) return /* @__PURE__ */ jsx("div", { className: f.cx("account"), ...root, children: /* @__PURE__ */ jsx("p", { className: f.cx("notice"), children: f.t.organizationMissing }) });
|
|
1370
|
+
const manage = seat.can.manageMembers;
|
|
1371
|
+
const label = (r) => roles.find((c) => c.role === r)?.name || r;
|
|
1372
|
+
const add = async (e) => {
|
|
1373
|
+
e.preventDefault();
|
|
1374
|
+
const r = await run(() => auth.organizations.add(id, { email, role, locale: props.locale }));
|
|
1375
|
+
if (!r.ok) return;
|
|
1376
|
+
setEmail("");
|
|
1377
|
+
setDone(f.t.memberAdded.replace("{email}", r.member.email));
|
|
1378
|
+
await load();
|
|
1379
|
+
};
|
|
1380
|
+
const change = async (m, next) => {
|
|
1381
|
+
const r = await run(() => auth.organizations.setRole(id, m.userId, next));
|
|
1382
|
+
if (r.ok) await load();
|
|
1383
|
+
};
|
|
1384
|
+
const remove = async (m) => {
|
|
1385
|
+
setAsking(null);
|
|
1386
|
+
const r = await run(() => auth.organizations.remove(id, m.userId));
|
|
1387
|
+
if (!r.ok) return;
|
|
1388
|
+
if (m.you) setSeat(null);
|
|
1389
|
+
else await load();
|
|
1390
|
+
};
|
|
1391
|
+
const inviteAgain = async (m) => {
|
|
1392
|
+
const r = await run(() => auth.organizations.inviteAgain(id, m.userId, { locale: props.locale }));
|
|
1393
|
+
if (r.ok) setDone(f.t.memberInvitationSent);
|
|
1394
|
+
};
|
|
1395
|
+
return /* @__PURE__ */ jsxs("div", { className: f.cx("account"), ...root, children: [
|
|
1396
|
+
/* @__PURE__ */ jsxs("section", { className: f.cx("section"), children: [
|
|
1397
|
+
/* @__PURE__ */ jsxs("h2", { className: f.cx("heading"), children: [
|
|
1398
|
+
f.t.members,
|
|
1399
|
+
" \xB7 ",
|
|
1400
|
+
seat.name
|
|
1401
|
+
] }),
|
|
1402
|
+
problem && /* @__PURE__ */ jsx("p", { role: "alert", className: f.cx("error"), children: f.say(problem) }),
|
|
1403
|
+
members === null ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1404
|
+
/* @__PURE__ */ jsx("p", { className: f.cx("notice"), children: f.t.membersHidden }),
|
|
1405
|
+
auth.session && (asking === auth.session.user.id ? /* @__PURE__ */ jsxs("span", { role: "group", "aria-label": f.t.memberLeave, children: [
|
|
1406
|
+
/* @__PURE__ */ jsx("span", { children: f.t.memberLeaveConfirm.replace("{org}", seat.name) }),
|
|
1407
|
+
" ",
|
|
1408
|
+
/* @__PURE__ */ jsx(
|
|
1409
|
+
f.Button,
|
|
1410
|
+
{
|
|
1411
|
+
type: "button",
|
|
1412
|
+
disabled: f.busy,
|
|
1413
|
+
className: f.cx("providerButton"),
|
|
1414
|
+
onClick: () => void remove({ userId: auth.session.user.id, you: true }),
|
|
1415
|
+
children: f.t.yes
|
|
1416
|
+
}
|
|
1417
|
+
),
|
|
1418
|
+
/* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(null), children: f.t.cancel })
|
|
1419
|
+
] }) : /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(auth.session.user.id), children: f.t.memberLeave }))
|
|
1420
|
+
] }) : /* @__PURE__ */ jsx("ul", { className: f.cx("sessions"), children: members.map((m) => {
|
|
1421
|
+
const who = m.name || m.email;
|
|
1422
|
+
return /* @__PURE__ */ jsxs("li", { className: f.cx("session"), children: [
|
|
1423
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1424
|
+
who,
|
|
1425
|
+
m.name ? ` \xB7 ${m.email}` : "",
|
|
1426
|
+
m.you ? ` (${f.t.memberYou})` : "",
|
|
1427
|
+
m.invited ? ` \xB7 ${f.t.memberInvited}` : "",
|
|
1428
|
+
m.manager ? ` \xB7 ${f.t.memberManager}` : "",
|
|
1429
|
+
" \xB7 ",
|
|
1430
|
+
when(m.since)
|
|
1431
|
+
] }),
|
|
1432
|
+
" ",
|
|
1433
|
+
manage && roles.length > 0 ? /* @__PURE__ */ jsx(
|
|
1434
|
+
"select",
|
|
1435
|
+
{
|
|
1436
|
+
"aria-label": `${f.t.memberRole}: ${who}`,
|
|
1437
|
+
className: f.cx("input"),
|
|
1438
|
+
value: m.role,
|
|
1439
|
+
disabled: f.busy,
|
|
1440
|
+
onChange: (e) => void change(m, e.target.value),
|
|
1441
|
+
children: roles.map((c) => /* @__PURE__ */ jsx("option", { value: c.role, children: c.name || c.role }, c.role))
|
|
1442
|
+
}
|
|
1443
|
+
) : /* @__PURE__ */ jsx("span", { children: label(m.role) }),
|
|
1444
|
+
" ",
|
|
1445
|
+
asking === m.userId ? /* @__PURE__ */ jsxs("span", { role: "group", "aria-label": m.you ? f.t.memberLeave : f.t.memberRemove, children: [
|
|
1446
|
+
/* @__PURE__ */ jsx("span", { children: m.you ? f.t.memberLeaveConfirm.replace("{org}", seat.name) : f.t.memberRemoveConfirm.replace("{who}", who) }),
|
|
1447
|
+
" ",
|
|
1448
|
+
/* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void remove(m), children: f.t.yes }),
|
|
1449
|
+
/* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(null), children: f.t.cancel })
|
|
1450
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1451
|
+
manage && m.invited && /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void inviteAgain(m), children: f.t.memberInviteAgain }),
|
|
1452
|
+
(manage || m.you) && /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(m.userId), children: m.you ? f.t.memberLeave : f.t.memberRemove })
|
|
1453
|
+
] })
|
|
1454
|
+
] }, m.userId);
|
|
1455
|
+
}) }),
|
|
1456
|
+
done && /* @__PURE__ */ jsx("p", { role: "status", className: f.cx("notice"), children: done })
|
|
1457
|
+
] }),
|
|
1458
|
+
manage && roles.length > 0 && /* @__PURE__ */ jsxs("form", { className: f.cx("section"), onSubmit: add, noValidate: true, children: [
|
|
1459
|
+
/* @__PURE__ */ jsx("h2", { className: f.cx("heading"), children: f.t.memberAdd }),
|
|
1460
|
+
/* @__PURE__ */ jsx(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "off", required: true, onChange: setEmail }),
|
|
1461
|
+
/* @__PURE__ */ jsxs("label", { className: f.cx("field"), children: [
|
|
1462
|
+
/* @__PURE__ */ jsx("span", { className: f.cx("label"), children: f.t.memberRole }),
|
|
1463
|
+
/* @__PURE__ */ jsx("select", { name: "role", className: f.cx("input"), value: role, onChange: (e) => setRole(e.target.value), children: roles.map((c) => /* @__PURE__ */ jsx("option", { value: c.role, children: c.name || c.role }, c.role)) })
|
|
1464
|
+
] }),
|
|
1465
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.memberAdd })
|
|
1466
|
+
] })
|
|
1467
|
+
] });
|
|
1468
|
+
}
|
|
1218
1469
|
function PasskeysPart({ props, account, accountUrl, when }) {
|
|
1219
1470
|
const auth = useAuth();
|
|
1220
1471
|
const { f, done, setDone, run, general } = useSection(props);
|
|
@@ -1636,6 +1887,7 @@ function useAuth() {
|
|
|
1636
1887
|
...client,
|
|
1637
1888
|
signIn: {
|
|
1638
1889
|
...client.signIn,
|
|
1890
|
+
anonymously: (f) => then(client.signIn.anonymously(f)),
|
|
1639
1891
|
email: (f) => then(client.signIn.email(f)),
|
|
1640
1892
|
mfa: (f) => then(client.signIn.mfa(f)),
|
|
1641
1893
|
magicLinkVerify: (f) => then(client.signIn.magicLinkVerify(f)),
|
|
@@ -1651,7 +1903,9 @@ function useAuth() {
|
|
|
1651
1903
|
// What is on screen says the new name, and knows when the session ended.
|
|
1652
1904
|
update: (f) => then(client.account.update(f)),
|
|
1653
1905
|
changePassword: (f) => then(client.account.changePassword(f)),
|
|
1654
|
-
signOutEverywhere: () => then(client.account.signOutEverywhere())
|
|
1906
|
+
signOutEverywhere: () => then(client.account.signOutEverywhere()),
|
|
1907
|
+
// The guest is now the account: what is on screen says so.
|
|
1908
|
+
upgrade: (f) => then(client.account.upgrade(f))
|
|
1655
1909
|
},
|
|
1656
1910
|
session,
|
|
1657
1911
|
status,
|
|
@@ -1664,6 +1918,7 @@ export {
|
|
|
1664
1918
|
CauthyProvider,
|
|
1665
1919
|
ForgotPassword,
|
|
1666
1920
|
GoogleOneTap,
|
|
1921
|
+
OrganizationMembers,
|
|
1667
1922
|
ResetPassword,
|
|
1668
1923
|
SignIn,
|
|
1669
1924
|
SignUp,
|