add a copy totp button on kv pages with __vaultui_totp_path
This commit is contained in:
parent
760e16c371
commit
506fdbd1cb
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<string, unknown> };
|
||||
|
@ -49,6 +52,46 @@ export class KVSecretCodeVew extends Component<KVSecretViewDataProps, { syntax:
|
|||
}
|
||||
}
|
||||
|
||||
class CopyTOTPButton extends Component<
|
||||
{ baseMount: string; totpKey: string; api: API },
|
||||
{ code: string }
|
||||
> {
|
||||
buttonRef = createRef<HTMLButtonElement>();
|
||||
|
||||
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 (
|
||||
<Button
|
||||
buttonRef={this.buttonRef}
|
||||
text={i18next.t("kv_secret_copy_totp_btn")}
|
||||
color="primary"
|
||||
data-clipboard-text={this.state.code}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class KVSecretNormalVew extends Component<KVSecretViewDataProps> {
|
||||
render() {
|
||||
return (
|
||||
|
@ -70,19 +113,22 @@ export class KVSecretNormalVew extends Component<KVSecretViewDataProps> {
|
|||
</Grid>
|
||||
);
|
||||
})}
|
||||
<br />
|
||||
|
||||
{(() => {
|
||||
if (this.props.data.has("__vaultui_totp_path")) {
|
||||
const value = this.props.data.get("__vaultui_totp_path") as string;
|
||||
const baseMount = value.split("/")[0];
|
||||
const secretItem = value.split("/")[1];
|
||||
const totpKey = value.split("/")[1];
|
||||
|
||||
return (
|
||||
<p>
|
||||
<CopyTOTPButton api={this.props.api} baseMount={baseMount} totpKey={totpKey} />
|
||||
<Button
|
||||
text={i18next.t("kv_secret_view_totp_btn")}
|
||||
color="primary"
|
||||
route={totpListURL(baseMount, secretItem)}
|
||||
color="secondary"
|
||||
route={totpListURL(baseMount, totpKey)}
|
||||
/>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
})()}
|
||||
|
|
Loading…
Reference in a new issue