1
0
Fork 0

Rework how KeyValueSecretView works.

This commit is contained in:
Kitteh 2021-05-25 08:34:30 +01:00
parent 4930b8e727
commit 4b3eb6b3c6

View file

@ -3,12 +3,53 @@ import { Page } from "../../../types/Page";
import { SecretTitleElement } from "../SecretTitleElement"; import { SecretTitleElement } from "../SecretTitleElement";
import { getCapabilities } from "../../../api/sys/getCapabilities"; import { getCapabilities } from "../../../api/sys/getCapabilities";
import { getSecret } from "../../../api/kv/getSecret"; import { getSecret } from "../../../api/kv/getSecret";
import { render } from "preact"; import { Component, JSX, render } from "preact";
import { sortedObjectMap } from "../../../utils"; import { sortedObjectMap } from "../../../utils";
import { undeleteSecret } from "../../../api/kv/undeleteSecret"; import { undeleteSecret } from "../../../api/kv/undeleteSecret";
import Prism from "prismjs"; import Prism from "prismjs";
import i18next from "i18next"; import i18next from "i18next";
export type KVSecretViewProps = {
kvData: Record<string, unknown>;
};
export class KVSecretVew extends Component<KVSecretViewProps, unknown> {
render(): JSX.Element {
const secretsMap = sortedObjectMap(this.props.kvData);
let isMultiLevelJSON = false;
for (const value of secretsMap.values()) {
if (typeof value == "object") isMultiLevelJSON = true;
}
if (isMultiLevelJSON) {
const jsonText = JSON.stringify(
sortedObjectMap(secretsMap as unknown as Record<string, unknown>),
null,
4,
);
const highlightedJson = Prism.highlight(jsonText, Prism.languages.json, "json");
return (
<pre
class="code-block language-json line-numbers"
dangerouslySetInnerHTML={{ __html: highlightedJson }}
/>
);
} else {
return (
<>
{Array.from(secretsMap).map((data: [string, string]) => (
<div class="uk-grid uk-grid-small uk-text-left" uk-grid>
<CopyableInputBox text={data[0]} copyable />
<CopyableInputBox text={data[1]} copyable />
</div>
))}
</>
);
}
}
}
export class KeyValueSecretPage extends Page { export class KeyValueSecretPage extends Page {
constructor() { constructor() {
super(); super();
@ -28,64 +69,6 @@ export class KeyValueSecretPage extends Page {
this.state.secretPath, this.state.secretPath,
this.state.secretItem, this.state.secretItem,
); );
render(
<div>
<p id="buttonsBlock">
{
// Delete Button
caps.includes("delete") && (
<button
class="uk-button uk-button-danger"
onClick={async () => {
await this.router.changePage("KEY_VALUE_DELETE");
}}
>
{((): string => {
let deleteButtonText = i18next.t("kv_secret_delete_btn");
if (this.state.secretMountType == "kv-v2" && this.state.secretVersion == null) {
deleteButtonText = i18next.t("kv_secret_delete_all_btn");
} else if (
this.state.secretMountType == "kv-v2" &&
this.state.secretVersion != null
) {
deleteButtonText = i18next.t("kv_secret_delete_version_btn", {
version: this.state.secretVersion,
});
}
return deleteButtonText;
})()}
</button>
)
}
{caps.includes("update") && this.state.secretVersion == null && (
<button
class="uk-button uk-button-primary"
onClick={async () => {
await this.router.changePage("KEY_VALUE_SECRET_EDIT");
}}
>
{i18next.t("kv_secret_edit_btn")}
</button>
)}
{this.state.secretMountType == "kv-v2" && (
<button
class="uk-button uk-button-secondary"
onClick={async () => {
await this.router.changePage("KEY_VALUE_VERSIONS");
}}
>
{i18next.t("kv_secret_versions_btn")}
</button>
)}
</p>
<p id="loadingText">{i18next.t("kv_secret_loading")}</p>
<div id="kvList"></div>
</div>,
this.router.pageContentElement,
);
const kvList = document.querySelector("#kvList");
let isSecretNestedJson = false;
const secretInfo = await getSecret( const secretInfo = await getSecret(
this.state.baseMount, this.state.baseMount,
@ -96,70 +79,95 @@ export class KeyValueSecretPage extends Page {
); );
// On kv-v2, secrets can be deleted temporarily with the ability to restore // On kv-v2, secrets can be deleted temporarily with the ability to restore
if (secretInfo == null && this.state.secretMountType == "kv-v2") { // Do not show any buttons when the secret is deleted.
try { let secretIsDeleted = secretInfo == null && this.state.secretMountType == "kv-v2";
document.querySelector("#buttonsBlock").remove();
document.getElementById("loadingText").remove();
} catch (_) {
// Do Nothing
}
render(
<>
<p>{i18next.t("kv_secret_deleted_text")}</p>
<button
class="uk-button uk-button-primary"
onClick={async () => {
await undeleteSecret(
this.state.baseMount,
this.state.secretPath,
this.state.secretItem,
this.state.secretVersion,
);
await this.router.refresh();
}}
>
{i18next.t("kv_secret_restore_btn")}
</button>
</>,
kvList,
);
return;
}
const secretsMap = sortedObjectMap(secretInfo); render(
<div>
<p id="buttonsBlock">
{
// Delete Button
!secretIsDeleted &&
caps.includes("delete") && (
<button
class="uk-button uk-button-danger"
onClick={async () => {
await this.router.changePage("KEY_VALUE_DELETE");
}}
>
{((): string => {
// Delete Secret on kv-v1
let deleteButtonText = i18next.t("kv_secret_delete_btn");
if (this.state.secretMountType == "kv-v2" && this.state.secretVersion == null) {
// Delete All
deleteButtonText = i18next.t("kv_secret_delete_all_btn");
} else if (
this.state.secretMountType == "kv-v2" &&
this.state.secretVersion != null
) {
// Delete Version X
deleteButtonText = i18next.t("kv_secret_delete_version_btn", {
version: this.state.secretVersion,
});
}
return deleteButtonText;
})()}
</button>
)
}
{
!secretIsDeleted &&
caps.includes("update") && this.state.secretVersion == null && (
<button
class="uk-button uk-button-primary"
onClick={async () => {
await this.router.changePage("KEY_VALUE_SECRET_EDIT");
}}
>
{i18next.t("kv_secret_edit_btn")}
</button>
)}
{
!secretIsDeleted &&
this.state.secretMountType == "kv-v2" && (
<button
class="uk-button uk-button-secondary"
onClick={async () => {
await this.router.changePage("KEY_VALUE_VERSIONS");
}}
>
{i18next.t("kv_secret_versions_btn")}
</button>
)}
</p>
for (const value of secretsMap.values()) { {!secretIsDeleted &&
if (typeof value == "object") isSecretNestedJson = true; <KVSecretVew kvData={secretInfo} />
} }
if (isSecretNestedJson) { {secretIsDeleted &&
const jsonText = JSON.stringify( <>
sortedObjectMap(secretsMap as unknown as Record<string, unknown>), <p>{i18next.t("kv_secret_deleted_text")}</p>
null, <button
4, class="uk-button uk-button-primary"
); onClick={async () => {
const highlightedJson = Prism.highlight(jsonText, Prism.languages.json, "json"); await undeleteSecret(
render( this.state.baseMount,
<pre this.state.secretPath,
class="code-block language-json line-numbers" this.state.secretItem,
dangerouslySetInnerHTML={{ __html: highlightedJson }} this.state.secretVersion,
/>, );
kvList, await this.router.refresh();
); }}
} else { >
render( {i18next.t("kv_secret_restore_btn")}
<> </button>
{Array.from(secretsMap).map((data: [string, string]) => ( </>
<div class="uk-grid uk-grid-small uk-text-left" uk-grid> }
<CopyableInputBox text={data[0]} copyable />
<CopyableInputBox text={data[1]} copyable /> </div>,
</div> this.router.pageContentElement,
))} );
</>,
kvList,
);
}
document.getElementById("loadingText").remove();
} }
async renderPageTitle(): Promise<void> { async renderPageTitle(): Promise<void> {