From 1ccb432cbc44ce973942c09b089610a85f5a9fee Mon Sep 17 00:00:00 2001 From: Kitteh Date: Sat, 22 May 2021 15:40:03 +0100 Subject: [PATCH] Implement deleting of TOTP codes. Closes #2. --- src/allPages.ts | 2 ++ src/api/totp/deleteTOTP.ts | 15 +++++++++ src/pages/Secrets/TOTP/TOTPDelete.tsx | 45 +++++++++++++++++++++++++++ src/pages/Secrets/TOTP/TOTPView.tsx | 26 ++++++++++++++-- src/translations/en.js | 7 +++++ 5 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 src/api/totp/deleteTOTP.ts create mode 100644 src/pages/Secrets/TOTP/TOTPDelete.tsx diff --git a/src/allPages.ts b/src/allPages.ts index a5387c5..b24f3e4 100644 --- a/src/allPages.ts +++ b/src/allPages.ts @@ -26,6 +26,7 @@ import { PwGenPage } from "./pages/PwGen"; import { SecretsHomePage } from "./pages/Secrets/SecretsHome"; import { SetLanguagePage } from "./pages/SetLanguage"; import { SetVaultURLPage } from "./pages/SetVaultURL"; +import { TOTPDeletePage } from "./pages/Secrets/TOTP/TOTPDelete"; import { TOTPViewPage } from "./pages/Secrets/TOTP/TOTPView"; import { TransitDecryptPage } from "./pages/Secrets/Transit/TransitDecrypt"; import { TransitEncryptPage } from "./pages/Secrets/Transit/TransitEncrypt"; @@ -58,6 +59,7 @@ export const allPages: pagesList = { ME: new MePage(), TOTP: new TOTPViewPage(), NEW_TOTP: new NewTOTPPage(), + TOTP_DELETE: new TOTPDeletePage(), LOGIN: new LoginPage(), SET_VAULT_URL: new SetVaultURLPage(), UNSEAL: new UnsealPage(), diff --git a/src/api/totp/deleteTOTP.ts b/src/api/totp/deleteTOTP.ts new file mode 100644 index 0000000..ddfb685 --- /dev/null +++ b/src/api/totp/deleteTOTP.ts @@ -0,0 +1,15 @@ +import { appendAPIURL, getHeaders } from "../apiUtils"; + +export async function deleteTOTP(baseMount: string, name: string): Promise { + const request = new Request(appendAPIURL(`/v1/${baseMount}/keys/${name}`), { + method: "DELETE", + headers: getHeaders(), + }); + const resp = await fetch(request); + if (!resp.ok) { + const data = (await resp.json()) as { errors?: string[] }; + if ("errors" in data) { + throw new Error(data.errors[0]); + } + } +} diff --git a/src/pages/Secrets/TOTP/TOTPDelete.tsx b/src/pages/Secrets/TOTP/TOTPDelete.tsx new file mode 100644 index 0000000..7362466 --- /dev/null +++ b/src/pages/Secrets/TOTP/TOTPDelete.tsx @@ -0,0 +1,45 @@ +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../SecretTitleElement"; +import { deleteTOTP } from "../../../api/totp/deleteTOTP"; +import { render } from "preact"; +import i18next from "i18next"; + +export class TOTPDeletePage extends Page { + constructor() { + super(); + } + + async cleanup(): Promise { + this.state.secretItem = ""; + } + + async goBack(): Promise { + this.state.secretItem = ""; + await this.router.changePage("TOTP"); + } + async render(): Promise { + render( +
+
{i18next.t("totp_delete_text")}
+ +
, + this.router.pageContentElement, + ); + } + + async getPageTitle(): Promise { + return await SecretTitleElement(this.router, i18next.t("totp_delete_suffix")); + } + + get name(): string { + return i18next.t("totp_delete_title"); + } +} diff --git a/src/pages/Secrets/TOTP/TOTPView.tsx b/src/pages/Secrets/TOTP/TOTPView.tsx index f4b2f87..aeae375 100644 --- a/src/pages/Secrets/TOTP/TOTPView.tsx +++ b/src/pages/Secrets/TOTP/TOTPView.tsx @@ -1,7 +1,10 @@ import { Component, JSX, render } from "preact"; import { CopyableInputBox } from "../../../elements/ReactCopyableInputBox"; import { DoesNotExistError } from "../../../types/internalErrors"; +import { MarginInline } from "../../../elements/ReactMarginInline"; import { Page } from "../../../types/Page"; +import { PageRouter } from "z-pagerouter"; +import { PageState } from "../../../PageState"; import { SecretTitleElement } from "../SecretTitleElement"; import { getTOTPCode } from "../../../api/totp/getTOTPCode"; import { getTOTPKeys } from "../../../api/totp/getTOTPKeys"; @@ -9,7 +12,7 @@ import { setErrorText } from "../../../pageUtils"; import i18next from "i18next"; export class RefreshingTOTPGridItem extends Component< - { baseMount: string; totpKey: string }, + { baseMount: string; totpKey: string; router: PageRouter }, { totpValue: string } > { constructor() { @@ -36,6 +39,20 @@ export class RefreshingTOTPGridItem extends Component<
+
+ + + +
); } @@ -54,6 +71,7 @@ export class TOTPViewPage extends Page { } async render(): Promise { + this.state.secretItem = ""; render(