diff --git a/src/api.js b/src/api.js index bbb5e15..85e6a2e 100644 --- a/src/api.js +++ b/src/api.js @@ -1,7 +1,5 @@ - import { getAPIURL, getToken, removeDoubleSlash } from "./utils.js"; - -export const DoesNotExistError = new Error("Does not exist."); +import { DoesNotExistError } from "./types/internalErrors.js"; export async function lookupSelf() { const request = new Request(getAPIURL() + "/v1/auth/token/lookup-self", { @@ -38,6 +36,22 @@ export async function renewSelf() { }); } +export async function sealVault() { + const request = new Request(getAPIURL() + "/v1/sys/seal", { + method: 'PUT', + headers: { + "X-Vault-Token": getToken(), + }, + }); + return fetch(request).then(response => { + return response.json(); + }).then(data => { + if ("errors" in data) { + throw new Error(data.errors[0]); + } + }); +} + export async function usernameLogin(username, password) { const request = new Request(getAPIURL() + `/v1/auth/userpass/login/${username}`, { method: 'POST', @@ -97,6 +111,10 @@ export async function submitUnsealKey(key) { } export async function getCapabilities(baseMount, secretPath, name) { + return await getCapabilitiesPath(removeDoubleSlash(baseMount + secretPath.join("/") + "/" + name)) +} + +export async function getCapabilitiesPath(path) { const request = new Request(getAPIURL() + "/v1/sys/capabilities-self", { method: "POST", headers: { @@ -105,7 +123,7 @@ export async function getCapabilities(baseMount, secretPath, name) { }, body: JSON.stringify( { - "paths": [removeDoubleSlash(baseMount + secretPath.join("/") + "/" + name)] + "paths": [removeDoubleSlash(path)] } ) }); diff --git a/src/elements/QRScanner.js b/src/elements/QRScanner.js index baf45c3..191634a 100644 --- a/src/elements/QRScanner.js +++ b/src/elements/QRScanner.js @@ -42,5 +42,5 @@ export async function QRScanner(onScan) { } }; - return; + return QRInput; } \ No newline at end of file diff --git a/src/pageUtils.js b/src/pageUtils.js index 65d2f05..21ea1c7 100644 --- a/src/pageUtils.js +++ b/src/pageUtils.js @@ -1,7 +1,50 @@ -import UIkit from 'uikit/dist/js/uikit.min.js'; import { makeElement } from "./htmlUtils.js"; +import { lookupSelf, getSealStatus } from './api.js'; +import { getAPIURL } from "./utils.js"; + +import UIkit from 'uikit/dist/js/uikit.min.js'; import i18next from 'i18next'; +async function prePageChecksReal() { + if (pageState.language.length == 0) { + changePage("SET_LANGUAGE"); + throw new Error("Language Not Set"); + } + if (!getAPIURL()) { + changePage("SET_VAULT_URL"); + throw new Error("Vault URL Not Set"); + } + + try { + let sealStatus = await getSealStatus(); + if (sealStatus.sealed) { + changePage("UNSEAL"); + throw new Error("Vault Sealed"); + } + } catch (e) { + throw e; + } + + try { + await lookupSelf(); + } catch (e) { + changePage("LOGIN") + throw e; + } +} + +export async function prePageChecks() { + try { + await prePageChecksReal(); + } catch (e) { + console.log("OHNO", e) + return false; + } + return true; +} + + + export function addClipboardNotifications(clipboard, timeout = 1000) { clipboard.on('success', _ => { UIkit.notification(i18next.t("notification_copy_success"), { diff --git a/src/pages/Home.js b/src/pages/Home.js index 90f6a17..995c0b2 100644 --- a/src/pages/Home.js +++ b/src/pages/Home.js @@ -1,5 +1,5 @@ import { Page } from "../types/Page.js"; -import { setErrorText, changePage } from "../pageUtils.js"; +import { setErrorText, changePage, prePageChecks } from "../pageUtils.js"; import { getAPIURL, getToken } from "../utils.js"; import { makeElement } from "../htmlUtils.js"; import { getSealStatus, lookupSelf, getMounts } from "../api.js"; @@ -11,25 +11,7 @@ export class HomePage extends Page { } async render() { pageContent.innerHTML = ""; - if (pageState.language.length == 0) { - changePage("SET_LANGUAGE"); - return; - } - if (!getAPIURL()) { - changePage("SET_VAULT_URL"); - return; - } - if (!getToken()) { - pageState.token = ""; - changePage("LOGIN"); - return; - } - let sealStatus = await getSealStatus(); - if (sealStatus.sealed) { - changePage("UNSEAL"); - return; - } - + if (!(await prePageChecks())) return; const textList = makeElement({ tag: "ul", diff --git a/src/pages/KeyValue/KeyValueView.js b/src/pages/KeyValue/KeyValueView.js index 09f2d0a..293c511 100644 --- a/src/pages/KeyValue/KeyValueView.js +++ b/src/pages/KeyValue/KeyValueView.js @@ -1,9 +1,11 @@ import { Page } from "../../types/Page.js"; -import { DoesNotExistError, getSecrets } from "../../api.js"; +import { getSecrets } from "../../api.js"; import { setErrorText, setTitleElement, changePage } from "../../pageUtils.js"; import { makeElement } from "../../htmlUtils.js"; +import { DoesNotExistError } from "../../types/internalErrors.js"; import i18next from 'i18next'; + export class KeyValueViewPage extends Page { constructor() { super(); diff --git a/src/pages/Me.js b/src/pages/Me.js index 5eb73cc..2fc84a8 100644 --- a/src/pages/Me.js +++ b/src/pages/Me.js @@ -1,8 +1,8 @@ import { Page } from "../types/Page.js"; -import { addClipboardNotifications, setErrorText, setPageContent, changePage } from "../pageUtils.js"; +import { addClipboardNotifications, setErrorText, setPageContent, changePage, prePageChecks } from "../pageUtils.js"; import { makeElement } from "../htmlUtils.js"; import { getToken } from "../utils.js"; -import { renewSelf } from "../api.js"; +import { renewSelf, getCapabilitiesPath, sealVault } from "../api.js"; import ClipboardJS from "clipboard"; import i18next from 'i18next'; @@ -13,6 +13,9 @@ export class MePage extends Page { } async render() { + console.log("owo", await prePageChecks()); + + if (!(await prePageChecks())) return; setPageContent(makeElement({ tag: "ul", class: "uk-nav", @@ -56,6 +59,25 @@ export class MePage extends Page { } }) }), + makeElement({ + tag: "li", + children: makeElement({ + tag: "a", + condition: await (async () => { + try { + let caps = await getCapabilitiesPath("sys/seal"); + return caps.includes("sudo") && caps.includes("update"); + } catch (e) { + return !true; + } + })(), + text: i18next.t("seal_vault_btn"), + onclick: async () => { + await sealVault(); + changePage("UNSEAL_VAULT"); + } + }) + }), makeElement({ tag: "li", children: makeElement({ diff --git a/src/pages/TOTP/TOTPView.js b/src/pages/TOTP/TOTPView.js index eb593b9..581ea40 100644 --- a/src/pages/TOTP/TOTPView.js +++ b/src/pages/TOTP/TOTPView.js @@ -1,8 +1,9 @@ import { Page } from "../../types/Page.js"; -import { getTOTPKeys, getTOTPCode, DoesNotExistError } from "../../api.js"; +import { getTOTPKeys, getTOTPCode } from "../../api.js"; import { setTitleElement, setPageContent, changePage, setErrorText } from "../../pageUtils.js"; import { CopyableInputBox } from "../../elements/CopyableInputBox.js"; import { makeElement } from "../../htmlUtils.js"; +import { DoesNotExistError } from "../../types/internalErrors.js"; import i18next from 'i18next'; export class TOTPViewPage extends Page { diff --git a/src/pages/Transit/TransitView.js b/src/pages/Transit/TransitView.js index 99c5210..ba9bc8f 100644 --- a/src/pages/Transit/TransitView.js +++ b/src/pages/Transit/TransitView.js @@ -1,7 +1,8 @@ import { Page } from "../../types/Page.js"; -import { DoesNotExistError, getTransitKeys } from "../../api.js"; +import { getTransitKeys } from "../../api.js"; import { setErrorText, setTitleElement, changePage } from "../../pageUtils.js"; import { makeElement } from "../../htmlUtils.js"; +import { DoesNotExistError } from "../../types/internalErrors.js"; import i18next from 'i18next'; export class TransitViewPage extends Page { diff --git a/src/translations/en.js b/src/translations/en.js index 8a297fe..5b8fbfc 100644 --- a/src/translations/en.js +++ b/src/translations/en.js @@ -22,6 +22,7 @@ module.exports = { // Me Page "me_page_title": "Me/Settings", "log_out_btn": "Log Out", + "seal_vault_btn": "Seal Vault", "copy_token_btn": "Copy Token", "renew_lease_btn": "Renew Token Lease", "change_language_btn": "Change Language", diff --git a/src/types/internalErrors.js b/src/types/internalErrors.js new file mode 100644 index 0000000..d4af230 --- /dev/null +++ b/src/types/internalErrors.js @@ -0,0 +1,4 @@ +// These are all errors that the user won't see +// but are used internally. + +export const DoesNotExistError = new Error("Does not exist.") \ No newline at end of file