add some more pages and page links better
This commit is contained in:
parent
c62cd89771
commit
ff8a2995cb
|
@ -12,9 +12,9 @@ export async function deleteSecret(
|
|||
|
||||
const mountInfo = await getMount(baseMount);
|
||||
if (mountInfo.options.version == "2") {
|
||||
secretURL = `/v1/${baseMount}/metadata/${secretPath.join("")}/${name}`;
|
||||
secretURL = `/v1/${baseMount}/metadata/${secretPath.join("/")}/${name}`;
|
||||
} else {
|
||||
secretURL = `/v1/${baseMount}/${secretPath.join("")}/${name}`;
|
||||
secretURL = `/v1/${baseMount}/${secretPath.join("/")}/${name}`;
|
||||
}
|
||||
secretURL = removeDoubleSlash(secretURL).replace(/\/$/, "");
|
||||
request = new Request(appendAPIURL(secretURL), {
|
||||
|
|
|
@ -10,10 +10,10 @@ export async function getSecrets(
|
|||
let secretMountType = "kv-v2"
|
||||
|
||||
if (secretMountType == "kv-v2") {
|
||||
secretURL = `/v1/${baseMount}/metadata/${secretPath.join("")}?list=true`;
|
||||
secretURL = `/v1/${baseMount}/metadata/${secretPath.join("/")}?list=true`;
|
||||
} else {
|
||||
// cubbyhole and v1 are identical
|
||||
secretURL = `/v1/${baseMount}/${secretPath.join("")}?list=true`;
|
||||
secretURL = `/v1/${baseMount}/${secretPath.join("/")}?list=true`;
|
||||
}
|
||||
const request = new Request(appendAPIURL(secretURL), {
|
||||
headers: getHeaders(),
|
||||
|
|
23
src/main.tsx
23
src/main.tsx
|
@ -52,6 +52,9 @@ import { KeyValueView } from "./ui/pages/Secrets/KeyValue/KeyValueView";
|
|||
import { KeyValueSecret } from "./ui/pages/Secrets/KeyValue/KeyValueSecret";
|
||||
import { KeyValueSecretEdit } from "./ui/pages/Secrets/KeyValue/KeyValueSecretsEdit";
|
||||
import { KeyValueDelete } from "./ui/pages/Secrets/KeyValue/KeyValueDelete";
|
||||
import { TransitView } from "./ui/pages/Secrets/Transit/TransitView";
|
||||
import { TransitViewSecret } from "./ui/pages/Secrets/Transit/TransitViewSecret";
|
||||
import { NewTransitKey } from "./ui/pages/Secrets/Transit/NewTransitKey";
|
||||
|
||||
async function onLoad(): Promise<void> {
|
||||
const Main = () => (
|
||||
|
@ -72,19 +75,25 @@ async function onLoad(): Promise<void> {
|
|||
<NewTOTPEngine path="/secrets/new_secrets_engine/totp" />
|
||||
<NewTransitEngine path="/secrets/new_secrets_engine/trasit" />
|
||||
|
||||
<TOTPView path="/secrets/totp/list/:mount" state={pageState} />
|
||||
<TOTPNew path="/secrets/totp/new/:mount" state={pageState} />
|
||||
<TOTPDelete path="/secrets/totp/delete/:mount/:item" state={pageState} />
|
||||
<KeyValueView path="/secrets/kv/list/:baseMount/:secretPath*?" state={pageState} />
|
||||
<KeyValueSecret path="/secrets/kv/view/:item/:baseMount/:secretPath+" state={pageState} />
|
||||
<KeyValueSecretEdit path="/secrets/kv/edit/:item/:baseMount/:secretPath+" state={pageState} />
|
||||
<KeyValueDelete path="/secrets/kv/delete/:item/:baseMount/:secretPath+" state={pageState} />
|
||||
|
||||
<TOTPView path="/secrets/totp/list/:baseMount" state={pageState} />
|
||||
<TOTPNew path="/secrets/totp/new/:baseMount" state={pageState} />
|
||||
<TOTPDelete path="/secrets/totp/delete/:baseMount/:item" state={pageState} />
|
||||
|
||||
<TransitView path="/secrets/transit/list/:baseMount" state={pageState} />
|
||||
<TransitViewSecret path="/secrets/transit/view/:baseMount/:secretItem" state={pageState} />
|
||||
<NewTransitKey path="/secrets/transit/new/:baseMount" state={pageState} />
|
||||
|
||||
<KeyValueView path="/secrets/kv/list/:mount+" state={pageState} />
|
||||
<KeyValueSecret path="/secrets/kv/view/:item/:mount+" state={pageState} />
|
||||
<KeyValueSecretEdit path="/secrets/kv/edit/:item/:mount+" state={pageState} />
|
||||
<KeyValueDelete path="/secrets/kv/delete/:item/:mount+" state={pageState} />
|
||||
|
||||
<div default><p>PAGE NOT YET IMPLEMENTED</p></div>
|
||||
|
||||
</Router>
|
||||
);
|
||||
|
||||
render(
|
||||
<>
|
||||
<NavBar />
|
||||
|
|
|
@ -4,19 +4,22 @@ import { deleteSecret } from "../../../../api/kv/deleteSecret";
|
|||
import { Component, render } from "preact";
|
||||
import i18next from "i18next";
|
||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||
import { splitKVMount } from "./splitKVMount";
|
||||
|
||||
export class KeyValueDelete extends Component<DefaultPageProps> {
|
||||
render() {
|
||||
const mount = this.props.matches["mount"];
|
||||
const mountSplit = splitKVMount(mount);
|
||||
const baseMount = mountSplit.baseMount;
|
||||
const secretPath = mountSplit.restOfMount;
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
const secretPath = this.props.matches["secretPath"].split("/");
|
||||
const item = this.props.matches["item"];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SecretTitleElement type="kv" item={this.props.matches["item"]} mount={mount} suffix={i18next.t("kv_sec_edit_suffix")} />
|
||||
<SecretTitleElement
|
||||
type="kv"
|
||||
baseMount={baseMount}
|
||||
secretPath={secretPath}
|
||||
item={item}
|
||||
suffix={i18next.t("kv_sec_edit_suffix")}
|
||||
/>
|
||||
<div>
|
||||
<h5>{i18next.t("kv_delete_text")}</h5>
|
||||
<button
|
||||
|
@ -24,7 +27,7 @@ export class KeyValueDelete extends Component<DefaultPageProps> {
|
|||
onClick={async () => {
|
||||
await deleteSecret(
|
||||
baseMount,
|
||||
secretPath.map((e) => e + "/"),
|
||||
secretPath,
|
||||
item,
|
||||
);
|
||||
window.history.back();
|
||||
|
|
|
@ -1,25 +1,29 @@
|
|||
import { Form } from "../../../elements/Form";
|
||||
import { Margin } from "../../../elements/Margin";
|
||||
import { Page } from "../../../../types/Page";
|
||||
import { SecretTitleElement } from "../SecretTitleElement";
|
||||
import { createOrUpdateSecret } from "../../../../api/kv/createOrUpdateSecret";
|
||||
import { render } from "preact";
|
||||
import { Component, render } from "preact";
|
||||
import { setErrorText } from "../../../../pageUtils";
|
||||
import i18next from "i18next";
|
||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||
import { route } from "preact-router";
|
||||
import { kvViewURL } from "../../pageLinks";
|
||||
|
||||
export class KeyValueNewPage extends Page {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
export class KeyValueNewPage extends Component<DefaultPageProps> {
|
||||
render(){
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
const secretPath = (this.props.matches["secretPath"] || "").split("/");
|
||||
|
||||
async goBack(): Promise<void> {
|
||||
await this.router.changePage("KEY_VALUE_VIEW");
|
||||
}
|
||||
|
||||
async render(): Promise<void> {
|
||||
render(
|
||||
return(
|
||||
<>
|
||||
<SecretTitleElement
|
||||
type="kv"
|
||||
baseMount={baseMount}
|
||||
secretPath={secretPath}
|
||||
suffix={i18next.t("kv_sec_edit_suffix")}
|
||||
/>
|
||||
<div>
|
||||
<Form onSubmit={async (formData) => await this.newKVSecretHandleForm(formData)}>
|
||||
<Form onSubmit={async (formData) => await this.newKVSecretHandleForm(formData, baseMount, secretPath)}>
|
||||
<Margin>
|
||||
<input
|
||||
class="uk-input uk-form-width-medium"
|
||||
|
@ -33,41 +37,28 @@ export class KeyValueNewPage extends Page {
|
|||
{i18next.t("kv_new_create_btn")}
|
||||
</button>
|
||||
</Form>
|
||||
</div>,
|
||||
this.router.pageContentElement,
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
async newKVSecretHandleForm(formData: FormData): Promise<void> {
|
||||
async newKVSecretHandleForm(formData: FormData, baseMount: string, secretPath: string[]): Promise<void> {
|
||||
const path = formData.get("path") as string;
|
||||
let keyData = {};
|
||||
|
||||
if (["kv-v1", "cubbyhole"].includes(this.state.secretMountType)) {
|
||||
keyData = { key: "value" };
|
||||
}
|
||||
// TODO: check only do this on kv v1
|
||||
let keyData = { "key": "value" };
|
||||
|
||||
try {
|
||||
await createOrUpdateSecret(
|
||||
this.state.baseMount,
|
||||
this.state.secretPath,
|
||||
baseMount,
|
||||
secretPath,
|
||||
path,
|
||||
keyData,
|
||||
);
|
||||
await this.router.changePage("KEY_VALUE_VIEW");
|
||||
route(kvViewURL(baseMount, secretPath, path))
|
||||
} catch (e: unknown) {
|
||||
const error = e as Error;
|
||||
setErrorText(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
//async renderPageTitle(): Promise<void> {
|
||||
// render(
|
||||
// <SecretTitleElement page={this} suffix={i18next.t("kv_new_suffix")} />,
|
||||
// this.router.pageTitleElement,
|
||||
// );
|
||||
//}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("kv_new_title");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,17 +2,14 @@ import { CodeBlock } from "../../../elements/CodeBlock";
|
|||
import { Component, JSX, render } from "preact";
|
||||
import { CopyableInputBox } from "../../../elements/CopyableInputBox";
|
||||
import { Grid, GridSizes } from "../../../elements/Grid";
|
||||
import { Page } from "../../../../types/Page";
|
||||
import { SecretTitleElement } from "../SecretTitleElement";
|
||||
import { getCapabilities } from "../../../../api/sys/getCapabilities";
|
||||
import { getSecret } from "../../../../api/kv/getSecret";
|
||||
import { sortedObjectMap } from "../../../../utils";
|
||||
import { undeleteSecret } from "../../../../api/kv/undeleteSecret";
|
||||
import i18next from "i18next";
|
||||
import { splitKVMount } from "./splitKVMount";
|
||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||
import { getMount } from "../../../../api/sys/getMounts";
|
||||
import { route } from "preact-router";
|
||||
import { kvDeleteURL, kvEditURL } from "../../pageLinks";
|
||||
|
||||
export type KVSecretViewProps = {
|
||||
kvData: Record<string, unknown>;
|
||||
|
@ -55,10 +52,8 @@ type KeyValueSecretState = {
|
|||
|
||||
export class KeyValueSecret extends Component<DefaultPageProps, KeyValueSecretState> {
|
||||
async componentDidMount() {
|
||||
const mount = this.props.matches["mount"];
|
||||
const mountSplit = splitKVMount(mount);
|
||||
const baseMount = mountSplit.baseMount;
|
||||
const secretPath = mountSplit.restOfMount;
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
const secretPath = this.props.matches["secretPath"].split("/");
|
||||
const secretItem = this.props.matches["item"];
|
||||
|
||||
const caps = (
|
||||
|
@ -84,24 +79,25 @@ export class KeyValueSecret extends Component<DefaultPageProps, KeyValueSecretSt
|
|||
|
||||
}
|
||||
render() {
|
||||
if (!this.state.baseMount) return;
|
||||
|
||||
// TODO: maybe add some sort of version viewing
|
||||
// no idea what gonna do for that
|
||||
if (!this.state.baseMount) return;
|
||||
|
||||
return (
|
||||
<>
|
||||
<SecretTitleElement type="kv" item={this.props.matches["item"]} mount={this.props.matches["mount"]} suffix={i18next.t("kv_sec_edit_suffix")} />
|
||||
<SecretTitleElement
|
||||
type="kv"
|
||||
item={this.props.matches["item"]}
|
||||
baseMount={this.state.baseMount}
|
||||
secretPath={this.state.secretPath}
|
||||
suffix={i18next.t("kv_sec_edit_suffix")}
|
||||
/>
|
||||
<div>
|
||||
<p id="buttonsBlock">
|
||||
{
|
||||
// Delete Button
|
||||
this.state.caps.includes("delete") && (
|
||||
<button
|
||||
class="uk-button uk-button-danger"
|
||||
onClick={async () => {
|
||||
route("/secrets/kv/delete/" + this.state.secretItem + "/" + this.state.baseMount + "/" + this.state.secretPath.join("/"))
|
||||
//await this.router.changePage("KEY_VALUE_DELETE");
|
||||
route(kvDeleteURL(this.state.baseMount, this.state.secretPath, this.state.secretItem))
|
||||
}}
|
||||
>
|
||||
{i18next.t("kv_secret_delete_btn")}
|
||||
|
@ -112,7 +108,7 @@ export class KeyValueSecret extends Component<DefaultPageProps, KeyValueSecretSt
|
|||
<button
|
||||
class="uk-button uk-button-primary"
|
||||
onClick={async () => {
|
||||
route("/secrets/kv/edit/" + this.state.secretItem + "/" + this.state.baseMount + "/" + this.state.secretPath.join("/"))
|
||||
route(kvEditURL(this.state.baseMount, this.state.secretPath, this.state.secretItem))
|
||||
}}
|
||||
>
|
||||
{i18next.t("kv_secret_edit_btn")}
|
||||
|
@ -125,14 +121,5 @@ export class KeyValueSecret extends Component<DefaultPageProps, KeyValueSecretSt
|
|||
</>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
//async renderPageTitle(): Promise<void> {
|
||||
// render(<SecretTitleElement page={this} />, this.router.pageTitleElement);
|
||||
//}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("kv_secret_title");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,6 @@ import { setErrorText } from "../../../../pageUtils";
|
|||
import { sortedObjectMap, verifyJSONString } from "../../../../utils";
|
||||
import i18next from "i18next";
|
||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||
import { splitKVMount } from "./splitKVMount";
|
||||
import { route } from "preact-router";
|
||||
//import { highlightElement } from "prismjs";
|
||||
|
||||
export type KVEditProps = {
|
||||
baseMount: string;
|
||||
|
@ -109,28 +106,21 @@ export class KVEditor extends Component<KVEditProps, KVEditState> {
|
|||
|
||||
export class KeyValueSecretEdit extends Component<DefaultPageProps> {
|
||||
render() {
|
||||
const mount = this.props.matches["mount"];
|
||||
const mountSplit = splitKVMount(mount);
|
||||
const baseMount = mountSplit.baseMount;
|
||||
const restOfMount = mountSplit.restOfMount;
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
const secretPath = this.props.matches["secretPath"].split("/");
|
||||
const item = this.props.matches["item"];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SecretTitleElement type="kv" mount={mount} item={this.props.matches["item"]} suffix={i18next.t("kv_sec_edit_suffix")} />
|
||||
<KVEditor baseMount={baseMount} secretPath={restOfMount} secretItem={item} />
|
||||
<SecretTitleElement
|
||||
type="kv"
|
||||
baseMount={baseMount}
|
||||
secretPath={secretPath}
|
||||
item={this.props.matches["item"]}
|
||||
suffix={i18next.t("kv_sec_edit_suffix")}
|
||||
/>
|
||||
<KVEditor baseMount={baseMount} secretPath={secretPath} secretItem={item} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
//async renderPageTitle(): Promise<void> {
|
||||
// render(
|
||||
// <SecretTitleElement page={this} suffix={i18next.t("kv_sec_edit_suffix")} />,
|
||||
// this.router.pageTitleElement,
|
||||
// );
|
||||
//}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("kv_sec_edit_title");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@ import { setErrorText } from "../../../../pageUtils";
|
|||
import i18next from "i18next";
|
||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||
import { route } from "preact-router";
|
||||
import { splitKVMount } from "./splitKVMount";
|
||||
import { delSecretsEngineURL, kvListURL, kvNewURL, kvViewURL } from "../../pageLinks";
|
||||
import { getMount } from "../../../../api/sys/getMounts";
|
||||
|
||||
|
||||
export type KVKeysListProps = DefaultPageProps & {
|
||||
|
@ -22,15 +23,16 @@ type KVKeysListState = {
|
|||
searchQuery: string;
|
||||
};
|
||||
|
||||
function SecretsList(baseMount: string, restOfMount: string[], secrets: string[]): JSX.Element[] {
|
||||
function SecretsList(baseMount: string, secretPath: string[], secrets: string[]): JSX.Element[] {
|
||||
return secrets.map((secret) => (
|
||||
<li>
|
||||
<a
|
||||
onClick={async () => {
|
||||
console.log(baseMount, secretPath, secret)
|
||||
if (secret.endsWith("/")) {
|
||||
route("/secrets/kv/list/" + baseMount + "/" + restOfMount.join("/") + "/" + secret)
|
||||
route(kvListURL(baseMount, [...secretPath, secret.replace("/", "")].filter((e)=>e.length > 0)))
|
||||
} else {
|
||||
route("/secrets/kv/view/" + secret + "/" + baseMount + "/" + restOfMount.join("/"))
|
||||
route(kvViewURL(baseMount, secretPath, secret))
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
@ -54,7 +56,7 @@ export class KVKeysList extends Component<KVKeysListProps, KVKeysListState> {
|
|||
try {
|
||||
const keys = await getSecrets(
|
||||
this.props.baseMount,
|
||||
this.props.secretPath.map((e) => e + "/"),
|
||||
this.props.secretPath,
|
||||
);
|
||||
this.setState({
|
||||
dataLoaded: true,
|
||||
|
@ -118,7 +120,6 @@ export class KVKeysList extends Component<KVKeysListProps, KVKeysListState> {
|
|||
this.setState({
|
||||
searchQuery: (this.searchBarRef.current as unknown as HTMLInputElement).value,
|
||||
});
|
||||
console.log("meow");
|
||||
}}
|
||||
/>
|
||||
<br />
|
||||
|
@ -140,60 +141,65 @@ export class KVKeysList extends Component<KVKeysListProps, KVKeysListState> {
|
|||
type KeyValueViewState = {
|
||||
pathCaps: string[];
|
||||
mountCaps: string[];
|
||||
mountType: string;
|
||||
}
|
||||
|
||||
export class KeyValueView extends Component<DefaultPageProps, KeyValueViewState> {
|
||||
async componentDidMount() {
|
||||
const mount = this.props.matches["mount"];
|
||||
const mountSplit = splitKVMount(mount);
|
||||
const baseMount = mountSplit.baseMount;
|
||||
const restOfMount = mountSplit.restOfMount;
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
const secretPath = this.props.matches["secretPath"].split("/");
|
||||
|
||||
const mountsPath = "/sys/mounts/" + baseMount;
|
||||
const currentPath = baseMount + restOfMount.join();
|
||||
const currentPath = baseMount + secretPath.join();
|
||||
const caps = await getCapabilitiesPath([mountsPath, currentPath]);
|
||||
|
||||
const mount = await getMount(baseMount);
|
||||
|
||||
this.setState({
|
||||
mountCaps: caps[mountsPath],
|
||||
pathCaps: caps[currentPath],
|
||||
mountType: mount.type,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.state.pathCaps) return;
|
||||
|
||||
const mount = this.props.matches["mount"];
|
||||
const mountSplit = splitKVMount(mount);
|
||||
const baseMount = mountSplit.baseMount;
|
||||
const restOfMount = mountSplit.restOfMount;
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
const secretPath = this.props.matches["secretPath"].split("/");
|
||||
|
||||
return (
|
||||
<>
|
||||
<SecretTitleElement type="kv" mount={mount} item={this.props.matches["item"]} />
|
||||
<SecretTitleElement
|
||||
type="kv"
|
||||
baseMount={baseMount}
|
||||
secretPath={secretPath}
|
||||
item={this.props.matches["item"]}
|
||||
/>
|
||||
<p>
|
||||
{this.state.pathCaps.includes("create") && (
|
||||
<button
|
||||
class="uk-button uk-button-primary"
|
||||
onClick={async () => {
|
||||
route("/secrets/kv/new/" + mount)
|
||||
route(kvNewURL(baseMount, secretPath.length > 0 ? secretPath : null))
|
||||
}}
|
||||
>
|
||||
{i18next.t("kv_view_new_btn")}
|
||||
</button>
|
||||
)}
|
||||
{restOfMount.length == 0 && this.state.mountCaps.includes("delete") && (
|
||||
{secretPath.length == 0 && this.state.mountCaps.includes("delete") && (
|
||||
<button
|
||||
class="uk-button uk-button-danger"
|
||||
onClick={async () => {
|
||||
route("/secrets/delete_engine/" + mount)
|
||||
route(delSecretsEngineURL(baseMount))
|
||||
}}
|
||||
>
|
||||
{i18next.t("kv_view_delete_btn")}
|
||||
</button>
|
||||
)}
|
||||
</p>
|
||||
{//"TODO: " == "cubbyhole" && <p>{i18next.t("kv_view_cubbyhole_text")}</p>}
|
||||
}
|
||||
<KVKeysList baseMount={baseMount} secretPath={restOfMount} state={this.props.state} />
|
||||
{this.state.mountType == "cubbyhole" && <p>{i18next.t("kv_view_cubbyhole_text")}</p>}
|
||||
<KVKeysList baseMount={baseMount} secretPath={secretPath} state={this.props.state} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
export function splitKVMount(mount: string): { baseMount: string, restOfMount: string[] } {
|
||||
const baseMount = mount.split("/")[0];
|
||||
const restOfMount = mount.split("/");
|
||||
restOfMount.shift();
|
||||
|
||||
return {
|
||||
baseMount,
|
||||
restOfMount
|
||||
};
|
||||
}
|
|
@ -8,6 +8,7 @@ import { setErrorText } from "../../../../pageUtils";
|
|||
import i18next from "i18next";
|
||||
import { PageTitle } from "../../../elements/PageTitle";
|
||||
import { route } from "preact-router";
|
||||
import { kvListURL } from "../../pageLinks";
|
||||
|
||||
export class NewKVEngine extends Component {
|
||||
render() {
|
||||
|
@ -57,7 +58,7 @@ export class NewKVEngine extends Component {
|
|||
version: version,
|
||||
},
|
||||
});
|
||||
route("/secrets/kv/list/" + name + "/")
|
||||
route(kvListURL(name, []));
|
||||
} catch (e) {
|
||||
const error = e as Error;
|
||||
setErrorText(error.message);
|
||||
|
|
|
@ -8,6 +8,7 @@ import { setErrorText } from "../../../../pageUtils";
|
|||
import i18next from "i18next";
|
||||
import { route } from "preact-router";
|
||||
import { PageTitle } from "../../../elements/PageTitle";
|
||||
import { totpListURL } from "../../pageLinks";
|
||||
|
||||
export class NewTOTPEngine extends Component {
|
||||
render() {
|
||||
|
@ -43,7 +44,7 @@ export class NewTOTPEngine extends Component {
|
|||
name: name,
|
||||
type: "totp",
|
||||
});
|
||||
route("/secrets/totp/list/" + name + "/")
|
||||
route(totpListURL(name));
|
||||
} catch (e) {
|
||||
const error = e as Error;
|
||||
setErrorText(error.message);
|
||||
|
|
|
@ -1,29 +1,28 @@
|
|||
import { route } from "preact-router";
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
import { Page } from "../../../types/Page";
|
||||
import { kvListURL } from "../pageLinks";
|
||||
|
||||
type SecretTitleElementProps = {
|
||||
type: string;
|
||||
mount: string;
|
||||
baseMount: string;
|
||||
secretPath?: string[];
|
||||
item?: string;
|
||||
suffix?: string;
|
||||
};
|
||||
|
||||
export function SecretTitleElement(props: SecretTitleElementProps): JSX.Element {
|
||||
const type = props.type;
|
||||
const mount = props.mount;
|
||||
const item = props.item || "";
|
||||
const suffix = props.suffix || "";
|
||||
|
||||
const baseMount = mount.split("/")[0];
|
||||
const restOfMount = mount.split("/");
|
||||
restOfMount.shift();
|
||||
const baseMount = props.baseMount;
|
||||
const secretPath = props.secretPath || [];
|
||||
|
||||
|
||||
return (
|
||||
<h3 class="uk-card-title" id="pageTitle">
|
||||
|
||||
<div>
|
||||
<a
|
||||
test-data="secrets-title-first-slash"
|
||||
onClick={async () => {
|
||||
route("/secrets");
|
||||
}}
|
||||
|
@ -31,22 +30,25 @@ export function SecretTitleElement(props: SecretTitleElementProps): JSX.Element
|
|||
{"/ "}
|
||||
</a>
|
||||
|
||||
<a href={"/secrets/" + type + "/list/" + baseMount + "/"}>
|
||||
{baseMount + " "}
|
||||
<a href={"/secrets/" + type + "/list/" + baseMount + "/"} test-data="secrets-title-baseMount">
|
||||
{baseMount + "/ "}
|
||||
</a>
|
||||
|
||||
{...restOfMount.map((secretPath, index, secretPaths) => (
|
||||
<a
|
||||
{...secretPath.map((secretPath, index, secretPaths) => {
|
||||
// TODO: find where a '' is returned so dont need this
|
||||
if (secretPath.length < 1) return;
|
||||
return <a test-data="secrets-title-secretPath"
|
||||
onClick={async () => {
|
||||
|
||||
if (type == "kv") {
|
||||
let secretPath = secretPaths.slice(0, index + 1);
|
||||
route("/secrets/kv/list/" + baseMount + "/" + secretPath.join("/"))
|
||||
route(kvListURL(baseMount, secretPath))
|
||||
}
|
||||
}}
|
||||
>
|
||||
{secretPath + "/" + " "}
|
||||
</a>
|
||||
))}
|
||||
})}
|
||||
{item.length != 0 && <span>{item}</span>}
|
||||
{suffix.length != 0 && <span>{suffix}</span>}
|
||||
</div>
|
||||
|
|
|
@ -5,35 +5,34 @@ import { Component, render } from "preact";
|
|||
import i18next from "i18next";
|
||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||
import { route } from "preact-router";
|
||||
import { totpListURL } from "../../pageLinks";
|
||||
|
||||
export class TOTPDelete extends Component<DefaultPageProps> {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h5>{i18next.t("totp_delete_text")}</h5>
|
||||
<button
|
||||
class="uk-button uk-button-danger"
|
||||
onClick={async () => {
|
||||
let mount = this.props.matches["mount"];
|
||||
let item = this.props.matches["item"];
|
||||
await deleteTOTP(mount, item);
|
||||
route("/secrets/totp/list/" + mount)
|
||||
}}
|
||||
>
|
||||
{i18next.t("kv_delete_btn")}
|
||||
</button>
|
||||
</div>
|
||||
<>
|
||||
<SecretTitleElement
|
||||
type="totp"
|
||||
baseMount={this.props.matches["baseMount"]}
|
||||
item={this.props.matches["item"]}
|
||||
suffix={i18next.t("totp_delete_suffix")}
|
||||
/>
|
||||
<div>
|
||||
<h5>{i18next.t("totp_delete_text")}</h5>
|
||||
<button
|
||||
class="uk-button uk-button-danger"
|
||||
onClick={async () => {
|
||||
let baseMount = this.props.matches["baseMount"];
|
||||
let item = this.props.matches["item"];
|
||||
await deleteTOTP(baseMount, item);
|
||||
route(totpListURL(baseMount));
|
||||
}}
|
||||
>
|
||||
{i18next.t("kv_delete_btn")}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
//async renderPageTitle(): Promise<void> {
|
||||
// render(
|
||||
// <SecretTitleElement page={this} suffix={i18next.t("totp_delete_suffix")} />,
|
||||
// this.router.pageTitleElement,
|
||||
// );
|
||||
//}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("totp_delete_title");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ function removeDashSpaces(str: string): string {
|
|||
return str;
|
||||
}
|
||||
|
||||
export class TOTPNewForm extends Component<{ mount: string }, { qrMode: boolean }> {
|
||||
export class TOTPNewForm extends Component<{ baseMount: string }, { qrMode: boolean }> {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
|
@ -40,8 +40,8 @@ export class TOTPNewForm extends Component<{ mount: string }, { qrMode: boolean
|
|||
};
|
||||
|
||||
try {
|
||||
await addNewTOTP(this.props.mount, parms);
|
||||
route("/secrets/totp/list/" + this.props.mount)
|
||||
await addNewTOTP(this.props.baseMount, parms);
|
||||
route("/secrets/totp/list/" + this.props.baseMount)
|
||||
} catch (e: unknown) {
|
||||
const error = e as Error;
|
||||
setErrorText(`API Error: ${error.message}`);
|
||||
|
@ -121,23 +121,12 @@ export class TOTPNewForm extends Component<{ mount: string }, { qrMode: boolean
|
|||
|
||||
export class TOTPNew extends Component<DefaultPageProps> {
|
||||
render() {
|
||||
let mount = this.props.matches["mount"];
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
return (
|
||||
<>
|
||||
<SecretTitleElement type="totp" mount={mount} suffix={i18next.t("totp_new_suffix")} />
|
||||
<TOTPNewForm mount={this.props.matches["mount"]} />
|
||||
<SecretTitleElement type="totp" baseMount={baseMount} suffix={i18next.t("totp_new_suffix")} />
|
||||
<TOTPNewForm baseMount={baseMount} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
//async renderPageTitle(): Promise<void> {
|
||||
// render(
|
||||
// <SecretTitleElement page={this} suffix={i18next.t("totp_new_suffix")} />,
|
||||
// this.router.pageTitleElement,
|
||||
// );
|
||||
//}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("totp_new_title");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,10 @@ import { setErrorText } from "../../../../pageUtils";
|
|||
import i18next from "i18next";
|
||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||
import { route } from "preact-router";
|
||||
import { delSecretsEngineURL, totpNewURL } from "../../pageLinks";
|
||||
|
||||
type TOTPGridItemProps = {
|
||||
mount: string; totpKey: string; canDelete: boolean;
|
||||
baseMount: string; totpKey: string; canDelete: boolean;
|
||||
}
|
||||
|
||||
export class RefreshingTOTPGridItem extends Component<
|
||||
|
@ -29,7 +30,7 @@ export class RefreshingTOTPGridItem extends Component<
|
|||
timer: unknown;
|
||||
|
||||
updateTOTPCode(): void {
|
||||
void getTOTPCode(this.props.mount, this.props.totpKey).then((code) => {
|
||||
void getTOTPCode(this.props.baseMount, this.props.totpKey).then((code) => {
|
||||
this.setState({ totpValue: code });
|
||||
});
|
||||
}
|
||||
|
@ -56,7 +57,7 @@ export class RefreshingTOTPGridItem extends Component<
|
|||
<button
|
||||
class="uk-button uk-button-danger"
|
||||
onClick={async () => {
|
||||
route("/secrets/totp/delete/" + this.props.mount + "/" + this.props.totpKey);
|
||||
route("/secrets/totp/delete/" + this.props.baseMount + "/" + this.props.totpKey);
|
||||
}}
|
||||
>
|
||||
{i18next.t("totp_view_secret_delete_btn")}
|
||||
|
@ -69,15 +70,12 @@ export class RefreshingTOTPGridItem extends Component<
|
|||
}
|
||||
}
|
||||
|
||||
type TOTPViewProps = DefaultPageProps & {
|
||||
}
|
||||
|
||||
type TOTPViewState = {
|
||||
capabilities?: CapabilitiesType;
|
||||
totpItems: TOTPGridItemProps[];
|
||||
}
|
||||
|
||||
export class TOTPView extends Component<TOTPViewProps, TOTPViewState> {
|
||||
export class TOTPView extends Component<DefaultPageProps, TOTPViewState> {
|
||||
constructor() {
|
||||
super();
|
||||
this.refresher = undefined;
|
||||
|
@ -87,22 +85,22 @@ export class TOTPView extends Component<TOTPViewProps, TOTPViewState> {
|
|||
refresher: number;
|
||||
|
||||
async componentDidMount() {
|
||||
var mount = this.props.matches["mount"];
|
||||
const mountsPath = "/sys/mounts/" + mount;
|
||||
const caps = await getCapabilitiesPath([mountsPath, mount]);
|
||||
var baseMount = this.props.matches["baseMount"];
|
||||
const mountsPath = "/sys/mounts/" + baseMount;
|
||||
const caps = await getCapabilitiesPath([mountsPath, baseMount]);
|
||||
|
||||
let totpItems: TOTPGridItemProps[] = [];
|
||||
|
||||
// TODO: tidy this up i guess
|
||||
try {
|
||||
totpItems = await Promise.all(
|
||||
Array.from(await getTOTPKeys(mount)).map(async (key) => {
|
||||
Array.from(await getTOTPKeys(baseMount)).map(async (key) => {
|
||||
const totpCaps = await getCapsPath(
|
||||
removeDoubleSlash(mount + "code/" + key),
|
||||
removeDoubleSlash(baseMount + "/code/" + key),
|
||||
);
|
||||
if (totpCaps.includes("read")) {
|
||||
return {
|
||||
mount: mount,
|
||||
baseMount: baseMount,
|
||||
totpKey: key,
|
||||
canDelete: totpCaps.includes("delete"),
|
||||
};
|
||||
|
@ -124,22 +122,22 @@ export class TOTPView extends Component<TOTPViewProps, TOTPViewState> {
|
|||
|
||||
render() {
|
||||
if (!this.state.capabilities) return;
|
||||
var mount = this.props.matches["mount"];
|
||||
var baseMount = this.props.matches["baseMount"];
|
||||
|
||||
const mountsPath = "/sys/mounts/" + mount;
|
||||
const mountsPath = "/sys/mounts/" + baseMount;
|
||||
const mountCaps = this.state.capabilities[mountsPath];
|
||||
const totpCaps = this.state.capabilities[mount];
|
||||
const totpCaps = this.state.capabilities[baseMount];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SecretTitleElement type="totp" mount={mount} />
|
||||
<SecretTitleElement type="totp" baseMount={baseMount} />
|
||||
<div>
|
||||
<p>
|
||||
{totpCaps.includes("create") && (
|
||||
<button
|
||||
class="uk-button uk-button-primary"
|
||||
onClick={async () => {
|
||||
route("/secrets/totp/new/" + mount)
|
||||
route(totpNewURL(baseMount))
|
||||
}}
|
||||
>
|
||||
{i18next.t("totp_view_new_btn")}
|
||||
|
@ -149,7 +147,7 @@ export class TOTPView extends Component<TOTPViewProps, TOTPViewState> {
|
|||
<button
|
||||
class="uk-button uk-button-danger"
|
||||
onClick={async () => {
|
||||
route("/secrets/delete_engine/" + mount)
|
||||
route(delSecretsEngineURL(baseMount))
|
||||
}}
|
||||
>
|
||||
{i18next.t("totp_view_delete_btn")}
|
||||
|
@ -164,7 +162,7 @@ export class TOTPView extends Component<TOTPViewProps, TOTPViewState> {
|
|||
} else {
|
||||
return this.state.totpItems.map((totpItem) => {
|
||||
return <RefreshingTOTPGridItem
|
||||
mount={totpItem.mount}
|
||||
baseMount={totpItem.baseMount}
|
||||
totpKey={totpItem.totpKey}
|
||||
canDelete={totpItem.canDelete}
|
||||
/>
|
||||
|
@ -178,8 +176,4 @@ export class TOTPView extends Component<TOTPViewProps, TOTPViewState> {
|
|||
|
||||
);
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("totp_view_title");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,89 +1,89 @@
|
|||
import { Form } from "../../../elements/Form";
|
||||
import { Margin } from "../../../elements/Margin";
|
||||
import { MarginInline } from "../../../elements/MarginInline";
|
||||
import { Page } from "../../../../types/Page";
|
||||
import { SecretTitleElement } from "../SecretTitleElement";
|
||||
import { newTransitKey } from "../../../../api/transit/newTransitKey";
|
||||
import { render } from "preact";
|
||||
import { Component } from "preact";
|
||||
import { setErrorText } from "../../../../pageUtils";
|
||||
import i18next from "i18next";
|
||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||
import { route } from "preact-router";
|
||||
import { transitViewSecretURL } from "../../pageLinks";
|
||||
|
||||
export class NewTransitKeyPage extends Page {
|
||||
export class NewTransitKey extends Component<DefaultPageProps> {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
async render(): Promise<void> {
|
||||
render(
|
||||
<Form
|
||||
onSubmit={async (data) => {
|
||||
await this.onSubmit(data);
|
||||
}}
|
||||
>
|
||||
<Margin>
|
||||
<input
|
||||
class="uk-input uk-form-width-medium"
|
||||
name="name"
|
||||
placeholder={i18next.t("transit_new_key_name_input")}
|
||||
type="text"
|
||||
required
|
||||
/>
|
||||
</Margin>
|
||||
<Margin>
|
||||
<select class="uk-select uk-form-width-medium" name="type">
|
||||
{[
|
||||
"aes128-gcm96",
|
||||
"aes256-gcm96",
|
||||
"chacha20-poly1305",
|
||||
"ed25519",
|
||||
"ecdsa-p256",
|
||||
"ecdsa-p384",
|
||||
"ecdsa-p521",
|
||||
"rsa-2048",
|
||||
"rsa-3072",
|
||||
"rsa-4096",
|
||||
].map((type) => (
|
||||
<option label={type} value={type}>
|
||||
{type}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</Margin>
|
||||
<p class="uk-text-danger" id="errorText" />
|
||||
<MarginInline>
|
||||
<button class="uk-button uk-button-primary" type="submit">
|
||||
{i18next.t("transit_new_key_create_btn")}
|
||||
</button>
|
||||
</MarginInline>
|
||||
</Form>,
|
||||
this.router.pageContentElement,
|
||||
render() {
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
return (
|
||||
<>
|
||||
<SecretTitleElement
|
||||
type="transit"
|
||||
baseMount={baseMount}
|
||||
suffix={i18next.t("transit_new_key_suffix")}
|
||||
/>
|
||||
<Form
|
||||
onSubmit={async (data) => {
|
||||
await this.onSubmit(data);
|
||||
}}
|
||||
>
|
||||
<Margin>
|
||||
<input
|
||||
class="uk-input uk-form-width-medium"
|
||||
name="name"
|
||||
placeholder={i18next.t("transit_new_key_name_input")}
|
||||
type="text"
|
||||
required
|
||||
/>
|
||||
</Margin>
|
||||
<Margin>
|
||||
<select class="uk-select uk-form-width-medium" name="type">
|
||||
{[
|
||||
"aes128-gcm96",
|
||||
"aes256-gcm96",
|
||||
"chacha20-poly1305",
|
||||
"ed25519",
|
||||
"ecdsa-p256",
|
||||
"ecdsa-p384",
|
||||
"ecdsa-p521",
|
||||
"rsa-2048",
|
||||
"rsa-3072",
|
||||
"rsa-4096",
|
||||
].map((type) => (
|
||||
<option label={type} value={type}>
|
||||
{type}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</Margin>
|
||||
<p class="uk-text-danger" id="errorText" />
|
||||
<MarginInline>
|
||||
<button class="uk-button uk-button-primary" type="submit">
|
||||
{i18next.t("transit_new_key_create_btn")}
|
||||
</button>
|
||||
</MarginInline>
|
||||
</Form>
|
||||
</>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
async onSubmit(data: FormData): Promise<void> {
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
|
||||
const name = data.get("name") as string;
|
||||
const type = data.get("type") as string;
|
||||
|
||||
try {
|
||||
await newTransitKey(this.state.baseMount, {
|
||||
await newTransitKey(baseMount, {
|
||||
name: name,
|
||||
type: type,
|
||||
});
|
||||
this.state.secretItem = name;
|
||||
await this.router.changePage("TRANSIT_VIEW_SECRET");
|
||||
route(transitViewSecretURL(baseMount, name))
|
||||
} catch (e) {
|
||||
const error = e as Error;
|
||||
setErrorText(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
//async renderPageTitle(): Promise<void> {
|
||||
// render(
|
||||
// <SecretTitleElement page={this} suffix={i18next.t("transit_new_key_suffix")} />,
|
||||
// this.router.pageTitleElement,
|
||||
// );
|
||||
//}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("transit_new_key_title");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
import { Component, JSX, render } from "preact";
|
||||
import { Page } from "../../../../types/Page";
|
||||
import { SecretTitleElement } from "../SecretTitleElement";
|
||||
import { getCapabilitiesPath } from "../../../../api/sys/getCapabilities";
|
||||
import { CapabilitiesType, getCapabilitiesPath } from "../../../../api/sys/getCapabilities";
|
||||
import { getTransitKeys } from "../../../../api/transit/getTransitKeys";
|
||||
import i18next from "i18next";
|
||||
import { route } from "preact-router";
|
||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||
import { delSecretsEngineURL, transitNewSecretURL, transitViewSecretURL } from "../../pageLinks";
|
||||
|
||||
type TransitViewListState = {
|
||||
contentLoaded: boolean;
|
||||
transitKeysList: string[];
|
||||
};
|
||||
|
||||
export class TransitViewListItem extends Component<{ page: Page }, TransitViewListState> {
|
||||
export class TransitViewListItem extends Component<{ baseMount: string }, TransitViewListState> {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
|
@ -22,7 +24,7 @@ export class TransitViewListItem extends Component<{ page: Page }, TransitViewLi
|
|||
timer: unknown;
|
||||
|
||||
getTransitKeys(): void {
|
||||
void getTransitKeys(this.props.page.state.baseMount)
|
||||
void getTransitKeys(this.props.baseMount)
|
||||
.then((keys) => {
|
||||
this.setState({
|
||||
contentLoaded: true,
|
||||
|
@ -56,8 +58,7 @@ export class TransitViewListItem extends Component<{ page: Page }, TransitViewLi
|
|||
<li>
|
||||
<a
|
||||
onClick={async () => {
|
||||
this.props.page.state.secretItem = key;
|
||||
await this.props.page.router.changePage("TRANSIT_VIEW_SECRET");
|
||||
route(transitViewSecretURL(this.props.baseMount, key))
|
||||
}}
|
||||
>
|
||||
{key}
|
||||
|
@ -69,31 +70,32 @@ export class TransitViewListItem extends Component<{ page: Page }, TransitViewLi
|
|||
}
|
||||
}
|
||||
|
||||
export class TransitViewPage extends Page {
|
||||
constructor() {
|
||||
super();
|
||||
export class TransitView extends Component<DefaultPageProps, {caps: CapabilitiesType}> {
|
||||
async componentDidMount() {
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
const mountsPath = "/sys/mounts/" + baseMount;
|
||||
|
||||
const caps = await getCapabilitiesPath([mountsPath, baseMount]);
|
||||
this.setState({caps})
|
||||
}
|
||||
|
||||
async goBack(): Promise<void> {
|
||||
await this.router.changePage("SECRETS_HOME");
|
||||
}
|
||||
render() {
|
||||
if (!this.state.caps) return;
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
const mountsPath = "/sys/mounts/" + baseMount;
|
||||
const mountCaps = this.state.caps[mountsPath];
|
||||
const transitCaps = this.state.caps[baseMount];
|
||||
|
||||
async render(): Promise<void> {
|
||||
this.state.secretItem = "";
|
||||
|
||||
const mountsPath = "/sys/mounts/" + this.state.baseMount;
|
||||
const caps = await getCapabilitiesPath([mountsPath, this.state.baseMount]);
|
||||
const mountCaps = caps[mountsPath];
|
||||
const transitCaps = caps[this.state.baseMount];
|
||||
|
||||
render(
|
||||
return (
|
||||
<>
|
||||
<SecretTitleElement type="transit" baseMount={baseMount} />
|
||||
|
||||
<p>
|
||||
{transitCaps.includes("create") && (
|
||||
<button
|
||||
class="uk-button uk-button-primary"
|
||||
onClick={async () => {
|
||||
await this.router.changePage("TRANSIT_NEW_KEY");
|
||||
route(transitNewSecretURL(baseMount));
|
||||
}}
|
||||
>
|
||||
{i18next.t("transit_view_new_btn")}
|
||||
|
@ -103,24 +105,15 @@ export class TransitViewPage extends Page {
|
|||
<button
|
||||
class="uk-button uk-button-danger"
|
||||
onClick={async () => {
|
||||
await this.router.changePage("DELETE_SECRET_ENGINE");
|
||||
route(delSecretsEngineURL(baseMount))
|
||||
}}
|
||||
>
|
||||
{i18next.t("transit_view_delete_btn")}
|
||||
</button>
|
||||
)}
|
||||
</p>
|
||||
<TransitViewListItem page={this} />
|
||||
</>,
|
||||
this.router.pageContentElement,
|
||||
<TransitViewListItem baseMount={baseMount} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
//async renderPageTitle(): Promise<void> {
|
||||
// render(<SecretTitleElement page={this} />, this.router.pageTitleElement);
|
||||
//}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("transit_view_title");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,22 +3,27 @@ import { Page } from "../../../../types/Page";
|
|||
import { SecretTitleElement } from "../SecretTitleElement";
|
||||
import { Tile } from "../../../elements/Tile";
|
||||
import { getTransitKey } from "../../../../api/transit/getTransitKey";
|
||||
import { render } from "preact";
|
||||
import { Component, render } from "preact";
|
||||
import i18next from "i18next";
|
||||
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
||||
import { TransitKeyType } from "../../../../api/types/transit";
|
||||
|
||||
export class TransitViewSecretPage extends Page {
|
||||
constructor() {
|
||||
super();
|
||||
export class TransitViewSecret extends Component<DefaultPageProps, {transitKey: TransitKeyType}> {
|
||||
async componentDidMount() {
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
const secretItem = this.props.matches["secretItem"];
|
||||
const transitKey = await getTransitKey(baseMount, secretItem);
|
||||
this.setState({transitKey});
|
||||
}
|
||||
|
||||
async goBack(): Promise<void> {
|
||||
await this.router.changePage("TRANSIT_VIEW");
|
||||
}
|
||||
render() {
|
||||
if (!this.state.transitKey) return;
|
||||
const baseMount = this.props.matches["baseMount"];
|
||||
const secretItem = this.props.matches["secretItem"];
|
||||
const transitKey = this.state.transitKey;
|
||||
|
||||
|
||||
async render(): Promise<void> {
|
||||
const transitKey = await getTransitKey(this.state.baseMount, this.state.secretItem);
|
||||
|
||||
render(
|
||||
return (
|
||||
<Grid size={GridSizes.MATCHING_TWO_ROWS}>
|
||||
{transitKey.supports_encryption && (
|
||||
<Tile
|
||||
|
@ -26,7 +31,7 @@ export class TransitViewSecretPage extends Page {
|
|||
description={i18next.t("transit_view_encrypt_description")}
|
||||
icon="lock"
|
||||
iconText={i18next.t("transit_view_encrypt_icon_text")}
|
||||
onclick={async () => await this.router.changePage("TRANSIT_ENCRYPT")}
|
||||
onclick={async () => {} /*await this.router.changePage("TRANSIT_ENCRYPT")*/}
|
||||
/>
|
||||
)}
|
||||
{transitKey.supports_decryption && (
|
||||
|
@ -35,7 +40,7 @@ export class TransitViewSecretPage extends Page {
|
|||
description={i18next.t("transit_view_decrypt_description")}
|
||||
icon="mail"
|
||||
iconText={i18next.t("transit_view_decrypt_icon_text")}
|
||||
onclick={async () => await this.router.changePage("TRANSIT_DECRYPT")}
|
||||
onclick={async () => {} /*await this.router.changePage("TRANSIT_DECRYPT")*/}
|
||||
/>
|
||||
)}
|
||||
{transitKey.supports_decryption && (
|
||||
|
@ -44,19 +49,10 @@ export class TransitViewSecretPage extends Page {
|
|||
description={i18next.t("transit_view_rewrap_description")}
|
||||
icon="code"
|
||||
iconText={i18next.t("transit_view_rewrap_icon_text")}
|
||||
onclick={async () => await this.router.changePage("TRANSIT_REWRAP")}
|
||||
onclick={async () => {} /*await this.router.changePage("TRANSIT_REWRAP")*/}
|
||||
/>
|
||||
)}
|
||||
</Grid>,
|
||||
this.router.pageContentElement,
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
//async renderPageTitle(): Promise<void> {
|
||||
// render(<SecretTitleElement page={this} />, this.router.pageTitleElement);
|
||||
//}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("transit_view_secret_title");
|
||||
}
|
||||
}
|
||||
|
|
55
src/ui/pages/pageLinks.tsx
Normal file
55
src/ui/pages/pageLinks.tsx
Normal file
|
@ -0,0 +1,55 @@
|
|||
// Delete Secret Engine
|
||||
|
||||
export function delSecretsEngineURL(baseMount: string): string {
|
||||
return `/secrets/delete_engine/${baseMount}`;
|
||||
}
|
||||
|
||||
// Secrets / Key Value
|
||||
|
||||
export function kvNewURL(baseMount: string, secretPath?: string[]): string {
|
||||
return `/secrets/kv/new/${baseMount}` + secretPath ? `/${secretPath.join("/")}` : "";
|
||||
}
|
||||
|
||||
export function kvDeleteURL(baseMount: string, secretPath: string[], secret: string): string {
|
||||
return `/secrets/kv/delete/${secret}/${baseMount}/${secretPath.join("/")}`;
|
||||
}
|
||||
|
||||
export function kvEditURL(baseMount: string, secretPath: string[], secret: string): string {
|
||||
return `/secrets/kv/edit/${secret}/${baseMount}/${secretPath.join("/")}`;
|
||||
}
|
||||
|
||||
export function kvViewURL(baseMount: string, secretPath: string[], secret: string): string {
|
||||
return `/secrets/kv/view/${secret}/${baseMount}/${secretPath.join("/")}`;
|
||||
}
|
||||
|
||||
export function kvListURL(baseMount: string, secretPath: string[]): string {
|
||||
console.log(baseMount, secretPath);
|
||||
return `/secrets/kv/list/${baseMount}/${secretPath.join("/")}`;
|
||||
}
|
||||
|
||||
// Secrets / TOTP
|
||||
|
||||
export function totpNewURL(baseMount: string): string {
|
||||
return `/secrets/totp/new/${baseMount}`;
|
||||
}
|
||||
|
||||
export function totpListURL(baseMount: string): string {
|
||||
return `/secrets/totp/list/${baseMount}`;
|
||||
}
|
||||
|
||||
export function totpDeleteURL(baseMount: string, secret: string): string {
|
||||
return `/secrets/totp/delete/${baseMount}/${secret}`;
|
||||
}
|
||||
|
||||
// Secrets / Transit
|
||||
|
||||
export function transitNewSecretURL(baseMount: string): string {
|
||||
return `/secrets/transit/new/${baseMount}`;
|
||||
}
|
||||
|
||||
export function transitViewSecretURL(baseMount: string, secret: string): string {
|
||||
return `/secrets/transit/view/${baseMount}/${secret}`;
|
||||
}
|
||||
|
||||
|
||||
//
|
Loading…
Reference in a new issue