1
0
Fork 0

Lint code harder.

This commit is contained in:
Kitteh 2021-05-10 11:35:14 +01:00
parent f4aa14f968
commit a347939896
59 changed files with 345 additions and 341 deletions

View file

@ -1,18 +1,20 @@
{ {
"extends": [
"eslint:recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:@typescript-eslint/recommended"
],
"plugins": [ "plugins": [
"sort-imports-es6-autofix", "sort-imports-es6-autofix",
"@typescript-eslint" "@typescript-eslint"
], ],
"extends": [
"eslint:recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
"parserOptions": { "parserOptions": {
"ecmaVersion": 12, "ecmaVersion": 12,
"sourceType": "module", "sourceType": "module",
"experimentalObjectRestSpread": true "experimentalObjectRestSpread": true,
"project": "./tsconfig.json"
}, },
"globals": { "globals": {
"pageContent": "writable", "pageContent": "writable",

View file

@ -71,7 +71,7 @@ export class PageState {
} }
get currentSecretPath(): string[] { get currentSecretPath(): string[] {
return JSON.parse(localStorage.getItem('currentSecretPath') || "[]"); return JSON.parse(localStorage.getItem('currentSecretPath') || "[]") as string[];
} }
set currentSecretPath(value: string[]) { set currentSecretPath(value: string[]) {
localStorage.setItem('currentSecretPath', JSON.stringify(value)); localStorage.setItem('currentSecretPath', JSON.stringify(value));
@ -104,14 +104,14 @@ export class PageState {
} }
get currentPage(): Page | string { get currentPage(): Page | string {
const curPage = localStorage.getItem('currentPage') || "HOME"; const curPage = localStorage.getItem('currentPage') || "HOME";
return (allPages as any)[curPage]; return allPages[curPage];
} }
set currentPage(value: Page | string) { set currentPage(value: Page | string) {
if (typeof value == 'object') { if (typeof value == 'object') {
const key = getKeyByObjectPropertyValue(allPages, value); const key = getKeyByObjectPropertyValue(allPages, value);
localStorage.setItem('currentPage', key); localStorage.setItem('currentPage', key);
} else { } else {
localStorage.setItem('currentPage', (value as string)); localStorage.setItem('currentPage', value);
} }
} }
} }

View file

@ -1,6 +1,6 @@
import { pageState } from "../globalPageState"; import { pageState } from "../globalPageState";
export function getHeaders(): any { export function getHeaders(): Record<string, string> {
return { return {
"X-Vault-Token": pageState.token, "X-Vault-Token": pageState.token,
} }

View file

@ -8,13 +8,12 @@ export async function usernameLogin(username: string, password: string): Promise
}, },
body: JSON.stringify({ "username": username, "password": password }) body: JSON.stringify({ "username": username, "password": password })
}); });
return fetch(request).then(response => {
return response.json(); const resp = await fetch(request);
}).then(data => { const data = await resp.json() as { auth?: { client_token: string }; errors?: string[] };
if ("auth" in data) { if ("auth" in data) {
return data.auth.client_token; return data.auth.client_token;
} else if ("errors" in data) { } else if ("errors" in data) {
throw new Error(data.errors[0]); throw new Error(data.errors[0]);
} }
});
} }

View file

@ -30,7 +30,7 @@ export async function createOrUpdateSecret(
}); });
const response = await fetch(request); const response = await fetch(request);
if (!response.ok) { if (!response.ok) {
const json = await response.json(); const json = await response.json() as {errors: string[]};
throw new Error(json.errors[0]); throw new Error(json.errors[0]);
} }
} }

View file

@ -32,12 +32,12 @@ export async function deleteSecret(
secretURL = removeDoubleSlash(secretURL).replace(/\/$/, ""); secretURL = removeDoubleSlash(secretURL).replace(/\/$/, "");
request = new Request(appendAPIURL(secretURL), { request = new Request(appendAPIURL(secretURL), {
method: "DELETE", method: "DELETE",
headers: (getHeaders() as any), headers: getHeaders(),
}); });
} }
const response = await fetch(request); const response = await fetch(request);
if (!response.ok) { if (!response.ok) {
const json = await response.json(); const json = await response.json() as {errors: string[]};
throw new Error(json.errors[0]); throw new Error(json.errors[0]);
} }
} }

View file

@ -6,7 +6,7 @@ export async function getSecret(
secretPath: string[], secretPath: string[],
name: string, name: string,
version: string|null = null version: string|null = null
): Promise<Record<any, any>> { ): Promise<Record<string, unknown>> {
let secretURL = ""; let secretURL = "";
if (mountType == "kv-v2") { if (mountType == "kv-v2") {
secretURL = `/v1/${baseMount}/data/${secretPath.join("")}/${name}`; secretURL = `/v1/${baseMount}/data/${secretPath.join("")}/${name}`;
@ -16,12 +16,14 @@ export async function getSecret(
secretURL = `/v1/${baseMount}/${secretPath.join("")}/${name}`; secretURL = `/v1/${baseMount}/${secretPath.join("")}/${name}`;
} }
const request = new Request(appendAPIURL(secretURL), { const request = new Request(appendAPIURL(secretURL), {
headers: (getHeaders() as any), headers: getHeaders(),
}); });
return fetch(request).then(response => { const resp = await fetch(request);
return response.json(); const data = await resp.json() as unknown;
}).then(data => { if (mountType == "kv-v2") {
return mountType == "kv-v2" ? data.data.data : data.data; return (data as {data: {data: Record<string, unknown>}}).data.data;
}); } else {
return (data as {data: Record<string, unknown>}).data;
}
} }

View file

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

View file

@ -14,14 +14,12 @@ export async function getSecrets(
secretURL = `/v1/${baseMount}/${secretPath.join("")}?list=true`; secretURL = `/v1/${baseMount}/${secretPath.join("")}?list=true`;
} }
const request = new Request(appendAPIURL(secretURL), { const request = new Request(appendAPIURL(secretURL), {
headers: (getHeaders() as any), headers: getHeaders(),
}); });
return fetch(request).then(response => { const resp = await fetch(request);
if (response.status == 404) { if (resp.status == 404) {
throw DoesNotExistError; throw DoesNotExistError;
} }
return response.json(); const data = await resp.json() as { data: { keys: string[] } };
}).then(data => {
return data.data.keys; return data.data.keys;
});
} }

View file

@ -30,7 +30,7 @@ export async function undeleteSecret(
}); });
const response = await fetch(request); const response = await fetch(request);
if (!response.ok) { if (!response.ok) {
const json = await response.json(); const json = await response.json() as {errors: string[]};
throw new Error(json.errors[0]); throw new Error(json.errors[0]);
} }
} }

View file

@ -15,11 +15,9 @@ export async function getCapabilitiesPath(path: string): Promise<string[]> {
} }
) )
}); });
return fetch(request).then(response => { const response = await fetch(request);
return response.json(); const data = await response.json() as {capabilities: string[]};
}).then(data => {
return data.capabilities; return data.capabilities;
});
} }
export async function getCapabilities( export async function getCapabilities(

View file

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

View file

@ -8,9 +8,7 @@ export type SealStatusType = {
export async function getSealStatus(): Promise<SealStatusType> { export async function getSealStatus(): Promise<SealStatusType> {
const request = new Request(appendAPIURL("/v1/sys/seal-status")); const request = new Request(appendAPIURL("/v1/sys/seal-status"));
return fetch(request).then(response => { const resp = await fetch(request)
return response.json(); const data = await resp.json() as SealStatusType;
}).then(data => {
return data; return data;
});
} }

View file

@ -1,17 +1,15 @@
import { appendAPIURL, getHeaders } from "../apiUtils";
import { TokenInfo } from "../types/token"; import { TokenInfo } from "../types/token";
import { appendAPIURL, getHeaders } from "../apiUtils";
export async function lookupSelf(): Promise<TokenInfo> { export async function lookupSelf(): Promise<TokenInfo> {
const request = new Request(appendAPIURL("/v1/auth/token/lookup-self"), { const request = new Request(appendAPIURL("/v1/auth/token/lookup-self"), {
headers: getHeaders(), headers: getHeaders(),
}); });
return fetch(request).then(response => { const resp = await fetch(request);
return response.json(); const data = await resp.json() as { data?: TokenInfo; errors?: string[] };
}).then(data => {
if ("data" in data) { if ("data" in data) {
return data.data; return data.data;
} else if ("errors" in data) { } else if ("errors" in data) {
throw new Error(data.errors[0]); throw new Error(data.errors[0]);
} }
});
} }

View file

@ -9,11 +9,9 @@ export async function renewSelf(): Promise<void> {
}, },
body: JSON.stringify({}) body: JSON.stringify({})
}); });
return fetch(request).then(response => { const resp = await fetch(request)
return response.json(); const data = await resp.json() as { errors?: string[] };
}).then(data => {
if ("errors" in data) { if ("errors" in data) {
throw new Error(data.errors[0]); throw new Error(data.errors[0]);
} }
});
} }

