@protobase/ui 0.53.6 → 0.53.8
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/account/account-page.js +8 -3
- package/dist/account/blocks/delete-account-block.js +22 -0
- package/dist/account/delete-account-dialog.js +71 -0
- package/dist/account/delete-account-section.js +26 -0
- package/dist/account/messages.js +20 -2
- package/dist/app/pages/render-node.js +3 -1
- package/dist/auth/auth-messages.js +1 -0
- package/dist/auth/auth-provider.js +9 -0
- package/dist/package.js +1 -1
- package/dist/shell/assets/{app-lIH0RyO8.js → app-D0QfXMxK.js} +8 -8
- package/dist/shell/assets/{index-BUHPj0Eg.js → index-f5Nt4-Hd.js} +2 -2
- package/dist/shell/assets/{records-map-_qjIukY1.js → records-map-nmljawiv.js} +2 -2
- package/dist/shell/assets/{shared-protobase-ui-MwC2WreJ.js → shared-protobase-ui-BDt_1A9W.js} +2 -2
- package/dist/shell/index.html +3 -3
- package/dist/shell/protobase.shell.json +1 -1
- package/dist/shell/protobase.sw.js +2 -2
- package/dist/shell-source-maps/assets/app-D0QfXMxK.js.map +1 -0
- package/dist/shell-source-maps/assets/{index-BUHPj0Eg.js.map → index-f5Nt4-Hd.js.map} +1 -1
- package/dist/shell-source-maps/assets/{records-map-_qjIukY1.js.map → records-map-nmljawiv.js.map} +1 -1
- package/dist/shell-source-maps/assets/{shared-protobase-ui-MwC2WreJ.js.map → shared-protobase-ui-BDt_1A9W.js.map} +1 -1
- package/package.json +4 -4
- package/dist/shell-source-maps/assets/app-lIH0RyO8.js.map +0 -1
|
@@ -16,11 +16,15 @@ import { jsx } from "react/jsx-runtime";
|
|
|
16
16
|
const useAccountPage = () => {
|
|
17
17
|
const { account } = useAdminMeta();
|
|
18
18
|
const auth = useAuth();
|
|
19
|
-
const { mcp } = auth;
|
|
19
|
+
const { mcp, accountDeletion } = auth;
|
|
20
20
|
const linkable = linkableProviders(auth).length > 0;
|
|
21
21
|
return useMemo(() => {
|
|
22
22
|
if (!account) return void 0;
|
|
23
|
-
const hidden = /* @__PURE__ */ new Set([
|
|
23
|
+
const hidden = /* @__PURE__ */ new Set([
|
|
24
|
+
...mcp ? [] : ["ConnectedApps"],
|
|
25
|
+
...linkable ? [] : ["ConnectedAccounts"],
|
|
26
|
+
...accountDeletion ? [] : ["DeleteAccount"]
|
|
27
|
+
]);
|
|
24
28
|
return {
|
|
25
29
|
...account,
|
|
26
30
|
tree: shownAccountTree(account.tree, hidden)
|
|
@@ -28,7 +32,8 @@ const useAccountPage = () => {
|
|
|
28
32
|
}, [
|
|
29
33
|
account,
|
|
30
34
|
mcp,
|
|
31
|
-
linkable
|
|
35
|
+
linkable,
|
|
36
|
+
accountDeletion
|
|
32
37
|
]);
|
|
33
38
|
};
|
|
34
39
|
/** `/-/account`, and `/-/account/<tab>` for one of its tabs: the signed-in person's account page. */
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { text } from "../messages.js";
|
|
2
|
+
import { useAuth } from "../../auth/auth-provider.js";
|
|
3
|
+
import { AccountLoading } from "./account-loading.js";
|
|
4
|
+
import { useAccountData } from "./use-account-data.js";
|
|
5
|
+
import { DeleteAccountSection } from "../delete-account-section.js";
|
|
6
|
+
import { useCallback } from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
//#region src/account/blocks/delete-account-block.tsx
|
|
9
|
+
/** The `DeleteAccount` block: the signed-in person deletes their own account, which signs them out; staff signed in as them cannot. */
|
|
10
|
+
const DeleteAccountBlock = () => {
|
|
11
|
+
const { session, state, deleteAccount } = useAuth();
|
|
12
|
+
const { account } = session;
|
|
13
|
+
const { data: methods, error } = useAccountData(useCallback(() => account.signInMethods(), [account]), text("couldNotReadMethods"));
|
|
14
|
+
if (!methods) return /* @__PURE__ */ jsx(AccountLoading, { error });
|
|
15
|
+
return /* @__PURE__ */ jsx(DeleteAccountSection, {
|
|
16
|
+
hasPassword: methods.account.password,
|
|
17
|
+
staff: state.kind === "signed-in" && Boolean(state.staff),
|
|
18
|
+
onDelete: deleteAccount
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { DeleteAccountBlock };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { text } from "./messages.js";
|
|
2
|
+
import { Button } from "../primitives/button.js";
|
|
3
|
+
import { Dialog } from "../primitives/dialog.js";
|
|
4
|
+
import { Input } from "../primitives/input.js";
|
|
5
|
+
import { SectionError } from "./account-section.js";
|
|
6
|
+
import { authMessage } from "../auth/auth-messages.js";
|
|
7
|
+
import { useId, useState } from "react";
|
|
8
|
+
import { AuthError } from "@protobase/client";
|
|
9
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
//#region src/account/delete-account-dialog.tsx
|
|
11
|
+
const deletionMessage = (error) => {
|
|
12
|
+
if (error.code === "LAST_ADMIN") return text("deleteAccountLastAdmin");
|
|
13
|
+
if (error.code === "ACCOUNT_LOCKED") return text("deleteAccountLocked");
|
|
14
|
+
return authMessage(error);
|
|
15
|
+
};
|
|
16
|
+
/** Asks the person to confirm deleting their own account, with their password when it has one. */
|
|
17
|
+
const DeleteAccountDialog = ({ hasPassword, onDelete, onClose }) => {
|
|
18
|
+
const [password, setPassword] = useState("");
|
|
19
|
+
const [busy, setBusy] = useState(false);
|
|
20
|
+
const [error, setError] = useState();
|
|
21
|
+
const formId = useId();
|
|
22
|
+
const confirm = async () => {
|
|
23
|
+
setBusy(true);
|
|
24
|
+
setError(void 0);
|
|
25
|
+
try {
|
|
26
|
+
await onDelete(hasPassword ? password : void 0);
|
|
27
|
+
} catch (failure) {
|
|
28
|
+
if (!(failure instanceof AuthError)) throw failure;
|
|
29
|
+
setError(deletionMessage(failure));
|
|
30
|
+
setBusy(false);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
return /* @__PURE__ */ jsx(Dialog, {
|
|
34
|
+
title: text("deleteAccountQuestion"),
|
|
35
|
+
description: text("deleteAccountWarning"),
|
|
36
|
+
onClose,
|
|
37
|
+
actions: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Button, {
|
|
38
|
+
onClick: onClose,
|
|
39
|
+
children: text("cancel")
|
|
40
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
41
|
+
variant: "danger",
|
|
42
|
+
type: "submit",
|
|
43
|
+
form: formId,
|
|
44
|
+
loading: busy,
|
|
45
|
+
disabled: hasPassword && !password,
|
|
46
|
+
children: text("deleteAccountConfirm")
|
|
47
|
+
})] }),
|
|
48
|
+
children: /* @__PURE__ */ jsxs("form", {
|
|
49
|
+
id: formId,
|
|
50
|
+
className: "flex flex-col gap-4",
|
|
51
|
+
onSubmit: (event) => {
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
confirm();
|
|
54
|
+
},
|
|
55
|
+
children: [hasPassword && /* @__PURE__ */ jsxs("label", {
|
|
56
|
+
className: "flex flex-col gap-1.5 font-medium",
|
|
57
|
+
children: [text("deleteAccountPassword"), /* @__PURE__ */ jsx(Input, {
|
|
58
|
+
type: "password",
|
|
59
|
+
name: "current-password",
|
|
60
|
+
autoComplete: "current-password",
|
|
61
|
+
autoFocus: true,
|
|
62
|
+
value: password,
|
|
63
|
+
invalid: Boolean(error),
|
|
64
|
+
onChange: (event) => setPassword(event.target.value)
|
|
65
|
+
})]
|
|
66
|
+
}), /* @__PURE__ */ jsx(SectionError, { message: error })]
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
//#endregion
|
|
71
|
+
export { DeleteAccountDialog };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { text } from "./messages.js";
|
|
2
|
+
import { Button } from "../primitives/button.js";
|
|
3
|
+
import { AccountSection } from "./account-section.js";
|
|
4
|
+
import { DeleteAccountDialog } from "./delete-account-dialog.js";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/account/delete-account-section.tsx
|
|
8
|
+
/** Deletes the signed-in person's own account, once they confirm it in a dialog. */
|
|
9
|
+
const DeleteAccountSection = ({ hasPassword, staff, onDelete }) => {
|
|
10
|
+
const [confirming, setConfirming] = useState(false);
|
|
11
|
+
return /* @__PURE__ */ jsxs(AccountSection, {
|
|
12
|
+
title: text("deleteAccount"),
|
|
13
|
+
description: staff ? text("deleteAccountStaff") : text("deleteAccountDescription"),
|
|
14
|
+
children: [!staff && /* @__PURE__ */ jsx(Button, {
|
|
15
|
+
variant: "danger",
|
|
16
|
+
onClick: () => setConfirming(true),
|
|
17
|
+
children: text("deleteAccount")
|
|
18
|
+
}), confirming && /* @__PURE__ */ jsx(DeleteAccountDialog, {
|
|
19
|
+
hasPassword,
|
|
20
|
+
onDelete,
|
|
21
|
+
onClose: () => setConfirming(false)
|
|
22
|
+
})]
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
export { DeleteAccountSection };
|
package/dist/account/messages.js
CHANGED
|
@@ -153,7 +153,16 @@ const text = defineMessages({
|
|
|
153
153
|
mcpAddress: "MCP address",
|
|
154
154
|
mcpAddressDescription: "Add this address to an AI assistant or code editor that speaks MCP, as a custom connector or remote MCP server. It opens this app in your browser, where you sign in and allow it; it then works with your access.",
|
|
155
155
|
copyMcpAddress: "Copy the MCP address",
|
|
156
|
-
addToClaude: "Add to Claude"
|
|
156
|
+
addToClaude: "Add to Claude",
|
|
157
|
+
deleteAccount: "Delete account",
|
|
158
|
+
deleteAccountDescription: "Delete your account and sign out everywhere. You can no longer sign in with it, and this cannot be undone.",
|
|
159
|
+
deleteAccountStaff: "Staff signed in as someone cannot delete their account.",
|
|
160
|
+
deleteAccountQuestion: "Delete your account?",
|
|
161
|
+
deleteAccountWarning: "Your account, its sign-in methods and every device signed in to it are deleted. This cannot be undone.",
|
|
162
|
+
deleteAccountPassword: "Enter your password to confirm.",
|
|
163
|
+
deleteAccountConfirm: "Delete my account",
|
|
164
|
+
deleteAccountLastAdmin: "You are the last admin of this app. Make someone else an admin first.",
|
|
165
|
+
deleteAccountLocked: "This account is locked, so it cannot be deleted."
|
|
157
166
|
},
|
|
158
167
|
nl: {
|
|
159
168
|
account: "Account",
|
|
@@ -307,7 +316,16 @@ const text = defineMessages({
|
|
|
307
316
|
mcpAddress: "MCP-adres",
|
|
308
317
|
mcpAddressDescription: "Voeg dit adres toe aan een AI-assistent of code-editor die MCP spreekt, als aangepaste connector of externe MCP-server. Die opent deze app in je browser, waar je inlogt en hem toestaat; daarna werkt hij met jouw toegang.",
|
|
309
318
|
copyMcpAddress: "Het MCP-adres kopiëren",
|
|
310
|
-
addToClaude: "Toevoegen aan Claude"
|
|
319
|
+
addToClaude: "Toevoegen aan Claude",
|
|
320
|
+
deleteAccount: "Account verwijderen",
|
|
321
|
+
deleteAccountDescription: "Verwijder je account en log overal uit. Je kunt er daarna niet meer mee inloggen, en dit kan niet ongedaan worden gemaakt.",
|
|
322
|
+
deleteAccountStaff: "Een medewerker die als iemand anders is ingelogd, kan diens account niet verwijderen.",
|
|
323
|
+
deleteAccountQuestion: "Je account verwijderen?",
|
|
324
|
+
deleteAccountWarning: "Je account, je inlogmethoden en elk apparaat dat ermee is ingelogd worden verwijderd. Dit kan niet ongedaan worden gemaakt.",
|
|
325
|
+
deleteAccountPassword: "Vul je wachtwoord in om te bevestigen.",
|
|
326
|
+
deleteAccountConfirm: "Mijn account verwijderen",
|
|
327
|
+
deleteAccountLastAdmin: "Je bent de laatste beheerder van deze app. Maak eerst iemand anders beheerder.",
|
|
328
|
+
deleteAccountLocked: "Dit account is vergrendeld en kan dus niet worden verwijderd."
|
|
311
329
|
}
|
|
312
330
|
});
|
|
313
331
|
//#endregion
|
|
@@ -24,6 +24,7 @@ import { TabBlock, TabsBlock } from "./blocks/tabs.js";
|
|
|
24
24
|
import { UsersBlock } from "../../users/users-block.js";
|
|
25
25
|
import { ConnectedAccountsBlock } from "../../account/blocks/connected-accounts-block.js";
|
|
26
26
|
import { ConnectedAppsBlock } from "../../account/blocks/connected-apps-block.js";
|
|
27
|
+
import { DeleteAccountBlock } from "../../account/blocks/delete-account-block.js";
|
|
27
28
|
import { DevicesBlock } from "../../account/blocks/devices-block.js";
|
|
28
29
|
import { PasskeysBlock } from "../../account/blocks/passkeys-block.js";
|
|
29
30
|
import { PasswordBlock } from "../../account/blocks/password-block.js";
|
|
@@ -61,7 +62,8 @@ const blocks = {
|
|
|
61
62
|
TwoFactor: TwoFactorBlock,
|
|
62
63
|
ConnectedAccounts: ConnectedAccountsBlock,
|
|
63
64
|
Devices: DevicesBlock,
|
|
64
|
-
ConnectedApps: ConnectedAppsBlock
|
|
65
|
+
ConnectedApps: ConnectedAppsBlock,
|
|
66
|
+
DeleteAccount: DeleteAccountBlock
|
|
65
67
|
};
|
|
66
68
|
const isInline = (child) => typeof child === "string" || !child.custom && child.type === "Link";
|
|
67
69
|
/** Text and links run together as one paragraph, like a sentence with a link in it; other elements stand alone. */
|
|
@@ -100,6 +100,7 @@ const messages = {
|
|
|
100
100
|
PREVIOUSLY_REGISTERED: "passkeyAdded",
|
|
101
101
|
ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED: "passkeyAdded",
|
|
102
102
|
SESSION_NOT_FRESH: "notFresh",
|
|
103
|
+
SESSION_EXPIRED: "notFresh",
|
|
103
104
|
PASSWORD_COMPROMISED: "passwordLeaked"
|
|
104
105
|
};
|
|
105
106
|
const lookup = (ids, code) => {
|
|
@@ -25,6 +25,7 @@ const AuthProvider = ({ session: given, origin, nativeBridge, children }) => {
|
|
|
25
25
|
const [signInFirst, setSignInFirst] = useState("password");
|
|
26
26
|
const [passwordReset, setPasswordReset] = useState(false);
|
|
27
27
|
const [changeEmail, setChangeEmail] = useState(false);
|
|
28
|
+
const [accountDeletion, setAccountDeletion] = useState(false);
|
|
28
29
|
const [mcp, setMcp] = useState();
|
|
29
30
|
const [canSignUp, setCanSignUp] = useState(false);
|
|
30
31
|
const [passkeyDomains, setPasskeyDomains] = useState([]);
|
|
@@ -110,6 +111,7 @@ const AuthProvider = ({ session: given, origin, nativeBridge, children }) => {
|
|
|
110
111
|
setSignInFirst(status.signInFirst ?? "password");
|
|
111
112
|
setPasswordReset(status.passwordReset && !nativeBridge);
|
|
112
113
|
setChangeEmail(Boolean(status.changeEmail));
|
|
114
|
+
setAccountDeletion(Boolean(status.accountDeletion));
|
|
113
115
|
setMcp(status.mcp);
|
|
114
116
|
setCanSignUp(Boolean(status.signUp));
|
|
115
117
|
setPasskeyDomains(status.passkeyDomains ?? []);
|
|
@@ -141,6 +143,7 @@ const AuthProvider = ({ session: given, origin, nativeBridge, children }) => {
|
|
|
141
143
|
signInFirst,
|
|
142
144
|
passwordReset,
|
|
143
145
|
changeEmail,
|
|
146
|
+
accountDeletion,
|
|
144
147
|
mcp,
|
|
145
148
|
canSignUp,
|
|
146
149
|
passkeyDomains,
|
|
@@ -190,6 +193,11 @@ const AuthProvider = ({ session: given, origin, nativeBridge, children }) => {
|
|
|
190
193
|
await session.signOut();
|
|
191
194
|
setState(signedOutState());
|
|
192
195
|
},
|
|
196
|
+
deleteAccount: async (password) => {
|
|
197
|
+
await session.deleteAccount(password);
|
|
198
|
+
await push.forget();
|
|
199
|
+
setState(signedOutState());
|
|
200
|
+
},
|
|
193
201
|
push
|
|
194
202
|
}), [
|
|
195
203
|
push,
|
|
@@ -199,6 +207,7 @@ const AuthProvider = ({ session: given, origin, nativeBridge, children }) => {
|
|
|
199
207
|
signInFirst,
|
|
200
208
|
passwordReset,
|
|
201
209
|
changeEmail,
|
|
210
|
+
accountDeletion,
|
|
202
211
|
mcp,
|
|
203
212
|
canSignUp,
|
|
204
213
|
passkeyDomains,
|
package/dist/package.js
CHANGED