From 13ea95a552423e78498f7939ff7fa0a35308fed4 Mon Sep 17 00:00:00 2001 From: Kitteh Date: Fri, 7 May 2021 11:53:26 +0100 Subject: [PATCH] Move API unctions to their own iles. --- src/api.js | 379 ---------------------- src/api/addNewTOTP.js | 19 ++ src/api/apiUtils.js | 9 + src/api/createOrUpdateSecret.js | 31 ++ src/api/deleteSecret.js | 38 +++ src/api/getCapabilities.js | 27 ++ src/api/getMounts.js | 13 + src/api/getSealStatus.js | 11 + src/api/getSecret.js | 22 ++ src/api/getSecretMetadata.js | 14 + src/api/getSecrets.js | 24 ++ src/api/getTOTPCode.js | 13 + src/api/getTOTPKeys.js | 17 + src/api/getTransitKeys.js | 17 + src/api/index.js | 23 ++ src/api/lookupSelf.js | 17 + src/api/renewSelf.js | 20 ++ src/api/sealVault.js | 16 + src/api/submitUnsealKey.js | 19 ++ src/api/transitDecrypt.js | 22 ++ src/api/transitEncrypt.js | 22 ++ src/api/undeleteSecret.js | 32 ++ src/api/usernameLogin.js | 21 ++ src/main.js | 2 +- src/pageUtils.js | 3 +- src/pages/Home.js | 3 +- src/pages/KeyValue/KeyValueDelete.js | 2 +- src/pages/KeyValue/KeyValueNew.js | 2 +- src/pages/KeyValue/KeyValueSecret.js | 4 +- src/pages/KeyValue/KeyValueSecretsEdit.js | 3 +- src/pages/KeyValue/KeyValueVersions.js | 2 +- src/pages/KeyValue/KeyValueView.js | 2 +- src/pages/Login.js | 3 +- src/pages/Me.js | 4 +- src/pages/TOTP/NewTOTP.js | 3 +- src/pages/TOTP/TOTPView.js | 3 +- src/pages/Transit/TransitDecrypt.js | 2 +- src/pages/Transit/TransitEncrypt.js | 2 +- src/pages/Transit/TransitView.js | 2 +- src/pages/Unseal.js | 3 +- 40 files changed, 475 insertions(+), 396 deletions(-) delete mode 100644 src/api.js create mode 100644 src/api/addNewTOTP.js create mode 100644 src/api/apiUtils.js create mode 100644 src/api/createOrUpdateSecret.js create mode 100644 src/api/deleteSecret.js create mode 100644 src/api/getCapabilities.js create mode 100644 src/api/getMounts.js create mode 100644 src/api/getSealStatus.js create mode 100644 src/api/getSecret.js create mode 100644 src/api/getSecretMetadata.js create mode 100644 src/api/getSecrets.js create mode 100644 src/api/getTOTPCode.js create mode 100644 src/api/getTOTPKeys.js create mode 100644 src/api/getTransitKeys.js create mode 100644 src/api/index.js create mode 100644 src/api/lookupSelf.js create mode 100644 src/api/renewSelf.js create mode 100644 src/api/sealVault.js create mode 100644 src/api/submitUnsealKey.js create mode 100644 src/api/transitDecrypt.js create mode 100644 src/api/transitEncrypt.js create mode 100644 src/api/undeleteSecret.js create mode 100644 src/api/usernameLogin.js diff --git a/src/api.js b/src/api.js deleted file mode 100644 index 3273951..0000000 --- a/src/api.js +++ /dev/null @@ -1,379 +0,0 @@ -import { DoesNotExistError } from "./types/internalErrors.js"; -import { getObjectKeys, removeDoubleSlash } from "./utils.js"; -import { pageState } from "./globalPageState.js"; - -function getHeaders() { - return { - "X-Vault-Token": pageState.token, - } -} - -const appendAPIURL = (url) => pageState.apiURL + url; - -export async function lookupSelf() { - const request = new Request(appendAPIURL("/v1/auth/token/lookup-self"), { - headers: getHeaders(), - }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - if ("data" in data) { - return data.data; - } else if ("errors" in data) { - throw new Error(data.errors[0]); - } - }); -} - -export async function renewSelf() { - const request = new Request(appendAPIURL("/v1/auth/token/renew-self"), { - method: 'POST', - headers: { - ...getHeaders(), - 'Content-Type': 'application/json' - }, - body: JSON.stringify({}) - }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - if ("errors" in data) { - throw new Error(data.errors[0]); - } - }); -} - -export async function sealVault() { - const request = new Request(appendAPIURL("/v1/sys/seal"), { - method: 'PUT', - headers: getHeaders(), - }); - 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(appendAPIURL(`/v1/auth/userpass/login/${username}`), { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ "username": username, "password": password }) - }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - if ("auth" in data) { - return data.auth.client_token; - } else if ("errors" in data) { - throw new Error(data.errors[0]); - } - }); -} - -export async function getMounts() { - const request = new Request(appendAPIURL("/v1/sys/internal/ui/mounts"), { - headers: getHeaders(), - }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - return data.data.secret; - }); -} - -export async function getSealStatus() { - const request = new Request(appendAPIURL("/v1/sys/seal-status")); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - return data; - }); -} - -export async function submitUnsealKey(key) { - const request = new Request(appendAPIURL("/v1/sys/unseal"), { - method: "POST", - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - "key": key - }) - }); - let response = await fetch(request); - if (!response.ok) { - let json = await response.json(); - throw new Error(json.errors[0]); - } -} - -export async function getCapabilities(baseMount, secretPath, name) { - return await getCapabilitiesPath(removeDoubleSlash(baseMount + secretPath.join("/") + "/" + name)) -} - -export async function getCapabilitiesPath(path) { - const request = new Request(appendAPIURL("/v1/sys/capabilities-self"), { - method: "POST", - headers: { - 'Content-Type': 'application/json', - ...getHeaders(), - }, - body: JSON.stringify( - { - "paths": [removeDoubleSlash(path)] - } - ) - }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - return data.capabilities; - }); -} - -export async function getSecrets(baseMount, mountType, secretPath) { - let secretURL = ""; - if (mountType == "kv-v2") { - secretURL = `/v1/${baseMount}/metadata/${secretPath.join("")}?list=true`; - } else { - // cubbyhole and v1 are identical - secretURL = `/v1/${baseMount}/${secretPath.join("")}?list=true`; - } - const request = new Request(appendAPIURL(secretURL), { - headers: getHeaders(), - }); - return fetch(request).then(response => { - if (response.status == 404) { - throw DoesNotExistError; - } - return response.json(); - }).then(data => { - return data.data.keys; - }); - -} - -export async function getSecretMetadata(baseMount, secretPath, name) { - const request = new Request(appendAPIURL(`/v1/${baseMount}/metadata/${secretPath.join("")}/${name}`), { - headers: getHeaders(), - }); - - return fetch(request).then(response => { - return response.json(); - }).then(data => { - return data.data; - }); -} - -export async function undeleteSecret(baseMount, secretPath, name, version = null) { - let secretURL = `/v1/${baseMount}/undelete/${secretPath.join("/")}/${name}`; - secretURL = removeDoubleSlash(secretURL).replace(/\/$/, ""); - if (version == null) { - let meta = await getSecretMetadata( - baseMount, - secretPath, - name - ); - let versions = getObjectKeys(meta.versions); - version = String(versions[versions.length-1]); - } - - let request = new Request(appendAPIURL(secretURL), { - method: "POST", - headers: { - ...getHeaders(), - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ "versions": [version] }) - }); - let response = await fetch(request); - if (!response.ok) { - let json = await response.json(); - throw new Error(json.errors[0]); - } -} - - -export async function getSecret(baseMount, mountType, secretPath, name, version = null) { - let secretURL = ""; - if (mountType == "kv-v2") { - secretURL = `/v1/${baseMount}/data/${secretPath.join("")}/${name}`; - if (version != null) secretURL += `?version=${version}`; - } else { - secretURL = `/v1/${baseMount}/${secretPath.join("")}/${name}`; - } - const request = new Request(appendAPIURL(secretURL), { - headers: getHeaders(), - }); - - return fetch(request).then(response => { - return response.json(); - }).then(data => { - return mountType == "kv-v2" ? data.data.data : data.data; - }); -} - -export async function deleteSecret(baseMount, mountType, secretPath, name, version = null) { - let secretURL = ""; - - let request; - - if (mountType == "kv-v2" && version != null) { - secretURL = `/v1/${baseMount}/delete/${secretPath.join("")}/${name}`; - secretURL = removeDoubleSlash(secretURL).replace(/\/$/, ""); - request = new Request(appendAPIURL(secretURL), { - method: "POST", - headers: { - ...getHeaders(), - 'Content-Type': 'application/json', - }, - body: version != null ? JSON.stringify({ "versions": [version] }) : "{}" - }); - } else { - if (mountType == "kv-v2") { - secretURL = `/v1/${baseMount}/metadata/${secretPath.join("")}/${name}`; - } else { - secretURL = `/v1/${baseMount}/${secretPath.join("")}/${name}`; - } - secretURL = removeDoubleSlash(secretURL).replace(/\/$/, ""); - request = new Request(appendAPIURL(secretURL), { - method: "DELETE", - headers: getHeaders(), - }); - } - - - let response = await fetch(request); - if (!response.ok) { - let json = await response.json(); - throw new Error(json.errors[0]); - } -} - -export async function createOrUpdateSecret(baseMount, mountType, secretPath, name, data) { - let secretURL = ""; - let APIData = {}; - - if (mountType == "kv-v2") { - secretURL = `/v1/${baseMount}/data/${secretPath.join("/")}/${name}`; - APIData = { "data": data }; - } else { - secretURL = `/v1/${baseMount}/${secretPath.join("/")}/${name}`; - APIData = data; - } - - secretURL = removeDoubleSlash(secretURL).replace(/\/$/, ""); - const request = new Request(appendAPIURL(secretURL), { - method: "POST", - headers: { - 'Content-Type': 'application/json', - ...getHeaders(), - }, - body: JSON.stringify(APIData, null, 0) - }); - let response = await fetch(request); - if (!response.ok) { - let json = await response.json(); - throw new Error(json.errors[0]); - } -} - -export async function getTransitKeys(baseMount) { - const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), { - headers: getHeaders(), - }); - return fetch(request).then(response => { - if (response.status == 404) { - throw DoesNotExistError; - } - return response.json(); - }).then(data => { - return data.data.keys; - }); -} - -export async function transitEncrypt(baseMount, name, data) { - const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/encrypt/${name}`)), { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...getHeaders(), - }, - body: JSON.stringify({plaintext: data}) - }); - let response = await fetch(request); - if (!response.ok) { - let json = await response.json(); - throw new Error(json.errors[0]); - } else { - let json = await response.json(); - return json.data; - } -} - -export async function transitDecrypt(baseMount, name, data) { - const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/decrypt/${name}`)), { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...getHeaders(), - }, - body: JSON.stringify({ciphertext: data}) - }); - let response = await fetch(request); - if (!response.ok) { - let json = await response.json(); - throw new Error(json.errors[0]); - } else { - let json = await response.json(); - return json.data; - } -} - - -export async function getTOTPKeys(baseMount) { - const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), { - headers: getHeaders(), - }); - return fetch(request).then(response => { - if (response.status == 404) { - throw DoesNotExistError; - } - return response.json(); - }).then(data => { - return data.data.keys; - }); -} - -export async function getTOTPCode(baseMount, name) { - const request = new Request(appendAPIURL(`/v1/${baseMount}/code/${name}`), { - headers: getHeaders(), - }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - return data.data.code; - }); -} - -export async function addNewTOTP(baseMount, parms) { - const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/keys/${parms.name}`)), { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...getHeaders(), - }, - body: JSON.stringify(parms) - }); - let response = await fetch(request); - if (!response.ok) { - let json = await response.json(); - throw new Error(json.errors[0]); - } -} diff --git a/src/api/addNewTOTP.js b/src/api/addNewTOTP.js new file mode 100644 index 0000000..139e9ab --- /dev/null +++ b/src/api/addNewTOTP.js @@ -0,0 +1,19 @@ +import { removeDoubleSlash } from "../utils.js"; +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function addNewTOTP(baseMount, parms) { + const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/keys/${parms.name}`)), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...getHeaders(), + }, + body: JSON.stringify(parms) + }); + let response = await fetch(request); + if (!response.ok) { + let json = await response.json(); + throw new Error(json.errors[0]); + } +} diff --git a/src/api/apiUtils.js b/src/api/apiUtils.js new file mode 100644 index 0000000..96a934e --- /dev/null +++ b/src/api/apiUtils.js @@ -0,0 +1,9 @@ +import { pageState } from "../globalPageState.js"; + +export function getHeaders() { + return { + "X-Vault-Token": pageState.token, + } +} + +export const appendAPIURL = (url) => pageState.apiURL + url; \ No newline at end of file diff --git a/src/api/createOrUpdateSecret.js b/src/api/createOrUpdateSecret.js new file mode 100644 index 0000000..0fa33dd --- /dev/null +++ b/src/api/createOrUpdateSecret.js @@ -0,0 +1,31 @@ +import { removeDoubleSlash } from "../utils.js"; +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function createOrUpdateSecret(baseMount, mountType, secretPath, name, data) { + let secretURL = ""; + let APIData = {}; + + if (mountType == "kv-v2") { + secretURL = `/v1/${baseMount}/data/${secretPath.join("/")}/${name}`; + APIData = { "data": data }; + } else { + secretURL = `/v1/${baseMount}/${secretPath.join("/")}/${name}`; + APIData = data; + } + + secretURL = removeDoubleSlash(secretURL).replace(/\/$/, ""); + const request = new Request(appendAPIURL(secretURL), { + method: "POST", + headers: { + 'Content-Type': 'application/json', + ...getHeaders(), + }, + body: JSON.stringify(APIData, null, 0) + }); + let response = await fetch(request); + if (!response.ok) { + let json = await response.json(); + throw new Error(json.errors[0]); + } +} diff --git a/src/api/deleteSecret.js b/src/api/deleteSecret.js new file mode 100644 index 0000000..ac8648e --- /dev/null +++ b/src/api/deleteSecret.js @@ -0,0 +1,38 @@ +import { removeDoubleSlash } from "../utils.js"; +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function deleteSecret(baseMount, mountType, secretPath, name, version = null) { + let secretURL = ""; + + let request; + + if (mountType == "kv-v2" && version != null) { + secretURL = `/v1/${baseMount}/delete/${secretPath.join("")}/${name}`; + secretURL = removeDoubleSlash(secretURL).replace(/\/$/, ""); + request = new Request(appendAPIURL(secretURL), { + method: "POST", + headers: { + ...getHeaders(), + 'Content-Type': 'application/json', + }, + body: version != null ? JSON.stringify({ "versions": [version] }) : "{}" + }); + } else { + if (mountType == "kv-v2") { + secretURL = `/v1/${baseMount}/metadata/${secretPath.join("")}/${name}`; + } else { + secretURL = `/v1/${baseMount}/${secretPath.join("")}/${name}`; + } + secretURL = removeDoubleSlash(secretURL).replace(/\/$/, ""); + request = new Request(appendAPIURL(secretURL), { + method: "DELETE", + headers: getHeaders(), + }); + } + let response = await fetch(request); + if (!response.ok) { + let json = await response.json(); + throw new Error(json.errors[0]); + } +} diff --git a/src/api/getCapabilities.js b/src/api/getCapabilities.js new file mode 100644 index 0000000..d5d954b --- /dev/null +++ b/src/api/getCapabilities.js @@ -0,0 +1,27 @@ +import { removeDoubleSlash } from "../utils.js"; +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function getCapabilitiesPath(path) { + const request = new Request(appendAPIURL("/v1/sys/capabilities-self"), { + method: "POST", + headers: { + 'Content-Type': 'application/json', + ...getHeaders(), + }, + body: JSON.stringify( + { + "paths": [removeDoubleSlash(path)] + } + ) + }); + return fetch(request).then(response => { + return response.json(); + }).then(data => { + return data.capabilities; + }); +} + +export async function getCapabilities(baseMount, secretPath, name) { + return await getCapabilitiesPath(removeDoubleSlash(baseMount + secretPath.join("/") + "/" + name)); +} diff --git a/src/api/getMounts.js b/src/api/getMounts.js new file mode 100644 index 0000000..b4a62d2 --- /dev/null +++ b/src/api/getMounts.js @@ -0,0 +1,13 @@ +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function getMounts() { + const request = new Request(appendAPIURL("/v1/sys/internal/ui/mounts"), { + headers: getHeaders(), + }); + return fetch(request).then(response => { + return response.json(); + }).then(data => { + return data.data.secret; + }); +} diff --git a/src/api/getSealStatus.js b/src/api/getSealStatus.js new file mode 100644 index 0000000..b0b0758 --- /dev/null +++ b/src/api/getSealStatus.js @@ -0,0 +1,11 @@ +import { appendAPIURL } from "./apiUtils.js"; + + +export async function getSealStatus() { + const request = new Request(appendAPIURL("/v1/sys/seal-status")); + return fetch(request).then(response => { + return response.json(); + }).then(data => { + return data; + }); +} diff --git a/src/api/getSecret.js b/src/api/getSecret.js new file mode 100644 index 0000000..92a8829 --- /dev/null +++ b/src/api/getSecret.js @@ -0,0 +1,22 @@ +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function getSecret(baseMount, mountType, secretPath, name, version = null) { + let secretURL = ""; + if (mountType == "kv-v2") { + secretURL = `/v1/${baseMount}/data/${secretPath.join("")}/${name}`; + if (version != null) + secretURL += `?version=${version}`; + } else { + secretURL = `/v1/${baseMount}/${secretPath.join("")}/${name}`; + } + const request = new Request(appendAPIURL(secretURL), { + headers: getHeaders(), + }); + + return fetch(request).then(response => { + return response.json(); + }).then(data => { + return mountType == "kv-v2" ? data.data.data : data.data; + }); +} diff --git a/src/api/getSecretMetadata.js b/src/api/getSecretMetadata.js new file mode 100644 index 0000000..ec67292 --- /dev/null +++ b/src/api/getSecretMetadata.js @@ -0,0 +1,14 @@ +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function getSecretMetadata(baseMount, secretPath, name) { + const request = new Request(appendAPIURL(`/v1/${baseMount}/metadata/${secretPath.join("")}/${name}`), { + headers: getHeaders(), + }); + + return fetch(request).then(response => { + return response.json(); + }).then(data => { + return data.data; + }); +} diff --git a/src/api/getSecrets.js b/src/api/getSecrets.js new file mode 100644 index 0000000..2ea6b11 --- /dev/null +++ b/src/api/getSecrets.js @@ -0,0 +1,24 @@ +import { DoesNotExistError } from "../types/internalErrors.js"; +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function getSecrets(baseMount, mountType, secretPath) { + let secretURL = ""; + if (mountType == "kv-v2") { + secretURL = `/v1/${baseMount}/metadata/${secretPath.join("")}?list=true`; + } else { + // cubbyhole and v1 are identical + secretURL = `/v1/${baseMount}/${secretPath.join("")}?list=true`; + } + const request = new Request(appendAPIURL(secretURL), { + headers: getHeaders(), + }); + return fetch(request).then(response => { + if (response.status == 404) { + throw DoesNotExistError; + } + return response.json(); + }).then(data => { + return data.data.keys; + }); +} diff --git a/src/api/getTOTPCode.js b/src/api/getTOTPCode.js new file mode 100644 index 0000000..bae6473 --- /dev/null +++ b/src/api/getTOTPCode.js @@ -0,0 +1,13 @@ +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function getTOTPCode(baseMount, name) { + const request = new Request(appendAPIURL(`/v1/${baseMount}/code/${name}`), { + headers: getHeaders(), + }); + return fetch(request).then(response => { + return response.json(); + }).then(data => { + return data.data.code; + }); +} diff --git a/src/api/getTOTPKeys.js b/src/api/getTOTPKeys.js new file mode 100644 index 0000000..c470866 --- /dev/null +++ b/src/api/getTOTPKeys.js @@ -0,0 +1,17 @@ +import { DoesNotExistError } from "../types/internalErrors.js"; +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function getTOTPKeys(baseMount) { + const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), { + headers: getHeaders(), + }); + return fetch(request).then(response => { + if (response.status == 404) { + throw DoesNotExistError; + } + return response.json(); + }).then(data => { + return data.data.keys; + }); +} diff --git a/src/api/getTransitKeys.js b/src/api/getTransitKeys.js new file mode 100644 index 0000000..d7454ce --- /dev/null +++ b/src/api/getTransitKeys.js @@ -0,0 +1,17 @@ +import { DoesNotExistError } from "../types/internalErrors.js"; +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function getTransitKeys(baseMount) { + const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), { + headers: getHeaders(), + }); + return fetch(request).then(response => { + if (response.status == 404) { + throw DoesNotExistError; + } + return response.json(); + }).then(data => { + return data.data.keys; + }); +} diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..061eaf6 --- /dev/null +++ b/src/api/index.js @@ -0,0 +1,23 @@ +export * from "addNewTOTP.js"; +export * from "api.js"; +export * from "apiUtils.js"; +export * from "createOrUpdateSecret.js"; +export * from "deleteSecret.js"; +export * from "getCapabilities.js"; +export * from "getCapabilitiesPath.js"; +export * from "getMounts.js"; +export * from "getSealStatus.js"; +export * from "getSecret.js"; +export * from "getSecretMetadata.js"; +export * from "getSecrets.js"; +export * from "getTOTPCode.js"; +export * from "getTOTPKeys.js"; +export * from "getTransitKeys.js"; +export * from "lookupSelf.js"; +export * from "renewSelf.js"; +export * from "sealVault.js"; +export * from "submitUnsealKey.js"; +export * from "transitDecrypt.js"; +export * from "transitEncrypt.js"; +export * from "undeleteSecret.js"; +export * from "usernameLogin.js"; \ No newline at end of file diff --git a/src/api/lookupSelf.js b/src/api/lookupSelf.js new file mode 100644 index 0000000..f54f9c5 --- /dev/null +++ b/src/api/lookupSelf.js @@ -0,0 +1,17 @@ +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function lookupSelf() { + const request = new Request(appendAPIURL("/v1/auth/token/lookup-self"), { + headers: getHeaders(), + }); + return fetch(request).then(response => { + return response.json(); + }).then(data => { + if ("data" in data) { + return data.data; + } else if ("errors" in data) { + throw new Error(data.errors[0]); + } + }); +} diff --git a/src/api/renewSelf.js b/src/api/renewSelf.js new file mode 100644 index 0000000..fee7c08 --- /dev/null +++ b/src/api/renewSelf.js @@ -0,0 +1,20 @@ +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function renewSelf() { + const request = new Request(appendAPIURL("/v1/auth/token/renew-self"), { + method: 'POST', + headers: { + ...getHeaders(), + 'Content-Type': 'application/json' + }, + body: JSON.stringify({}) + }); + return fetch(request).then(response => { + return response.json(); + }).then(data => { + if ("errors" in data) { + throw new Error(data.errors[0]); + } + }); +} diff --git a/src/api/sealVault.js b/src/api/sealVault.js new file mode 100644 index 0000000..40a14da --- /dev/null +++ b/src/api/sealVault.js @@ -0,0 +1,16 @@ +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function sealVault() { + const request = new Request(appendAPIURL("/v1/sys/seal"), { + method: 'PUT', + headers: getHeaders(), + }); + return fetch(request).then(response => { + return response.json(); + }).then(data => { + if ("errors" in data) { + throw new Error(data.errors[0]); + } + }); +} diff --git a/src/api/submitUnsealKey.js b/src/api/submitUnsealKey.js new file mode 100644 index 0000000..e29e1f4 --- /dev/null +++ b/src/api/submitUnsealKey.js @@ -0,0 +1,19 @@ +import { appendAPIURL } from "./apiUtils.js"; + + +export async function submitUnsealKey(key) { + const request = new Request(appendAPIURL("/v1/sys/unseal"), { + method: "POST", + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + "key": key + }) + }); + let response = await fetch(request); + if (!response.ok) { + let json = await response.json(); + throw new Error(json.errors[0]); + } +} diff --git a/src/api/transitDecrypt.js b/src/api/transitDecrypt.js new file mode 100644 index 0000000..f74888e --- /dev/null +++ b/src/api/transitDecrypt.js @@ -0,0 +1,22 @@ +import { removeDoubleSlash } from "../utils.js"; +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function transitDecrypt(baseMount, name, data) { + const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/decrypt/${name}`)), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...getHeaders(), + }, + body: JSON.stringify({ ciphertext: data }) + }); + let response = await fetch(request); + if (!response.ok) { + let json = await response.json(); + throw new Error(json.errors[0]); + } else { + let json = await response.json(); + return json.data; + } +} diff --git a/src/api/transitEncrypt.js b/src/api/transitEncrypt.js new file mode 100644 index 0000000..b3e98ca --- /dev/null +++ b/src/api/transitEncrypt.js @@ -0,0 +1,22 @@ +import { removeDoubleSlash } from "../utils.js"; +import { appendAPIURL, getHeaders } from "./apiUtils.js"; + + +export async function transitEncrypt(baseMount, name, data) { + const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/encrypt/${name}`)), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...getHeaders(), + }, + body: JSON.stringify({ plaintext: data }) + }); + let response = await fetch(request); + if (!response.ok) { + let json = await response.json(); + throw new Error(json.errors[0]); + } else { + let json = await response.json(); + return json.data; + } +} diff --git a/src/api/undeleteSecret.js b/src/api/undeleteSecret.js new file mode 100644 index 0000000..7ae2471 --- /dev/null +++ b/src/api/undeleteSecret.js @@ -0,0 +1,32 @@ +import { getObjectKeys, removeDoubleSlash } from "../utils.js"; +import { appendAPIURL, getHeaders } from "./apiUtils.js"; +import { getSecretMetadata } from "./getSecretMetadata"; + + +export async function undeleteSecret(baseMount, secretPath, name, version = null) { + let secretURL = `/v1/${baseMount}/undelete/${secretPath.join("/")}/${name}`; + secretURL = removeDoubleSlash(secretURL).replace(/\/$/, ""); + if (version == null) { + let meta = await getSecretMetadata( + baseMount, + secretPath, + name + ); + let versions = getObjectKeys(meta.versions); + version = String(versions[versions.length - 1]); + } + + let request = new Request(appendAPIURL(secretURL), { + method: "POST", + headers: { + ...getHeaders(), + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ "versions": [version] }) + }); + let response = await fetch(request); + if (!response.ok) { + let json = await response.json(); + throw new Error(json.errors[0]); + } +} diff --git a/src/api/usernameLogin.js b/src/api/usernameLogin.js new file mode 100644 index 0000000..afea14f --- /dev/null +++ b/src/api/usernameLogin.js @@ -0,0 +1,21 @@ +import { appendAPIURL } from "./apiUtils.js"; + + +export async function usernameLogin(username, password) { + const request = new Request(appendAPIURL(`/v1/auth/userpass/login/${username}`), { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ "username": username, "password": password }) + }); + return fetch(request).then(response => { + return response.json(); + }).then(data => { + if ("auth" in data) { + return data.auth.client_token; + } else if ("errors" in data) { + throw new Error(data.errors[0]); + } + }); +} diff --git a/src/main.js b/src/main.js index 696c5a5..d026043 100644 --- a/src/main.js +++ b/src/main.js @@ -17,7 +17,7 @@ import { changePage, renderPage, } from "./pageUtils.js"; -import { getSealStatus } from './api.js'; +import { getSealStatus } from "./api/getSealStatus"; import { makeElement } from "./htmlUtils.js"; import { pageState } from "./globalPageState.js"; diff --git a/src/pageUtils.js b/src/pageUtils.js index f414d01..e63cc07 100644 --- a/src/pageUtils.js +++ b/src/pageUtils.js @@ -1,4 +1,5 @@ -import { getSealStatus, lookupSelf } from './api.js'; +import { getSealStatus } from "./api/getSealStatus"; +import { lookupSelf } from "./api/lookupSelf"; import { makeElement } from "./htmlUtils.js"; import { pageState } from "./globalPageState.js"; import UIkit from 'uikit/dist/js/uikit.min.js'; diff --git a/src/pages/Home.js b/src/pages/Home.js index b1ba22e..6c12401 100644 --- a/src/pages/Home.js +++ b/src/pages/Home.js @@ -1,6 +1,7 @@ import { Page } from "../types/Page.js"; import { changePage, prePageChecks, setErrorText } from "../pageUtils.js"; -import { getMounts, lookupSelf } from "../api.js"; +import { getMounts } from "../api/getMounts"; +import { lookupSelf } from "../api/lookupSelf"; import { makeElement } from "../htmlUtils.js"; import { pageState } from "../globalPageState.js"; import i18next from 'i18next'; diff --git a/src/pages/KeyValue/KeyValueDelete.js b/src/pages/KeyValue/KeyValueDelete.js index 0f0626a..a18c123 100644 --- a/src/pages/KeyValue/KeyValueDelete.js +++ b/src/pages/KeyValue/KeyValueDelete.js @@ -1,6 +1,6 @@ import { Page } from "../../types/Page.js"; import { changePage, setPageContent, setTitleElement } from "../../pageUtils.js"; -import { deleteSecret } from "../../api.js"; +import { deleteSecret } from "../../api/deleteSecret"; import { makeElement } from "../../htmlUtils.js"; import { pageState } from "../../globalPageState.js"; import i18next from 'i18next'; diff --git a/src/pages/KeyValue/KeyValueNew.js b/src/pages/KeyValue/KeyValueNew.js index 5aa5c82..6adad38 100644 --- a/src/pages/KeyValue/KeyValueNew.js +++ b/src/pages/KeyValue/KeyValueNew.js @@ -1,6 +1,6 @@ import { Page } from "../../types/Page.js"; import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils.js"; -import { createOrUpdateSecret } from "../../api.js"; +import { createOrUpdateSecret } from "../../api/createOrUpdateSecret"; import { makeElement } from "../../htmlUtils.js"; import { pageState } from "../../globalPageState.js"; import i18next from 'i18next'; diff --git a/src/pages/KeyValue/KeyValueSecret.js b/src/pages/KeyValue/KeyValueSecret.js index 691c9fa..883acd7 100644 --- a/src/pages/KeyValue/KeyValueSecret.js +++ b/src/pages/KeyValue/KeyValueSecret.js @@ -1,7 +1,9 @@ import { CopyableInputBox } from "../../elements/CopyableInputBox.js"; import { Page } from "../../types/Page.js"; import { changePage, setPageContent, setTitleElement } from "../../pageUtils.js"; -import { getCapabilities, getSecret, undeleteSecret } from "../../api.js"; +import { getSecret } from "../../api/getSecret"; +import { undeleteSecret } from "../../api/undeleteSecret"; +import { getCapabilities } from "../../api/getCapabilities"; import { makeElement } from "../../htmlUtils.js"; import { pageState } from "../../globalPageState.js"; import Prism from "prismjs"; diff --git a/src/pages/KeyValue/KeyValueSecretsEdit.js b/src/pages/KeyValue/KeyValueSecretsEdit.js index 4bffc58..708ad2e 100644 --- a/src/pages/KeyValue/KeyValueSecretsEdit.js +++ b/src/pages/KeyValue/KeyValueSecretsEdit.js @@ -1,7 +1,8 @@ import { CodeJar } from "codejar"; import { Page } from "../../types/Page.js"; import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils.js"; -import { createOrUpdateSecret, getSecret } from "../../api.js"; +import { createOrUpdateSecret } from "../../api/createOrUpdateSecret.js"; +import { getSecret } from "../../api/getSecret.js"; import { makeElement } from "../../htmlUtils.js"; import { pageState } from "../../globalPageState.js"; import { verifyJSONString } from "../../utils.js"; diff --git a/src/pages/KeyValue/KeyValueVersions.js b/src/pages/KeyValue/KeyValueVersions.js index 53e8dea..440237c 100644 --- a/src/pages/KeyValue/KeyValueVersions.js +++ b/src/pages/KeyValue/KeyValueVersions.js @@ -1,6 +1,6 @@ import { Page } from "../../types/Page.js"; import { changePage, setPageContent, setTitleElement } from "../../pageUtils.js"; -import { getSecretMetadata } from "../../api.js"; +import { getSecretMetadata } from "../../api/getSecretMetadata.js"; import { makeElement } from "../../htmlUtils.js"; import { pageState } from "../../globalPageState.js"; import i18next from 'i18next'; diff --git a/src/pages/KeyValue/KeyValueView.js b/src/pages/KeyValue/KeyValueView.js index 4ff95fa..813e5cd 100644 --- a/src/pages/KeyValue/KeyValueView.js +++ b/src/pages/KeyValue/KeyValueView.js @@ -1,7 +1,7 @@ import { DoesNotExistError } from "../../types/internalErrors.js"; import { Page } from "../../types/Page.js"; import { changePage, setErrorText, setTitleElement } from "../../pageUtils.js"; -import { getSecrets } from "../../api.js"; +import { getSecrets } from "../../api/getSecrets"; import { makeElement } from "../../htmlUtils.js"; import { pageState } from "../../globalPageState.js"; import i18next from 'i18next'; diff --git a/src/pages/Login.js b/src/pages/Login.js index 1441d25..9618394 100644 --- a/src/pages/Login.js +++ b/src/pages/Login.js @@ -2,7 +2,8 @@ import { Margin } from "../elements/Margin.js"; import { MarginInline } from "../elements/MarginInline.js"; import { Page } from "../types/Page.js"; import { changePage, setErrorText, setPageContent } from "../pageUtils.js"; -import { lookupSelf, usernameLogin } from "../api.js"; +import { usernameLogin } from "../api/usernameLogin"; +import { lookupSelf } from "../api/lookupSelf"; import { makeElement } from "../htmlUtils.js"; import { pageState } from "../globalPageState.js"; import i18next from 'i18next'; diff --git a/src/pages/Me.js b/src/pages/Me.js index 42c91fb..02e3041 100644 --- a/src/pages/Me.js +++ b/src/pages/Me.js @@ -1,6 +1,8 @@ import { Page } from "../types/Page.js"; import { addClipboardNotifications, changePage, prePageChecks, setErrorText, setPageContent } from "../pageUtils.js"; -import { getCapabilitiesPath, renewSelf, sealVault } from "../api.js"; +import { getCapabilitiesPath } from "../api/getCapabilities.js"; +import { renewSelf } from "../api/renewSelf.js"; +import { sealVault } from "../api/sealVault.js"; import { makeElement } from "../htmlUtils.js"; import { pageState } from "../globalPageState.js"; import ClipboardJS from "clipboard"; diff --git a/src/pages/TOTP/NewTOTP.js b/src/pages/TOTP/NewTOTP.js index a74f645..da3acd5 100644 --- a/src/pages/TOTP/NewTOTP.js +++ b/src/pages/TOTP/NewTOTP.js @@ -1,12 +1,13 @@ import { Margin } from "../../elements/Margin.js"; import { MarginInline } from "../../elements/MarginInline.js"; import { Page } from "../../types/Page.js"; -import { addNewTOTP } from "../../api.js"; +import { addNewTOTP } from "../../api/addNewTOTP"; import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils.js"; import { makeElement } from "../../htmlUtils.js"; import { pageState } from "../../globalPageState.js"; import i18next from 'i18next'; + export class NewTOTPPage extends Page { constructor() { super(); diff --git a/src/pages/TOTP/TOTPView.js b/src/pages/TOTP/TOTPView.js index a209596..948a604 100644 --- a/src/pages/TOTP/TOTPView.js +++ b/src/pages/TOTP/TOTPView.js @@ -2,7 +2,8 @@ import { CopyableInputBox } from "../../elements/CopyableInputBox.js"; import { DoesNotExistError } from "../../types/internalErrors.js"; import { Page } from "../../types/Page.js"; import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils.js"; -import { getTOTPCode, getTOTPKeys } from "../../api.js"; +import { getTOTPCode } from "../../api/getTOTPCode"; +import { getTOTPKeys } from "../../api/getTOTPKeys"; import { makeElement } from "../../htmlUtils.js"; import { pageState } from "../../globalPageState.js"; import i18next from 'i18next'; diff --git a/src/pages/Transit/TransitDecrypt.js b/src/pages/Transit/TransitDecrypt.js index fb3ab8a..f0be0d1 100644 --- a/src/pages/Transit/TransitDecrypt.js +++ b/src/pages/Transit/TransitDecrypt.js @@ -4,7 +4,7 @@ import { Page } from "../../types/Page.js"; import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils.js"; import { makeElement } from "../../htmlUtils.js"; import { pageState } from "../../globalPageState.js"; -import { transitDecrypt } from "../../api.js"; +import { transitDecrypt } from "../../api/transitDecrypt"; import UIkit from 'uikit/dist/js/uikit.min.js'; import i18next from "i18next"; diff --git a/src/pages/Transit/TransitEncrypt.js b/src/pages/Transit/TransitEncrypt.js index 9fc32a0..3ca6a23 100644 --- a/src/pages/Transit/TransitEncrypt.js +++ b/src/pages/Transit/TransitEncrypt.js @@ -4,7 +4,7 @@ import { Page } from "../../types/Page.js"; import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils.js"; import { makeElement } from "../../htmlUtils.js"; import { pageState } from "../../globalPageState.js"; -import { transitEncrypt } from "../../api.js"; +import { transitEncrypt } from "../../api/transitEncrypt"; import UIkit from 'uikit/dist/js/uikit.min.js'; import i18next from "i18next"; diff --git a/src/pages/Transit/TransitView.js b/src/pages/Transit/TransitView.js index 3928f56..e6fd9a9 100644 --- a/src/pages/Transit/TransitView.js +++ b/src/pages/Transit/TransitView.js @@ -1,7 +1,7 @@ import { DoesNotExistError } from "../../types/internalErrors.js"; import { Page } from "../../types/Page.js"; import { changePage, setErrorText, setTitleElement } from "../../pageUtils.js"; -import { getTransitKeys } from "../../api.js"; +import { getTransitKeys } from "../../api/getTransitKeys"; import { makeElement } from "../../htmlUtils.js"; import { pageState } from "../../globalPageState.js"; import i18next from 'i18next'; diff --git a/src/pages/Unseal.js b/src/pages/Unseal.js index a7ccfba..ad89924 100644 --- a/src/pages/Unseal.js +++ b/src/pages/Unseal.js @@ -2,7 +2,8 @@ import { MarginInline } from "../elements/MarginInline.js"; import { Page } from "../types/Page.js"; import { QRScanner } from "../elements/QRScanner.js"; import { changePage, setErrorText, setPageContent } from "../pageUtils.js"; -import { getSealStatus, submitUnsealKey } from "../api.js"; +import { getSealStatus } from "../api/getSealStatus.js"; +import { submitUnsealKey } from "../api/submitUnsealKey.js"; import { makeElement } from "../htmlUtils.js"; import i18next from 'i18next';