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.
|
- Managing versions of secrets in v2 mounts.
|
||||||
- Editing and Viewing Key/Value secrets in JSON, JSON5, Yaml, etc with default settings for both.
|
- 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.
|
- 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
|
### TOTP
|
||||||
- Can view and delete TOTP codes.
|
- Can view and delete TOTP codes.
|
||||||
- Ability to scan a QR code, input a URI or input a key for adding 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_all_btn: "Delete All Versions",
|
||||||
kv_secret_delete_version_btn: "Delete Version {{ version }}",
|
kv_secret_delete_version_btn: "Delete Version {{ version }}",
|
||||||
kv_secret_versions_btn: "Versions",
|
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",
|
kv_secret_syntax: "Syntax",
|
||||||
|
|
||||||
// Key Value Secret Editor Page
|
// Key Value Secret Editor Page
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { API } from "../../../../api/API";
|
||||||
import { Button } from "../../../elements/Button";
|
import { Button } from "../../../elements/Button";
|
||||||
import { CodeBlock } from "../../../elements/CodeBlock";
|
import { CodeBlock } from "../../../elements/CodeBlock";
|
||||||
import { Component, JSX, createRef } from "preact";
|
import { Component, JSX, createRef } from "preact";
|
||||||
|
@ -9,10 +10,12 @@ import { InputWithTitle } from "../../../elements/InputWithTitle";
|
||||||
import { SecretTitleElement } from "../SecretTitleElement";
|
import { SecretTitleElement } from "../SecretTitleElement";
|
||||||
import { Select, SelectOption } from "../../../elements/forms/Select";
|
import { Select, SelectOption } from "../../../elements/forms/Select";
|
||||||
import { SupportedLanguages, dumpData, toPrismCode } from "../../../../utils/dataInterchange";
|
import { SupportedLanguages, dumpData, toPrismCode } from "../../../../utils/dataInterchange";
|
||||||
|
import { addClipboardNotifications } from "../../../../utils/clipboardNotifs";
|
||||||
import { kvDeleteURL, kvEditURL, kvVersionsURL, totpListURL } from "../../pageLinks";
|
import { kvDeleteURL, kvEditURL, kvVersionsURL, totpListURL } from "../../pageLinks";
|
||||||
import { sendErrorNotification } from "../../../elements/ErrorMessage";
|
import { sendErrorNotification } from "../../../elements/ErrorMessage";
|
||||||
import { sortedObjectMap } from "../../../../utils";
|
import { sortedObjectMap } from "../../../../utils";
|
||||||
import { splitKVPath } from "./kvPathUtils";
|
import { splitKVPath } from "./kvPathUtils";
|
||||||
|
import ClipboardJS from "clipboard";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
type KVSecretViewDataProps = DefaultPageProps & { data: Map<string, unknown> };
|
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> {
|
export class KVSecretNormalVew extends Component<KVSecretViewDataProps> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
@ -70,19 +113,22 @@ export class KVSecretNormalVew extends Component<KVSecretViewDataProps> {
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<br />
|
|
||||||
{(() => {
|
{(() => {
|
||||||
if (this.props.data.has("__vaultui_totp_path")) {
|
if (this.props.data.has("__vaultui_totp_path")) {
|
||||||
const value = this.props.data.get("__vaultui_totp_path") as string;
|
const value = this.props.data.get("__vaultui_totp_path") as string;
|
||||||
const baseMount = value.split("/")[0];
|
const baseMount = value.split("/")[0];
|
||||||
const secretItem = value.split("/")[1];
|
const totpKey = value.split("/")[1];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<p>
|
||||||
text={i18next.t("kv_secret_view_totp_btn")}
|
<CopyTOTPButton api={this.props.api} baseMount={baseMount} totpKey={totpKey} />
|
||||||
color="primary"
|
<Button
|
||||||
route={totpListURL(baseMount, secretItem)}
|
text={i18next.t("kv_secret_view_totp_btn")}
|
||||||
/>
|
color="secondary"
|
||||||
|
route={totpListURL(baseMount, totpKey)}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})()}
|
})()}
|
||||||
|
|
Loading…
Reference in a new issue