View file

@ -6,11 +6,9 @@ export async function sealVault(): Promise<void> {
method: 'PUT', method: 'PUT',
headers: getHeaders(), headers: getHeaders(),
}); });
return fetch(request).then(response => { const resp = await fetch(request)
return response.json(); const data = await resp.json() as { errors?: string[] };
}).then(data => {
if ("errors" in data) { if ("errors" in data) {
throw new Error(data.errors[0]); throw new Error(data.errors[0]);
} }
});
} }

View file

@ -10,9 +10,11 @@ export async function submitUnsealKey(key: string): Promise<void> {
"key": key "key": key
}) })
}); });
const response = await fetch(request); const resp = await fetch(request)
if (!response.ok) { if (!resp.ok) {
const json = await response.json(); const data = await resp.json() as { errors?: string[] };
throw new Error(json.errors[0]); if ("errors" in data) {
throw new Error(data.errors[0]);
}
} }
} }

View file

@ -1,7 +1,6 @@
import { appendAPIURL, getHeaders } from "../apiUtils"; import { appendAPIURL, getHeaders } from "../apiUtils";
import { removeDoubleSlash } from "../../utils"; import { removeDoubleSlash } from "../../utils";
export async function addNewTOTP(baseMount: string, parms: {name: string}): Promise<void> { export async function addNewTOTP(baseMount: string, parms: {name: string}): Promise<void> {
const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/keys/${parms.name}`)), { const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/keys/${parms.name}`)), {
method: 'POST', method: 'POST',
@ -11,9 +10,11 @@ export async function addNewTOTP(baseMount: string, parms: {name: string}): Prom
}, },
body: JSON.stringify(parms) body: JSON.stringify(parms)
}); });
const response = await fetch(request); const resp = await fetch(request)
if (!response.ok) { if (!resp.ok) {
const json = await response.json(); const data = await resp.json() as { errors?: string[] };
throw new Error(json.errors[0]); if ("errors" in data) {
throw new Error(data.errors[0]);
}
} }
} }

View file

@ -5,9 +5,7 @@ export async function getTOTPCode(baseMount: string, name: string): Promise<stri
new Request(appendAPIURL(`/v1/${baseMount}/code/${name}`), { new Request(appendAPIURL(`/v1/${baseMount}/code/${name}`), {
headers: getHeaders(), headers: getHeaders(),
}); });
return fetch(request).then(response => { const resp = await fetch(request)
return response.json(); const data = await resp.json() as {data: {code: string}};
}).then(data => {
return data.data.code; return data.data.code;
});
} }

View file

@ -1,17 +1,15 @@
import { DoesNotExistError } from "../../types/internalErrors"; import { DoesNotExistError } from "../../types/internalErrors";
import { appendAPIURL, getHeaders } from "../apiUtils"; import { appendAPIURL, getHeaders } from "../apiUtils";
export async function getTOTPKeys(baseMount: string): Promise<string[]> { export async function getTOTPKeys(baseMount: string): Promise<string[]> {
const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), { const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), {
headers: getHeaders(), headers: getHeaders(),
}); });
return fetch(request).then(response => {
if (response.status == 404) { const resp = await fetch(request);
if (resp.status == 404) {
throw DoesNotExistError; throw DoesNotExistError;
} }
return response.json(); const data = await resp.json() as {data: {keys: string[] }};
}).then(data => {
return data.data.keys; return data.data.keys;
});
} }

View file

@ -1,17 +1,16 @@
import { DoesNotExistError } from "../../types/internalErrors"; import { DoesNotExistError } from "../../types/internalErrors";
import { appendAPIURL, getHeaders } from "../apiUtils";
import { TransitKeyType } from "../types/transit"; import { TransitKeyType } from "../types/transit";
import { appendAPIURL, getHeaders } from "../apiUtils";
export async function getTransitKey(baseMount: string, name: string): Promise<TransitKeyType> { export async function getTransitKey(baseMount: string, name: string): Promise<TransitKeyType> {
const request = new Request(appendAPIURL(`/v1/${baseMount}/keys/${name}`), { const request = new Request(appendAPIURL(`/v1/${baseMount}/keys/${name}`), {
headers: getHeaders(), headers: getHeaders(),
}); });
return fetch(request).then(response => {
if (response.status == 404) { const resp = await fetch(request);
if (resp.status == 404) {
throw DoesNotExistError; throw DoesNotExistError;
} }
return response.json(); const data = await resp.json() as { data: TransitKeyType };
}).then(data => {
return data.data; return data.data;
});
} }

View file

@ -5,12 +5,10 @@ export async function getTransitKeys(baseMount: string): Promise<string[]> {
const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), { const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), {
headers: getHeaders(), headers: getHeaders(),
}); });
return fetch(request).then(response => { const resp = await fetch(request);
if (response.status == 404) { if (resp.status == 404) {
throw DoesNotExistError; throw DoesNotExistError;
} }
return response.json(); const data = await resp.json() as { data: string[] };
}).then(data => { return data.data;
return data.data.keys;
});
} }

View file

@ -22,12 +22,12 @@ export async function transitDecrypt(
}, },
body: JSON.stringify(payload) body: JSON.stringify(payload)
}); });
const response = await fetch(request); const response = await fetch(request);
const data = await response.json() as { errors?: string[]; data?: DecryptionResult; };
if (!response.ok) { if (!response.ok) {
const json = await response.json(); throw new Error(data.errors[0]);
throw new Error(json.errors[0]);
} else { } else {
const json = await response.json(); return data.data;
return json.data;
} }
} }

View file

@ -22,12 +22,12 @@ export async function transitEncrypt(
}, },
body: JSON.stringify(payload) body: JSON.stringify(payload)
}); });
const response = await fetch(request); const response = await fetch(request);
const data = await response.json() as { errors?: string[]; data?: EncryptionResult; };
if (!response.ok) { if (!response.ok) {
const json = await response.json(); throw new Error(data.errors[0]);
throw new Error(json.errors[0]);
} else { } else {
const json = await response.json(); return data.data;
return json.data;
} }
} }

View file

@ -23,12 +23,12 @@ export async function transitRewrap(
}, },
body: JSON.stringify(payload) body: JSON.stringify(payload)
}); });
const response = await fetch(request); const response = await fetch(request);
const data = await response.json() as { errors?: string[]; data?: RewrapResult; };
if (!response.ok) { if (!response.ok) {
const json = await response.json(); throw new Error(data.errors[0]);
throw new Error(json.errors[0]);
} else { } else {
const json = await response.json(); return data.data;
return json.data;
} }
} }

View file

@ -9,11 +9,11 @@ export type TokenInfo = {
id: string; id: string;
identity_policies: string[]; identity_policies: string[];
issue_time: string; issue_time: string;
meta: any; meta: Record<string, string>;
num_uses: number; num_uses: number;
orphan: Boolean; orphan: boolean;
path: string; path: string;
policies: string[]; policies: string[];
renewable: Boolean; renewable: boolean;
ttl: number; ttl: number;
} }

View file

@ -14,10 +14,10 @@ export const enum TransitKeyTypes {
// Type when used to make new transit keys. // Type when used to make new transit keys.
export type TransitKeyBaseType = { export type TransitKeyBaseType = {
name: string; name: string;
convergent_encryption: Boolean; convergent_encryption: boolean;
derived: Boolean; derived: boolean;
exportable: Boolean; exportable: boolean;
allow_plaintext_backup: Boolean; allow_plaintext_backup: boolean;
type: keyof typeof TransitKeyTypes; type: keyof typeof TransitKeyTypes;
} }
@ -28,8 +28,8 @@ export type TransitKeyType = TransitKeyBaseType & {
}; };
min_decryption_version: number; min_decryption_version: number;
min_encryption_version: number; min_encryption_version: number;
supports_encryption: Boolean; supports_encryption: boolean;
supports_decryption: Boolean; supports_decryption: boolean;
supports_derivation: Boolean; supports_derivation: boolean;
supports_signing: Boolean; supports_signing: boolean;
} }

View file

