From 0695adec71923bc7e978bd7086cae81abb639f74 Mon Sep 17 00:00:00 2001
From: ChaotiCryptidz
Date: Fri, 21 Jan 2022 21:56:09 +0000
Subject: [PATCH] remove setErrorText and replace it with proper error text &
notifs
---
src/pageUtils.ts | 20 ------
src/ui/elements/ErrorMessage.tsx | 63 ++++++++++++++++
src/ui/pages/Access/AccessHome.tsx | 8 +--
src/ui/pages/Access/Auth/AuthHome.tsx | 13 ++--
src/ui/pages/Access/Auth/AuthViewConfig.tsx | 15 +++-
.../Auth/userpass/UserPassUserDelete.tsx | 20 +++++-
.../Access/Auth/userpass/UserPassUserEdit.tsx | 25 +++++--
.../Access/Auth/userpass/UserPassUserNew.tsx | 14 ++--
.../Access/Auth/userpass/UserPassUserView.tsx | 11 ++-
.../Auth/userpass/UserPassUsersList.tsx | 11 ++-
src/ui/pages/Home.tsx | 18 ++++-
src/ui/pages/Login.tsx | 2 +-
src/ui/pages/Login_Token.tsx | 25 +++++--
src/ui/pages/Login_Username.tsx | 16 ++++-
src/ui/pages/Me.tsx | 28 +++++---
src/ui/pages/Policies/PoliciesHome.tsx | 22 +++---
src/ui/pages/Policies/PolicyDelete.tsx | 33 ++++++---
src/ui/pages/Policies/PolicyEdit.tsx | 66 +++++++++--------
src/ui/pages/Policies/PolicyNew.tsx | 57 +++++++++------
src/ui/pages/Policies/PolicyView.tsx | 16 +++--
src/ui/pages/PwGen.tsx | 1 +
src/ui/pages/Secrets/DeleteSecretsEngine.tsx | 13 ++--
.../pages/Secrets/KeyValue/KeyValueDelete.tsx | 32 +++++++--
.../pages/Secrets/KeyValue/KeyValueEdit.tsx | 72 +++++++++++--------
.../pages/Secrets/KeyValue/KeyValueList.tsx | 36 ++++++----
src/ui/pages/Secrets/KeyValue/KeyValueNew.tsx | 60 +++++++++-------
.../Secrets/KeyValue/KeyValueVersions.tsx | 12 +++-
.../pages/Secrets/KeyValue/KeyValueView.tsx | 14 +++-
.../pages/Secrets/NewEngines/NewKVEngine.tsx | 14 ++--
.../Secrets/NewEngines/NewTOTPEngine.tsx | 14 ++--
.../Secrets/NewEngines/NewTransitEngine.tsx | 14 ++--
src/ui/pages/Secrets/SecretsHome.tsx | 22 +++---
src/ui/pages/Secrets/TOTP/TOTPDelete.tsx | 20 +++++-
src/ui/pages/Secrets/TOTP/TOTPList.tsx | 60 ++++++++--------
src/ui/pages/Secrets/TOTP/TOTPNew.tsx | 11 ++-
.../pages/Secrets/TOTP/TOTPNewGenerated.tsx | 9 ++-
.../pages/Secrets/Transit/TransitDecrypt.tsx | 15 ++--
.../pages/Secrets/Transit/TransitEncrypt.tsx | 14 ++--
src/ui/pages/Secrets/Transit/TransitList.tsx | 40 ++++++-----
src/ui/pages/Secrets/Transit/TransitNew.tsx | 18 +++--
.../pages/Secrets/Transit/TransitRewrap.tsx | 25 +++++--
src/ui/pages/Secrets/Transit/TransitView.tsx | 11 ++-
src/ui/pages/SetLanguage.tsx | 3 -
src/ui/pages/SetVaultURL.tsx | 2 +-
src/ui/pages/Unseal.tsx | 13 ++--
45 files changed, 695 insertions(+), 333 deletions(-)
create mode 100644 src/ui/elements/ErrorMessage.tsx
diff --git a/src/pageUtils.ts b/src/pageUtils.ts
index 4190924..fe4bfff 100644
--- a/src/pageUtils.ts
+++ b/src/pageUtils.ts
@@ -60,23 +60,3 @@ export function addClipboardNotifications(clipboard: ClipboardJS, timeout = 1000
);
});
}
-
-export function setErrorText(text: string): void {
- const errorTextElement = document.querySelector("#errorText");
- if (errorTextElement) {
- /* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
- const p = document.querySelector("#errorText") as HTMLParagraphElement;
- p.innerText = `Error: ${text}`;
- /* eslint-enable @typescript-eslint/no-unnecessary-type-assertion */
- }
- UIkit.notification({
- message: `Error: ${text}`,
- status: "danger",
- pos: "top-center",
- timeout: 2000,
- });
-}
-
-export function notImplemented(): void {
- setErrorText(i18next.t("not_implemented"));
-}
diff --git a/src/ui/elements/ErrorMessage.tsx b/src/ui/elements/ErrorMessage.tsx
new file mode 100644
index 0000000..9dc293a
--- /dev/null
+++ b/src/ui/elements/ErrorMessage.tsx
@@ -0,0 +1,63 @@
+import { Component, createRef } from "preact";
+import UIkit from "uikit";
+import i18next from "i18next";
+
+type ErrorMessageState = {
+ errorMessage: string;
+};
+
+// Use only when a error text element can't be used
+// e.g inside componentDidMount
+export function sendErrorNotification(errorMessage: string) {
+ UIkit.notification({
+ message: `Error: ${errorMessage}`,
+ status: "danger",
+ pos: "top-center",
+ timeout: 2000,
+ });
+}
+
+export function notImplementedNotification(): void {
+ sendErrorNotification(i18next.t("not_implemented"));
+}
+
+export class ErrorMessage extends Component {
+ public setErrorMessage(errorMessage: string) {
+ this.setState({
+ errorMessage: `Error: ${errorMessage}`,
+ });
+
+ sendErrorNotification(errorMessage);
+
+ // make browser focus on the change.
+ this.errorMessageRef.current.focus();
+ }
+
+ public clear() {
+ this.setState({ errorMessage: "" });
+ }
+
+ errorMessageRef = createRef();
+
+ render() {
+ return (
+
+ {this.state.errorMessage || ""}
+
+ );
+ }
+}
diff --git a/src/ui/pages/Access/AccessHome.tsx b/src/ui/pages/Access/AccessHome.tsx
index 8a8c5b3..c055e27 100644
--- a/src/ui/pages/Access/AccessHome.tsx
+++ b/src/ui/pages/Access/AccessHome.tsx
@@ -3,7 +3,7 @@ import { DefaultPageProps } from "../../../types/DefaultPageProps";
import { Grid, GridSizes } from "../../elements/Grid";
import { PageTitle } from "../../elements/PageTitle";
import { Tile } from "../../elements/Tile";
-import { notImplemented } from "../../../pageUtils";
+import { notImplementedNotification } from "../../elements/ErrorMessage";
import { route } from "preact-router";
import i18next from "i18next";
@@ -23,19 +23,19 @@ export class AccessHomePage extends Component {
title={i18next.t("access_entities_title")}
description={i18next.t("access_entities_description")}
icon="user"
- onclick={async () => notImplemented()}
+ onclick={async () => notImplementedNotification()}
/>
notImplemented()}
+ onclick={async () => notImplementedNotification()}
/>
notImplemented()}
+ onclick={async () => notImplementedNotification()}
/>
>
diff --git a/src/ui/pages/Access/Auth/AuthHome.tsx b/src/ui/pages/Access/Auth/AuthHome.tsx
index bcb3954..e3b2453 100644
--- a/src/ui/pages/Access/Auth/AuthHome.tsx
+++ b/src/ui/pages/Access/Auth/AuthHome.tsx
@@ -4,7 +4,7 @@ import { Component, JSX } from "preact";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
import { PageTitle } from "../../../elements/PageTitle";
import { authViewConfigURL, userPassUserListURL } from "../../pageLinks";
-import { notImplemented } from "../../../../pageUtils";
+import { notImplementedNotification, sendErrorNotification } from "../../../elements/ErrorMessage";
import { objectToMap } from "../../../../utils";
import { route } from "preact-router";
import i18next from "i18next";
@@ -46,7 +46,7 @@ export function AuthListElement(props: AuthListElementProps): JSX.Element {
@@ -55,8 +55,13 @@ export function AuthListElement(props: AuthListElementProps): JSX.Element {
export class AuthHome extends Component }> {
async componentDidMount() {
- const authList = objectToMap(await this.props.api.listAuth()) as Map;
- this.setState({ authList });
+ try {
+ const authList = objectToMap(await this.props.api.listAuth()) as Map;
+ this.setState({ authList });
+ } catch (e: unknown) {
+ const error = e as Error;
+ sendErrorNotification(error.message);
+ }
}
render() {
if (!this.state.authList) return;
diff --git a/src/ui/pages/Access/Auth/AuthViewConfig.tsx b/src/ui/pages/Access/Auth/AuthViewConfig.tsx
index a8c7c84..f9f57cf 100644
--- a/src/ui/pages/Access/Auth/AuthViewConfig.tsx
+++ b/src/ui/pages/Access/Auth/AuthViewConfig.tsx
@@ -4,18 +4,27 @@ import { DefaultPageProps } from "../../../../types/DefaultPageProps";
import { HeaderAndContent } from "../../../elements/HeaderAndContent";
import { PageTitle } from "../../../elements/PageTitle";
import { objectToMap, toStr } from "../../../../utils";
+import { sendErrorNotification } from "../../../elements/ErrorMessage";
import i18next from "i18next";
export class AuthViewConfig extends Component {
async componentDidMount() {
const baseMount = this.props.matches["baseMount"];
- const authList = objectToMap(await this.props.api.listAuth()) as Map;
- const authMethod = authList.get(baseMount + "/");
- this.setState({ authMethod: authMethod });
+ try {
+ const authList = objectToMap(await this.props.api.listAuth()) as Map;
+ const authMethod = authList.get(baseMount + "/");
+ this.setState({ authMethod: authMethod });
+ } catch (e: unknown) {
+ const error = e as Error;
+ sendErrorNotification(error.message);
+ }
}
+
render() {
if (!this.state.authMethod) return;
+
const baseMount = this.props.matches["baseMount"];
+
const authMethod = this.state.authMethod;
return (
diff --git a/src/ui/pages/Access/Auth/userpass/UserPassUserDelete.tsx b/src/ui/pages/Access/Auth/userpass/UserPassUserDelete.tsx
index f55e83c..96f5577 100644
--- a/src/ui/pages/Access/Auth/userpass/UserPassUserDelete.tsx
+++ b/src/ui/pages/Access/Auth/userpass/UserPassUserDelete.tsx
@@ -1,12 +1,16 @@
import { Button } from "../../../../elements/Button";
-import { Component } from "preact";
+import { Component, createRef } from "preact";
import { DefaultPageProps } from "../../../../../types/DefaultPageProps";
+import { ErrorMessage } from "../../../../elements/ErrorMessage";
+import { Margin } from "../../../../elements/Margin";
import { PageTitle } from "../../../../elements/PageTitle";
import { route } from "preact-router";
import { userPassUserListURL } from "../../../pageLinks";
import i18next from "i18next";
export class UserPassUserDelete extends Component {
+ errorMessageRef = createRef();
+
render() {
const baseMount = this.props.matches["baseMount"];
const user = this.props.matches["user"];
@@ -16,12 +20,22 @@ export class UserPassUserDelete extends Component {
{i18next.t("userpass_user_delete_text")}
+
+
+
+
+
diff --git a/src/ui/pages/Access/Auth/userpass/UserPassUserEdit.tsx b/src/ui/pages/Access/Auth/userpass/UserPassUserEdit.tsx
index afbc669..5b0eb32 100644
--- a/src/ui/pages/Access/Auth/userpass/UserPassUserEdit.tsx
+++ b/src/ui/pages/Access/Auth/userpass/UserPassUserEdit.tsx
@@ -1,6 +1,7 @@
import { Button } from "../../../../elements/Button";
-import { Component } from "preact";
+import { Component, createRef } from "preact";
import { DefaultPageProps } from "../../../../../types/DefaultPageProps";
+import { ErrorMessage, sendErrorNotification } from "../../../../elements/ErrorMessage";
import { Form } from "../../../../elements/Form";
import { InputWithTitle } from "../../../../elements/InputWithTitle";
import { Margin } from "../../../../elements/Margin";
@@ -8,7 +9,6 @@ import { MarginInline } from "../../../../elements/MarginInline";
import { PageTitle } from "../../../../elements/PageTitle";
import { UserType } from "../../../../../api/types/user";
import { route } from "preact-router";
-import { setErrorText } from "../../../../../pageUtils";
import { toStr } from "../../../../../utils";
import { userPassUserViewURL } from "../../../pageLinks";
import i18next from "i18next";
@@ -16,12 +16,19 @@ import i18next from "i18next";
const removeEmptyStrings = (arr: string[]) => arr.filter((e) => e.length > 0);
export class UserPassUserEdit extends Component {
+ errorMessageRef = createRef();
+
async componentDidMount() {
const baseMount = this.props.matches["baseMount"];
const user = this.props.matches["user"];
- const user_data = await this.props.api.getUserPassUser(baseMount, user);
- this.setState({ user_data });
+ try {
+ const user_data = await this.props.api.getUserPassUser(baseMount, user);
+ this.setState({ user_data });
+ } catch (e: unknown) {
+ const error = e as Error;
+ sendErrorNotification(error.message);
+ }
}
render() {
@@ -111,7 +118,11 @@ export class UserPassUserEdit extends Component
-
+
+
+
+
+
@@ -134,7 +145,9 @@ export class UserPassUserEdit extends Component 0) {
apiData.password = password;
}
@@ -144,7 +157,7 @@ export class UserPassUserEdit extends Component {
+ errorMessageRef = createRef();
+
render() {
return (
<>
@@ -33,7 +35,11 @@ export class UserPassUserNew extends Component {
placeholder={i18next.t("common_password")}
/>
-
+
+
+
+
+
@@ -56,7 +62,7 @@ export class UserPassUserNew extends Component {
route(userPassUserViewURL(baseMount, data.get("username") as string));
} catch (e: unknown) {
const error = e as Error;
- setErrorText(error.message);
+ this.errorMessageRef.current.setErrorMessage(error.message);
}
}
}
diff --git a/src/ui/pages/Access/Auth/userpass/UserPassUserView.tsx b/src/ui/pages/Access/Auth/userpass/UserPassUserView.tsx
index 2ac6ee8..1b9c0b5 100644
--- a/src/ui/pages/Access/Auth/userpass/UserPassUserView.tsx
+++ b/src/ui/pages/Access/Auth/userpass/UserPassUserView.tsx
@@ -5,6 +5,7 @@ import { HeaderAndContent } from "../../../../elements/HeaderAndContent";
import { Margin } from "../../../../elements/Margin";
import { PageTitle } from "../../../../elements/PageTitle";
import { UserType } from "../../../../../api/types/user";
+import { sendErrorNotification } from "../../../../elements/ErrorMessage";
import { toStr } from "../../../../../utils";
import { userPassUserDeleteURL, userPassUserEditURL } from "../../../pageLinks";
import i18next from "i18next";
@@ -14,14 +15,20 @@ export class UserPassUserView extends Component {
async componentDidMount() {
const baseMount = this.props.matches["baseMount"];
- const users = await this.props.api.listUserPassUsers(baseMount);
- this.setState({ users });
+
+ try {
+ const users = await this.props.api.listUserPassUsers(baseMount);
+ this.setState({ users });
+ } catch (e: unknown) {
+ const error = e as Error;
+ sendErrorNotification(error.message);
+ }
}
render() {
diff --git a/src/ui/pages/Home.tsx b/src/ui/pages/Home.tsx
index beb9c1e..d69d2c5 100644
--- a/src/ui/pages/Home.tsx
+++ b/src/ui/pages/Home.tsx
@@ -5,8 +5,9 @@ import { Margin } from "../elements/Margin";
import { PageTitle } from "../elements/PageTitle";
import { Tile } from "../elements/Tile";
import { TokenInfo } from "../../api/types/token";
-import { pageChecks, setErrorText } from "../../pageUtils";
+import { pageChecks } from "../../pageUtils";
import { route } from "preact-router";
+import { sendErrorNotification } from "../elements/ErrorMessage";
import i18next from "i18next";
type HomeState = {
@@ -17,18 +18,31 @@ type HomeState = {
export class Home extends Component {
async componentDidMount() {
+ // Always call pageChecks on /home
if (await pageChecks("/home", this.props.api, this.props.settings)) return;
+ try {
+ await this.populateState();
+ } catch (e: unknown) {
+ const error = e as Error;
+ sendErrorNotification(error.message);
+ }
+ }
+
+ async populateState() {
+ // Check if logged in otherise redirect to /login
let selfTokenInfo: TokenInfo;
try {
selfTokenInfo = await this.props.api.lookupSelf();
} catch (e: unknown) {
const error = e as Error;
- setErrorText(error.message);
+
if (error.message == "permission denied") {
this.props.settings.token = "";
route("/login", true);
return;
+ } else {
+ throw error;
}
}
diff --git a/src/ui/pages/Login.tsx b/src/ui/pages/Login.tsx
index c9a6acd..2d6ad68 100644
--- a/src/ui/pages/Login.tsx
+++ b/src/ui/pages/Login.tsx
@@ -19,7 +19,7 @@ export class Login extends Component {
{i18next.t("log_in_with_username")}
-
+
-
diff --git a/src/ui/pages/Login_Token.tsx b/src/ui/pages/Login_Token.tsx
index 8919c7d..9d992f5 100644
--- a/src/ui/pages/Login_Token.tsx
+++ b/src/ui/pages/Login_Token.tsx
@@ -1,14 +1,16 @@
import { Button } from "../elements/Button";
-import { Component, JSX } from "preact";
+import { Component, JSX, createRef } from "preact";
import { DefaultPageProps } from "../../types/DefaultPageProps";
+import { ErrorMessage } from "../elements/ErrorMessage";
import { Form } from "../elements/Form";
import { Margin } from "../elements/Margin";
import { MarginInline } from "../elements/MarginInline";
import { route } from "preact-router";
-import { setErrorText } from "../../pageUtils";
import i18next from "i18next";
export class TokenLoginForm extends Component {
+ errorMessageRef = createRef();
+
render(): JSX.Element {
return (
;
@@ -73,13 +76,18 @@ export class PolicyEditor extends Component
-
+
+
+
+
this.onCodeUpdate(code)}
+ onUpdate={(code) => {
+ this.setState({ code: code });
+ }}
/>
@@ -101,11 +109,7 @@ export class PolicyEdit extends Component {
<>
>
);
diff --git a/src/ui/pages/Policies/PolicyNew.tsx b/src/ui/pages/Policies/PolicyNew.tsx
index 5b73d38..85fb3c4 100644
--- a/src/ui/pages/Policies/PolicyNew.tsx
+++ b/src/ui/pages/Policies/PolicyNew.tsx
@@ -1,37 +1,50 @@
import { Button } from "../../elements/Button";
-import { Component } from "preact";
+import { Component, createRef } from "preact";
import { DefaultPageProps } from "../../../types/DefaultPageProps";
+import { ErrorMessage } from "../../elements/ErrorMessage";
import { Form } from "../../elements/Form";
import { Margin } from "../../elements/Margin";
import { PageTitle } from "../../elements/PageTitle";
import { policyViewURL } from "../pageLinks";
import { route } from "preact-router";
-import { setErrorText } from "../../../pageUtils";
import i18next from "i18next";
export class PolicyNew extends Component {
+ errorMessageRef = createRef();
+
+ async onFormSubmit(formData: FormData) {
+ const name = formData.get("name") as string;
+
+ let policies: string[] = [];
+
+ try {
+ policies = await this.props.api.getPolicies();
+ } catch (e: unknown) {
+ const error = e as Error;
+ this.errorMessageRef.current.setErrorMessage(error.message);
+ return;
+ }
+
+ if (policies.includes(name)) {
+ this.errorMessageRef.current.setErrorMessage(i18next.t("policy_new_already_exists"));
+ return;
+ }
+
+ try {
+ await this.props.api.createOrUpdatePolicy(name, " ");
+ route(policyViewURL(name));
+ } catch (e: unknown) {
+ const error = e as Error;
+ this.errorMessageRef.current.setErrorMessage(error.message);
+ }
+ }
+
render() {
return (
<>
diff --git a/src/ui/pages/Policies/PolicyView.tsx b/src/ui/pages/Policies/PolicyView.tsx
index f84af39..2ce6382 100644
--- a/src/ui/pages/Policies/PolicyView.tsx
+++ b/src/ui/pages/Policies/PolicyView.tsx
@@ -5,6 +5,7 @@ import { DefaultPageProps } from "../../../types/DefaultPageProps";
import { Margin } from "../../elements/Margin";
import { PageTitle } from "../../elements/PageTitle";
import { policyDeleteURL, policyEditURL } from "../pageLinks";
+import { sendErrorNotification } from "../../elements/ErrorMessage";
import i18next from "i18next";
export class PolicyView extends Component<
@@ -13,11 +14,16 @@ export class PolicyView extends Component<
> {
async componentDidMount() {
const policyName = this.props.matches["policyName"];
- const policy = await this.props.api.getPolicy(policyName);
- this.setState({
- policy,
- policyName,
- });
+ try {
+ const policy = await this.props.api.getPolicy(policyName);
+ this.setState({
+ policy,
+ policyName,
+ });
+ } catch (e: unknown) {
+ const error = e as Error;
+ sendErrorNotification(error.message);
+ }
}
render() {
diff --git a/src/ui/pages/PwGen.tsx b/src/ui/pages/PwGen.tsx
index 0b2dd62..c8ad994 100644
--- a/src/ui/pages/PwGen.tsx
+++ b/src/ui/pages/PwGen.tsx
@@ -61,6 +61,7 @@ export class PasswordGenerator extends Component();
alphabetSelector = createRef();
diff --git a/src/ui/pages/Secrets/DeleteSecretsEngine.tsx b/src/ui/pages/Secrets/DeleteSecretsEngine.tsx
index 0987a73..21f8162 100644
--- a/src/ui/pages/Secrets/DeleteSecretsEngine.tsx
+++ b/src/ui/pages/Secrets/DeleteSecretsEngine.tsx
@@ -1,14 +1,17 @@
import { Button } from "../../elements/Button";
-import { Component } from "preact";
+import { Component, createRef } from "preact";
import { DefaultPageProps } from "../../../types/DefaultPageProps";
+import { ErrorMessage } from "../../elements/ErrorMessage";
import { Form } from "../../elements/Form";
+import { Margin } from "../../elements/Margin";
import { MarginInline } from "../../elements/MarginInline";
import { PageTitle } from "../../elements/PageTitle";
import { route } from "preact-router";
-import { setErrorText } from "../../../pageUtils";
import i18next from "i18next";
export class DeleteSecretsEngine extends Component {
+ errorMessageRef = createRef();
+
render() {
return (
<>
@@ -22,7 +25,9 @@ export class DeleteSecretsEngine extends Component {
>
{i18next.t("delete_secrets_engine_message")}
-
+
+
+
@@ -38,7 +43,7 @@ export class DeleteSecretsEngine extends Component {
route("/secrets");
} catch (e: unknown) {
const error = e as Error;
- setErrorText(error.message);
+ this.errorMessageRef.current.setErrorMessage(error.message);
}
}
}
diff --git a/src/ui/pages/Secrets/KeyValue/KeyValueDelete.tsx b/src/ui/pages/Secrets/KeyValue/KeyValueDelete.tsx
index d8ca957..248d761 100644
--- a/src/ui/pages/Secrets/KeyValue/KeyValueDelete.tsx
+++ b/src/ui/pages/Secrets/KeyValue/KeyValueDelete.tsx
@@ -1,13 +1,17 @@
import { Button } from "../../../elements/Button";
-import { Component } from "preact";
+import { Component, createRef } from "preact";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
+import { ErrorMessage } from "../../../elements/ErrorMessage";
+import { Margin } from "../../../elements/Margin";
import { SecretTitleElement } from "../SecretTitleElement";
import { kvListURL, kvViewURL } from "../../pageLinks";
import { route } from "preact-router";
import i18next from "i18next";
export class KeyValueDelete extends Component {
- render() {
+ errorMessageRef = createRef();
+
+ async onDelete() {
const baseMount = this.props.matches["baseMount"];
const secretPath = this.props.matches["secretPath"].split("/");
const item = this.props.matches["item"];
@@ -20,6 +24,20 @@ export class KeyValueDelete extends Component {
? kvListURL(baseMount, secretPath)
: kvViewURL(baseMount, secretPath, item, "null");
+ try {
+ await this.props.api.deleteSecret(baseMount, secretPath, item, version);
+ route(buttonRoute);
+ } catch (e: unknown) {
+ const error = e as Error;
+ this.errorMessageRef.current.setErrorMessage(error.message);
+ }
+ }
+
+ render() {
+ const baseMount = this.props.matches["baseMount"];
+ const secretPath = this.props.matches["secretPath"].split("/");
+ const item = this.props.matches["item"];
+
return (
<>
{
/>
{i18next.t("kv_delete_text")}
+
+
+
+
+
>
diff --git a/src/ui/pages/Secrets/KeyValue/KeyValueEdit.tsx b/src/ui/pages/Secrets/KeyValue/KeyValueEdit.tsx
index 4b95a89..4e23b32 100644
--- a/src/ui/pages/Secrets/KeyValue/KeyValueEdit.tsx
+++ b/src/ui/pages/Secrets/KeyValue/KeyValueEdit.tsx
@@ -2,7 +2,9 @@ import { Button } from "../../../elements/Button";
import { CodeEditor } from "../../../elements/CodeEditor";
import { Component, JSX, createRef } from "preact";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
+import { ErrorMessage, sendErrorNotification } from "../../../elements/ErrorMessage";
import { InputWithTitle } from "../../../elements/InputWithTitle";
+import { Margin } from "../../../elements/Margin";
import { SecretTitleElement } from "../SecretTitleElement";
import {
SupportedLanguages,
@@ -10,7 +12,6 @@ import {
parseData,
toPrismCode,
} from "../../../../utils/dataInterchange";
-import { setErrorText } from "../../../../pageUtils";
import { sortedObjectMap } from "../../../../utils";
import i18next from "i18next";
@@ -41,30 +42,18 @@ export class KVEditor extends Component {
};
}
- async editorSave(): Promise {
- if (!this.state.dataLoaded) return;
- const editorContent = this.state.code;
+ errorMessageRef = createRef();
- try {
- parseData(editorContent, this.state.syntax);
- } catch {
- setErrorText(i18next.t("kv_sec_edit_invalid_data_err"));
- return;
+ async componentDidMount() {
+ this.setState({ syntax: this.props.settings.kvEditorDefaultLanguage });
+ if (!this.state.dataLoaded) {
+ try {
+ await this.loadData();
+ } catch (e: unknown) {
+ const error = e as Error;
+ sendErrorNotification(error.message);
+ }
}
-
- await this.props.api.createOrUpdateSecret(
- this.props.baseMount,
- this.props.secretPath.map((e) => e + "/"),
- this.props.secretItem,
- parseData(editorContent, this.state.syntax),
- );
- window.history.back();
- }
-
- onCodeUpdate(code: string): void {
- this.setState({
- code: code,
- });
}
async loadData() {
@@ -80,10 +69,28 @@ export class KVEditor extends Component {
});
}
- async componentDidMount() {
- this.setState({ syntax: this.props.settings.kvEditorDefaultLanguage });
- if (!this.state.dataLoaded) {
- await this.loadData();
+ async editorSave(): Promise {
+ if (!this.state.dataLoaded) return;
+ const editorContent = this.state.code;
+
+ try {
+ parseData(editorContent, this.state.syntax);
+ } catch {
+ this.errorMessageRef.current.setErrorMessage(i18next.t("kv_sec_edit_invalid_data_err"));
+ return;
+ }
+
+ try {
+ await this.props.api.createOrUpdateSecret(
+ this.props.baseMount,
+ this.props.secretPath.map((e) => e + "/"),
+ this.props.secretItem,
+ parseData(editorContent, this.state.syntax),
+ );
+ window.history.back();
+ } catch (e: unknown) {
+ const error = e as Error;
+ this.errorMessageRef.current.setErrorMessage(error.message);
}
}
@@ -123,13 +130,20 @@ export class KVEditor extends Component {
})}
-
+
+
+
+
+
this.onCodeUpdate(code)}
+ onUpdate={(code) => {
+ this.setState({ code });
+ }}
/>
+
-
+
+
+
diff --git a/src/ui/pages/Secrets/TOTP/TOTPNewGenerated.tsx b/src/ui/pages/Secrets/TOTP/TOTPNewGenerated.tsx
index 2111a98..0b9f7de 100644
--- a/src/ui/pages/Secrets/TOTP/TOTPNewGenerated.tsx
+++ b/src/ui/pages/Secrets/TOTP/TOTPNewGenerated.tsx
@@ -2,6 +2,7 @@ import { Button } from "../../../elements/Button";
import { Component, JSX, createRef } from "preact";
import { CopyableInputBox } from "../../../elements/CopyableInputBox";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
+import { ErrorMessage } from "../../../elements/ErrorMessage";
import { Form } from "../../../elements/Form";
import { InputWithTitle } from "../../../elements/InputWithTitle";
import { Margin } from "../../../elements/Margin";
@@ -9,7 +10,6 @@ import { MarginInline } from "../../../elements/MarginInline";
import { NewTOTPResp } from "../../../../api/types/totp";
import { SecretTitleElement } from "../SecretTitleElement";
import { route } from "preact-router";
-import { setErrorText } from "../../../../pageUtils";
import { totpListURL } from "../../pageLinks";
import i18next from "i18next";
@@ -17,6 +17,7 @@ export class TOTPNewGeneratedForm extends Component<
{ baseMount: string } & DefaultPageProps,
{ exportedData: NewTOTPResp }
> {
+ errorMessageRef = createRef();
uriInputRef = createRef();
render(): JSX.Element {
@@ -93,7 +94,9 @@ export class TOTPNewGeneratedForm extends Component<
-
+
+
+
@@ -140,7 +143,7 @@ export class TOTPNewGeneratedForm extends Component<
}
} catch (e: unknown) {
const error = e as Error;
- setErrorText(`API Error: ${error.message}`);
+ this.errorMessageRef.current.setErrorMessage(error.message);
}
}
}
diff --git a/src/ui/pages/Secrets/Transit/TransitDecrypt.tsx b/src/ui/pages/Secrets/Transit/TransitDecrypt.tsx
index 38548c7..e6767ce 100644
--- a/src/ui/pages/Secrets/Transit/TransitDecrypt.tsx
+++ b/src/ui/pages/Secrets/Transit/TransitDecrypt.tsx
@@ -1,17 +1,19 @@
import { Button } from "../../../elements/Button";
-import { Component } from "preact";
+import { Component, createRef } from "preact";
import { CopyableBox } from "../../../elements/CopyableBox";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
+import { ErrorMessage } from "../../../elements/ErrorMessage";
import { FileUploadInput } from "../../../elements/FileUploadInput";
import { Form } from "../../../elements/Form";
import { InputWithTitle } from "../../../elements/InputWithTitle";
import { Margin } from "../../../elements/Margin";
import { SecretTitleElement } from "../SecretTitleElement";
import { fileToBase64 } from "../../../../htmlUtils";
-import { setErrorText } from "../../../../pageUtils";
import i18next from "i18next";
export class TransitDecrypt extends Component {
+ errorMessageRef = createRef();
+
render() {
const baseMount = this.props.matches["baseMount"];
const secretItem = this.props.matches["secretItem"];
@@ -43,7 +45,11 @@ export class TransitDecrypt extends Component
-
+
+
+
+
+
>
@@ -74,6 +80,7 @@ export class TransitDecrypt extends Component 0) {
+ // TODO: please stop using atob
ciphertext = atob(
(await fileToBase64(ciphertext_file)).replace("data:text/plain;base64,", ""),
);
@@ -92,7 +99,7 @@ export class TransitDecrypt extends Component {
+ errorMessageRef = createRef();
+
render() {
const baseMount = this.props.matches["baseMount"];
const secretItem = this.props.matches["secretItem"];
@@ -43,7 +45,11 @@ export class TransitEncrypt extends Component
-
+
+
+
+
+
>
@@ -87,7 +93,7 @@ export class TransitEncrypt extends Component {
- this.setState({
- contentLoaded: true,
- transitKeysList: keys,
- });
- })
- .catch((_) => {
- this.setState({
- contentLoaded: true,
- transitKeysList: [],
- });
- });
+ async getTransitKeys() {
+ const transitKeys = await this.props.api.getTransitKeys(this.props.baseMount);
+ this.setState({
+ contentLoaded: true,
+ transitKeysList: transitKeys,
+ });
}
- componentDidMount(): void {
- this.getTransitKeys();
+ async componentDidMount() {
+ try {
+ await this.getTransitKeys();
+ } catch (e: unknown) {
+ const error = e as Error;
+ sendErrorNotification(error.message);
+ }
}
render(): JSX.Element {
@@ -79,8 +76,13 @@ export class TransitList extends Component {
- constructor() {
- super();
- }
+ errorMessageRef = createRef();
+
render() {
const baseMount = this.props.matches["baseMount"];
+
return (
<>
{
))}
-
+
+
+
+
+
@@ -80,7 +84,7 @@ export class TransitNew extends Component {
route(transitViewSecretURL(baseMount, name));
} catch (e) {
const error = e as Error;
- setErrorText(error.message);
+ this.errorMessageRef.current.setErrorMessage(error.message);
}
}
}
diff --git a/src/ui/pages/Secrets/Transit/TransitRewrap.tsx b/src/ui/pages/Secrets/Transit/TransitRewrap.tsx
index 40aece8..4584abf 100644
--- a/src/ui/pages/Secrets/Transit/TransitRewrap.tsx
+++ b/src/ui/pages/Secrets/Transit/TransitRewrap.tsx
@@ -1,13 +1,13 @@
import { Button } from "../../../elements/Button";
-import { Component } from "preact";
+import { Component, createRef } from "preact";
import { CopyableBox } from "../../../elements/CopyableBox";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
+import { ErrorMessage, sendErrorNotification } from "../../../elements/ErrorMessage";
import { Form } from "../../../elements/Form";
import { Margin } from "../../../elements/Margin";
import { SecretTitleElement } from "../SecretTitleElement";
import { TransitKeyType } from "../../../../api/types/transit";
import { objectToMap } from "../../../../utils";
-import { setErrorText } from "../../../../pageUtils";
import i18next from "i18next";
type versionOption = { version: string; label: string };
@@ -18,12 +18,19 @@ type TransitRewrapState = {
};
export class TransitRewrap extends Component {
+ errorMessageRef = createRef();
+
async componentDidMount() {
const baseMount = this.props.matches["baseMount"];
const secretItem = this.props.matches["secretItem"];
- this.setState({
- transitKey: await this.props.api.getTransitKey(baseMount, secretItem),
- });
+
+ try {
+ const transitKey = await this.props.api.getTransitKey(baseMount, secretItem);
+ this.setState({ transitKey });
+ } catch (e: unknown) {
+ const error = e as Error;
+ sendErrorNotification(error.message);
+ }
}
render() {
@@ -83,7 +90,11 @@ export class TransitRewrap extends Component
-
+
+
+
+
+
>
@@ -115,7 +126,7 @@ export class TransitRewrap extends Component {
- constructor() {
- super();
- }
render() {
return (
<>
diff --git a/src/ui/pages/SetVaultURL.tsx b/src/ui/pages/SetVaultURL.tsx
index 1527486..dde57ac 100644
--- a/src/ui/pages/SetVaultURL.tsx
+++ b/src/ui/pages/SetVaultURL.tsx
@@ -22,7 +22,7 @@ export class SetVaultURL extends Component {
required
/>
-
+
diff --git a/src/ui/pages/Unseal.tsx b/src/ui/pages/Unseal.tsx
index a299eb9..9a195cc 100644
--- a/src/ui/pages/Unseal.tsx
+++ b/src/ui/pages/Unseal.tsx
@@ -1,11 +1,12 @@
import { Button } from "../elements/Button";
-import { Component, JSX } from "preact";
+import { Component, JSX, createRef } from "preact";
import { DefaultPageProps } from "../../types/DefaultPageProps";
+import { ErrorMessage } from "../elements/ErrorMessage";
+import { Margin } from "../elements/Margin";
import { PageTitle } from "../elements/PageTitle";
import { UnsealForm } from "./Unseal_Form";
import { UnsealQR } from "./Unseal_QR";
import { route } from "preact-router";
-import { setErrorText } from "../../pageUtils";
import { toStr } from "../../utils";
import i18next from "i18next";
@@ -38,7 +39,7 @@ export class Unseal extends Component {
this.updateStateWithSealStatus();
} catch (e: unknown) {
const error = e as Error;
- setErrorText(error.message);
+ this.errorMessageRef.current.setErrorMessage(error.message);
}
}
@@ -66,6 +67,8 @@ export class Unseal extends Component {
this.setState({ timer: timer });
}
+ errorMessageRef = createRef();
+
render(): JSX.Element {
return (
<>
@@ -77,7 +80,9 @@ export class Unseal extends Component {
max={this.state.keys_needed}
/>
-
+
+
+
{i18next.t("unseal_keys_progress", {