diff --git a/README.md b/README.md index 95ecb35..9d30896 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ VaultUI is a user interface for [Hashicorp Vault](https://www.hashicorp.com/prod - Managing versions of secrets in v2 mounts. - Editing and Viewing Key/Value secrets in JSON, JSON5, Yaml, etc with default settings for both. - Search bar for easily finding a secret on mobile. +- Can add a `__vaultui_totp_path` attribute (example: `__vaultui_totp_path: "totp/gitlab"`) to KV secrets to add a link for viewing of affiliated TOTP paths. ### TOTP - Can view and delete TOTP codes. - Ability to scan a QR code, input a URI or input a key for adding TOTP codes. diff --git a/src/translations/en.js b/src/translations/en.js index 61a74b4..8e9ea0f 100644 --- a/src/translations/en.js +++ b/src/translations/en.js @@ -167,7 +167,8 @@ module.exports = { kv_secret_delete_all_btn: "Delete All Versions", kv_secret_delete_version_btn: "Delete Version {{ version }}", kv_secret_versions_btn: "Versions", - kv_secret_view_totp_btn: "View TOTP", + kv_secret_view_totp_btn: "View TOTP Entry", + kv_secret_copy_totp_btn: "Copy Current TOTP Code", kv_secret_syntax: "Syntax", // Key Value Secret Editor Page diff --git a/src/ui/pages/Secrets/KeyValue/KeyValueView.tsx b/src/ui/pages/Secrets/KeyValue/KeyValueView.tsx index ecfa207..49f551f 100644 --- a/src/ui/pages/Secrets/KeyValue/KeyValueView.tsx +++ b/src/ui/pages/Secrets/KeyValue/KeyValueView.tsx @@ -1,3 +1,4 @@ +import { API } from "../../../../api/API"; import { Button } from "../../../elements/Button"; import { CodeBlock } from "../../../elements/CodeBlock"; import { Component, JSX, createRef } from "preact"; @@ -9,10 +10,12 @@ import { InputWithTitle } from "../../../elements/InputWithTitle"; import { SecretTitleElement } from "../SecretTitleElement"; import { Select, SelectOption } from "../../../elements/forms/Select"; import { SupportedLanguages, dumpData, toPrismCode } from "../../../../utils/dataInterchange"; +import { addClipboardNotifications } from "../../../../utils/clipboardNotifs"; import { kvDeleteURL, kvEditURL, kvVersionsURL, totpListURL } from "../../pageLinks"; import { sendErrorNotification } from "../../../elements/ErrorMessage"; import { sortedObjectMap } from "../../../../utils"; import { splitKVPath } from "./kvPathUtils"; +import ClipboardJS from "clipboard"; import i18next from "i18next"; type KVSecretViewDataProps = DefaultPageProps & { data: Map }; @@ -49,6 +52,46 @@ export class KVSecretCodeVew extends Component { + buttonRef = createRef(); + + timer: unknown; + + updateTOTPCode(): void { + void this.props.api.getTOTPCode(this.props.baseMount, this.props.totpKey).then((code) => { + this.setState({ code }); + }); + } + + componentDidMount(): void { + this.updateTOTPCode(); + this.timer = setInterval(() => { + this.updateTOTPCode(); + }, 3000); + + const clipboard = new ClipboardJS(this.buttonRef.current); + addClipboardNotifications(clipboard, 600); + } + + componentWillUnmount(): void { + clearInterval(this.timer as number); + } + + render(): JSX.Element { + return ( +