@ -10,7 +10,7 @@ export interface CopyableInputBoxType extends HTMLElement {
export function CopyableInputBox(text: string, copyable = true): CopyableInputBoxType { export function CopyableInputBox(text: string, copyable = true): CopyableInputBoxType {
const inputBoxDiv = (makeElement({ tag: "div" }) as CopyableInputBoxType); const inputBoxDiv = (makeElement({ tag: "div" }) as CopyableInputBoxType);
let inputBoxCopyButton = null; let inputBoxCopyButton: HTMLElement = null;
if (copyable) { if (copyable) {
inputBoxCopyButton = makeElement({ inputBoxCopyButton = makeElement({
tag: "a", tag: "a",
@ -30,8 +30,8 @@ export function CopyableInputBox(text: string, copyable = true): CopyableInputBo
const inputBoxInput = makeElement({ const inputBoxInput = makeElement({
tag: "input", tag: "input",
class: ["uk-input", "uk-input-copyable"], class: ["uk-input", "uk-input-copyable"],
attributes: { "readonly": true, "type": "text" }, attributes: { "readonly": "true", "type": "text" },
}); }) as HTMLInputElement;
const inputBoxInner = MarginInline([ const inputBoxInner = MarginInline([
inputBoxCopyButton, inputBoxCopyButton,
@ -40,7 +40,7 @@ export function CopyableInputBox(text: string, copyable = true): CopyableInputBo
inputBoxDiv.appendChild(inputBoxInner); inputBoxDiv.appendChild(inputBoxInner);
inputBoxDiv.setText = function (text) { inputBoxDiv.setText = function (text) {
(inputBoxInput as HTMLInputElement).value = `${text}`; inputBoxInput.value = `${text}`;
if (copyable) { if (copyable) {
inputBoxCopyButton.dataset.clipboardText = `${text}`; inputBoxCopyButton.dataset.clipboardText = `${text}`;
} }

View file

@ -2,10 +2,19 @@ import { addClipboardNotifications } from "../pageUtils";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import ClipboardJS from "clipboard"; import ClipboardJS from "clipboard";
import FileSaver from 'file-saver'; import FileSaver from 'file-saver';
import UIkit from 'uikit/dist/js/uikit.min.js';
import i18next from 'i18next'; import i18next from 'i18next';
export function CopyableModal(name: string, contentString: string): Element { type FileSaverType = {
return makeElement({ saveAs: (blob: Blob, name: string) => void;
}
type ModalType = HTMLElement & {
show: () => void;
}
export function CopyableModal(name: string, contentString: string): ModalType {
const modal = makeElement({
tag: "div", tag: "div",
class: "modal-sections", class: "modal-sections",
attributes: { attributes: {
@ -53,9 +62,9 @@ export function CopyableModal(name: string, contentString: string): Element {
"data-clipboard-text": contentString "data-clipboard-text": contentString
}, },
text: i18next.t("copy_modal_download_btn"), text: i18next.t("copy_modal_download_btn"),
onclick: _ => { onclick: () => {
const blob = new Blob([contentString], {type: "text/plain;charset=utf-8"}); const blob = new Blob([contentString], { type: "text/plain;charset=utf-8" });
FileSaver.saveAs(blob, "result.txt"); (FileSaver as FileSaverType).saveAs(blob, "result.txt");
} }
}), }),
makeElement({ makeElement({
@ -82,5 +91,9 @@ export function CopyableModal(name: string, contentString: string): Element {
}), }),
] ]
}) })
}); }) as ModalType;
modal.show = () => {
(UIkit as { modal: (ModalType) => { show: () => void } }).modal(modal).show();
}
return modal;
} }

View file

@ -35,7 +35,7 @@ export async function QRScanner(onScan: (code: string) => void): Promise<QRScann
if (lastSeenValue == value) return; if (lastSeenValue == value) return;
onScan(value); onScan(value);
}); });
qrScanner.start(); void qrScanner.start();
QRInput.deinit = () => { QRInput.deinit = () => {
try { try {

View file

@ -1,7 +1,7 @@
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
type TileParams = { type TileParams = {
condition: Boolean; condition: boolean;
title: string; title: string;
description: string; description: string;
icon: string; icon: string;

View file

@ -1,19 +0,0 @@
import { appendAPIURL, getHeaders } from "../api/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({})
});
return fetch(request).then(response => {
return response.json();
}).then(data => {
if ("errors" in data) {
throw new Error(data.errors[0]);
}
});
}

View file

@ -2,7 +2,7 @@ import { de, enGB, fr, it, nl, ru } from 'date-fns/locale'
import { formatDistance as formatDistanceReal} from 'date-fns'; import { formatDistance as formatDistanceReal} from 'date-fns';
import { pageState } from "./globalPageState"; import { pageState } from "./globalPageState";
function getLocale(): any { function getLocale(): Locale {
return { return {
"en": enGB, "en": enGB,
"fr": fr, "fr": fr,

View file

@ -1,7 +1,7 @@
import { getObjectKeys } from "./utils"; import { getObjectKeys } from "./utils";
type optionsFunctionsObject = { type optionsFunctionsObject = {
[key: string]: (e: any, arg: any) => void [key: string]: (e: Element, arg: unknown) => void
} }
const optionsFunctions: optionsFunctionsObject = { const optionsFunctions: optionsFunctionsObject = {
@ -13,9 +13,9 @@ const optionsFunctions: optionsFunctionsObject = {
}, },
"id": (e: Element, arg: string) => e.id = arg, "id": (e: Element, arg: string) => e.id = arg,
"html": (e: Element, arg: string) => e.innerHTML = arg, "html": (e: Element, arg: string) => e.innerHTML = arg,
"onclick": (e: HTMLButtonElement, arg: any) => e.onclick = arg, "onclick": (e: Element, arg: () => void) => (e as HTMLButtonElement).onclick = arg,
"attributes": setElementAttributes, "attributes": setElementAttributes,
"text": (e: HTMLParagraphElement, arg: string) => e.innerText = arg, "text": (e: Element, arg: string) => (e as HTMLParagraphElement).innerText = arg,
"children": (e: Element, arg: Element | Element[]) => { "children": (e: Element, arg: Element | Element[]) => {
if (Array.isArray(arg)) { if (Array.isArray(arg)) {
arg.forEach(child => { arg.forEach(child => {
@ -34,13 +34,12 @@ interface ElementInfo {
class?: string | string[]; class?: string | string[];
id?: string; id?: string;
html?: string; html?: string;
attributes?: { attributes?: Record<string, string>;
[propName: string]: any
};
children?: Element | Element[]; children?: Element | Element[];
text?: string; text?: string;
thenRun?: (e: Element) => void; thenRun?: (e: Element) => void;
[propName: string]: any; onclick?: () => void;
[propName: string]: unknown;
} }
export function makeElement(elementInfo: ElementInfo): HTMLElement { export function makeElement(elementInfo: ElementInfo): HTMLElement {
@ -49,14 +48,14 @@ export function makeElement(elementInfo: ElementInfo): HTMLElement {
for (const key of Object.getOwnPropertyNames(elementInfo)) { for (const key of Object.getOwnPropertyNames(elementInfo)) {
if (getObjectKeys(optionsFunctions).includes(key)) { if (getObjectKeys(optionsFunctions).includes(key)) {
(optionsFunctions as any)[key](element, elementInfo[key]); optionsFunctions[key](element, elementInfo[key]);
} }
} }
return element; return element;
} }
export function setElementAttributes(element: Element, attributes: { [propName: string]: any }): void { export function setElementAttributes(element: Element, attributes: Record<string, string>): void {
for (const key of Object.getOwnPropertyNames(attributes)) { for (const key of Object.getOwnPropertyNames(attributes)) {
element.setAttribute(key, attributes[key]); element.setAttribute(key, attributes[key]);
} }

View file

@ -2,14 +2,16 @@
// JS & CSS // JS & CSS
/* eslint-disable */
import "./scss/main.scss"; import "./scss/main.scss";
import Icons from 'uikit/dist/js/uikit-icons.min.js'; import Icons from 'uikit/dist/js/uikit-icons.min.js';
import UIkit from 'uikit/dist/js/uikit.min.js'; import UIkit from 'uikit/dist/js/uikit.min.js';
// @ts-ignore
UIkit.use(Icons); UIkit.use(Icons);
/* eslint-disable */
import Prism from "prismjs"; import Prism from "prismjs";
import "prismjs/components/prism-json"; import "prismjs/components/prism-json";
// @ts-ignore
Prism.highlightAll(); Prism.highlightAll();
/* eslint-enable */ /* eslint-enable */
@ -29,14 +31,19 @@ import i18next from 'i18next';
// @ts-ignore // @ts-ignore
import translations from './translations/index.mjs' import translations from './translations/index.mjs'
function ListItem(children) { function ListItem(children: Element[] | Element): HTMLElement {
return makeElement({ return makeElement({
tag: "li", tag: "li",
children: children children: children
}); });
} }
async function onLoad() { declare global {
interface Window { pageContent: Element; }
}
function onLoad(): void {
document.body.innerHTML = ""; document.body.innerHTML = "";
document.body.appendChild(makeElement({ document.body.appendChild(makeElement({
tag: "nav", tag: "nav",
@ -52,17 +59,17 @@ async function onLoad() {
ListItem(makeElement({ ListItem(makeElement({
tag: "a", tag: "a",
text: i18next.t("home_btn"), text: i18next.t("home_btn"),
onclick: _ => { changePage("HOME"); } onclick: () => { changePage("HOME"); }
})), })),
ListItem(makeElement({ ListItem(makeElement({
tag: "a", tag: "a",
text: i18next.t("back_btn"), text: i18next.t("back_btn"),
onclick: _ => { (pageState.currentPage as Page).goBack(); } onclick: () => { (pageState.currentPage as Page).goBack(); }
})), })),
ListItem(makeElement({ ListItem(makeElement({
tag: "a", tag: "a",
text: i18next.t("refresh_btn"), text: i18next.t("refresh_btn"),
onclick: _ => { changePage(pageState.currentPageString); } onclick: () => { changePage(pageState.currentPageString); }
})), })),
] ]
}) })
@ -77,7 +84,7 @@ async function onLoad() {
ListItem(makeElement({ ListItem(makeElement({
tag: "a", tag: "a",
text: i18next.t("me_btn"), text: i18next.t("me_btn"),
onclick: _ => { changePage("ME"); } onclick: () => { changePage("ME"); }
})) }))
] ]
}) })
@ -105,43 +112,44 @@ async function onLoad() {
}) })
})); }));
(window as any).pageContent = document.querySelector("#pageContent"); window.pageContent = document.querySelector("#pageContent");
if (process.env.NODE_ENV == "development") { if (process.env.NODE_ENV == "development") {
await playground(); playground();
} }
renderPage(); renderPage();
setInterval(async () => { setInterval(() => {
if (pageState.currentPageString != "UNSEAL") { if (pageState.currentPageString != "UNSEAL") {
if (pageState.apiURL.length != 0) { return; } if (pageState.apiURL.length != 0) { return; }
const sealStatus = await getSealStatus(); void getSealStatus().then((sealStatus) => {
if (sealStatus.sealed) { if (sealStatus.sealed) {
changePage("UNSEAL"); changePage("UNSEAL");
return; return;
} }
});
} }
}, 5000); }, 5000);
} }
document.addEventListener('DOMContentLoaded', async function () { document.addEventListener('DOMContentLoaded', function () {
console.log("Loading..."); console.log("Loading...");
// @ts-expect-error // @ts-expect-error
console.log("Build Data:", BUILD_STRING); console.log("Build Data:", BUILD_STRING);
i18next.init({ void i18next.init({
lng: pageState.language, lng: pageState.language,
fallbackLng: 'en', fallbackLng: 'en',
debug: true, debug: true,
// @ts-ignore // @ts-ignore
resources: Object.fromEntries(Object.entries(translations).map(([k, v]) => [k, { translation: v }])), resources: Object.fromEntries(Object.entries(translations).map(([k, v]) => [k, { translation: v }])),
interpolation: { interpolation: {
format: function (value, format, _) { format: function (value: unknown, format, _): string {
if (format === 'until_date' && value instanceof Date) return formatDistance(new Date(), new Date(value)); if (format === 'until_date' && value instanceof Date) return formatDistance(new Date(), new Date(value));
return value; return value as string;
} }
} }
}).then(async function (_) { }).then(function (_) {
await onLoad(); onLoad();
}); });
}, false); }, false);

View file

@ -46,13 +46,13 @@ export async function prePageChecks(): Promise<boolean> {
export function addClipboardNotifications(clipboard: ClipboardJS, timeout = 1000): void { export function addClipboardNotifications(clipboard: ClipboardJS, timeout = 1000): void {
clipboard.on('success', () => { clipboard.on('success', () => {
(UIkit as any).notification(i18next.t("notification_copy_success"), { (UIkit as {notification: (title: unknown, options: unknown) => void}).notification(i18next.t("notification_copy_success"), {
status: 'success', status: 'success',
timeout: timeout timeout: timeout
}); });
}); });
clipboard.on('error', function (e: Error) { clipboard.on('error', function (e: Error) {
(UIkit as any).notification(i18next.t("notification_copy_error", { (UIkit as {notification: (title: unknown, options: unknown) => void}).notification(i18next.t("notification_copy_error", {
"error": e.message "error": e.message
}), { }), {
status: 'danger', status: 'danger',
@ -64,9 +64,9 @@ export function addClipboardNotifications(clipboard: ClipboardJS, timeout = 1000
export function setErrorText(text: string): void { export function setErrorText(text: string): void {
const errorTextElement = document.querySelector("#errorText"); const errorTextElement = document.querySelector("#errorText");
if (errorTextElement) { if (errorTextElement) {
(document.querySelector("#errorText") as HTMLElement).innerText = `Error: ${text}`; (document.querySelector("#errorText") as HTMLParagraphElement).innerText = `Error: ${text}`;
} }
(UIkit as any).notification({ (UIkit as {notification: (options: unknown) => void}).notification({
message: `Error: ${text}`, message: `Error: ${text}`,
status: 'danger', status: 'danger',
pos: 'top-center', pos: 'top-center',
@ -87,13 +87,13 @@ export function changePage(page: string, shouldSwitch = true): void {
export function renderPage(): void { export function renderPage(): void {
document.documentElement.dir = pageState.pageDirection; document.documentElement.dir = pageState.pageDirection;
console.log("Rendering Page: ", (pageState.currentPage as Page).name); console.log("Rendering Page: ", (pageState.currentPage as Page).name);
(document.querySelector("#pageContent") as HTMLElement).innerHTML = ""; (document.querySelector("#pageContent") ).innerHTML = "";
setPageTitle((pageState.currentPage as Page).name); setPageTitle((pageState.currentPage as Page).name);
(pageState.currentPage as Page).render(); (pageState.currentPage as Page).render();
} }
export function setPageTitle(title: string | HTMLElement): void { export function setPageTitle(title: string | HTMLElement): void {
const pageTitle = (document.getElementById("pageTitle") as HTMLElement); const pageTitle = (document.getElementById("pageTitle") );
pageTitle.innerHTML = ""; pageTitle.innerHTML = "";
if (typeof title === "string") { if (typeof title === "string") {
pageTitle.innerText = title.toString(); pageTitle.innerText = title.toString();
@ -154,7 +154,7 @@ export function setTitleElement(pageState: PageState): void {
} }
export function setPageContent(content: string | HTMLElement): void { export function setPageContent(content: string | HTMLElement): void {
const pageContent = (document.getElementById("pageContent") as HTMLElement); const pageContent = (document.getElementById("pageContent") );
if (typeof content === "string") { if (typeof content === "string") {
pageContent.innerHTML = content; pageContent.innerHTML = content;
} else { } else {

View file

@ -1,6 +1,6 @@
import { MountType, getMounts } from "../api/sys/getMounts";
import { Page } from "../types/Page"; import { Page } from "../types/Page";
import { changePage, prePageChecks, setErrorText, setPageContent } from "../pageUtils"; import { changePage, prePageChecks, setErrorText, setPageContent } from "../pageUtils";
import { getMounts } from "../api/sys/getMounts";
import { lookupSelf } from "../api/sys/lookupSelf"; import { lookupSelf } from "../api/sys/lookupSelf";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import { pageState } from "../globalPageState"; import { pageState } from "../globalPageState";
@ -48,9 +48,10 @@ export class HomePage extends Page {
tag: "li", tag: "li",
text: i18next.t("your_token_expires_in", {"date": new Date(selfTokenInfo.expire_time)}) text: i18next.t("your_token_expires_in", {"date": new Date(selfTokenInfo.expire_time)})
})); }));
} catch (e) { } catch (e: unknown) {
setErrorText(e.message); const error = e as Error;
if (e.message == "permission denied") { setErrorText(error.message);
if (error.message == "permission denied") {
pageState.token = ""; pageState.token = "";
changePage("LOGIN"); changePage("LOGIN");
} }
@ -68,7 +69,7 @@ export class HomePage extends Page {
// sort it by secretPath so it's in alphabetical order consistantly. // sort it by secretPath so it's in alphabetical order consistantly.
const mountsMap = sortedObjectMap(mounts); const mountsMap = sortedObjectMap(mounts);
mountsMap.forEach(function (mount, baseMount) { mountsMap.forEach(function (mount: MountType, baseMount) {
if (typeof mount != 'object') return; if (typeof mount != 'object') return;
if (mount == null) return; if (mount == null) return;
if (!("type" in mount)) return; if (!("type" in mount)) return;
@ -97,7 +98,7 @@ export class HomePage extends Page {
children: makeElement({ children: makeElement({
tag: "a", tag: "a",
text: linkText, text: linkText,
onclick: _ => { onclick: () => {
pageState.currentBaseMount = baseMount; pageState.currentBaseMount = baseMount;
pageState.currentMountType = mountType; pageState.currentMountType = mountType;
changePage(linkPage); changePage(linkPage);

View file

@ -31,8 +31,8 @@ export class KeyValueDeletePage extends Page {
tag: "button", tag: "button",
class: ["uk-button", "uk-button-danger"], class: ["uk-button", "uk-button-danger"],
text: i18next.t("kv_delete_btn"), text: i18next.t("kv_delete_btn"),
onclick: _ => { onclick: () => {
deleteSecret( void deleteSecret(
pageState.currentBaseMount, pageState.currentBaseMount,
pageState.currentMountType, pageState.currentMountType,
pageState.currentSecretPath, pageState.currentSecretPath,

View file

@ -29,7 +29,7 @@ export class KeyValueNewPage extends Page {
tag: "input", tag: "input",
class: ["uk-input", "uk-form-width-medium"], class: ["uk-input", "uk-form-width-medium"],
attributes: { attributes: {
required: true, required: "true",
type: "text", type: "text",
placeholder: i18next.t("kv_new_path"), placeholder: i18next.t("kv_new_path"),
name: "path" name: "path"
@ -53,9 +53,9 @@ export class KeyValueNewPage extends Page {
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(this.addKVNewForm); setPageContent(this.addKVNewForm);
this.addKVNewForm.addEventListener("submit", function (e) { this.addKVNewForm.addEventListener("submit", function (e: Event) {
e.preventDefault(); e.preventDefault();
this.newKVSecretHandleForm(); (this as KeyValueNewPage).newKVSecretHandleForm();
}.bind(this)); }.bind(this));
} }
@ -77,7 +77,7 @@ export class KeyValueNewPage extends Page {
).then(_ => { ).then(_ => {
changePage("KEY_VALUE_VIEW"); changePage("KEY_VALUE_VIEW");
return; return;
}).catch(e => { }).catch((e: Error) => {
setErrorText(e.message); setErrorText(e.message);
}); });
} }

View file

@ -66,7 +66,7 @@ export class KeyValueSecretPage extends Page {
tag: "button", tag: "button",
id: "deleteButton", id: "deleteButton",
class: ["uk-button", "uk-button-danger"], class: ["uk-button", "uk-button-danger"],
onclick: _ => { changePage("KEY_VALUE_DELETE"); }, onclick: () => { changePage("KEY_VALUE_DELETE"); },
text: deleteButtonText text: deleteButtonText
})); }));
} }
@ -76,7 +76,7 @@ export class KeyValueSecretPage extends Page {
tag: "button", tag: "button",
id: "editButton", id: "editButton",
class: ["uk-button", "uk-margin", "uk-button-primary"], class: ["uk-button", "uk-margin", "uk-button-primary"],
onclick: _ => { changePage("KEY_VALUE_SECRET_EDIT"); }, onclick: () => { changePage("KEY_VALUE_SECRET_EDIT"); },
text: i18next.t("kv_secret_edit_btn") text: i18next.t("kv_secret_edit_btn")
})); }));
} }
@ -86,12 +86,12 @@ export class KeyValueSecretPage extends Page {
tag: "button", tag: "button",
id: "versionsButton", id: "versionsButton",
class: ["uk-button", "uk-button-secondary"], class: ["uk-button", "uk-button-secondary"],
onclick: _ => { changePage("KEY_VALUE_VERSIONS"); }, onclick: () => { changePage("KEY_VALUE_VERSIONS"); },
text: i18next.t("kv_secret_versions_btn") text: i18next.t("kv_secret_versions_btn")
})); }));
} }
getSecret( void getSecret(
pageState.currentBaseMount, pageState.currentBaseMount,
pageState.currentMountType, pageState.currentMountType,
pageState.currentSecretPath, pageState.currentSecretPath,
@ -113,7 +113,7 @@ export class KeyValueSecretPage extends Page {
id: "restoreButton", id: "restoreButton",
class: ["uk-button", "uk-button-primary"], class: ["uk-button", "uk-button-primary"],
onclick: () => { onclick: () => {
undeleteSecret( void undeleteSecret(
pageState.currentBaseMount, pageState.currentBaseMount,
pageState.currentSecretPath, pageState.currentSecretPath,
pageState.currentSecret, pageState.currentSecret,
@ -133,14 +133,18 @@ export class KeyValueSecretPage extends Page {
} }
if (isSecretNestedJson) { if (isSecretNestedJson) {
const jsonText = JSON.stringify(sortedObjectMap(secretsMap as Record<any, any>), null, 4); const jsonText = JSON.stringify(
sortedObjectMap(secretsMap as unknown as Record<string, unknown>),
null,
4
);
kvList.appendChild(makeElement({ kvList.appendChild(makeElement({
tag: "pre", tag: "pre",
class: ["code-block", "language-json", "line-numbers"], class: ["code-block", "language-json", "line-numbers"],
html: Prism.highlight(jsonText, Prism.languages.json, 'json') html: (Prism as { highlight: (text: string, language: null, languageStr: string) => string }).highlight(jsonText, null, 'json')
})); }));
} else { } else {
secretsMap.forEach((value, key) => { secretsMap.forEach((value: string, key: string) => {
const kvListElement = this.makeKVListElement(key, value); const kvListElement = this.makeKVListElement(key, value);
kvList.appendChild(kvListElement); kvList.appendChild(kvListElement);
}, this); }, this);

View file

@ -43,7 +43,7 @@ export class KeyValueSecretEditPage extends Page {
saveButton saveButton
] ]
})); }));
getSecret( void getSecret(
pageState.currentBaseMount, pageState.currentBaseMount,
pageState.currentMountType, pageState.currentMountType,
pageState.currentSecretPath, pageState.currentSecretPath,
@ -70,7 +70,7 @@ export class KeyValueSecretEditPage extends Page {
).then(_ => { ).then(_ => {
changePage("KEY_VALUE_SECRET"); changePage("KEY_VALUE_SECRET");
return; return;
}).catch(e => { }).catch((e: Error) => {
setErrorText(e.message); setErrorText(e.message);
}); });
}; };

View file

@ -39,7 +39,7 @@ export class KeyValueVersionsPage extends Page {
children: makeElement({ children: makeElement({
tag: "a", tag: "a",
text: `v${ver}`, text: `v${ver}`,
onclick: _ => { onclick: () => {
pageState.currentSecretVersion = ver; pageState.currentSecretVersion = ver;
changePage("KEY_VALUE_SECRET"); changePage("KEY_VALUE_SECRET");
} }

View file

@ -61,7 +61,7 @@ export class KeyValueViewPage extends Page {
children: makeElement({ children: makeElement({
tag: "a", tag: "a",
text: secret, text: secret,
onclick: _ => { onclick: () => {
if (secret.endsWith("/")) { if (secret.endsWith("/")) {
pageState.pushCurrentSecretPath(secret); pageState.pushCurrentSecretPath(secret);
changePage("KEY_VALUE_VIEW"); changePage("KEY_VALUE_VIEW");
@ -75,8 +75,9 @@ export class KeyValueViewPage extends Page {
}) })
] ]
})); }));
} catch (e) { } catch (e: unknown) {
if (e == DoesNotExistError) { const error = e as Error;
if (error == DoesNotExistError) {
// getSecrets also 404's on no keys so dont go all the way back. // getSecrets also 404's on no keys so dont go all the way back.
if (pageState.currentSecretPath.length != 0) { if (pageState.currentSecretPath.length != 0) {
return this.goBack(); return this.goBack();
@ -87,7 +88,7 @@ export class KeyValueViewPage extends Page {
})); }));
} }
} else { } else {
setErrorText(e.message); setErrorText(error.message);
} }
} }
} }

View file

@ -20,7 +20,7 @@ export class LoginPage extends Page {
tag: "input", tag: "input",
class: ["uk-input", "uk-form-width-medium"], class: ["uk-input", "uk-form-width-medium"],
attributes: { attributes: {
required: true, required: "true",
type: "password", type: "password",
placeholder: i18next.t("token_input"), placeholder: i18next.t("token_input"),
name: "token" name: "token"
@ -45,7 +45,7 @@ export class LoginPage extends Page {
id: "usernameInput", id: "usernameInput",
class: ["uk-input", "uk-form-width-medium"], class: ["uk-input", "uk-form-width-medium"],
attributes: { attributes: {
required: true, required: "true",
type: "text", type: "text",
placeholder: i18next.t("username_input"), placeholder: i18next.t("username_input"),
name: "username" name: "username"
@ -56,7 +56,7 @@ export class LoginPage extends Page {
id: "passwordInput", id: "passwordInput",
class: ["uk-input", "uk-form-width-medium"], class: ["uk-input", "uk-form-width-medium"],
attributes: { attributes: {
required: true, required: "true",
type: "password", type: "password",
placeholder: i18next.t("password_input"), placeholder: i18next.t("password_input"),
name: "password" name: "password"
@ -127,7 +127,7 @@ export class LoginPage extends Page {
pageState.token = token as string; pageState.token = token as string;
lookupSelf().then(_ => { lookupSelf().then(_ => {
changePage("HOME"); changePage("HOME");
}).catch(e => { }).catch((e: Error) => {
document.getElementById("tokenInput").classList.add("uk-form-danger"); document.getElementById("tokenInput").classList.add("uk-form-danger");
if (e.message == "permission denied") { if (e.message == "permission denied") {
setErrorText(i18next.t("token_login_error")); setErrorText(i18next.t("token_login_error"));
@ -145,7 +145,7 @@ export class LoginPage extends Page {
).then(res => { ).then(res => {
pageState.token = res; pageState.token = res;
changePage("HOME"); changePage("HOME");
}).catch(e => { }).catch((e: Error) => {
document.getElementById("usernameInput").classList.add("uk-form-danger"); document.getElementById("usernameInput").classList.add("uk-form-danger");
document.getElementById("passwordInput").classList.add("uk-form-danger"); document.getElementById("passwordInput").classList.add("uk-form-danger");
setErrorText(e.message); setErrorText(e.message);

View file

@ -53,7 +53,7 @@ export class MePage extends Page {
onclick: () => { onclick: () => {
renewSelf().then(() => { renewSelf().then(() => {
changePage("HOME"); changePage("HOME");
}).catch(e => { }).catch((e: Error) => {
setErrorText(e.message); setErrorText(e.message);
}); });
} }

View file

@ -1,10 +1,10 @@
import { CopyableInputBox, CopyableInputBoxType } from "../elements/CopyableInputBox"; import { CopyableInputBox, CopyableInputBoxType } from "../elements/CopyableInputBox";
import { Margin } from "../elements/Margin"; import { Margin } from "../elements/Margin";
import { Option } from "../elements/Option";
import { Page } from "../types/Page"; import { Page } from "../types/Page";
import { makeElement } from "../htmlUtils"; import { makeElement } from "../htmlUtils";
import { setPageContent } from "../pageUtils"; import { setPageContent } from "../pageUtils";
import i18next from 'i18next'; import i18next from 'i18next';
import { Option } from "../elements/Option";
const passwordLengthMin = 1; const passwordLengthMin = 1;
const passwordLengthMax = 64; const passwordLengthMax = 64;
@ -55,7 +55,7 @@ export class PwGenPage extends Page {
passwordAlphabet: HTMLSelectElement; passwordAlphabet: HTMLSelectElement;
passwordForm: HTMLFormElement; passwordForm: HTMLFormElement;
async render(): Promise<void> { render(): void {
setPageContent(""); setPageContent("");
this.passwordBox = CopyableInputBox(genPassword(passwordOptionsDefault)) ; this.passwordBox = CopyableInputBox(genPassword(passwordOptionsDefault)) ;
@ -70,9 +70,9 @@ export class PwGenPage extends Page {
class: ["uk-range", "uk-width-1-2"], class: ["uk-range", "uk-width-1-2"],
attributes: { attributes: {
type: "range", type: "range",
value: passwordLengthDefault, value: passwordLengthDefault.toString(),
max: passwordLengthMax, max: passwordLengthMax.toString(),
min: passwordLengthMin, min: passwordLengthMin.toString(),
}, },
}) as HTMLInputElement; }) as HTMLInputElement;
@ -124,7 +124,7 @@ export class PwGenPage extends Page {
this.passwordLengthTitle.innerText = this.getPasswordLengthText(); this.passwordLengthTitle.innerText = this.getPasswordLengthText();
this.passwordBox.setText(genPassword({ this.passwordBox.setText(genPassword({
length: (this.passwordLengthRange.value as unknown) as number, length: (this.passwordLengthRange.value as unknown) as number,
alphabet: this.passwordAlphabet.value as string, alphabet: this.passwordAlphabet.value ,
})); }));
} }

View file

@ -55,7 +55,7 @@ export class SetLanguagePage extends Page {
const language = formData.get("language") as string; const language = formData.get("language") as string;
pageState.language = language; pageState.language = language;
console.log(pageState.language); console.log(pageState.language);
i18next.changeLanguage(language).then((t) => { void i18next.changeLanguage(language).then((t) => {
changePage("HOME", false); changePage("HOME", false);
pageState.pageDirection = t("language_direction"); pageState.pageDirection = t("language_direction");
location.reload(); location.reload();

View file

@ -19,7 +19,7 @@ export class SetVaultURLPage extends Page {
tag: "input", tag: "input",
class: ["uk-input", "uk-form-width-medium"], class: ["uk-input", "uk-form-width-medium"],
attributes: { attributes: {
required: true, required: "true",
type: "text", type: "text",
placeholder: "Vault URL", placeholder: "Vault URL",
name: "vaultURL" name: "vaultURL"

View file

@ -33,7 +33,7 @@ export class NewTOTPPage extends Page {
tag: "input", tag: "input",
class: ["uk-input", "uk-form-width-medium"], class: ["uk-input", "uk-form-width-medium"],
attributes: { attributes: {
required: true, required: "true",
type: "text", type: "text",
placeholder: i18next.t("totp_new_name_text"), placeholder: i18next.t("totp_new_name_text"),
name: "name" name: "name"
@ -89,7 +89,7 @@ export class NewTOTPPage extends Page {
}; };
addNewTOTP(pageState.currentBaseMount, parms).then(_ => { addNewTOTP(pageState.currentBaseMount, parms).then(_ => {
changePage("TOTP"); changePage("TOTP");
}).catch(e => { }).catch((e: Error) => {
setErrorText(`API Error: ${e.message}`); setErrorText(`API Error: ${e.message}`);
}); });
}); });

View file

@ -24,7 +24,7 @@ export class TOTPViewPage extends Page {
refresher: number; refresher: number;
totpListElements: Record<string, TOTPListElement>; totpListElements: Record<string, TOTPListElement>;
async render(): Promise<void> { render(): void {
setTitleElement(pageState); setTitleElement(pageState);
const totpList = makeElement({ tag: "div" }); const totpList = makeElement({ tag: "div" });
setPageContent(makeElement({ setPageContent(makeElement({
@ -33,7 +33,7 @@ export class TOTPViewPage extends Page {
makeElement({ makeElement({
tag: "a", tag: "a",
text: i18next.t("totp_view_new_btn"), text: i18next.t("totp_view_new_btn"),
onclick: _ => { changePage("NEW_TOTP"); } onclick: () => { changePage("NEW_TOTP"); }
}), }),
makeElement({ makeElement({
tag: "p", tag: "p",
@ -48,14 +48,14 @@ export class TOTPViewPage extends Page {
getTOTPKeys(pageState.currentBaseMount).then(res => { getTOTPKeys(pageState.currentBaseMount).then(res => {
res.forEach(async function (totpKeyName) { res.forEach(function (totpKeyName) {
const totpListElement = this.makeTOTPListElement(totpKeyName); const totpListElement = (this as TOTPViewPage).makeTOTPListElement(totpKeyName);
totpList.appendChild(totpListElement); totpList.appendChild(totpListElement);
this.totpListElements[totpKeyName] = totpListElement; (this as TOTPViewPage).totpListElements[totpKeyName] = totpListElement;
await this.updateTOTPElement(totpKeyName, totpListElement); void (this as TOTPViewPage).updateTOTPElement(totpKeyName, totpListElement);
}, this); }, this);
document.getElementById("loadingText").remove(); document.getElementById("loadingText").remove();
}).catch(e => { }).catch((e: Error) => {
if (e == DoesNotExistError) { if (e == DoesNotExistError) {
const loadingText = document.getElementById("loadingText"); const loadingText = document.getElementById("loadingText");
loadingText.innerText = i18next.t("totp_view_empty"); loadingText.innerText = i18next.t("totp_view_empty");
@ -64,12 +64,12 @@ export class TOTPViewPage extends Page {
} }
}); });
const totpRefresher = async () => { const totpRefresher = () => {
await Promise.all(Array.from(objectToMap(this.totpListElements)).map((kv) => { void Promise.all(Array.from(objectToMap(this.totpListElements)).map((kv: [string, TOTPListElement]) => {
return this.updateTOTPElement(...kv); return this.updateTOTPElement(...kv);
})) }))
} }
await totpRefresher(); void totpRefresher();
this.refresher = setInterval(totpRefresher, 3000) as unknown as number; this.refresher = setInterval(totpRefresher, 3000) as unknown as number;
} }
@ -92,7 +92,7 @@ export class TOTPViewPage extends Page {
children: [totpKeyBox, totpValueBox] children: [totpKeyBox, totpValueBox]
}) as TOTPListElement; }) as TOTPListElement;
gridElement.setCode = totpValueBox.setText; gridElement.setCode = (code: string) => totpValueBox.setText(code);
return gridElement; return gridElement;
} }

View file

@ -6,7 +6,6 @@ import { changePage, setErrorText, setPageContent, setTitleElement } from "../..
import { fileToBase64, makeElement } from "../../htmlUtils"; import { fileToBase64, makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState"; import { pageState } from "../../globalPageState";
import { transitDecrypt } from "../../api/transit/transitDecrypt"; import { transitDecrypt } from "../../api/transit/transitDecrypt";
import UIkit from 'uikit/dist/js/uikit.min.js';
import i18next from "i18next"; import i18next from "i18next";
export class TransitDecryptPage extends Page { export class TransitDecryptPage extends Page {
@ -20,7 +19,7 @@ export class TransitDecryptPage extends Page {
transitDecryptForm: HTMLFormElement; transitDecryptForm: HTMLFormElement;
async render(): Promise<void> { render(): void {
setTitleElement(pageState); setTitleElement(pageState);
setPageContent(makeElement({ setPageContent(makeElement({
tag: "div" tag: "div"
@ -74,7 +73,7 @@ export class TransitDecryptPage extends Page {
setPageContent(this.transitDecryptForm); setPageContent(this.transitDecryptForm);
this.transitDecryptForm.addEventListener("submit", async function (e: Event) { this.transitDecryptForm.addEventListener("submit", async function (e: Event) {
e.preventDefault(); e.preventDefault();
await this.transitDecryptFormHandler(); await (this as TransitDecryptPage).transitDecryptFormHandler();
}.bind(this)); }.bind(this));
} }
@ -87,11 +86,11 @@ export class TransitDecryptPage extends Page {
const ciphertext_file = formData.get("ciphertext_file") as File; const ciphertext_file = formData.get("ciphertext_file") as File;
if (ciphertext_file.size > 0) { if (ciphertext_file.size > 0) {
ciphertext = atob((await fileToBase64(ciphertext_file) as string).replace("data:text/plain;base64,", "")); ciphertext = atob((await fileToBase64(ciphertext_file) ).replace("data:text/plain;base64,", ""));
} }
try { try {
let res = await transitDecrypt( const res = await transitDecrypt(
pageState.currentBaseMount, pageState.currentBaseMount,
pageState.currentSecret, pageState.currentSecret,
{ ciphertext: ciphertext }, { ciphertext: ciphertext },
@ -102,9 +101,10 @@ export class TransitDecryptPage extends Page {
} }
const modal = CopyableModal(i18next.t("transit_decrypt_decryption_result_modal_title"), plaintext); const modal = CopyableModal(i18next.t("transit_decrypt_decryption_result_modal_title"), plaintext);
document.body.querySelector("#pageContent").appendChild(modal); document.body.querySelector("#pageContent").appendChild(modal);
UIkit.modal(modal).show(); modal.show();
} catch (e) { } catch (e: unknown) {
setErrorText(`API Error: ${e.message}`); const error = e as Error;
setErrorText(`API Error: ${error.message}`);
} }
} }

View file

@ -6,7 +6,6 @@ import { changePage, setErrorText, setPageContent, setTitleElement } from "../..
import { fileToBase64, makeElement } from "../../htmlUtils"; import { fileToBase64, makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState"; import { pageState } from "../../globalPageState";
import { transitEncrypt } from "../../api/transit/transitEncrypt"; import { transitEncrypt } from "../../api/transit/transitEncrypt";
import UIkit from 'uikit/dist/js/uikit.min.js';
import i18next from "i18next"; import i18next from "i18next";
@ -22,7 +21,7 @@ export class TransitEncryptPage extends Page {
transitEncryptForm: HTMLFormElement; transitEncryptForm: HTMLFormElement;
async render(): Promise<void> { render(): void {
setTitleElement(pageState); setTitleElement(pageState);
setPageContent(makeElement({ setPageContent(makeElement({
tag: "div" tag: "div"
@ -75,9 +74,9 @@ export class TransitEncryptPage extends Page {
}) as HTMLFormElement; }) as HTMLFormElement;
setPageContent(this.transitEncryptForm); setPageContent(this.transitEncryptForm);
this.transitEncryptForm.addEventListener("submit", async function (e) { this.transitEncryptForm.addEventListener("submit", async function (e: Event) {
e.preventDefault(); e.preventDefault();
await this.transitEncryptFormHandler(); await (this as TransitEncryptPage).transitEncryptFormHandler();
}.bind(this)); }.bind(this));
} }
@ -90,23 +89,24 @@ export class TransitEncryptPage extends Page {
const plaintext_file = formData.get("plaintext_file") as File; const plaintext_file = formData.get("plaintext_file") as File;
if (plaintext_file.size > 0) { if (plaintext_file.size > 0) {
plaintext = (await fileToBase64(plaintext_file) as string).replace("data:text/plain;base64,", ""); plaintext = (await fileToBase64(plaintext_file) ).replace("data:text/plain;base64,", "");
plaintext = base64Checkbox == "on" ? atob(plaintext) : plaintext; plaintext = base64Checkbox == "on" ? atob(plaintext) : plaintext;
} else { } else {
plaintext = base64Checkbox == "on" ? plaintext : btoa(plaintext); plaintext = base64Checkbox == "on" ? plaintext : btoa(plaintext);
} }
try { try {
let res = await transitEncrypt( const res = await transitEncrypt(
pageState.currentBaseMount, pageState.currentBaseMount,
pageState.currentSecret, pageState.currentSecret,
{ plaintext: plaintext } { plaintext: plaintext }
); );
const modal = CopyableModal(i18next.t("transit_encrypt_encryption_result_modal_title"), res.ciphertext); const modal = CopyableModal(i18next.t("transit_encrypt_encryption_result_modal_title"), res.ciphertext);
document.body.querySelector("#pageContent").appendChild(modal); document.body.querySelector("#pageContent").appendChild(modal);
UIkit.modal(modal).show(); modal.show();
} catch (e) { } catch (e: unknown) {
setErrorText(`API Error: ${e.message}`); const error = e as Error;
setErrorText(`API Error: ${error.message}`);
} }
} }

View file

@ -1,16 +1,14 @@
import { CopyableModal } from "../../elements/CopyableModal"; import { CopyableModal } from "../../elements/CopyableModal";
import { FileUploadInput } from "../../elements/FileUploadInput";
import { Margin } from "../../elements/Margin"; import { Margin } from "../../elements/Margin";
import { Option } from "../../elements/Option";
import { Page } from "../../types/Page"; import { Page } from "../../types/Page";
import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils"; import { changePage, setErrorText, setPageContent, setTitleElement } from "../../pageUtils";
import { makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState";
import UIkit from 'uikit/dist/js/uikit.min.js';
import i18next from "i18next";
import { getTransitKey } from "../../api/transit/getTransitKey"; import { getTransitKey } from "../../api/transit/getTransitKey";
import { makeElement } from "../../htmlUtils";
import { objectToMap } from "../../utils"; import { objectToMap } from "../../utils";
import { Option } from "../../elements/Option"; import { pageState } from "../../globalPageState";
import { transitRewrap } from "../../api/transit/transitRewrap"; import { transitRewrap } from "../../api/transit/transitRewrap";
import i18next from "i18next";
type versionOption = { version: string; label: string } type versionOption = { version: string; label: string }
@ -27,17 +25,17 @@ export class TransitRewrapPage extends Page {
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState); setTitleElement(pageState);
let transitKey = await getTransitKey(pageState.currentBaseMount, pageState.currentSecret); const transitKey = await getTransitKey(pageState.currentBaseMount, pageState.currentSecret);
let stringVersions = Array.from(objectToMap(transitKey.keys).keys()).reverse() as any as string[]; const stringVersions = Array.from(objectToMap(transitKey.keys).keys()).reverse() as unknown as string[];
let versions = stringVersions.map((val) => parseInt(val, 10)) as any as number[]; const versions = stringVersions.map((val): number => parseInt(val, 10));
// get the selectable version options in the same // get the selectable version options in the same
// format the official UI uses. // format the official UI uses.
// e.g: ["2 (latest)", "1"] // e.g: ["2 (latest)", "1"]
let options: versionOption[] = versions.map((val): versionOption => { const options: versionOption[] = versions.map((val): versionOption => {
let i18nkey = val == Math.max(...versions) ? const i18nkey = val == Math.max(...versions) ?
"transit_rewrap_latest_version_option_text" "transit_rewrap_latest_version_option_text"
: :
"transit_rewrap_version_option_text"; "transit_rewrap_version_option_text";
@ -83,15 +81,14 @@ export class TransitRewrapPage extends Page {
setPageContent(this.transitRewrapForm); setPageContent(this.transitRewrapForm);
this.transitRewrapForm.addEventListener("submit", async function (e: Event) { this.transitRewrapForm.addEventListener("submit", async function (e: Event) {
e.preventDefault(); e.preventDefault();
await this.transitRewrapFormHandler(); await (this as TransitRewrapPage).transitRewrapFormHandler();
}.bind(this)); }.bind(this));
} }
async transitRewrapFormHandler(): Promise<void> { async transitRewrapFormHandler(): Promise<void> {
const formData = new FormData(this.transitRewrapForm); const formData = new FormData(this.transitRewrapForm);
const ciphertext = formData.get("ciphertext") as string;
try { try {
let res = await transitRewrap( const res = await transitRewrap(
pageState.currentBaseMount, pageState.currentBaseMount,
pageState.currentSecret, pageState.currentSecret,
{ {
@ -101,9 +98,10 @@ export class TransitRewrapPage extends Page {
); );
const modal = CopyableModal(i18next.t("transit_rewrap_result_modal_title"), res.ciphertext); const modal = CopyableModal(i18next.t("transit_rewrap_result_modal_title"), res.ciphertext);
document.body.querySelector("#pageContent").appendChild(modal); document.body.querySelector("#pageContent").appendChild(modal);
UIkit.modal(modal).show(); modal.show();
} catch (e) { } catch (e: unknown) {
setErrorText(`API Error: ${e.message}`); const error = e as Error;
setErrorText(`API Error: ${error.message}`);
} }
} }

View file

@ -46,7 +46,7 @@ export class TransitViewPage extends Page {
children: makeElement({ children: makeElement({
tag: "a", tag: "a",
text: secret, text: secret,
onclick: _ => { onclick: () => {
pageState.currentSecret = secret; pageState.currentSecret = secret;
changePage("TRANSIT_VIEW_SECRET"); changePage("TRANSIT_VIEW_SECRET");
} }
@ -55,14 +55,15 @@ export class TransitViewPage extends Page {
}) })
] ]
})); }));
} catch (e) { } catch (e: unknown) {
if (e == DoesNotExistError) { const error = e as Error;
if (error == DoesNotExistError) {
transitViewContent.appendChild(makeElement({ transitViewContent.appendChild(makeElement({
tag: "p", tag: "p",
text: i18next.t("transit_view_none_here_text") text: i18next.t("transit_view_none_here_text")
})); }));
} else { } else {
setErrorText(e.message); setErrorText(error.message);
} }
} }
} }

View file

@ -1,10 +1,10 @@
import { Page } from "../../types/Page"; import { Page } from "../../types/Page";
import { Tile } from "../../elements/Tile";
import { changePage, setPageContent, setTitleElement } from "../../pageUtils"; import { changePage, setPageContent, setTitleElement } from "../../pageUtils";
import { getTransitKey } from "../../api/transit/getTransitKey";
import { makeElement } from "../../htmlUtils"; import { makeElement } from "../../htmlUtils";
import { pageState } from "../../globalPageState"; import { pageState } from "../../globalPageState";
import i18next from 'i18next'; import i18next from 'i18next';
import { getTransitKey } from "../../api/transit/getTransitKey";
import { Tile } from "../../elements/Tile";
export class TransitViewSecretPage extends Page { export class TransitViewSecretPage extends Page {
constructor() { constructor() {
@ -18,7 +18,7 @@ export class TransitViewSecretPage extends Page {
async render(): Promise<void> { async render(): Promise<void> {
setTitleElement(pageState); setTitleElement(pageState);
let transitKey = await getTransitKey(pageState.currentBaseMount, pageState.currentSecret); const transitKey = await getTransitKey(pageState.currentBaseMount, pageState.currentSecret);
setPageContent(makeElement({ setPageContent(makeElement({
tag: "div", tag: "div",

View file

@ -41,9 +41,16 @@ export class UnsealPage extends Page {
} }
makeRefresher(): void { makeRefresher(): void {
this.refresher = setInterval(async function () { const id = setInterval(() => {
this.updateSealProgress(await getSealStatus()); void (this as UnsealPage).doRefresh().then(() => {});
}.bind(this), 1000) as unknown as number; return;
}, 1000);
this.refresher = id as unknown as number;
}
async doRefresh(): Promise<void> {
const status = await getSealStatus();
this.updateSealProgress(status);
} }
async render(): Promise<void> { async render(): Promise<void> {
@ -58,7 +65,7 @@ export class UnsealPage extends Page {
}) as HTMLParagraphElement; }) as HTMLParagraphElement;
this.unsealInputContent = makeElement({ this.unsealInputContent = makeElement({
tag: "div" tag: "div"
}) as HTMLElement; });
setPageContent(makeElement({ setPageContent(makeElement({
tag: "div", tag: "div",
children: [ children: [
@ -103,7 +110,7 @@ export class UnsealPage extends Page {
this.deinitWebcam(); this.deinitWebcam();
this.unsealInputContent.querySelectorAll('*').forEach(n => n.remove()) this.unsealInputContent.querySelectorAll('*').forEach(n => n.remove())
if (method == UnsealInputModes.FORM_INPUT) this.makeUnsealForm(); if (method == UnsealInputModes.FORM_INPUT) this.makeUnsealForm();
if (method == UnsealInputModes.QR_INPUT) this.makeQRInput(); if (method == UnsealInputModes.QR_INPUT) void this.makeQRInput();
this.setButtons(method); this.setButtons(method);
} }
@ -115,7 +122,7 @@ export class UnsealPage extends Page {
tag: "input", tag: "input",
class: ["uk-input", "uk-form-width-medium"], class: ["uk-input", "uk-form-width-medium"],
attributes: { attributes: {
required: true, required: "true",
type: "password", type: "password",
placeholder: i18next.t("key_input_placeholder"), placeholder: i18next.t("key_input_placeholder"),
name: "key" name: "key"
@ -129,15 +136,15 @@ export class UnsealPage extends Page {
] ]
}) as HTMLFormElement; }) as HTMLFormElement;
this.unsealInputContent.appendChild(this.unsealKeyForm); this.unsealInputContent.appendChild(this.unsealKeyForm);
this.unsealKeyForm.addEventListener("submit", function (e) { this.unsealKeyForm.addEventListener("submit", function (e: Event) {
e.preventDefault(); e.preventDefault();
this.handleKeySubmit(); void (this as UnsealPage).handleKeySubmit();
}.bind(this)); }.bind(this));
} }
async makeQRInput(): Promise<void> { async makeQRInput(): Promise<void> {
this.qrScanner = await QRScanner(function (code: string) { this.qrScanner = await QRScanner(function (code: string) {
this.submitKey(code); (this as UnsealPage).submitKey(code);
console.log('decoded qr code:', code) console.log('decoded qr code:', code)
}.bind(this)); }.bind(this));
this.unsealInputContent.appendChild(this.qrScanner); this.unsealInputContent.appendChild(this.qrScanner);
@ -162,15 +169,15 @@ export class UnsealPage extends Page {
submitKey(key: string): void { submitKey(key: string): void {
submitUnsealKey(key).then(_ => { submitUnsealKey(key).then(_ => {
getSealStatus().then(data => { void getSealStatus().then(data => {
this.updateSealProgress(data); void this.updateSealProgress(data);
}); });
}).catch(e => { }).catch((e: Error) => {
setErrorText(e.message); setErrorText(e.message);
}); });
} }
async handleKeySubmit(): Promise<void> { handleKeySubmit(): void {
const formData = new FormData(this.unsealKeyForm); const formData = new FormData(this.unsealKeyForm);
this.submitKey(formData.get("key") as string) this.submitKey(formData.get("key") as string)

View file

@ -1,3 +1,4 @@
import { PageState } from "./PageState";
import { pageState } from "./globalPageState"; import { pageState } from "./globalPageState";
import i18next from 'i18next'; import i18next from 'i18next';
@ -6,9 +7,13 @@ import i18next from 'i18next';
// before rendering. // before rendering.
// Also it only runs when process.env.NODE_ENV == "development" // Also it only runs when process.env.NODE_ENV == "development"
// Please empty this function before committing. declare global {
export async function playground(): Promise<void> { interface Window { pageState: PageState; i18next: unknown; }
console.log("Welcome to Playground!"); }
(window as any).pageState = pageState;
(window as any).i18next = i18next; // Please empty this function before committing.
export function playground(): void {
console.log("Welcome to Playground!");
window.pageState = pageState;
window.i18next = i18next;
} }

View file

@ -4,8 +4,9 @@ export class Page {
constructor() { constructor() {
// Do Nothing // Do Nothing
} }
render(): any { render(): unknown {
// Do Nothing // Do Nothing
return null;
} }
get name(): string { get name(): string {
return "Page"; return "Page";

View file

@ -5,13 +5,13 @@ export function removeDoubleSlash(str: string): string {
export const getObjectKeys = export const getObjectKeys =
(obj: Record<string, unknown>): string[] => Object.getOwnPropertyNames(obj); (obj: Record<string, unknown>): string[] => Object.getOwnPropertyNames(obj);
export const objectToMap = export const objectToMap =
(obj: Record<any, any>): Map<any, any> => new Map(Object.entries(obj)); (obj: Record<string, unknown>): Map<string, unknown> => new Map(Object.entries(obj));
export const sortedObjectMap = export const sortedObjectMap =
(obj: Record<string, unknown>): Map<any, any> => new Map(Object.entries(obj).sort()); (obj: Record<string, unknown>): Map<string, unknown> => new Map(Object.entries(obj).sort());
export function getKeyByObjectPropertyValue(map: Record<string, unknown>, searchValue: unknown): string { export function getKeyByObjectPropertyValue(map: Record<string, unknown>, searchValue: unknown): string {
for (const key of getObjectKeys(map)) { for (const key of getObjectKeys(map)) {
if ((map as any)[key] === searchValue) if (map[key] === searchValue)
return key; return key;
} }
} }