Rework how KeyValueSecretView works.
This commit is contained in:
parent
4930b8e727
commit
4b3eb6b3c6
|
@ -3,12 +3,53 @@ import { Page } from "../../../types/Page";
|
|||
import { SecretTitleElement } from "../SecretTitleElement";
|
||||
import { getCapabilities } from "../../../api/sys/getCapabilities";
|
||||
import { getSecret } from "../../../api/kv/getSecret";
|
||||
import { render } from "preact";
|
||||
import { Component, JSX, render } from "preact";
|
||||
import { sortedObjectMap } from "../../../utils";
|
||||
import { undeleteSecret } from "../../../api/kv/undeleteSecret";
|
||||
import Prism from "prismjs";
|
||||
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 {
|
||||
constructor() {
|
||||
super();
|
||||
|
@ -28,64 +69,6 @@ export class KeyValueSecretPage extends Page {
|
|||
this.state.secretPath,
|
||||
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(
|
||||
this.state.baseMount,
|
||||
|
@ -96,14 +79,73 @@ export class KeyValueSecretPage extends Page {
|
|||
);
|
||||
|
||||
// On kv-v2, secrets can be deleted temporarily with the ability to restore
|
||||
if (secretInfo == null && this.state.secretMountType == "kv-v2") {
|
||||
try {
|
||||
document.querySelector("#buttonsBlock").remove();
|
||||
document.getElementById("loadingText").remove();
|
||||
} catch (_) {
|
||||
// Do Nothing
|
||||
}
|
||||
// Do not show any buttons when the secret is deleted.
|
||||
let secretIsDeleted = secretInfo == null && this.state.secretMountType == "kv-v2";
|
||||
|
||||
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>
|
||||
|
||||
{!secretIsDeleted &&
|
||||
<KVSecretVew kvData={secretInfo} />
|
||||
}
|
||||
|
||||
{secretIsDeleted &&
|
||||
<>
|
||||
<p>{i18next.t("kv_secret_deleted_text")}</p>
|
||||
<button
|
||||
|
@ -120,46 +162,12 @@ export class KeyValueSecretPage extends Page {
|
|||
>
|
||||
{i18next.t("kv_secret_restore_btn")}
|
||||
</button>
|
||||
</>,
|
||||
kvList,
|
||||
);
|
||||
return;
|
||||
</>
|
||||
}
|
||||
|
||||
const secretsMap = sortedObjectMap(secretInfo);
|
||||
|
||||
for (const value of secretsMap.values()) {
|
||||
if (typeof value == "object") isSecretNestedJson = true;
|
||||
}
|
||||
|
||||
if (isSecretNestedJson) {
|
||||
const jsonText = JSON.stringify(
|
||||
sortedObjectMap(secretsMap as unknown as Record<string, unknown>),
|
||||
null,
|
||||
4,
|
||||
</div>,
|
||||
this.router.pageContentElement,
|
||||
);
|
||||
const highlightedJson = Prism.highlight(jsonText, Prism.languages.json, "json");
|
||||
render(
|
||||
<pre
|
||||
class="code-block language-json line-numbers"
|
||||
dangerouslySetInnerHTML={{ __html: highlightedJson }}
|
||||
/>,
|
||||
kvList,
|
||||
);
|
||||
} else {
|
||||
render(
|
||||
<>
|
||||
{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>
|
||||
))}
|
||||
</>,
|
||||
kvList,
|
||||
);
|
||||
}
|
||||
document.getElementById("loadingText").remove();
|
||||
}
|
||||
|
||||
async renderPageTitle(): Promise<void> {
|
||||
|
|
Loading…
Reference in a new issue