1
0
Fork 0

move all api functions into their own file, use that instead of globally

This commit is contained in:
ChaotiCryptidz 2022-01-07 15:27:10 +00:00
parent 1d037f0f19
commit 7476de83a4
85 changed files with 938 additions and 930 deletions

633
src/api/API.ts Normal file
View file

@ -0,0 +1,633 @@
import { Settings } from "../settings/Settings";
import { DoesNotExistError } from "../types/internalErrors";
import { removeDoubleSlash } from "../utils";
import { BaseAPIResponse } from "./types/api";
import { AuthListAPIType, AuthListType } from "./types/auth";
import { CapabilitiesType } from "./types/capabilities";
import { MountsType, MountType, NewMountParams } from "./types/mount";
import { SealStatusType } from "./types/seal";
import { TokenInfo } from "./types/token";
import {
DecryptionPayload,
DecryptionResult,
EncryptionPayload,
EncryptionResult,
RewrapPayload,
RewrapResult,
TransitKeyType,
} from "./types/transit";
import { UserType, UserTypeAPIResp } from "./types/user";
async function checkResponse(resp: Response): Promise<void> {
if (resp.ok) return;
if (resp.status == 404) throw DoesNotExistError;
let json: BaseAPIResponse;
try {
json = (await resp.json()) as BaseAPIResponse;
} catch {
// Do Nothing
}
if (json?.errors?.length >= 1) {
throw new Error(json.errors[0]);
}
}
export class API {
private settings: Settings;
constructor(settings: Settings) {
this.settings = settings;
}
getHeaders(): Record<string, string> {
return {
"X-Vault-Token": this.settings.token,
};
}
appendAPIURL(url: string): string {
return this.settings.apiURL + url;
}
// List all supported auth methods
async listAuth(): Promise<AuthListType> {
const request = new Request(this.appendAPIURL(`/v1/sys/auth`), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as AuthListAPIType;
return data.data;
}
// Tries to login with username and password, returns token
async usernameLogin(username: string, password: string): Promise<string> {
const request = new Request(this.appendAPIURL(`/v1/auth/userpass/login/${username}`), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ username: username, password: password }),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as {
auth: { client_token: string };
};
return data.auth.client_token;
}
async createOrUpdateUserPassUser(
path: string,
username: string,
data: Partial<UserType>,
): Promise<void> {
const request = new Request(
this.appendAPIURL(removeDoubleSlash(`/v1/auth/${path}/users/${username}`)),
{
method: "POST",
headers: {
"Content-Type": "application/json",
...this.getHeaders(),
},
body: JSON.stringify(data, null, 0),
},
);
const resp = await fetch(request);
await checkResponse(resp);
}
async deleteUserPassUser(path: string, username: string): Promise<void> {
const request = new Request(
this.appendAPIURL(removeDoubleSlash(`/v1/auth/${path}/users/${username}`)),
{
method: "DELETE",
headers: this.getHeaders(),
},
);
const resp = await fetch(request);
await checkResponse(resp);
}
async getUserPassUser(path: string, username: string): Promise<UserType> {
const request = new Request(this.appendAPIURL(`/v1/auth/${path}/users/${username}`), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as UserTypeAPIResp;
return data.data;
}
async listUserPassUsers(path: string): Promise<string[]> {
const request = new Request(this.appendAPIURL(`/v1/auth/${path}/users?list=true`), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { keys: string[] } };
return data.data.keys;
}
async getMount(mountName: string): Promise<MountType> {
const request = new Request(this.appendAPIURL("/v1/sys/internal/ui/mounts/" + mountName), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: MountType };
return data.data;
}
async getMounts(): Promise<MountsType> {
const request = new Request(this.appendAPIURL("/v1/sys/internal/ui/mounts"), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { secret: MountsType } };
return data.data.secret;
}
async newMount(parms: NewMountParams): Promise<void> {
const request = new Request(
this.appendAPIURL(removeDoubleSlash(`/v1/sys/mounts/${parms.name}`)),
{
method: "POST",
headers: {
"Content-Type": "application/json",
...this.getHeaders(),
},
body: JSON.stringify(parms),
},
);
const resp = await fetch(request);
await checkResponse(resp);
}
async deleteMount(mountPath: string): Promise<void> {
const request = new Request(this.appendAPIURL("/v1/sys/mounts/" + mountPath), {
method: "DELETE",
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
}
async getCapabilitiesPath(path: string | string[]): Promise<CapabilitiesType> {
if (!Array.isArray(path)) {
path = [path];
}
const request = new Request(this.appendAPIURL("/v1/sys/capabilities-self"), {
method: "POST",
headers: {
"Content-Type": "application/json",
...this.getHeaders(),
},
body: JSON.stringify({
paths: path,
}),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { capabilities: string[] };
return data;
}
async getCapsPath(path: string | string[]): Promise<string[]> {
return (await this.getCapabilitiesPath(path)).capabilities;
}
async getCapabilities(
baseMount: string,
secretPath: string[],
name: string,
): Promise<CapabilitiesType> {
return await this.getCapabilitiesPath(
removeDoubleSlash(baseMount + secretPath.join("/") + "/" + name),
);
}
async sealVault(): Promise<void> {
const request = new Request(this.appendAPIURL("/v1/sys/seal"), {
method: "PUT",
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
}
async submitUnsealKey(key: string): Promise<void> {
const request = new Request(this.appendAPIURL("/v1/sys/unseal"), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
key: key,
}),
});
const resp = await fetch(request);
await checkResponse(resp);
}
async getSealStatus(): Promise<SealStatusType> {
const request = new Request(this.appendAPIURL("/v1/sys/seal-status"));
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as SealStatusType;
return data;
}
async lookupSelf(): Promise<TokenInfo> {
const request = new Request(this.appendAPIURL("/v1/auth/token/lookup-self"), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: TokenInfo };
return data.data;
}
async renewSelf(): Promise<void> {
const request = new Request(this.appendAPIURL("/v1/auth/token/renew-self"), {
method: "POST",
headers: {
...this.getHeaders(),
"Content-Type": "application/json",
},
body: JSON.stringify({}),
});
const resp = await fetch(request);
await checkResponse(resp);
}
async createOrUpdatePolicy(name: string, policy_data: string): Promise<void> {
const request = new Request(this.appendAPIURL("/v1/sys/policies/acl/" + name), {
method: "POST",
headers: {
"Content-Type": "application/json",
...this.getHeaders(),
},
body: JSON.stringify({ policy: policy_data }, null, 0),
});
const resp = await fetch(request);
await checkResponse(resp);
}
async deletePolicy(name: string): Promise<void> {
const request = new Request(this.appendAPIURL("/v1/sys/policies/acl/" + name), {
method: "DELETE",
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
}
async getPolicies(): Promise<string[]> {
const request = new Request(this.appendAPIURL("/v1/sys/policies/acl?list=true"), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { keys: string[] } };
return data.data.keys;
}
async getPolicy(name: string): Promise<string> {
const request = new Request(this.appendAPIURL("/v1/sys/policies/acl/" + name), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { policy: string } };
return data.data.policy;
}
async createOrUpdateSecret(
baseMount: string,
secretPath: string[],
name: string,
data: Record<string, unknown>,
): Promise<void> {
let secretURL = "";
let APIData = {};
const mountInfo = await this.getMount(baseMount);
if (mountInfo.options.version == "2") {
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(this.appendAPIURL(secretURL), {
method: "POST",
headers: {
"Content-Type": "application/json",
...this.getHeaders(),
},
body: JSON.stringify(APIData, null, 0),
});
const resp = await fetch(request);
await checkResponse(resp);
}
async deleteSecret(baseMount: string, secretPath: string[], name: string): Promise<void> {
let secretURL = "";
let request;
const mountInfo = await this.getMount(baseMount);
if (mountInfo.options.version == "2") {
secretURL = `/v1/${baseMount}/metadata/${secretPath.join("/")}/${name}`;
} else {
secretURL = `/v1/${baseMount}/${secretPath.join("/")}/${name}`;
}
secretURL = removeDoubleSlash(secretURL).replace(/\/$/, "");
request = new Request(this.appendAPIURL(secretURL), {
method: "DELETE",
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
}
async getSecretKV1(
baseMount: string,
secretPath: string[],
name: string,
): Promise<Record<string, unknown>> {
const request = new Request(
this.appendAPIURL(`/v1/${baseMount}/${secretPath.join("")}/${name}`),
{
headers: this.getHeaders(),
},
);
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as unknown;
return (data as { data: Record<string, unknown> }).data;
}
async getSecretKV2(
baseMount: string,
secretPath: string[],
name: string,
): Promise<Record<string, unknown>> {
let secretURL = "";
secretURL = `/v1/${baseMount}/data/${secretPath.join("")}/${name}`;
const request = new Request(this.appendAPIURL(secretURL), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as unknown;
return (data as { data: { data: Record<string, unknown> } }).data.data;
}
async getSecret(
baseMount: string,
secretPath: string[],
name: string,
): Promise<Record<string, unknown>> {
const mountInfo = await this.getMount(baseMount);
if (mountInfo.options.version == "2") {
return await this.getSecretKV2(baseMount, secretPath, name);
} else {
return await this.getSecretKV1(baseMount, secretPath, name);
}
}
async getSecretMetadata(
baseMount: string,
secretPath: string[],
name: string,
): Promise<SecretMetadataType> {
const request = new Request(
this.appendAPIURL(`/v1/${baseMount}/metadata/${secretPath.join("")}/${name}`),
{
headers: this.getHeaders(),
},
);
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: SecretMetadataType };
return data.data;
}
async getSecrets(baseMount: string, secretPath: string[]): Promise<string[]> {
let secretURL = "";
const mountInfo = await this.getMount(baseMount);
if (mountInfo.options.version == "2") {
secretURL = `/v1/${baseMount}/metadata/${secretPath.join("/")}?list=true`;
} else {
secretURL = `/v1/${baseMount}/${secretPath.join("/")}?list=true`;
}
const request = new Request(this.appendAPIURL(secretURL), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { keys: string[] } };
return data.data.keys;
}
async addNewTOTP(baseMount: string, parms: { name: string }): Promise<void> {
const request = new Request(
this.appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/keys/${parms.name}`)),
{
method: "POST",
headers: {
"Content-Type": "application/json",
...this.getHeaders(),
},
body: JSON.stringify(parms),
},
);
const resp = await fetch(request);
await checkResponse(resp);
}
async deleteTOTP(baseMount: string, name: string): Promise<void> {
const request = new Request(this.appendAPIURL(`/v1/${baseMount}/keys/${name}`), {
method: "DELETE",
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
}
async getTOTPCode(baseMount: string, name: string): Promise<string> {
const request = new Request(this.appendAPIURL(`/v1/${baseMount}/code/${name}`), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { code: string } };
return data.data.code;
}
async getTOTPKeys(baseMount: string): Promise<string[]> {
const request = new Request(this.appendAPIURL(`/v1/${baseMount}/keys?list=true`), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { keys: string[] } };
return data.data.keys;
}
async getTransitKey(baseMount: string, name: string): Promise<TransitKeyType> {
const request = new Request(this.appendAPIURL(`/v1/${baseMount}/keys/${name}`), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: TransitKeyType };
return data.data;
}
async getTransitKeys(baseMount: string): Promise<string[]> {
const request = new Request(this.appendAPIURL(`/v1/${baseMount}/keys?list=true`), {
headers: this.getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { keys: string[] } };
return data.data.keys;
}
async newTransitKey(baseMount: string, parms: { name: string; type: string }): Promise<void> {
const request = new Request(
this.appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/keys/${parms.name}`)),
{
method: "POST",
headers: {
"Content-Type": "application/json",
...this.getHeaders(),
},
body: JSON.stringify(parms),
},
);
const resp = await fetch(request);
await checkResponse(resp);
}
async transitDecrypt(
baseMount: string,
name: string,
payload: DecryptionPayload,
): Promise<DecryptionResult> {
const request = new Request(
this.appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/decrypt/${name}`)),
{
method: "POST",
headers: {
"Content-Type": "application/json",
...this.getHeaders(),
},
body: JSON.stringify(payload),
},
);
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as {
data?: DecryptionResult;
};
return data.data;
}
async transitEncrypt(
baseMount: string,
name: string,
payload: EncryptionPayload,
): Promise<EncryptionResult> {
const request = new Request(
this.appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/encrypt/${name}`)),
{
method: "POST",
headers: {
"Content-Type": "application/json",
...this.getHeaders(),
},
body: JSON.stringify(payload),
},
);
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as {
data?: EncryptionResult;
};
return data.data;
}
async transitRewrap(
baseMount: string,
name: string,
payload: RewrapPayload,
): Promise<RewrapResult> {
const request = new Request(
this.appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/rewrap/${name}`)),
{
method: "POST",
headers: {
"Content-Type": "application/json",
...this.getHeaders(),
},
body: JSON.stringify(payload),
},
);
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as {
data?: RewrapResult;
};
return data.data;
}
}

View file

@ -1,13 +0,0 @@
import { AuthListAPIType, AuthListType } from "../types/auth";
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export async function listAuth(): Promise<AuthListType> {
const request = new Request(appendAPIURL(`/v1/sys/auth`), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as AuthListAPIType;
return data.data;
}

View file

@ -1,19 +0,0 @@
import { appendAPIURL, checkResponse } from "../apiUtils";
export async function usernameLogin(username: string, password: string): Promise<string> {
const request = new Request(appendAPIURL(`/v1/auth/userpass/login/${username}`), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ username: username, password: password }),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as {
auth: { client_token: string };
};
return data.auth.client_token;
}

View file

@ -1,23 +0,0 @@
import { UserType } from "../../types/userpass/user";
import { appendAPIURL, checkResponse, getHeaders } from "../../apiUtils";
import { removeDoubleSlash } from "../../../utils";
export async function createOrUpdateUserPassUser(
path: string,
username: string,
data: Partial<UserType>,
): Promise<void> {
const request = new Request(
appendAPIURL(removeDoubleSlash(`/v1/auth/${path}/users/${username}`)),
{
method: "POST",
headers: {
"Content-Type": "application/json",
...getHeaders(),
},
body: JSON.stringify(data, null, 0),
},
);
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,14 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../../apiUtils";
import { removeDoubleSlash } from "../../../utils";
export async function deleteUserPassUser(path: string, username: string): Promise<void> {
const request = new Request(
appendAPIURL(removeDoubleSlash(`/v1/auth/${path}/users/${username}`)),
{
method: "DELETE",
headers: getHeaders(),
},
);
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,13 +0,0 @@
import { UserType, UserTypeAPIResp } from "../../types/userpass/user";
import { appendAPIURL, checkResponse, getHeaders } from "../../apiUtils";
export async function getUserPassUser(path: string, username: string): Promise<UserType> {
const request = new Request(appendAPIURL(`/v1/auth/${path}/users/${username}`), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as UserTypeAPIResp;
return data.data;
}

View file

@ -1,12 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../../apiUtils";
export async function listUserPassUsers(path: string): Promise<string[]> {
const request = new Request(appendAPIURL(`/v1/auth/${path}/users?list=true`), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { keys: string[] } };
return data.data.keys;
}

View file

@ -1,34 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
import { getMount } from "../sys/getMounts";
import { removeDoubleSlash } from "../../utils";
export async function createOrUpdateSecret(
baseMount: string,
secretPath: string[],
name: string,
data: Record<string, unknown>,
): Promise<void> {
let secretURL = "";
let APIData = {};
const mountInfo = await getMount(baseMount);
if (mountInfo.options.version == "2") {
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),
});
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,26 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
import { getMount } from "../sys/getMounts";
import { removeDoubleSlash } from "../../utils";
export async function deleteSecret(
baseMount: string,
secretPath: string[],
name: string,
): Promise<void> {
let secretURL = "";
let request;
const mountInfo = await getMount(baseMount);
if (mountInfo.options.version == "2") {
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(),
});
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,52 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
import { getMount } from "../sys/getMounts";
export async function getSecretKV1(
baseMount: string,
secretPath: string[],
name: string,
): Promise<Record<string, unknown>> {
const request = new Request(appendAPIURL(`/v1/${baseMount}/${secretPath.join("")}/${name}`), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as unknown;
return (data as { data: Record<string, unknown> }).data;
}
export async function getSecretKV2(
baseMount: string,
secretPath: string[],
name: string,
): Promise<Record<string, unknown>> {
let secretURL = "";
secretURL = `/v1/${baseMount}/data/${secretPath.join("")}/${name}`;
const request = new Request(appendAPIURL(secretURL), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as unknown;
return (data as { data: { data: Record<string, unknown> } }).data.data;
}
export async function getSecret(
baseMount: string,
secretPath: string[],
name: string,
): Promise<Record<string, unknown>> {
const mountInfo = await getMount(baseMount);
if (mountInfo.options.version == "2") {
return await getSecretKV2(baseMount, secretPath, name);
} else {
return await getSecretKV1(baseMount, secretPath, name);
}
}

View file

@ -1,24 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
type SecretMetadataType = {
versions: Record<string, unknown>;
};
export async function getSecretMetadata(
baseMount: string,
secretPath: string[],
name: string,
): Promise<SecretMetadataType> {
const request = new Request(
appendAPIURL(`/v1/${baseMount}/metadata/${secretPath.join("")}/${name}`),
{
headers: getHeaders(),
},
);
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: SecretMetadataType };
return data.data;
}

View file

@ -1,24 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export async function getSecrets(baseMount: string, secretPath: string[]): Promise<string[]> {
let secretURL = "";
// TODO: FIX THIS
const secretMountType = "kv-v2";
if (secretMountType == "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(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { keys: string[] } };
return data.data.keys;
}

View file

@ -1,29 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
import { getObjectKeys, removeDoubleSlash } from "../../utils";
import { getSecretMetadata } from "./getSecretMetadata";
export async function undeleteSecret(
baseMount: string,
secretPath: string[],
name: string,
version: string | null = null,
): Promise<void> {
let secretURL = `/v1/${baseMount}/undelete/${secretPath.join("/")}/${name}`;
secretURL = removeDoubleSlash(secretURL).replace(/\/$/, "");
if (version == null) {
const meta = await getSecretMetadata(baseMount, secretPath, name);
const versions = getObjectKeys(meta.versions);
version = String(versions[versions.length - 1]);
}
const request = new Request(appendAPIURL(secretURL), {
method: "POST",
headers: {
...getHeaders(),
"Content-Type": "application/json",
},
body: JSON.stringify({ versions: [version] }),
});
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,10 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export async function deleteMount(mountPath: string): Promise<void> {
const request = new Request(appendAPIURL("/v1/sys/mounts/" + mountPath), {
method: "DELETE",
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,43 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
import { removeDoubleSlash } from "../../utils";
export type CapabilitiesType = {
[path: string]: string[];
capabilities?: string[];
};
export async function getCapabilitiesPath(path: string | string[]): Promise<CapabilitiesType> {
if (!Array.isArray(path)) {
path = [path];
}
const request = new Request(appendAPIURL("/v1/sys/capabilities-self"), {
method: "POST",
headers: {
"Content-Type": "application/json",
...getHeaders(),
},
body: JSON.stringify({
paths: path,
}),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { capabilities: string[] };
return data;
}
export async function getCapsPath(path: string | string[]): Promise<string[]> {
return (await getCapabilitiesPath(path)).capabilities;
}
export async function getCapabilities(
baseMount: string,
secretPath: string[],
name: string,
): Promise<CapabilitiesType> {
return await getCapabilitiesPath(
removeDoubleSlash(baseMount + secretPath.join("/") + "/" + name),
);
}

View file

@ -1,34 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export type MountType = {
type: string;
options: {
version: string;
};
};
export type MountsType = {
[key: string]: MountType;
};
export async function getMounts(): Promise<MountsType> {
const request = new Request(appendAPIURL("/v1/sys/internal/ui/mounts"), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { secret: MountsType } };
return data.data.secret;
}
export async function getMount(mountName: string): Promise<MountType> {
const request = new Request(appendAPIURL("/v1/sys/internal/ui/mounts/" + mountName), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: MountType };
return data.data;
}

View file

@ -1,16 +0,0 @@
import { appendAPIURL, checkResponse } from "../apiUtils";
export type SealStatusType = {
progress: number;
t: number;
sealed: boolean;
};
export async function getSealStatus(): Promise<SealStatusType> {
const request = new Request(appendAPIURL("/v1/sys/seal-status"));
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as SealStatusType;
return data;
}

View file

@ -1,13 +0,0 @@
import { TokenInfo } from "../types/token";
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export async function lookupSelf(): Promise<TokenInfo> {
const request = new Request(appendAPIURL("/v1/auth/token/lookup-self"), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: TokenInfo };
return data.data;
}

View file

@ -1,23 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
import { removeDoubleSlash } from "../../utils";
type NewMountParams = {
name: string;
type: string;
options?: {
version: string;
};
};
export async function newMount(parms: NewMountParams): Promise<void> {
const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/sys/mounts/${parms.name}`)), {
method: "POST",
headers: {
"Content-Type": "application/json",
...getHeaders(),
},
body: JSON.stringify(parms),
});
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,15 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../../apiUtils";
export async function createOrUpdatePolicy(name: string, policy_data: string): Promise<void> {
const request = new Request(appendAPIURL("/v1/sys/policies/acl/" + name), {
method: "POST",
headers: {
"Content-Type": "application/json",
...getHeaders(),
},
body: JSON.stringify({ policy: policy_data }, null, 0),
});
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,10 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../../apiUtils";
export async function deletePolicy(name: string): Promise<void> {
const request = new Request(appendAPIURL("/v1/sys/policies/acl/" + name), {
method: "DELETE",
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,12 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../../apiUtils";
export async function getPolicies(): Promise<string[]> {
const request = new Request(appendAPIURL("/v1/sys/policies/acl?list=true"), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { keys: string[] } };
return data.data.keys;
}

View file

@ -1,12 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../../apiUtils";
export async function getPolicy(name: string): Promise<string> {
const request = new Request(appendAPIURL("/v1/sys/policies/acl/" + name), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { policy: string } };
return data.data.policy;
}

View file

@ -1,14 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export async function renewSelf(): Promise<void> {
const request = new Request(appendAPIURL("/v1/auth/token/renew-self"), {
method: "POST",
headers: {
...getHeaders(),
"Content-Type": "application/json",
},
body: JSON.stringify({}),
});
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,10 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export async function sealVault(): Promise<void> {
const request = new Request(appendAPIURL("/v1/sys/seal"), {
method: "PUT",
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,15 +0,0 @@
import { appendAPIURL, checkResponse } from "../apiUtils";
export async function submitUnsealKey(key: string): Promise<void> {
const request = new Request(appendAPIURL("/v1/sys/unseal"), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
key: key,
}),
});
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,18 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
import { removeDoubleSlash } from "../../utils";
export async function addNewTOTP(baseMount: string, parms: { name: string }): Promise<void> {
const request = new Request(
appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/keys/${parms.name}`)),
{
method: "POST",
headers: {
"Content-Type": "application/json",
...getHeaders(),
},
body: JSON.stringify(parms),
},
);
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,10 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export async function deleteTOTP(baseMount: string, name: string): Promise<void> {
const request = new Request(appendAPIURL(`/v1/${baseMount}/keys/${name}`), {
method: "DELETE",
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,13 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export async function getTOTPCode(baseMount: string, name: string): Promise<string> {
const request = new Request(appendAPIURL(`/v1/${baseMount}/code/${name}`), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { code: string } };
return data.data.code;
}

View file

@ -1,13 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export async function getTOTPKeys(baseMount: string): Promise<string[]> {
const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { keys: string[] } };
return data.data.keys;
}

View file

@ -1,14 +0,0 @@
import { TransitKeyType } from "../types/transit";
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export async function getTransitKey(baseMount: string, name: string): Promise<TransitKeyType> {
const request = new Request(appendAPIURL(`/v1/${baseMount}/keys/${name}`), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: TransitKeyType };
return data.data;
}

View file

@ -1,13 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
export async function getTransitKeys(baseMount: string): Promise<string[]> {
const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), {
headers: getHeaders(),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as { data: { keys: string[] } };
return data.data.keys;
}

View file

@ -1,21 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
import { removeDoubleSlash } from "../../utils";
export async function newTransitKey(
baseMount: string,
parms: { name: string; type: string },
): Promise<void> {
const request = new Request(
appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/keys/${parms.name}`)),
{
method: "POST",
headers: {
"Content-Type": "application/json",
...getHeaders(),
},
body: JSON.stringify(parms),
},
);
const resp = await fetch(request);
await checkResponse(resp);
}

View file

@ -1,34 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
import { removeDoubleSlash } from "../../utils";
type DecryptionResult = {
plaintext: string;
};
type DecryptionPayload = {
ciphertext: string;
};
export async function transitDecrypt(
baseMount: string,
name: string,
payload: DecryptionPayload,
): Promise<DecryptionResult> {
const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/decrypt/${name}`)), {
method: "POST",
headers: {
"Content-Type": "application/json",
...getHeaders(),
},
body: JSON.stringify(payload),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as {
data?: DecryptionResult;
};
return data.data;
}

View file

@ -1,34 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
import { removeDoubleSlash } from "../../utils";
type EncryptionResult = {
ciphertext: string;
};
type EncryptionPayload = {
plaintext: string;
};
export async function transitEncrypt(
baseMount: string,
name: string,
payload: EncryptionPayload,
): Promise<EncryptionResult> {
const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/encrypt/${name}`)), {
method: "POST",
headers: {
"Content-Type": "application/json",
...getHeaders(),
},
body: JSON.stringify(payload),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as {
data?: EncryptionResult;
};
return data.data;
}

View file

@ -1,35 +0,0 @@
import { appendAPIURL, checkResponse, getHeaders } from "../apiUtils";
import { removeDoubleSlash } from "../../utils";
type RewrapResult = {
ciphertext: string;
};
type RewrapPayload = {
ciphertext: string;
key_version?: number;
};
export async function transitRewrap(
baseMount: string,
name: string,
payload: RewrapPayload,
): Promise<RewrapResult> {
const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/rewrap/${name}`)), {
method: "POST",
headers: {
"Content-Type": "application/json",
...getHeaders(),
},
body: JSON.stringify(payload),
});
const resp = await fetch(request);
await checkResponse(resp);
const data = (await resp.json()) as {
data?: RewrapResult;
};
return data.data;
}

View file

@ -0,0 +1,4 @@
export type CapabilitiesType = {
[path: string]: string[];
capabilities?: string[];
};

18
src/api/types/mount.ts Normal file
View file

@ -0,0 +1,18 @@
export type MountType = {
type: string;
options: {
version: string;
};
};
export type MountsType = {
[key: string]: MountType;
};
export type NewMountParams = {
name: string;
type: string;
options?: {
version: string;
};
};

5
src/api/types/seal.ts Normal file
View file

@ -0,0 +1,5 @@
export type SealStatusType = {
progress: number;
t: number;
sealed: boolean;
};

3
src/api/types/secret.ts Normal file
View file

@ -0,0 +1,3 @@
type SecretMetadataType = {
versions: Record<string, unknown>;
};

View file

@ -33,3 +33,28 @@ export type TransitKeyType = TransitKeyBaseType & {
supports_derivation: boolean;
supports_signing: boolean;
};
export type DecryptionResult = {
plaintext: string;
};
export type DecryptionPayload = {
ciphertext: string;
};
export type EncryptionResult = {
ciphertext: string;
};
export type EncryptionPayload = {
plaintext: string;
};
export type RewrapResult = {
ciphertext: string;
};
export type RewrapPayload = {
ciphertext: string;
key_version?: number;
};

4
src/globalAPI.ts Normal file
View file

@ -0,0 +1,4 @@
import { API } from "./api/API";
import { settings } from "./globalSettings";
export const api = new API(settings);

View file

@ -23,14 +23,15 @@ import translations from "./translations/index.mjs";
// Actual Imports
import { formatDistance } from "./formatDistance";
import { getSealStatus } from "./api/sys/getSealStatus";
//import { pageList } from "./allPages";
import { render } from "preact";
import { NavBar } from "./ui/elements/NavBar";
import { api } from "./globalAPI";
import { settings } from "./globalSettings";
import { playground } from "./playground";
import i18next from "i18next";
import { Main } from "./pages";
import { getCurrentUrl, route } from "preact-router";
async function onLoad(): Promise<void> {
document.documentElement.dir = settings.pageDirection;
@ -53,18 +54,20 @@ async function onLoad(): Promise<void> {
//await pageRouter.changePage(pageState.currentPage);
//setInterval(async () => {
// if ((await pageRouter.getCurrentPageID()) != "UNSEAL") {
// if (pageState.apiURL.length != 0) {
// return;
// }
// const sealStatus = await getSealStatus();
// if (sealStatus.sealed) {
// await pageRouter.changePage("UNSEAL");
// return;
// }
// }
//}, 5000);
setInterval(async () => {
console.log(getCurrentUrl());
if (getCurrentUrl() != "/unseal") {
// TODO: check if api is accessable, not if its not set
if (settings.apiURL.length == 0) {
return;
}
const sealStatus = await api.getSealStatus();
if (sealStatus.sealed) {
route("/unseal", false);
return;
}
}
}, 5000);
}
document.addEventListener(

View file

@ -1,12 +1,11 @@
import { Settings } from "./settings/Settings";
import { getSealStatus } from "./api/sys/getSealStatus";
import { lookupSelf } from "./api/sys/lookupSelf";
import { route } from "preact-router";
import ClipboardJS from "clipboard";
import UIkit from "uikit";
import i18next from "i18next";
import { API } from "./api/API";
async function prePageChecksReal(settings: Settings) {
async function prePageChecksReal(api: API, settings: Settings) {
if (settings.language.length == 0) {
route("/set_language", true);
throw new Error("Language Not Set");
@ -17,23 +16,23 @@ async function prePageChecksReal(settings: Settings) {
throw new Error("Vault URL Not Set");
}
const sealStatus = await getSealStatus();
const sealStatus = await api.getSealStatus();
if (sealStatus.sealed) {
route("/unseal", true);
throw new Error("Vault Sealed");
}
try {
await lookupSelf();
await api.lookupSelf();
} catch (e) {
route("/login", true);
throw e;
}
}
export async function prePageChecks(settings: Settings): Promise<boolean> {
export async function prePageChecks(api: API, settings: Settings): Promise<boolean> {
try {
await prePageChecksReal(settings);
await prePageChecksReal(api, settings);
} catch (e) {
console.log("OHNO", e);
return false;

View file

@ -1,5 +1,6 @@
import Router from "preact-router";
import { settings } from "./globalSettings";
import { api } from "./globalAPI";
import { DeleteSecretsEngine } from "./ui/pages/Secrets/DeleteSecretsEngine";
import { Home } from "./ui/pages/Home";
@ -44,54 +45,94 @@ import { UserPassUserEdit } from "./ui/pages/Access/Auth/userpass/UserPassUserEd
export const Main = () => (
<Router>
<Home path="/" settings={settings} />
<Me path="/me" settings={settings} />
<Login path="/login" settings={settings} />
<PasswordGenerator path="/pw_gen" />
<SetVaultURL path="/set_vault_url" settings={settings} />
<Unseal path="/unseal" settings={settings} />
<SetLanguage path="/set_language" settings={settings} />
<Home path="/" settings={settings} api={api} />
<Me path="/me" settings={settings} api={api} />
<Login path="/login" settings={settings} api={api} />
<PasswordGenerator path="/pw_gen" settings={settings} api={api} />
<SetVaultURL path="/set_vault_url" settings={settings} api={api} />
<Unseal path="/unseal" settings={settings} api={api} />
<SetLanguage path="/set_language" settings={settings} api={api} />
<Secrets path="/secrets" settings={settings} />
<DeleteSecretsEngine path="/secrets/delete_engine/:mount" settings={settings} />
<Secrets path="/secrets" settings={settings} api={api} />
<DeleteSecretsEngine path="/secrets/delete_engine/:mount" settings={settings} api={api} />
<NewSecretsEngine path="/secrets/new_secrets_engine" />
<NewKVEngine path="/secrets/new_secrets_engine/kv" />
<NewTOTPEngine path="/secrets/new_secrets_engine/totp" />
<NewTransitEngine path="/secrets/new_secrets_engine/trasit" />
<NewSecretsEngine path="/secrets/new_secrets_engine" settings={settings} api={api} />
<NewKVEngine path="/secrets/new_secrets_engine/kv" settings={settings} api={api} />
<NewTOTPEngine path="/secrets/new_secrets_engine/totp" settings={settings} api={api} />
<NewTransitEngine path="/secrets/new_secrets_engine/trasit" settings={settings} api={api} />
<KeyValueNew path="/secrets/kv/new/:baseMount/:secretPath*?" settings={settings} />
<KeyValueList path="/secrets/kv/list/:baseMount/:secretPath*?" settings={settings} />
<KeyValueView path="/secrets/kv/view/:item/:baseMount/:secretPath*?" settings={settings} />
<KeyValueEdit path="/secrets/kv/edit/:item/:baseMount/:secretPath*?" settings={settings} />
<KeyValueDelete path="/secrets/kv/delete/:item/:baseMount/:secretPath*?" settings={settings} />
<KeyValueNew path="/secrets/kv/new/:baseMount/:secretPath*?" settings={settings} api={api} />
<KeyValueList path="/secrets/kv/list/:baseMount/:secretPath*?" settings={settings} api={api} />
<KeyValueView
path="/secrets/kv/view/:item/:baseMount/:secretPath*?"
settings={settings}
api={api}
/>
<KeyValueEdit
path="/secrets/kv/edit/:item/:baseMount/:secretPath*?"
settings={settings}
api={api}
/>
<KeyValueDelete
path="/secrets/kv/delete/:item/:baseMount/:secretPath*?"
settings={settings}
api={api}
/>
<TOTPList path="/secrets/totp/list/:baseMount" settings={settings} />
<TOTPNew path="/secrets/totp/new/:baseMount" settings={settings} />
<TOTPDelete path="/secrets/totp/delete/:baseMount/:item" settings={settings} />
<TOTPList path="/secrets/totp/list/:baseMount" settings={settings} api={api} />
<TOTPNew path="/secrets/totp/new/:baseMount" settings={settings} api={api} />
<TOTPDelete path="/secrets/totp/delete/:baseMount/:item" settings={settings} api={api} />
<TransitNew path="/secrets/transit/new/:baseMount" settings={settings} />
<TransitList path="/secrets/transit/list/:baseMount" settings={settings} />
<TransitView path="/secrets/transit/view/:baseMount/:secretItem" settings={settings} />
<TransitEncrypt path="/secrets/transit/encrypt/:baseMount/:secretItem" settings={settings} />
<TransitDecrypt path="/secrets/transit/decrypt/:baseMount/:secretItem" settings={settings} />
<TransitRewrap path="/secrets/transit/rewrap/:baseMount/:secretItem" settings={settings} />
<TransitNew path="/secrets/transit/new/:baseMount" settings={settings} api={api} />
<TransitList path="/secrets/transit/list/:baseMount" settings={settings} api={api} />
<TransitView
path="/secrets/transit/view/:baseMount/:secretItem"
settings={settings}
api={api}
/>
<TransitEncrypt
path="/secrets/transit/encrypt/:baseMount/:secretItem"
settings={settings}
api={api}
/>
<TransitDecrypt
path="/secrets/transit/decrypt/:baseMount/:secretItem"
settings={settings}
api={api}
/>
<TransitRewrap
path="/secrets/transit/rewrap/:baseMount/:secretItem"
settings={settings}
api={api}
/>
<PoliciesHome path="/policies" settings={settings} />
<PolicyNew path="/policies/new" settings={settings} />
<PolicyView path="/policies/view/:policyName" settings={settings} />
<PolicyEdit path="/policies/edit/:policyName" settings={settings} />
<PolicyDelete path="/policies/delete/:policyName" settings={settings} />
<PoliciesHome path="/policies" settings={settings} api={api} />
<PolicyNew path="/policies/new" settings={settings} api={api} />
<PolicyView path="/policies/view/:policyName" settings={settings} api={api} />
<PolicyEdit path="/policies/edit/:policyName" settings={settings} api={api} />
<PolicyDelete path="/policies/delete/:policyName" settings={settings} api={api} />
<AccessHomePage path="/access" settings={settings} />
<AuthHome path="/access/auth" settings={settings} />
<AuthViewConfig path="/access/auth/view/:baseMount" settings={settings} />
<AccessHomePage path="/access" settings={settings} api={api} />
<AuthHome path="/access/auth" settings={settings} api={api} />
<AuthViewConfig path="/access/auth/view/:baseMount" settings={settings} api={api} />
<UserPassUsersList path="/access/auth/userpass/list/:baseMount" settings={settings} />
<UserPassUserNew path="/access/auth/userpass/new/:baseMount" settings={settings} />
<UserPassUserView path="/access/auth/userpass/view/:baseMount/:user" settings={settings} />
<UserPassUserEdit path="/access/auth/userpass/edit/:baseMount/:user" settings={settings} />
<UserPassUserDelete path="/access/auth/userpass/delete/:baseMount/:user" settings={settings} />
<UserPassUsersList path="/access/auth/userpass/list/:baseMount" settings={settings} api={api} />
<UserPassUserNew path="/access/auth/userpass/new/:baseMount" settings={settings} api={api} />
<UserPassUserView
path="/access/auth/userpass/view/:baseMount/:user"
settings={settings}
api={api}
/>
<UserPassUserEdit
path="/access/auth/userpass/edit/:baseMount/:user"
settings={settings}
api={api}
/>
<UserPassUserDelete
path="/access/auth/userpass/delete/:baseMount/:user"
settings={settings}
api={api}
/>
<div default>
<p>PAGE NOT YET IMPLEMENTED</p>

View file

@ -1,6 +1,8 @@
import { API } from "../api/API";
import { Settings } from "../settings/Settings";
export type DefaultPageProps = {
settings: Settings;
api: API;
matches?: { [key: string]: string };
};

View file

@ -9,7 +9,7 @@ import { PageTitle } from "../../elements/PageTitle";
export class AccessHomePage extends Component<DefaultPageProps> {
async componentDidMount() {
if (!(await prePageChecks(this.props.settings))) return;
if (!(await prePageChecks(this.props.api, this.props.settings))) return;
}
render() {

View file

@ -1,6 +1,5 @@
import { AuthMethod } from "../../../../api/types/auth";
import { Component, JSX } from "preact";
import { listAuth } from "../../../../api/auth/listAuth";
import { notImplemented } from "../../../../pageUtils";
import { objectToMap } from "../../../../utils";
import i18next from "i18next";
@ -52,7 +51,7 @@ export function AuthListElement(props: AuthListElementProps): JSX.Element {
export class AuthHome extends Component<DefaultPageProps, { authList: Map<String, AuthMethod> }> {
async componentDidMount() {
const authList = objectToMap(await listAuth()) as Map<string, AuthMethod>;
const authList = objectToMap(await this.props.api.listAuth()) as Map<string, AuthMethod>;
this.setState({ authList });
}
render() {

View file

@ -1,6 +1,5 @@
import { AuthMethod } from "../../../../api/types/auth";
import { HeaderAndContent } from "../../../elements/HeaderAndContent";
import { listAuth } from "../../../../api/auth/listAuth";
import { objectToMap, toStr } from "../../../../utils";
import { Component } from "preact";
import i18next from "i18next";
@ -10,7 +9,7 @@ import { PageTitle } from "../../../elements/PageTitle";
export class AuthViewConfig extends Component<DefaultPageProps, { authMethod: AuthMethod }> {
async componentDidMount() {
const baseMount = this.props.matches["baseMount"];
const authList = objectToMap(await listAuth()) as Map<string, AuthMethod>;
const authList = objectToMap(await this.props.api.listAuth()) as Map<string, AuthMethod>;
const authMethod = authList.get(baseMount + "/");
this.setState({ authMethod: authMethod });
}

View file

@ -1,4 +1,3 @@
import { deleteUserPassUser } from "../../../../../api/auth/userpass/deleteUserPassUser";
import { Component } from "preact";
import i18next from "i18next";
import { DefaultPageProps } from "../../../../../types/DefaultPageProps";
@ -19,7 +18,7 @@ export class UserPassUserDelete extends Component<DefaultPageProps> {
<button
class="uk-button uk-button-danger"
onClick={async () => {
await deleteUserPassUser(baseMount, user);
await this.props.api.deleteUserPassUser(baseMount, user);
route(userPassUserListURL(baseMount));
}}
>

View file

@ -2,10 +2,8 @@ import { Form } from "../../../../elements/Form";
import { InputWithTitle } from "../../../../elements/InputWithTitle";
import { Margin } from "../../../../elements/Margin";
import { MarginInline } from "../../../../elements/MarginInline";
import { UserType } from "../../../../../api/types/userpass/user";
import { createOrUpdateUserPassUser } from "../../../../../api/auth/userpass/createOrUpdateUserPassUser";
import { getUserPassUser } from "../../../../../api/auth/userpass/getUserPassUser";
import { Component, render } from "preact";
import { UserType } from "../../../../../api/types/user";
import { Component } from "preact";
import { setErrorText } from "../../../../../pageUtils";
import { toStr } from "../../../../../utils";
import i18next from "i18next";
@ -21,7 +19,7 @@ export class UserPassUserEdit extends Component<DefaultPageProps, { user_data: U
const baseMount = this.props.matches["baseMount"];
const user = this.props.matches["user"];
const user_data = await getUserPassUser(baseMount, user);
const user_data = await this.props.api.getUserPassUser(baseMount, user);
this.setState({ user_data });
}
@ -142,7 +140,7 @@ export class UserPassUserEdit extends Component<DefaultPageProps, { user_data: U
apiData.password = password;
}
try {
await createOrUpdateUserPassUser(baseMount, user, apiData);
await this.props.api.createOrUpdateUserPassUser(baseMount, user, apiData);
route(userPassUserViewURL(baseMount, user));
} catch (e: unknown) {
const error = e as Error;

View file

@ -1,9 +1,8 @@
import { Form } from "../../../../elements/Form";
import { Margin } from "../../../../elements/Margin";
import { MarginInline } from "../../../../elements/MarginInline";
import { UserType } from "../../../../../api/types/userpass/user";
import { createOrUpdateUserPassUser } from "../../../../../api/auth/userpass/createOrUpdateUserPassUser";
import { Component, render } from "preact";
import { UserType } from "../../../../../api/types/user";
import { Component } from "preact";
import { setErrorText } from "../../../../../pageUtils";
import i18next from "i18next";
import { DefaultPageProps } from "../../../../../types/DefaultPageProps";
@ -50,7 +49,11 @@ export class UserPassUserNew extends Component<DefaultPageProps> {
password: data.get("password") as string,
};
try {
await createOrUpdateUserPassUser(baseMount, data.get("username") as string, apiData);
await this.props.api.createOrUpdateUserPassUser(
baseMount,
data.get("username") as string,
apiData,
);
route(userPassUserViewURL(baseMount, data.get("username") as string));
} catch (e: unknown) {
const error = e as Error;

View file

@ -1,11 +1,10 @@
import { HeaderAndContent } from "../../../../elements/HeaderAndContent";
import { Margin } from "../../../../elements/Margin";
import { getUserPassUser } from "../../../../../api/auth/userpass/getUserPassUser";
import { Component } from "preact";
import { toStr } from "../../../../../utils";
import i18next from "i18next";
import { DefaultPageProps } from "../../../../../types/DefaultPageProps";
import { UserType } from "../../../../../api/types/userpass/user";
import { UserType } from "../../../../../api/types/user";
import { PageTitle } from "../../../../elements/PageTitle";
import { route } from "preact-router";
import { userPassUserDeleteURL, userPassUserEditURL } from "../../../pageLinks";
@ -15,7 +14,7 @@ export class UserPassUserView extends Component<DefaultPageProps, { user_data: U
const baseMount = this.props.matches["baseMount"];
const user = this.props.matches["user"];
const user_data = await getUserPassUser(baseMount, user);
const user_data = await this.props.api.getUserPassUser(baseMount, user);
this.setState({ user_data });
}

View file

@ -1,4 +1,3 @@
import { listUserPassUsers } from "../../../../../api/auth/userpass/listUserPassUsers";
import { Component } from "preact";
import i18next from "i18next";
import { DefaultPageProps } from "../../../../../types/DefaultPageProps";
@ -9,7 +8,7 @@ import { PageTitle } from "../../../../elements/PageTitle";
export class UserPassUsersList extends Component<DefaultPageProps, { users: string[] }> {
async componentDidMount() {
const baseMount = this.props.matches["baseMount"];
const users = await listUserPassUsers(baseMount);
const users = await this.props.api.listUserPassUsers(baseMount);
this.setState({ users });
}

View file

@ -4,8 +4,6 @@ import { Margin } from "../elements/Margin";
import { PageTitle } from "../elements/PageTitle";
import { Tile } from "../elements/Tile";
import { TokenInfo } from "../../api/types/token";
import { getCapabilitiesPath } from "../../api/sys/getCapabilities";
import { lookupSelf } from "../../api/sys/lookupSelf";
import { prePageChecks, setErrorText } from "../../pageUtils";
import { route } from "preact-router";
import i18next from "i18next";
@ -19,11 +17,11 @@ type HomeState = {
export class Home extends Component<DefaultPageProps, HomeState> {
async componentDidMount() {
if (!(await prePageChecks(this.props.settings))) return;
if (!(await prePageChecks(this.props.api, this.props.settings))) return;
let selfTokenInfo: TokenInfo;
try {
selfTokenInfo = await lookupSelf();
selfTokenInfo = await this.props.api.lookupSelf();
} catch (e: unknown) {
const error = e as Error;
setErrorText(error.message);
@ -34,7 +32,7 @@ export class Home extends Component<DefaultPageProps, HomeState> {
}
}
const caps = await getCapabilitiesPath(["sys/auth", "sys/policies"]);
const caps = await this.props.api.getCapabilitiesPath(["sys/auth", "sys/policies"]);
const authCaps = caps["sys/auth"];
const policiesCaps = caps["sys/policies"];

View file

@ -4,10 +4,8 @@ import { Form } from "../elements/Form";
import { Margin } from "../elements/Margin";
import { MarginInline } from "../elements/MarginInline";
import { PageTitle } from "../elements/PageTitle";
import { lookupSelf } from "../../api/sys/lookupSelf";
import { route } from "preact-router";
import { setErrorText } from "../../pageUtils";
import { usernameLogin } from "../../api/auth/usernameLogin";
import i18next from "i18next";
export class TokenLoginForm extends Component<DefaultPageProps> {
@ -42,7 +40,7 @@ export class TokenLoginForm extends Component<DefaultPageProps> {
this.props.settings.token = token as string;
try {
await lookupSelf();
await this.props.api.lookupSelf();
route("/");
} catch (e: unknown) {
const error = e as Error;
@ -95,7 +93,7 @@ export class UsernameLoginForm extends Component<DefaultPageProps> {
async onSubmit(data: FormData): Promise<void> {
try {
const res = await usernameLogin(
const res = await this.props.api.usernameLogin(
data.get("username") as string,
data.get("password") as string,
);
@ -127,10 +125,10 @@ export class Login extends Component<DefaultPageProps> {
<p id="errorText" class="uk-text-danger" />
<ul class="uk-switcher uk-margin switcher-container">
<li>
<TokenLoginForm settings={this.props.settings} />
<TokenLoginForm settings={this.props.settings} api={this.props.api} />
</li>
<li>
<UsernameLoginForm settings={this.props.settings} />
<UsernameLoginForm settings={this.props.settings} api={this.props.api} />
</li>
</ul>
</div>

View file

@ -2,10 +2,7 @@ import { Component, JSX, createRef } from "preact";
import { DefaultPageProps } from "../../types/DefaultPageProps";
import { PageTitle } from "../elements/PageTitle";
import { addClipboardNotifications, setErrorText } from "../../pageUtils";
import { getCapsPath } from "../../api/sys/getCapabilities";
import { renewSelf } from "../../api/sys/renewSelf";
import { route } from "preact-router";
import { sealVault } from "../../api/sys/sealVault";
import ClipboardJS from "clipboard";
import i18next from "i18next";
@ -45,7 +42,7 @@ export class Me extends Component<DefaultPageProps, MeState> {
async componentDidMount() {
let canSealVault = false;
try {
const caps = await getCapsPath("sys/seal");
const caps = await this.props.api.getCapsPath("sys/seal");
canSealVault = caps.includes("sudo") && caps.includes("update");
} catch (e) {
canSealVault = false;
@ -80,7 +77,7 @@ export class Me extends Component<DefaultPageProps, MeState> {
<a
onClick={async () => {
try {
await renewSelf();
await this.props.api.renewSelf();
route("/");
} catch (e: unknown) {
const error = e as Error;
@ -95,7 +92,7 @@ export class Me extends Component<DefaultPageProps, MeState> {
<li>
<a
onClick={async () => {
await sealVault();
await this.props.api.sealVault();
route("/unseal", true);
}}
>

View file

@ -1,5 +1,4 @@
import { Margin } from "../../elements/Margin";
import { getPolicies } from "../../../api/sys/policies/getPolicies";
import { prePageChecks } from "../../../pageUtils";
import { Component } from "preact";
import i18next from "i18next";
@ -10,9 +9,9 @@ import { policyNewURL, policyViewURL } from "../pageLinks";
export class PoliciesHome extends Component<DefaultPageProps, { policies: string[] }> {
async componentDidMount() {
if (!(await prePageChecks(this.props.settings))) return;
if (!(await prePageChecks(this.props.api, this.props.settings))) return;
let policies = await getPolicies();
let policies = await this.props.api.getPolicies();
policies = policies.sort();
policies = policies.filter(function (policy_name) {
return policy_name !== "root";

View file

@ -1,5 +1,4 @@
import { deletePolicy } from "../../../api/sys/policies/deletePolicy";
import { Component, render } from "preact";
import { Component } from "preact";
import { setErrorText } from "../../../pageUtils";
import i18next from "i18next";
import { DefaultPageProps } from "../../../types/DefaultPageProps";
@ -18,7 +17,7 @@ export class PolicyDelete extends Component<DefaultPageProps> {
class="uk-button uk-button-danger"
onClick={async () => {
try {
await deletePolicy(policyName);
await this.props.api.deletePolicy(policyName);
route("/policies");
} catch (e: unknown) {
const error = e as Error;

View file

@ -2,8 +2,6 @@ import { CodeEditor } from "../../elements/CodeEditor";
import { Component, JSX, render } from "preact";
import { Margin } from "../../elements/Margin";
import { MarginInline } from "../../elements/MarginInline";
import { createOrUpdatePolicy } from "../../../api/sys/policies/createOrUpdatePolicy";
import { getPolicy } from "../../../api/sys/policies/getPolicy";
import { setErrorText } from "../../../pageUtils";
import i18next from "i18next";
import { DefaultPageProps } from "../../../types/DefaultPageProps";
@ -11,7 +9,7 @@ import { PageTitle } from "../../elements/PageTitle";
import { route } from "preact-router";
import { policyViewURL } from "../pageLinks";
type PolicyEditorProps = {
type PolicyEditorProps = DefaultPageProps & {
policyName: string;
};
@ -37,7 +35,7 @@ export class PolicyEditor extends Component<PolicyEditorProps, PolicyEditorState
if (!this.state.dataLoaded) return;
try {
await createOrUpdatePolicy(this.props.policyName, this.state.code);
await this.props.api.createOrUpdatePolicy(this.props.policyName, this.state.code);
route(policyViewURL(this.props.policyName));
} catch (e: unknown) {
const error = e as Error;
@ -52,7 +50,7 @@ export class PolicyEditor extends Component<PolicyEditorProps, PolicyEditorState
}
async loadData(): Promise<void> {
const policyData = await getPolicy(this.props.policyName);
const policyData = await this.props.api.getPolicy(this.props.policyName);
this.setState({
dataLoaded: true,
policyData: policyData,
@ -100,7 +98,11 @@ export class PolicyEdit extends Component<DefaultPageProps> {
<>
<PageTitle title={i18next.t("policy_edit_title", { policy: policyName })} />
<div>
<PolicyEditor policyName={policyName} />
<PolicyEditor
settings={this.props.settings}
api={this.props.api}
policyName={policyName}
/>
</div>
</>
);

View file

@ -1,7 +1,5 @@
import { Form } from "../../elements/Form";
import { Margin } from "../../elements/Margin";
import { createOrUpdatePolicy } from "../../../api/sys/policies/createOrUpdatePolicy";
import { getPolicies } from "../../../api/sys/policies/getPolicies";
import { Component } from "preact";
import { setErrorText } from "../../../pageUtils";
import i18next from "i18next";
@ -19,13 +17,13 @@ export class PolicyNew extends Component<DefaultPageProps> {
<Form
onSubmit={async (formData) => {
const name = formData.get("name") as string;
if ((await getPolicies()).includes(name)) {
if ((await this.props.api.getPolicies()).includes(name)) {
setErrorText(i18next.t("policy_new_already_exists"));
return;
}
try {
await createOrUpdatePolicy(name, " ");
await this.props.api.createOrUpdatePolicy(name, " ");
route(policyViewURL(name));
} catch (e: unknown) {
const error = e as Error;

View file

@ -1,6 +1,5 @@
import { CodeBlock } from "../../elements/CodeBlock";
import { Margin } from "../../elements/Margin";
import { getPolicy } from "../../../api/sys/policies/getPolicy";
import { prePageChecks } from "../../../pageUtils";
import { Component } from "preact";
import i18next from "i18next";
@ -14,10 +13,10 @@ export class PolicyView extends Component<
{ policy: string; policyName: string }
> {
async componentDidMount() {
if (!(await prePageChecks(this.props.settings))) return;
if (!(await prePageChecks(this.props.api, this.props.settings))) return;
console.log(this.props);
const policyName = this.props.matches["policyName"];
const policy = await getPolicy(policyName);
const policy = await this.props.api.getPolicy(policyName);
this.setState({
policy,
policyName,

View file

@ -4,6 +4,7 @@ import { Form } from "../elements/Form";
import { Margin } from "../elements/Margin";
import { PageTitle } from "../elements/PageTitle";
import i18next from "i18next";
import { DefaultPageProps } from "../../types/DefaultPageProps";
const passwordLengthMin = 1;
const passwordLengthMax = 64;
@ -51,7 +52,7 @@ type PasswordGeneratorState = {
alphabet: string;
};
export class PasswordGenerator extends Component<{}, PasswordGeneratorState> {
export class PasswordGenerator extends Component<DefaultPageProps, PasswordGeneratorState> {
constructor() {
super();
this.state = {

View file

@ -3,7 +3,6 @@ import { DefaultPageProps } from "../../../types/DefaultPageProps";
import { Form } from "../../elements/Form";
import { MarginInline } from "../../elements/MarginInline";
import { PageTitle } from "../../elements/PageTitle";
import { deleteMount } from "../../../api/sys/deleteMount";
import { route } from "preact-router";
import { setErrorText } from "../../../pageUtils";
import i18next from "i18next";
@ -36,7 +35,7 @@ export class DeleteSecretsEngine extends Component<DefaultPageProps> {
async onSubmit(): Promise<void> {
try {
await deleteMount(this.props.matches["mount"]);
await this.props.api.deleteMount(this.props.matches["mount"]);
route("/secrets");
} catch (e: unknown) {
const error = e as Error;

View file

@ -1,7 +1,6 @@
import { Component, render } from "preact";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
import { SecretTitleElement } from "../SecretTitleElement";
import { deleteSecret } from "../../../../api/kv/deleteSecret";
import i18next from "i18next";
export class KeyValueDelete extends Component<DefaultPageProps> {
@ -24,7 +23,7 @@ export class KeyValueDelete extends Component<DefaultPageProps> {
<button
class="uk-button uk-button-danger"
onClick={async () => {
await deleteSecret(baseMount, secretPath, item);
await this.props.api.deleteSecret(baseMount, secretPath, item);
window.history.back();
}}
>

View file

@ -1,14 +1,12 @@
import { CodeEditor } from "../../../elements/CodeEditor";
import { Component, JSX, render } from "preact";
import { Component, JSX } from "preact";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
import { SecretTitleElement } from "../SecretTitleElement";
import { createOrUpdateSecret } from "../../../../api/kv/createOrUpdateSecret";
import { getSecret } from "../../../../api/kv/getSecret";
import { setErrorText } from "../../../../pageUtils";
import { sortedObjectMap, verifyJSONString } from "../../../../utils";
import i18next from "i18next";
export type KVEditProps = {
export type KVEditProps = DefaultPageProps & {
baseMount: string;
secretPath: string[];
secretItem: string;
@ -41,7 +39,7 @@ export class KVEditor extends Component<KVEditProps, KVEditState> {
return;
}
await createOrUpdateSecret(
await this.props.api.createOrUpdateSecret(
this.props.baseMount,
this.props.secretPath.map((e) => e + "/"),
this.props.secretItem,
@ -57,11 +55,13 @@ export class KVEditor extends Component<KVEditProps, KVEditState> {
}
loadData(): void {
void getSecret(
void this.props.api
.getSecret(
this.props.baseMount,
this.props.secretPath.map((e) => e + "/"),
this.props.secretItem,
).then((kvData) => {
)
.then((kvData) => {
this.setState({
dataLoaded: true,
kvData: kvData,
@ -118,7 +118,13 @@ export class KeyValueEdit extends Component<DefaultPageProps> {
item={this.props.matches["item"]}
suffix={i18next.t("kv_sec_edit_suffix")}
/>
<KVEditor baseMount={baseMount} secretPath={secretPath} secretItem={item} />
<KVEditor
settings={this.props.settings}
api={this.props.api}
baseMount={baseMount}
secretPath={secretPath}
secretItem={item}
/>
</>
);
}

View file

@ -1,16 +1,13 @@
import { CapabilitiesType, getCapabilitiesPath } from "../../../../api/sys/getCapabilities";
import { Component, JSX, createRef, render } from "preact";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
import { DoesNotExistError } from "../../../../types/internalErrors";
import { SecretTitleElement } from "../SecretTitleElement";
import { delSecretsEngineURL, kvListURL, kvNewURL, kvViewURL } from "../../pageLinks";
import { getMount } from "../../../../api/sys/getMounts";
import { getSecrets } from "../../../../api/kv/getSecrets";
import { route } from "preact-router";
import { setErrorText } from "../../../../pageUtils";
import i18next from "i18next";
export type KVKeysListProps = {
export type KVKeysListProps = DefaultPageProps & {
baseMount: string;
secretPath: string[];
};
@ -26,8 +23,8 @@ function SecretsList(baseMount: string, secretPath: string[], secrets: string[])
<li>
<a
onClick={async () => {
console.log(baseMount, secretPath, secret);
if (secret.endsWith("/")) {
// TODO: fix this mess ?
route(
kvListURL(
baseMount,
@ -57,7 +54,7 @@ export class KVKeysList extends Component<KVKeysListProps, KVKeysListState> {
async loadData(): Promise<void> {
try {
const keys = await getSecrets(this.props.baseMount, this.props.secretPath);
const keys = await this.props.api.getSecrets(this.props.baseMount, this.props.secretPath);
this.setState({
dataLoaded: true,
keys: keys,
@ -151,9 +148,9 @@ export class KeyValueList extends Component<DefaultPageProps, KeyValueListState>
const mountsPath = "/sys/mounts/" + baseMount;
const currentPath = baseMount + secretPath.join();
const caps = await getCapabilitiesPath([mountsPath, currentPath]);
const caps = await this.props.api.getCapabilitiesPath([mountsPath, currentPath]);
const mount = await getMount(baseMount);
const mount = await this.props.api.getMount(baseMount);
this.setState({
mountCaps: caps[mountsPath],
@ -201,7 +198,12 @@ export class KeyValueList extends Component<DefaultPageProps, KeyValueListState>
)}
</p>
{this.state.mountType == "cubbyhole" && <p>{i18next.t("kv_view_cubbyhole_text")}</p>}
<KVKeysList baseMount={baseMount} secretPath={secretPath} />
<KVKeysList
settings={this.props.settings}
api={this.props.api}
baseMount={baseMount}
secretPath={secretPath}
/>
</>
);
}

View file

@ -3,7 +3,6 @@ import { DefaultPageProps } from "../../../../types/DefaultPageProps";
import { Form } from "../../../elements/Form";
import { Margin } from "../../../elements/Margin";
import { SecretTitleElement } from "../SecretTitleElement";
import { createOrUpdateSecret } from "../../../../api/kv/createOrUpdateSecret";
import { kvViewURL } from "../../pageLinks";
import { route } from "preact-router";
import { setErrorText } from "../../../../pageUtils";
@ -57,7 +56,7 @@ export class KeyValueNew extends Component<DefaultPageProps> {
const keyData = { key: "value" };
try {
await createOrUpdateSecret(baseMount, secretPath, path, keyData);
await this.props.api.createOrUpdateSecret(baseMount, secretPath, path, keyData);
route(kvViewURL(baseMount, secretPath, path));
} catch (e: unknown) {
const error = e as Error;

View file

@ -4,8 +4,6 @@ import { CopyableInputBox } from "../../../elements/CopyableInputBox";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
import { Grid, GridSizes } from "../../../elements/Grid";
import { SecretTitleElement } from "../SecretTitleElement";
import { getCapabilities } from "../../../../api/sys/getCapabilities";
import { getSecret } from "../../../../api/kv/getSecret";
import { kvDeleteURL, kvEditURL } from "../../pageLinks";
import { route } from "preact-router";
import { sortedObjectMap } from "../../../../utils";
@ -56,7 +54,8 @@ export class KeyValueView extends Component<DefaultPageProps, KeyValueViewState>
const secretPath = this.props.matches["secretPath"].split("/");
const secretItem = this.props.matches["item"];
const caps = (await getCapabilities(baseMount, secretPath, secretItem)).capabilities;
const caps = (await this.props.api.getCapabilities(baseMount, secretPath, secretItem))
.capabilities;
const secretPathAPI = secretPath.map((e) => e + "/");
// TODO: this is a big hacky, fix when redo how api arguments work
@ -64,7 +63,7 @@ export class KeyValueView extends Component<DefaultPageProps, KeyValueViewState>
.replace("/", "")
.toString();
const secretInfo = await getSecret(baseMount, secretPathAPI, secretItem);
const secretInfo = await this.props.api.getSecret(baseMount, secretPathAPI, secretItem);
this.setState({
baseMount,
secretPath,

View file

@ -4,12 +4,12 @@ import { Margin } from "../../../elements/Margin";
import { MarginInline } from "../../../elements/MarginInline";
import { PageTitle } from "../../../elements/PageTitle";
import { kvListURL } from "../../pageLinks";
import { newMount } from "../../../../api/sys/newMount";
import { route } from "preact-router";
import { setErrorText } from "../../../../pageUtils";
import i18next from "i18next";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
export class NewKVEngine extends Component {
export class NewKVEngine extends Component<DefaultPageProps> {
render() {
return (
<>
@ -50,7 +50,7 @@ export class NewKVEngine extends Component {
const version = data.get("version") as string;
try {
await newMount({
await this.props.api.newMount({
name: name,
type: "kv",
options: {

View file

@ -3,13 +3,13 @@ import { Form } from "../../../elements/Form";
import { Margin } from "../../../elements/Margin";
import { MarginInline } from "../../../elements/MarginInline";
import { PageTitle } from "../../../elements/PageTitle";
import { newMount } from "../../../../api/sys/newMount";
import { route } from "preact-router";
import { setErrorText } from "../../../../pageUtils";
import { totpListURL } from "../../pageLinks";
import i18next from "i18next";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
export class NewTOTPEngine extends Component {
export class NewTOTPEngine extends Component<DefaultPageProps> {
render() {
return (
<>
@ -40,7 +40,7 @@ export class NewTOTPEngine extends Component {
const name = data.get("name") as string;
try {
await newMount({
await this.props.api.newMount({
name: name,
type: "totp",
});

View file

@ -3,12 +3,12 @@ import { Form } from "../../../elements/Form";
import { Margin } from "../../../elements/Margin";
import { MarginInline } from "../../../elements/MarginInline";
import { PageTitle } from "../../../elements/PageTitle";
import { newMount } from "../../../../api/sys/newMount";
import { route } from "preact-router";
import { setErrorText } from "../../../../pageUtils";
import i18next from "i18next";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
export class NewTransitEngine extends Component {
export class NewTransitEngine extends Component<DefaultPageProps> {
render() {
return (
<>
@ -39,7 +39,7 @@ export class NewTransitEngine extends Component {
const name = data.get("name") as string;
try {
await newMount({
await this.props.api.newMount({
name: name,
type: "transit",
});

View file

@ -4,8 +4,9 @@ import { PageTitle } from "../../elements/PageTitle";
import { Tile } from "../../elements/Tile";
import { route } from "preact-router";
import i18next from "i18next";
import { DefaultPageProps } from "../../../types/DefaultPageProps";
export class NewSecretsEngine extends Component {
export class NewSecretsEngine extends Component<DefaultPageProps> {
render() {
return (
<>

View file

@ -1,12 +1,11 @@
import { Component, JSX, render } from "preact";
import { DefaultPageProps } from "../../../types/DefaultPageProps";
import { MountType, getMounts } from "../../../api/sys/getMounts";
import { PageTitle } from "../../elements/PageTitle";
import { getCapsPath } from "../../../api/sys/getCapabilities";
import { prePageChecks } from "../../../pageUtils";
import { route } from "preact-router";
import { sortedObjectMap } from "../../../utils";
import i18next from "i18next";
import { MountType } from "../../../api/types/mount";
const supportedMountTypes = ["kv", "totp", "transit", "cubbyhole"];
@ -59,10 +58,10 @@ type SecretsState = {
export class Secrets extends Component<DefaultPageProps, SecretsState> {
async componentDidMount() {
if (!(await prePageChecks(this.props.settings))) return;
if (!(await prePageChecks(this.props.api, this.props.settings))) return;
const mountsCapabilities = await getCapsPath("/sys/mounts");
const mounts = await getMounts();
const mountsCapabilities = await this.props.api.getCapsPath("/sys/mounts");
const mounts = await this.props.api.getMounts();
// sort it by secretPath so it's in alphabetical order consistantly.
const mountsMap = sortedObjectMap(mounts);
this.setState({
@ -99,9 +98,7 @@ export class Secrets extends Component<DefaultPageProps, SecretsState> {
const mount = args[1];
console.log(baseMount, mount);
if (isSupportedMount(mount)) {
return (
<MountLink mount={mount} baseMount={baseMount} />
);
return <MountLink mount={mount} baseMount={baseMount} />;
}
})}
</ul>

View file

@ -1,7 +1,6 @@
import { Component, render } from "preact";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
import { SecretTitleElement } from "../SecretTitleElement";
import { deleteTOTP } from "../../../../api/totp/deleteTOTP";
import { route } from "preact-router";
import { totpListURL } from "../../pageLinks";
import i18next from "i18next";
@ -23,7 +22,7 @@ export class TOTPDelete extends Component<DefaultPageProps> {
onClick={async () => {
const baseMount = this.props.matches["baseMount"];
const item = this.props.matches["item"];
await deleteTOTP(baseMount, item);
await this.props.api.deleteTOTP(baseMount, item);
route(totpListURL(baseMount));
}}
>

View file

@ -1,8 +1,3 @@
import {
CapabilitiesType,
getCapabilitiesPath,
getCapsPath,
} from "../../../../api/sys/getCapabilities";
import { Component, JSX } from "preact";
import { CopyableInputBox } from "../../../elements/CopyableInputBox";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
@ -11,14 +6,13 @@ import { Grid, GridSizes } from "../../../elements/Grid";
import { MarginInline } from "../../../elements/MarginInline";
import { SecretTitleElement } from "../SecretTitleElement";
import { delSecretsEngineURL, totpNewURL } from "../../pageLinks";
import { getTOTPCode } from "../../../../api/totp/getTOTPCode";
import { getTOTPKeys } from "../../../../api/totp/getTOTPKeys";
import { removeDoubleSlash } from "../../../../utils";
import { route } from "preact-router";
import { setErrorText } from "../../../../pageUtils";
import i18next from "i18next";
import { CapabilitiesType } from "../../../../api/types/capabilities";
type TOTPGridItemProps = {
type TOTPGridItemProps = DefaultPageProps & {
baseMount: string;
totpKey: string;
canDelete: boolean;
@ -32,7 +26,7 @@ export class RefreshingTOTPGridItem extends Component<TOTPGridItemProps, { totpV
timer: unknown;
updateTOTPCode(): void {
void getTOTPCode(this.props.baseMount, this.props.totpKey).then((code) => {
void this.props.api.getTOTPCode(this.props.baseMount, this.props.totpKey).then((code) => {
this.setState({ totpValue: code });
});
}
@ -74,7 +68,7 @@ export class RefreshingTOTPGridItem extends Component<TOTPGridItemProps, { totpV
type TOTPListState = {
capabilities?: CapabilitiesType;
totpItems: TOTPGridItemProps[];
totpItems: Partial<TOTPGridItemProps>[];
};
export class TOTPList extends Component<DefaultPageProps, TOTPListState> {
@ -87,17 +81,18 @@ export class TOTPList extends Component<DefaultPageProps, TOTPListState> {
refresher: number;
async componentDidMount() {
const api = this.props.api;
const baseMount = this.props.matches["baseMount"];
const mountsPath = "/sys/mounts/" + baseMount;
const caps = await getCapabilitiesPath([mountsPath, baseMount]);
const caps = await api.getCapabilitiesPath([mountsPath, baseMount]);
let totpItems: TOTPGridItemProps[] = [];
let totpItems: Partial<TOTPGridItemProps>[] = [];
// TODO: tidy this up i guess
try {
totpItems = await Promise.all(
Array.from(await getTOTPKeys(baseMount)).map(async (key) => {
const totpCaps = await getCapsPath(removeDoubleSlash(baseMount + "/code/" + key));
Array.from(await api.getTOTPKeys(baseMount)).map(async (key) => {
const totpCaps = await api.getCapsPath(removeDoubleSlash(baseMount + "/code/" + key));
if (totpCaps.includes("read")) {
return {
baseMount: baseMount,
@ -162,6 +157,8 @@ export class TOTPList extends Component<DefaultPageProps, TOTPListState> {
return this.state.totpItems.map((totpItem) => {
return (
<RefreshingTOTPGridItem
settings={this.props.settings}
api={this.props.api}
baseMount={totpItem.baseMount}
totpKey={totpItem.totpKey}
canDelete={totpItem.canDelete}

View file

@ -5,7 +5,6 @@ import { Margin } from "../../../elements/Margin";
import { MarginInline } from "../../../elements/MarginInline";
import { QRScanner } from "../../../elements/QRScanner";
import { SecretTitleElement } from "../SecretTitleElement";
import { addNewTOTP } from "../../../../api/totp/addNewTOTP";
import { route } from "preact-router";
import { setErrorText } from "../../../../pageUtils";
import i18next from "i18next";
@ -20,7 +19,10 @@ function removeDashSpaces(str: string): string {
return str;
}
export class TOTPNewForm extends Component<{ baseMount: string }, { qrMode: boolean }> {
export class TOTPNewForm extends Component<
{ baseMount: string } & DefaultPageProps,
{ qrMode: boolean }
> {
constructor() {
super();
this.state = {
@ -39,7 +41,7 @@ export class TOTPNewForm extends Component<{ baseMount: string }, { qrMode: bool
};
try {
await addNewTOTP(this.props.baseMount, parms);
await this.props.api.addNewTOTP(this.props.baseMount, parms);
route("/secrets/totp/list/" + this.props.baseMount);
} catch (e: unknown) {
const error = e as Error;
@ -128,7 +130,7 @@ export class TOTPNew extends Component<DefaultPageProps> {
baseMount={baseMount}
suffix={i18next.t("totp_new_suffix")}
/>
<TOTPNewForm baseMount={baseMount} />
<TOTPNewForm settings={this.props.settings} api={this.props.api} baseMount={baseMount} />
</>
);
}

View file

@ -7,7 +7,6 @@ import { SecretTitleElement } from "../SecretTitleElement";
import { fileToBase64 } from "../../../../htmlUtils";
import { Component, render } from "preact";
import { setErrorText } from "../../../../pageUtils";
import { transitDecrypt } from "../../../../api/transit/transitDecrypt";
import UIkit from "uikit";
import i18next from "i18next";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
@ -64,7 +63,7 @@ export class TransitDecrypt extends Component<DefaultPageProps> {
}
try {
const res = await transitDecrypt(baseMount, secretItem, {
const res = await this.props.api.transitDecrypt(baseMount, secretItem, {
ciphertext: ciphertext,
});
let plaintext = res.plaintext;

View file

@ -7,7 +7,6 @@ import { SecretTitleElement } from "../SecretTitleElement";
import { fileToBase64 } from "../../../../htmlUtils";
import { Component, render } from "preact";
import { setErrorText } from "../../../../pageUtils";
import { transitEncrypt } from "../../../../api/transit/transitEncrypt";
import UIkit from "uikit";
import i18next from "i18next";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
@ -65,7 +64,7 @@ export class TransitEncrypt extends Component<DefaultPageProps> {
}
try {
const res = await transitEncrypt(baseMount, secretItem, {
const res = await this.props.api.transitEncrypt(baseMount, secretItem, {
plaintext: plaintext,
});
render(

View file

@ -1,18 +1,20 @@
import { CapabilitiesType, getCapabilitiesPath } from "../../../../api/sys/getCapabilities";
import { Component, JSX, render } from "preact";
import { Component, JSX } from "preact";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
import { SecretTitleElement } from "../SecretTitleElement";
import { delSecretsEngineURL, transitNewSecretURL, transitViewSecretURL } from "../../pageLinks";
import { getTransitKeys } from "../../../../api/transit/getTransitKeys";
import { route } from "preact-router";
import i18next from "i18next";
import { CapabilitiesType } from "../../../../api/types/capabilities";
type TransitViewListState = {
contentLoaded: boolean;
transitKeysList: string[];
};
export class TransitViewListItem extends Component<{ baseMount: string }, TransitViewListState> {
export class TransitViewListItem extends Component<
{ baseMount: string } & DefaultPageProps,
TransitViewListState
> {
constructor() {
super();
this.state = {
@ -24,7 +26,8 @@ export class TransitViewListItem extends Component<{ baseMount: string }, Transi
timer: unknown;
getTransitKeys(): void {
void getTransitKeys(this.props.baseMount)
void this.props.api
.getTransitKeys(this.props.baseMount)
.then((keys) => {
this.setState({
contentLoaded: true,
@ -75,7 +78,7 @@ export class TransitList extends Component<DefaultPageProps, { caps: Capabilitie
const baseMount = this.props.matches["baseMount"];
const mountsPath = "/sys/mounts/" + baseMount;
const caps = await getCapabilitiesPath([mountsPath, baseMount]);
const caps = await this.props.api.getCapabilitiesPath([mountsPath, baseMount]);
this.setState({ caps });
}
@ -112,7 +115,11 @@ export class TransitList extends Component<DefaultPageProps, { caps: Capabilitie
</button>
)}
</p>
<TransitViewListItem baseMount={baseMount} />
<TransitViewListItem
settings={this.props.settings}
api={this.props.api}
baseMount={baseMount}
/>
</>
);
}

View file

@ -4,7 +4,6 @@ import { Form } from "../../../elements/Form";
import { Margin } from "../../../elements/Margin";
import { MarginInline } from "../../../elements/MarginInline";
import { SecretTitleElement } from "../SecretTitleElement";
import { newTransitKey } from "../../../../api/transit/newTransitKey";
import { route } from "preact-router";
import { setErrorText } from "../../../../pageUtils";
import { transitViewSecretURL } from "../../pageLinks";
@ -75,7 +74,7 @@ export class TransitNew extends Component<DefaultPageProps> {
const type = data.get("type") as string;
try {
await newTransitKey(baseMount, {
await this.props.api.newTransitKey(baseMount, {
name: name,
type: type,
});

View file

@ -2,11 +2,9 @@ import { CopyableModal } from "../../../elements/CopyableModal";
import { Form } from "../../../elements/Form";
import { Margin } from "../../../elements/Margin";
import { SecretTitleElement } from "../SecretTitleElement";
import { getTransitKey } from "../../../../api/transit/getTransitKey";
import { objectToMap } from "../../../../utils";
import { Component, render } from "preact";
import { setErrorText } from "../../../../pageUtils";
import { transitRewrap } from "../../../../api/transit/transitRewrap";
import UIkit from "uikit";
import i18next from "i18next";
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
@ -19,7 +17,7 @@ export class TransitRewrap extends Component<DefaultPageProps, { transitKey: Tra
const baseMount = this.props.matches["baseMount"];
const secretItem = this.props.matches["secretItem"];
this.setState({
transitKey: await getTransitKey(baseMount, secretItem),
transitKey: await this.props.api.getTransitKey(baseMount, secretItem),
});
}
@ -89,7 +87,7 @@ export class TransitRewrap extends Component<DefaultPageProps, { transitKey: Tra
const baseMount = this.props.matches["baseMount"];
const secretItem = this.props.matches["secretItem"];
try {
const res = await transitRewrap(baseMount, secretItem, {
const res = await this.props.api.transitRewrap(baseMount, secretItem, {
ciphertext: data.get("ciphertext") as string,
key_version: parseInt(data.get("version") as string, 10),
});

View file

@ -4,7 +4,6 @@ import { Grid, GridSizes } from "../../../elements/Grid";
import { SecretTitleElement } from "../SecretTitleElement";
import { Tile } from "../../../elements/Tile";
import { TransitKeyType } from "../../../../api/types/transit";
import { getTransitKey } from "../../../../api/transit/getTransitKey";
import i18next from "i18next";
import { route } from "preact-router";
import {
@ -17,7 +16,7 @@ export class TransitView extends Component<DefaultPageProps, { transitKey: Trans
async componentDidMount() {
const baseMount = this.props.matches["baseMount"];
const secretItem = this.props.matches["secretItem"];
const transitKey = await getTransitKey(baseMount, secretItem);
const transitKey = await this.props.api.getTransitKey(baseMount, secretItem);
this.setState({ transitKey });
}

View file

@ -2,12 +2,10 @@ import { Component, JSX, render } from "preact";
import { Form } from "../elements/Form";
import { MarginInline } from "../elements/MarginInline";
import { QRScanner } from "../elements/QRScanner";
import { getSealStatus } from "../../api/sys/getSealStatus";
import { DefaultPageProps } from "../../types/DefaultPageProps";
import { PageTitle } from "../elements/PageTitle";
import { route } from "preact-router";
import { setErrorText } from "../../pageUtils";
import { submitUnsealKey } from "../../api/sys/submitUnsealKey";
import { toStr } from "../../utils";
import i18next from "i18next";
@ -65,7 +63,7 @@ export class Unseal extends Component<DefaultPageProps, UnsealPageState> {
async submitKey(key: string): Promise<void> {
try {
await submitUnsealKey(key);
await this.props.api.submitUnsealKey(key);
this.updateStateWithSealStatus();
} catch (e: unknown) {
const error = e as Error;
@ -74,7 +72,7 @@ export class Unseal extends Component<DefaultPageProps, UnsealPageState> {
}
updateStateWithSealStatus(): void {
void getSealStatus().then((data) => {
void this.props.api.getSealStatus().then((data) => {
this.setState({
keys_submitted: data.progress,
keys_needed: data.t,