From db02e0e91bf01554f534a48122a87fce50092906 Mon Sep 17 00:00:00 2001 From: Kitteh Date: Tue, 18 May 2021 11:10:47 +0100 Subject: [PATCH] Move Secrets home to its own page and move secrets pages into their own folder. --- readme.md | 2 +- src/allPages.ts | 38 ++++---- src/pages/Home.ts | 90 ++++-------------- .../{ => Secrets}/KeyValue/KeyValueDelete.ts | 6 +- .../{ => Secrets}/KeyValue/KeyValueNew.ts | 8 +- .../{ => Secrets}/KeyValue/KeyValueSecret.ts | 14 +-- .../KeyValue/KeyValueSecretsEdit.ts | 12 +-- .../KeyValue/KeyValueVersions.ts | 8 +- .../{ => Secrets}/KeyValue/KeyValueView.ts | 12 +-- .../{ => Secrets}/NewEngines/NewKVEngine.ts | 13 ++- .../{ => Secrets}/NewEngines/NewTOTPEngine.ts | 11 ++- .../NewEngines/NewTransitEngine.ts | 11 ++- src/pages/{ => Secrets}/NewSecretsEngine.ts | 4 +- src/pages/Secrets/SecretsHome.ts | 95 +++++++++++++++++++ src/pages/{ => Secrets}/TOTP/NewTOTP.ts | 12 +-- src/pages/{ => Secrets}/TOTP/TOTPView.ts | 20 ++-- .../{ => Secrets}/Transit/NewTransitKey.ts | 12 +-- .../{ => Secrets}/Transit/TransitDecrypt.ts | 16 ++-- .../{ => Secrets}/Transit/TransitEncrypt.ts | 16 ++-- .../{ => Secrets}/Transit/TransitRewrap.ts | 18 ++-- .../{ => Secrets}/Transit/TransitView.ts | 12 +-- .../Transit/TransitViewSecret.ts | 8 +- src/translations/en.js | 13 ++- src/translations/fr.js | 6 +- src/translations/ru.js | 6 +- webpack-dev.config.js | 60 ++++++++++++ webpack.config.js | 11 +-- 27 files changed, 325 insertions(+), 209 deletions(-) rename src/pages/{ => Secrets}/KeyValue/KeyValueDelete.ts (89%) rename src/pages/{ => Secrets}/KeyValue/KeyValueNew.ts (90%) rename src/pages/{ => Secrets}/KeyValue/KeyValueSecret.ts (92%) rename src/pages/{ => Secrets}/KeyValue/KeyValueSecretsEdit.ts (85%) rename src/pages/{ => Secrets}/KeyValue/KeyValueVersions.ts (85%) rename src/pages/{ => Secrets}/KeyValue/KeyValueView.ts (89%) rename src/pages/{ => Secrets}/NewEngines/NewKVEngine.ts (86%) rename src/pages/{ => Secrets}/NewEngines/NewTOTPEngine.ts (85%) rename src/pages/{ => Secrets}/NewEngines/NewTransitEngine.ts (85%) rename src/pages/{ => Secrets}/NewSecretsEngine.ts (94%) create mode 100644 src/pages/Secrets/SecretsHome.ts rename src/pages/{ => Secrets}/TOTP/NewTOTP.ts (89%) rename src/pages/{ => Secrets}/TOTP/TOTPView.ts (84%) rename src/pages/{ => Secrets}/Transit/NewTransitKey.ts (87%) rename src/pages/{ => Secrets}/Transit/TransitDecrypt.ts (87%) rename src/pages/{ => Secrets}/Transit/TransitEncrypt.ts (87%) rename src/pages/{ => Secrets}/Transit/TransitRewrap.ts (86%) rename src/pages/{ => Secrets}/Transit/TransitView.ts (84%) rename src/pages/{ => Secrets}/Transit/TransitViewSecret.ts (89%) create mode 100644 webpack-dev.config.js diff --git a/readme.md b/readme.md index 5515e36..257f704 100644 --- a/readme.md +++ b/readme.md @@ -14,7 +14,7 @@ The resulting built files will be in `dist/` Use whatever browser you want, I personally test on latest Microsoft Edge Dev build. ``` npm install --save-dev -WEBPACK_MODE=development BROWSER=google-chrome npx webpack serve +BROWSER=google-chrome npx webpack serve --config webpack-dev.config.js ``` ## Translating diff --git a/src/allPages.ts b/src/allPages.ts index 953290a..06b2923 100644 --- a/src/allPages.ts +++ b/src/allPages.ts @@ -1,28 +1,29 @@ import { HomePage } from "./pages/Home"; -import { KeyValueDeletePage } from "./pages/KeyValue/KeyValueDelete"; -import { KeyValueNewPage } from "./pages/KeyValue/KeyValueNew"; -import { KeyValueSecretEditPage } from "./pages/KeyValue/KeyValueSecretsEdit"; -import { KeyValueSecretPage } from "./pages/KeyValue/KeyValueSecret"; -import { KeyValueVersionsPage } from "./pages/KeyValue/KeyValueVersions"; -import { KeyValueViewPage } from "./pages/KeyValue/KeyValueView"; +import { KeyValueDeletePage } from "./pages/Secrets/KeyValue/KeyValueDelete"; +import { KeyValueNewPage } from "./pages/Secrets/KeyValue/KeyValueNew"; +import { KeyValueSecretEditPage } from "./pages/Secrets/KeyValue/KeyValueSecretsEdit"; +import { KeyValueSecretPage } from "./pages/Secrets/KeyValue/KeyValueSecret"; +import { KeyValueVersionsPage } from "./pages/Secrets/KeyValue/KeyValueVersions"; +import { KeyValueViewPage } from "./pages/Secrets/KeyValue/KeyValueView"; import { LoginPage } from "./pages/Login"; import { MePage } from "./pages/Me"; -import { NewKVEnginePage } from "./pages/NewEngines/NewKVEngine"; -import { NewSecretsEnginePage } from "./pages/NewSecretsEngine"; -import { NewTOTPEnginePage } from "./pages/NewEngines/NewTOTPEngine"; -import { NewTOTPPage } from "./pages/TOTP/NewTOTP"; -import { NewTransitEnginePage } from "./pages/NewEngines/NewTransitEngine"; -import { NewTransitKeyPage } from "./pages/Transit/NewTransitKey"; +import { NewKVEnginePage } from "./pages/Secrets/NewEngines/NewKVEngine"; +import { NewSecretsEnginePage } from "./pages/Secrets/NewSecretsEngine"; +import { NewTOTPEnginePage } from "./pages/Secrets/NewEngines/NewTOTPEngine"; +import { NewTOTPPage } from "./pages/Secrets/TOTP/NewTOTP"; +import { NewTransitEnginePage } from "./pages/Secrets/NewEngines/NewTransitEngine"; +import { NewTransitKeyPage } from "./pages/Secrets/Transit/NewTransitKey"; import { Page } from "./types/Page"; import { PwGenPage } from "./pages/PwGen"; +import { SecretsHomePage } from "./pages/Secrets/SecretsHome"; import { SetLanguagePage } from "./pages/SetLanguage"; import { SetVaultURLPage } from "./pages/SetVaultURL"; -import { TOTPViewPage } from "./pages/TOTP/TOTPView"; -import { TransitDecryptPage } from "./pages/Transit/TransitDecrypt"; -import { TransitEncryptPage } from "./pages/Transit/TransitEncrypt"; -import { TransitRewrapPage } from "./pages/Transit/TransitRewrap"; -import { TransitViewPage } from "./pages/Transit/TransitView"; -import { TransitViewSecretPage } from "./pages/Transit/TransitViewSecret"; +import { TOTPViewPage } from "./pages/Secrets/TOTP/TOTPView"; +import { TransitDecryptPage } from "./pages/Secrets/Transit/TransitDecrypt"; +import { TransitEncryptPage } from "./pages/Secrets/Transit/TransitEncrypt"; +import { TransitRewrapPage } from "./pages/Secrets/Transit/TransitRewrap"; +import { TransitViewPage } from "./pages/Secrets/Transit/TransitView"; +import { TransitViewSecretPage } from "./pages/Secrets/Transit/TransitViewSecret"; import { UnsealPage } from "./pages/Unseal"; import { getObjectKeys } from "./utils"; @@ -36,6 +37,7 @@ type pagesList = { export const allPages: pagesList = { HOME: new HomePage(), + SECRETS_HOME: new SecretsHomePage(), ME: new MePage(), TOTP: new TOTPViewPage(), NEW_TOTP: new NewTOTPPage(), diff --git a/src/pages/Home.ts b/src/pages/Home.ts index 5fed347..f1734c6 100644 --- a/src/pages/Home.ts +++ b/src/pages/Home.ts @@ -1,10 +1,8 @@ -import { MountType, getMounts } from "../api/sys/getMounts"; import { Page } from "../types/Page"; -import { getCapabilitiesPath } from "../api/sys/getCapabilities"; +import { Tile } from "../elements/Tile"; import { lookupSelf } from "../api/sys/lookupSelf"; import { makeElement } from "z-makeelement"; import { prePageChecks, setErrorText } from "../pageUtils"; -import { sortedObjectMap } from "../utils"; import i18next from "i18next"; export class HomePage extends Page { @@ -25,14 +23,14 @@ export class HomePage extends Page { tag: "li", children: makeElement({ tag: "span", - html: i18next.t("vaulturl_text", { text: this.state.apiURL }), + html: i18next.t("home_vaulturl_text", { text: this.state.apiURL }), }), }), makeElement({ tag: "li", children: makeElement({ tag: "a", - text: i18next.t("password_generator_btn"), + text: i18next.t("home_password_generator_btn"), onclick: async () => { await this.router.changePage("PW_GEN"); }, @@ -47,7 +45,7 @@ export class HomePage extends Page { textList.appendChild( makeElement({ tag: "li", - text: i18next.t("your_token_expires_in", { + text: i18next.t("home_your_token_expires_in", { date: new Date(selfTokenInfo.expire_time), }), }), @@ -61,74 +59,24 @@ export class HomePage extends Page { } } - const mountsCapabilities = await getCapabilitiesPath("/sys/mounts"); - if (mountsCapabilities.includes("sudo") && mountsCapabilities.includes("create")) { - textList.appendChild( - makeElement({ - tag: "button", - text: i18next.t("home_new_secrets_engine_button"), - class: ["uk-button", "uk-button-primary", "uk-margin-top"], - onclick: async () => { - await this.router.changePage("NEW_SECRETS_ENGINE"); - }, - }), - ); - } - - this.state.currentBaseMount = ""; - this.state.currentSecretPath = []; - this.state.currentSecret = ""; - this.state.currentSecretVersion = null; - - const navList = makeElement({ - tag: "ul", - class: ["uk-nav", "uk-nav-default", "uk-margin-top"], - }); - homePageContent.appendChild(navList); - - const mounts = await getMounts(); - // sort it by secretPath so it's in alphabetical order consistantly. - const mountsMap = sortedObjectMap(mounts); - - mountsMap.forEach((mount: MountType, baseMount) => { - if (typeof mount != "object") return; - if (mount == null) return; - if (!("type" in mount)) return; - if (!["kv", "totp", "transit", "cubbyhole"].includes(mount.type)) return; - - const mountType = mount.type == "kv" ? "kv-v" + String(mount.options.version) : mount.type; - - let linkText = ""; - let linkPage: string; - if (mount.type == "kv") { - linkText = `K/V (v${mount.options.version}) - ${baseMount}`; - linkPage = "KEY_VALUE_VIEW"; - } else if (mount.type == "totp") { - linkText = `TOTP - ${baseMount}`; - linkPage = "TOTP"; - } else if (mount.type == "transit") { - linkText = `Transit - ${baseMount}`; - linkPage = "TRANSIT_VIEW"; - } else if (mount.type == "cubbyhole") { - linkText = `Cubbyhole - ${baseMount}`; - linkPage = "KEY_VALUE_VIEW"; - } - - navList.appendChild( - makeElement({ - tag: "li", - children: makeElement({ - tag: "a", - text: linkText, + textList.appendChild( + makeElement({ + tag: "div", + class: + "uk-child-width-1-1@s uk-child-width-1-2@m uk-grid-small uk-grid-match uk-margin-top", + attributes: { "uk-grid": "" }, + children: [ + Tile({ + title: i18next.t("home_secrets_title"), + description: i18next.t("home_secrets_description"), + icon: "file-edit", onclick: async () => { - this.state.currentBaseMount = baseMount; - this.state.currentMountType = mountType; - await this.router.changePage(linkPage); + await this.router.changePage("SECRETS_HOME"); }, }), - }), - ); - }); + ], + }), + ); } get name(): string { return i18next.t("home_page_title"); diff --git a/src/pages/KeyValue/KeyValueDelete.ts b/src/pages/Secrets/KeyValue/KeyValueDelete.ts similarity index 89% rename from src/pages/KeyValue/KeyValueDelete.ts rename to src/pages/Secrets/KeyValue/KeyValueDelete.ts index 7472555..7a91edc 100644 --- a/src/pages/KeyValue/KeyValueDelete.ts +++ b/src/pages/Secrets/KeyValue/KeyValueDelete.ts @@ -1,6 +1,6 @@ -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { deleteSecret } from "../../api/kv/deleteSecret"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { deleteSecret } from "../../../api/kv/deleteSecret"; import { makeElement } from "z-makeelement"; import i18next from "i18next"; diff --git a/src/pages/KeyValue/KeyValueNew.ts b/src/pages/Secrets/KeyValue/KeyValueNew.ts similarity index 90% rename from src/pages/KeyValue/KeyValueNew.ts rename to src/pages/Secrets/KeyValue/KeyValueNew.ts index d2370e5..54dd3ba 100644 --- a/src/pages/KeyValue/KeyValueNew.ts +++ b/src/pages/Secrets/KeyValue/KeyValueNew.ts @@ -1,8 +1,8 @@ -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { createOrUpdateSecret } from "../../api/kv/createOrUpdateSecret"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { createOrUpdateSecret } from "../../../api/kv/createOrUpdateSecret"; import { makeElement } from "z-makeelement"; -import { setErrorText } from "../../pageUtils"; +import { setErrorText } from "../../../pageUtils"; import i18next from "i18next"; export class KeyValueNewPage extends Page { diff --git a/src/pages/KeyValue/KeyValueSecret.ts b/src/pages/Secrets/KeyValue/KeyValueSecret.ts similarity index 92% rename from src/pages/KeyValue/KeyValueSecret.ts rename to src/pages/Secrets/KeyValue/KeyValueSecret.ts index d411ef5..c9126dd 100644 --- a/src/pages/KeyValue/KeyValueSecret.ts +++ b/src/pages/Secrets/KeyValue/KeyValueSecret.ts @@ -1,11 +1,11 @@ -import { CopyableInputBox } from "../../elements/CopyableInputBox"; -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { getCapabilities } from "../../api/sys/getCapabilities"; -import { getSecret } from "../../api/kv/getSecret"; +import { CopyableInputBox } from "../../../elements/CopyableInputBox"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { getCapabilities } from "../../../api/sys/getCapabilities"; +import { getSecret } from "../../../api/kv/getSecret"; import { makeElement } from "z-makeelement"; -import { sortedObjectMap } from "../../utils"; -import { undeleteSecret } from "../../api/kv/undeleteSecret"; +import { sortedObjectMap } from "../../../utils"; +import { undeleteSecret } from "../../../api/kv/undeleteSecret"; import Prism from "prismjs"; import i18next from "i18next"; diff --git a/src/pages/KeyValue/KeyValueSecretsEdit.ts b/src/pages/Secrets/KeyValue/KeyValueSecretsEdit.ts similarity index 85% rename from src/pages/KeyValue/KeyValueSecretsEdit.ts rename to src/pages/Secrets/KeyValue/KeyValueSecretsEdit.ts index d5b35a3..bb71c5d 100644 --- a/src/pages/KeyValue/KeyValueSecretsEdit.ts +++ b/src/pages/Secrets/KeyValue/KeyValueSecretsEdit.ts @@ -1,11 +1,11 @@ import { CodeJar } from "codejar"; -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { createOrUpdateSecret } from "../../api/kv/createOrUpdateSecret"; -import { getSecret } from "../../api/kv/getSecret"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { createOrUpdateSecret } from "../../../api/kv/createOrUpdateSecret"; +import { getSecret } from "../../../api/kv/getSecret"; import { makeElement } from "z-makeelement"; -import { setErrorText } from "../../pageUtils"; -import { sortedObjectMap, verifyJSONString } from "../../utils"; +import { setErrorText } from "../../../pageUtils"; +import { sortedObjectMap, verifyJSONString } from "../../../utils"; import i18next from "i18next"; export class KeyValueSecretEditPage extends Page { diff --git a/src/pages/KeyValue/KeyValueVersions.ts b/src/pages/Secrets/KeyValue/KeyValueVersions.ts similarity index 85% rename from src/pages/KeyValue/KeyValueVersions.ts rename to src/pages/Secrets/KeyValue/KeyValueVersions.ts index 1bba1cb..e630390 100644 --- a/src/pages/KeyValue/KeyValueVersions.ts +++ b/src/pages/Secrets/KeyValue/KeyValueVersions.ts @@ -1,8 +1,8 @@ -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { getSecretMetadata } from "../../api/kv/getSecretMetadata"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { getSecretMetadata } from "../../../api/kv/getSecretMetadata"; import { makeElement } from "z-makeelement"; -import { objectToMap } from "../../utils"; +import { objectToMap } from "../../../utils"; import i18next from "i18next"; export class KeyValueVersionsPage extends Page { diff --git a/src/pages/KeyValue/KeyValueView.ts b/src/pages/Secrets/KeyValue/KeyValueView.ts similarity index 89% rename from src/pages/KeyValue/KeyValueView.ts rename to src/pages/Secrets/KeyValue/KeyValueView.ts index d8fe49e..1e482ac 100644 --- a/src/pages/KeyValue/KeyValueView.ts +++ b/src/pages/Secrets/KeyValue/KeyValueView.ts @@ -1,9 +1,9 @@ -import { DoesNotExistError } from "../../types/internalErrors"; -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { getSecrets } from "../../api/kv/getSecrets"; +import { DoesNotExistError } from "../../../types/internalErrors"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { getSecrets } from "../../../api/kv/getSecrets"; import { makeElement } from "z-makeelement"; -import { setErrorText } from "../../pageUtils"; +import { setErrorText } from "../../../pageUtils"; import i18next from "i18next"; export class KeyValueViewPage extends Page { @@ -15,7 +15,7 @@ export class KeyValueViewPage extends Page { this.state.popCurrentSecretPath(); await this.router.changePage("KEY_VALUE_VIEW"); } else { - await this.router.changePage("HOME"); + await this.router.changePage("SECRETS_HOME"); } } async render(): Promise { diff --git a/src/pages/NewEngines/NewKVEngine.ts b/src/pages/Secrets/NewEngines/NewKVEngine.ts similarity index 86% rename from src/pages/NewEngines/NewKVEngine.ts rename to src/pages/Secrets/NewEngines/NewKVEngine.ts index 4aa8caa..0eea261 100644 --- a/src/pages/NewEngines/NewKVEngine.ts +++ b/src/pages/Secrets/NewEngines/NewKVEngine.ts @@ -1,15 +1,18 @@ -import { Margin } from "../../elements/Margin"; -import { Option } from "../../elements/Option"; -import { Page } from "../../types/Page"; +import { Margin } from "../../../elements/Margin"; +import { Option } from "../../../elements/Option"; +import { Page } from "../../../types/Page"; import { makeElement } from "z-makeelement"; -import { newMount } from "../../api/sys/newMount"; -import { setErrorText } from "../../pageUtils"; +import { newMount } from "../../../api/sys/newMount"; +import { setErrorText } from "../../../pageUtils"; import i18next from "i18next"; export class NewKVEnginePage extends Page { constructor() { super(); } + async goBack(): Promise { + await this.router.changePage("SECRETS_HOME"); + } async render(): Promise { const newEngineForm = makeElement({ tag: "form", diff --git a/src/pages/NewEngines/NewTOTPEngine.ts b/src/pages/Secrets/NewEngines/NewTOTPEngine.ts similarity index 85% rename from src/pages/NewEngines/NewTOTPEngine.ts rename to src/pages/Secrets/NewEngines/NewTOTPEngine.ts index 3bfcad8..96525cf 100644 --- a/src/pages/NewEngines/NewTOTPEngine.ts +++ b/src/pages/Secrets/NewEngines/NewTOTPEngine.ts @@ -1,14 +1,17 @@ -import { Margin } from "../../elements/Margin"; -import { Page } from "../../types/Page"; +import { Margin } from "../../../elements/Margin"; +import { Page } from "../../../types/Page"; import { makeElement } from "z-makeelement"; -import { newMount } from "../../api/sys/newMount"; -import { setErrorText } from "../../pageUtils"; +import { newMount } from "../../../api/sys/newMount"; +import { setErrorText } from "../../../pageUtils"; import i18next from "i18next"; export class NewTOTPEnginePage extends Page { constructor() { super(); } + async goBack(): Promise { + await this.router.changePage("SECRETS_HOME"); + } async render(): Promise { const newEngineForm = makeElement({ tag: "form", diff --git a/src/pages/NewEngines/NewTransitEngine.ts b/src/pages/Secrets/NewEngines/NewTransitEngine.ts similarity index 85% rename from src/pages/NewEngines/NewTransitEngine.ts rename to src/pages/Secrets/NewEngines/NewTransitEngine.ts index c92d466..0ef2acb 100644 --- a/src/pages/NewEngines/NewTransitEngine.ts +++ b/src/pages/Secrets/NewEngines/NewTransitEngine.ts @@ -1,14 +1,17 @@ -import { Margin } from "../../elements/Margin"; -import { Page } from "../../types/Page"; +import { Margin } from "../../../elements/Margin"; +import { Page } from "../../../types/Page"; import { makeElement } from "z-makeelement"; -import { newMount } from "../../api/sys/newMount"; -import { setErrorText } from "../../pageUtils"; +import { newMount } from "../../../api/sys/newMount"; +import { setErrorText } from "../../../pageUtils"; import i18next from "i18next"; export class NewTransitEnginePage extends Page { constructor() { super(); } + async goBack(): Promise { + await this.router.changePage("SECRETS_HOME"); + } async render(): Promise { const newEngineForm = makeElement({ tag: "form", diff --git a/src/pages/NewSecretsEngine.ts b/src/pages/Secrets/NewSecretsEngine.ts similarity index 94% rename from src/pages/NewSecretsEngine.ts rename to src/pages/Secrets/NewSecretsEngine.ts index f5b38e8..deb70dd 100644 --- a/src/pages/NewSecretsEngine.ts +++ b/src/pages/Secrets/NewSecretsEngine.ts @@ -1,5 +1,5 @@ -import { Page } from "../types/Page"; -import { Tile } from "../elements/Tile"; +import { Page } from "../../types/Page"; +import { Tile } from "../../elements/Tile"; import { makeElement } from "z-makeelement"; import i18next from "i18next"; diff --git a/src/pages/Secrets/SecretsHome.ts b/src/pages/Secrets/SecretsHome.ts new file mode 100644 index 0000000..38a2f47 --- /dev/null +++ b/src/pages/Secrets/SecretsHome.ts @@ -0,0 +1,95 @@ +import { MountType, getMounts } from "../../api/sys/getMounts"; +import { Page } from "../../types/Page"; +import { getCapabilitiesPath } from "../../api/sys/getCapabilities"; +import { makeElement } from "z-makeelement"; +import { prePageChecks } from "../../pageUtils"; +import { sortedObjectMap } from "../../utils"; +import i18next from "i18next"; + +export class SecretsHomePage extends Page { + constructor() { + super(); + } + async goBack(): Promise { + await this.router.changePage("HOME"); + } + async render(): Promise { + await this.router.setPageContent(""); + if (!(await prePageChecks(this.router))) return; + + const homePageContent = makeElement({ tag: "div" }); + await this.router.setPageContent(homePageContent); + + const mountsCapabilities = await getCapabilitiesPath("/sys/mounts"); + if (mountsCapabilities.includes("sudo") && mountsCapabilities.includes("create")) { + homePageContent.appendChild( + makeElement({ + tag: "button", + text: i18next.t("secrets_home_new_secrets_engine_button"), + class: ["uk-button", "uk-button-primary"], + onclick: async () => { + await this.router.changePage("NEW_SECRETS_ENGINE"); + }, + }), + ); + } + + this.state.currentBaseMount = ""; + this.state.currentSecretPath = []; + this.state.currentSecret = ""; + this.state.currentSecretVersion = null; + + const navList = makeElement({ + tag: "ul", + class: ["uk-nav", "uk-nav-default", "uk-margin-top"], + }); + homePageContent.appendChild(navList); + + const mounts = await getMounts(); + // sort it by secretPath so it's in alphabetical order consistantly. + const mountsMap = sortedObjectMap(mounts); + + mountsMap.forEach((mount: MountType, baseMount) => { + if (typeof mount != "object") return; + if (mount == null) return; + if (!("type" in mount)) return; + if (!["kv", "totp", "transit", "cubbyhole"].includes(mount.type)) return; + + const mountType = mount.type == "kv" ? "kv-v" + String(mount.options.version) : mount.type; + + let linkText = ""; + let linkPage: string; + if (mount.type == "kv") { + linkText = `K/V (v${mount.options.version}) - ${baseMount}`; + linkPage = "KEY_VALUE_VIEW"; + } else if (mount.type == "totp") { + linkText = `TOTP - ${baseMount}`; + linkPage = "TOTP"; + } else if (mount.type == "transit") { + linkText = `Transit - ${baseMount}`; + linkPage = "TRANSIT_VIEW"; + } else if (mount.type == "cubbyhole") { + linkText = `Cubbyhole - ${baseMount}`; + linkPage = "KEY_VALUE_VIEW"; + } + + navList.appendChild( + makeElement({ + tag: "li", + children: makeElement({ + tag: "a", + text: linkText, + onclick: async () => { + this.state.currentBaseMount = baseMount; + this.state.currentMountType = mountType; + await this.router.changePage(linkPage); + }, + }), + }), + ); + }); + } + get name(): string { + return i18next.t("secrets_home_page_title"); + } +} diff --git a/src/pages/TOTP/NewTOTP.ts b/src/pages/Secrets/TOTP/NewTOTP.ts similarity index 89% rename from src/pages/TOTP/NewTOTP.ts rename to src/pages/Secrets/TOTP/NewTOTP.ts index 1756ef0..2fb2fba 100644 --- a/src/pages/TOTP/NewTOTP.ts +++ b/src/pages/Secrets/TOTP/NewTOTP.ts @@ -1,10 +1,10 @@ -import { Margin } from "../../elements/Margin"; -import { MarginInline } from "../../elements/MarginInline"; -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { addNewTOTP } from "../../api/totp/addNewTOTP"; +import { Margin } from "../../../elements/Margin"; +import { MarginInline } from "../../../elements/MarginInline"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { addNewTOTP } from "../../../api/totp/addNewTOTP"; import { makeElement } from "z-makeelement"; -import { setErrorText } from "../../pageUtils"; +import { setErrorText } from "../../../pageUtils"; import i18next from "i18next"; function replaceAll(str: string, replace: string, replaceWith: string): string { diff --git a/src/pages/TOTP/TOTPView.ts b/src/pages/Secrets/TOTP/TOTPView.ts similarity index 84% rename from src/pages/TOTP/TOTPView.ts rename to src/pages/Secrets/TOTP/TOTPView.ts index b442b19..46807d2 100644 --- a/src/pages/TOTP/TOTPView.ts +++ b/src/pages/Secrets/TOTP/TOTPView.ts @@ -1,12 +1,12 @@ -import { CopyableInputBox } from "../../elements/CopyableInputBox"; -import { DoesNotExistError } from "../../types/internalErrors"; -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { getTOTPCode } from "../../api/totp/getTOTPCode"; -import { getTOTPKeys } from "../../api/totp/getTOTPKeys"; +import { CopyableInputBox } from "../../../elements/CopyableInputBox"; +import { DoesNotExistError } from "../../../types/internalErrors"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { getTOTPCode } from "../../../api/totp/getTOTPCode"; +import { getTOTPKeys } from "../../../api/totp/getTOTPKeys"; import { makeElement } from "z-makeelement"; -import { objectToMap } from "../../utils"; -import { setErrorText } from "../../pageUtils"; +import { objectToMap } from "../../../utils"; +import { setErrorText } from "../../../pageUtils"; import i18next from "i18next"; export interface TOTPListElement extends HTMLElement { @@ -23,6 +23,10 @@ export class TOTPViewPage extends Page { refresher: number; totpListElements: Record; + async goBack(): Promise { + await this.router.changePage("SECRETS_HOME"); + } + async render(): Promise { const totpList = makeElement({ tag: "div" }); await this.router.setPageContent( diff --git a/src/pages/Transit/NewTransitKey.ts b/src/pages/Secrets/Transit/NewTransitKey.ts similarity index 87% rename from src/pages/Transit/NewTransitKey.ts rename to src/pages/Secrets/Transit/NewTransitKey.ts index 006b137..00db21a 100644 --- a/src/pages/Transit/NewTransitKey.ts +++ b/src/pages/Secrets/Transit/NewTransitKey.ts @@ -1,10 +1,10 @@ -import { Margin } from "../../elements/Margin"; -import { Option } from "../../elements/Option"; -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; +import { Margin } from "../../../elements/Margin"; +import { Option } from "../../../elements/Option"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; import { makeElement } from "z-makeelement"; -import { newTransitKey } from "../../api/transit/newTransitKey"; -import { setErrorText } from "../../pageUtils"; +import { newTransitKey } from "../../../api/transit/newTransitKey"; +import { setErrorText } from "../../../pageUtils"; import i18next from "i18next"; export class NewTransitKeyPage extends Page { diff --git a/src/pages/Transit/TransitDecrypt.ts b/src/pages/Secrets/Transit/TransitDecrypt.ts similarity index 87% rename from src/pages/Transit/TransitDecrypt.ts rename to src/pages/Secrets/Transit/TransitDecrypt.ts index e9da182..8b5d6b2 100644 --- a/src/pages/Transit/TransitDecrypt.ts +++ b/src/pages/Secrets/Transit/TransitDecrypt.ts @@ -1,12 +1,12 @@ -import { CopyableModal } from "../../elements/CopyableModal"; -import { FileUploadInput } from "../../elements/FileUploadInput"; -import { Margin } from "../../elements/Margin"; -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { fileToBase64 } from "../../htmlUtils"; +import { CopyableModal } from "../../../elements/CopyableModal"; +import { FileUploadInput } from "../../../elements/FileUploadInput"; +import { Margin } from "../../../elements/Margin"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { fileToBase64 } from "../../../htmlUtils"; import { makeElement } from "z-makeelement"; -import { setErrorText } from "../../pageUtils"; -import { transitDecrypt } from "../../api/transit/transitDecrypt"; +import { setErrorText } from "../../../pageUtils"; +import { transitDecrypt } from "../../../api/transit/transitDecrypt"; import i18next from "i18next"; export class TransitDecryptPage extends Page { diff --git a/src/pages/Transit/TransitEncrypt.ts b/src/pages/Secrets/Transit/TransitEncrypt.ts similarity index 87% rename from src/pages/Transit/TransitEncrypt.ts rename to src/pages/Secrets/Transit/TransitEncrypt.ts index 1cf1169..1ffaf9f 100644 --- a/src/pages/Transit/TransitEncrypt.ts +++ b/src/pages/Secrets/Transit/TransitEncrypt.ts @@ -1,12 +1,12 @@ -import { CopyableModal } from "../../elements/CopyableModal"; -import { FileUploadInput } from "../../elements/FileUploadInput"; -import { Margin } from "../../elements/Margin"; -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { fileToBase64 } from "../../htmlUtils"; +import { CopyableModal } from "../../../elements/CopyableModal"; +import { FileUploadInput } from "../../../elements/FileUploadInput"; +import { Margin } from "../../../elements/Margin"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { fileToBase64 } from "../../../htmlUtils"; import { makeElement } from "z-makeelement"; -import { setErrorText } from "../../pageUtils"; -import { transitEncrypt } from "../../api/transit/transitEncrypt"; +import { setErrorText } from "../../../pageUtils"; +import { transitEncrypt } from "../../../api/transit/transitEncrypt"; import i18next from "i18next"; export class TransitEncryptPage extends Page { diff --git a/src/pages/Transit/TransitRewrap.ts b/src/pages/Secrets/Transit/TransitRewrap.ts similarity index 86% rename from src/pages/Transit/TransitRewrap.ts rename to src/pages/Secrets/Transit/TransitRewrap.ts index 1c3cf68..558a229 100644 --- a/src/pages/Transit/TransitRewrap.ts +++ b/src/pages/Secrets/Transit/TransitRewrap.ts @@ -1,13 +1,13 @@ -import { CopyableModal } from "../../elements/CopyableModal"; -import { Margin } from "../../elements/Margin"; -import { Option } from "../../elements/Option"; -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { getTransitKey } from "../../api/transit/getTransitKey"; +import { CopyableModal } from "../../../elements/CopyableModal"; +import { Margin } from "../../../elements/Margin"; +import { Option } from "../../../elements/Option"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { getTransitKey } from "../../../api/transit/getTransitKey"; import { makeElement } from "z-makeelement"; -import { objectToMap } from "../../utils"; -import { setErrorText } from "../../pageUtils"; -import { transitRewrap } from "../../api/transit/transitRewrap"; +import { objectToMap } from "../../../utils"; +import { setErrorText } from "../../../pageUtils"; +import { transitRewrap } from "../../../api/transit/transitRewrap"; import i18next from "i18next"; type versionOption = { version: string; label: string }; diff --git a/src/pages/Transit/TransitView.ts b/src/pages/Secrets/Transit/TransitView.ts similarity index 84% rename from src/pages/Transit/TransitView.ts rename to src/pages/Secrets/Transit/TransitView.ts index 68440dc..938e71c 100644 --- a/src/pages/Transit/TransitView.ts +++ b/src/pages/Secrets/Transit/TransitView.ts @@ -1,9 +1,9 @@ -import { DoesNotExistError } from "../../types/internalErrors"; -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { getTransitKeys } from "../../api/transit/getTransitKeys"; +import { DoesNotExistError } from "../../../types/internalErrors"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { getTransitKeys } from "../../../api/transit/getTransitKeys"; import { makeElement } from "z-makeelement"; -import { setErrorText } from "../../pageUtils"; +import { setErrorText } from "../../../pageUtils"; import i18next from "i18next"; export class TransitViewPage extends Page { @@ -12,7 +12,7 @@ export class TransitViewPage extends Page { } async goBack(): Promise { - await this.router.changePage("HOME"); + await this.router.changePage("SECRETS_HOME"); } async render(): Promise { diff --git a/src/pages/Transit/TransitViewSecret.ts b/src/pages/Secrets/Transit/TransitViewSecret.ts similarity index 89% rename from src/pages/Transit/TransitViewSecret.ts rename to src/pages/Secrets/Transit/TransitViewSecret.ts index 556f591..3b96d90 100644 --- a/src/pages/Transit/TransitViewSecret.ts +++ b/src/pages/Secrets/Transit/TransitViewSecret.ts @@ -1,7 +1,7 @@ -import { Page } from "../../types/Page"; -import { SecretTitleElement } from "../../elements/SecretTitleElement"; -import { Tile } from "../../elements/Tile"; -import { getTransitKey } from "../../api/transit/getTransitKey"; +import { Page } from "../../../types/Page"; +import { SecretTitleElement } from "../../../elements/SecretTitleElement"; +import { Tile } from "../../../elements/Tile"; +import { getTransitKey } from "../../../api/transit/getTransitKey"; import { makeElement } from "z-makeelement"; import i18next from "i18next"; diff --git a/src/translations/en.js b/src/translations/en.js index 762dbaa..a05a388 100644 --- a/src/translations/en.js +++ b/src/translations/en.js @@ -34,10 +34,15 @@ module.exports = { // Home Page home_page_title: "Home", - vaulturl_text: "Vault URL: {{text}}", - password_generator_btn: "Password Generator", - your_token_expires_in: "Your token expires in {{date, until_date}}", - home_new_secrets_engine_button: "New Secrets Engine", + home_vaulturl_text: "Vault URL: {{text}}", + home_password_generator_btn: "Password Generator", + home_your_token_expires_in: "Your token expires in {{date, until_date}}", + home_secrets_title: "Secrets", + home_secrets_description: "View, create and manage secrets.", + + // Secrets Home Page + secrets_home_page_title: "Secrets", + secrets_home_new_secrets_engine_button: "New Secrets Engine", // New Secrets Engine Page new_secrets_engine_title: "New Secrets Engine", diff --git a/src/translations/fr.js b/src/translations/fr.js index 041dd8f..db70b34 100644 --- a/src/translations/fr.js +++ b/src/translations/fr.js @@ -31,9 +31,9 @@ module.exports = { // Home Page home_page_title: "Accueil", - vaulturl_text: "Adresse du Vault: {{text}}", - password_generator_btn: "Générateur de mot de passe", - your_token_expires_in: "Votre jeton expire dans {{date, until_date}}", + home_vaulturl_text: "Adresse du Vault: {{text}}", + home_password_generator_btn: "Générateur de mot de passe", + home_your_token_expires_in: "Votre jeton expire dans {{date, until_date}}", // Unseal Page unseal_vault_text: "Ouvrir le Vault", diff --git a/src/translations/ru.js b/src/translations/ru.js index c57d3b9..e461d7f 100644 --- a/src/translations/ru.js +++ b/src/translations/ru.js @@ -34,9 +34,9 @@ module.exports = { // Home Page home_page_title: "Главная страница", - vaulturl_text: "Адрес хранилища: {{text}}", - password_generator_btn: "Генератор паролей", - your_token_expires_in: "Продолжительность ключа: {{date, until_date}}", + home_vaulturl_text: "Адрес хранилища: {{text}}", + home_password_generator_btn: "Генератор паролей", + home_your_token_expires_in: "Продолжительность ключа: {{date, until_date}}", // Unseal Page unseal_vault_text: "Раскрыть хранилище", diff --git a/webpack-dev.config.js b/webpack-dev.config.js new file mode 100644 index 0000000..689ca05 --- /dev/null +++ b/webpack-dev.config.js @@ -0,0 +1,60 @@ +const path = require('path'); +const webpack = require('webpack'); +var os = require("os"); + +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const { GitRevisionPlugin } = require('git-revision-webpack-plugin'); +const gitRevisionPlugin = new GitRevisionPlugin(); +let commitHash = gitRevisionPlugin.commithash(); + + +module.exports = { + mode: "development", + cache: true, + entry: './src/main.ts', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'bundle.js', + }, + stats: { + colors: true, + timings: true, + }, + plugins: [ + new MiniCssExtractPlugin(), + new HtmlWebpackPlugin({ title: "VaultUI" }), + new webpack.DefinePlugin({ + BUILD_STRING: + JSON.stringify(`Built At: ${new Date().toString()} by ${os.userInfo().username}@${os.hostname()} on commit ${commitHash}`), + }) + ], + devServer: { + open: process.env.BROWSER || "microsoft-edge-dev", + }, + resolve: { + modules: ['node_modules'], + extensions: ['.tsx', '.ts', '.js', ".mjs"], + }, + + module: { + rules: [ + { + test: /\.(sa|sc|c)ss$/, + use: [ + MiniCssExtractPlugin.loader, + "css-loader", + "sass-loader" + ], + }, + { + test: /\.ts(x?)$/, + use: [ + { + loader: 'ts-loader' + } + ] + }, + ], + }, +}; \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index cfad622..708b8f9 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -28,24 +28,17 @@ var babelOptions = { ] }; -const VERBOSE = Object.getOwnPropertyNames(process.env).includes("VERBOSE") || !true; -const MODE = process.env.WEBPACK_MODE || "production" -const DEBUG = MODE != "production"; - let commitHash = gitRevisionPlugin.commithash(); -console.log("DEBUG:", DEBUG); - module.exports = { - mode: MODE, - cache: DEBUG, + mode: "production", + cache: false, entry: './src/main.ts', output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', }, stats: { - preset: VERBOSE ? "detailed" : "normal", colors: true, timings: true, },