From a3479398968ad14503b6bb696e58ee0affbdf002 Mon Sep 17 00:00:00 2001 From: Kitteh Date: Mon, 10 May 2021 11:35:14 +0100 Subject: [PATCH] Lint code harder. --- .eslintrc.json | 16 ++++---- src/PageState.ts | 6 +-- src/api/apiUtils.ts | 2 +- src/api/auth/usernameLogin.ts | 17 ++++---- src/api/kv/createOrUpdateSecret.ts | 2 +- src/api/kv/deleteSecret.ts | 4 +- src/api/kv/getSecret.ts | 16 ++++---- src/api/kv/getSecretMetadata.ts | 12 +++--- src/api/kv/getSecrets.ts | 20 ++++----- src/api/kv/undeleteSecret.ts | 2 +- src/api/sys/getCapabilities.ts | 8 ++-- src/api/sys/getMounts.ts | 18 ++++---- src/api/sys/getSealStatus.ts | 8 ++-- src/api/sys/lookupSelf.ts | 18 ++++---- src/api/sys/renewSelf.ts | 12 +++--- src/api/sys/sealVault.ts | 12 +++--- src/api/sys/submitUnsealKey.ts | 10 +++-- src/api/totp/addNewTOTP.ts | 11 ++--- src/api/totp/getTOTPCode.ts | 8 ++-- src/api/totp/getTOTPKeys.ts | 16 ++++---- src/api/transit/getTransitKey.ts | 17 ++++---- src/api/transit/getTransitKeys.ts | 14 +++---- src/api/transit/transitDecrypt.ts | 8 ++-- src/api/transit/transitEncrypt.ts | 8 ++-- src/api/transit/transitRewrap.ts | 8 ++-- src/api/types/token.ts | 6 +-- src/api/types/transit.ts | 16 ++++---- src/elements/CopyableInputBox.ts | 8 ++-- src/elements/CopyableModal.ts | 25 +++++++++--- src/elements/QRScanner.ts | 2 +- src/elements/Tile.ts | 2 +- src/elements/renewSelf.ts | 19 --------- src/formatDistance.ts | 2 +- src/htmlUtils.ts | 17 ++++---- src/main.ts | 50 +++++++++++++---------- src/pageUtils.ts | 14 +++---- src/pages/Home.ts | 13 +++--- src/pages/KeyValue/KeyValueDelete.ts | 4 +- src/pages/KeyValue/KeyValueNew.ts | 8 ++-- src/pages/KeyValue/KeyValueSecret.ts | 20 +++++---- src/pages/KeyValue/KeyValueSecretsEdit.ts | 4 +- src/pages/KeyValue/KeyValueVersions.ts | 2 +- src/pages/KeyValue/KeyValueView.ts | 9 ++-- src/pages/Login.ts | 10 ++--- src/pages/Me.ts | 2 +- src/pages/PwGen.ts | 12 +++--- src/pages/SetLanguage.ts | 2 +- src/pages/SetVaultURL.ts | 2 +- src/pages/TOTP/NewTOTP.ts | 4 +- src/pages/TOTP/TOTPView.ts | 22 +++++----- src/pages/Transit/TransitDecrypt.ts | 16 ++++---- src/pages/Transit/TransitEncrypt.ts | 18 ++++---- src/pages/Transit/TransitRewrap.ts | 32 +++++++-------- src/pages/Transit/TransitView.ts | 9 ++-- src/pages/Transit/TransitViewSecret.ts | 6 +-- src/pages/Unseal.ts | 33 +++++++++------ src/playground.ts | 15 ++++--- src/types/Page.ts | 3 +- src/utils.ts | 6 +-- 59 files changed, 345 insertions(+), 341 deletions(-) delete mode 100644 src/elements/renewSelf.ts diff --git a/.eslintrc.json b/.eslintrc.json index 1227a1e..3f10ff4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,18 +1,20 @@ { - "extends": [ - "eslint:recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:@typescript-eslint/recommended" - ], "plugins": [ "sort-imports-es6-autofix", "@typescript-eslint" ], + "extends": [ + "eslint:recommended", + "plugin:import/errors", + "plugin:import/warnings", + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking" + ], "parserOptions": { "ecmaVersion": 12, "sourceType": "module", - "experimentalObjectRestSpread": true + "experimentalObjectRestSpread": true, + "project": "./tsconfig.json" }, "globals": { "pageContent": "writable", diff --git a/src/PageState.ts b/src/PageState.ts index 36be881..f1037e8 100644 --- a/src/PageState.ts +++ b/src/PageState.ts @@ -71,7 +71,7 @@ export class PageState { } get currentSecretPath(): string[] { - return JSON.parse(localStorage.getItem('currentSecretPath') || "[]"); + return JSON.parse(localStorage.getItem('currentSecretPath') || "[]") as string[]; } set currentSecretPath(value: string[]) { localStorage.setItem('currentSecretPath', JSON.stringify(value)); @@ -104,14 +104,14 @@ export class PageState { } get currentPage(): Page | string { const curPage = localStorage.getItem('currentPage') || "HOME"; - return (allPages as any)[curPage]; + return allPages[curPage]; } set currentPage(value: Page | string) { if (typeof value == 'object') { const key = getKeyByObjectPropertyValue(allPages, value); localStorage.setItem('currentPage', key); } else { - localStorage.setItem('currentPage', (value as string)); + localStorage.setItem('currentPage', value); } } } \ No newline at end of file diff --git a/src/api/apiUtils.ts b/src/api/apiUtils.ts index c82d16c..7e2eef1 100644 --- a/src/api/apiUtils.ts +++ b/src/api/apiUtils.ts @@ -1,6 +1,6 @@ import { pageState } from "../globalPageState"; -export function getHeaders(): any { +export function getHeaders(): Record { return { "X-Vault-Token": pageState.token, } diff --git a/src/api/auth/usernameLogin.ts b/src/api/auth/usernameLogin.ts index 88ca35d..71080e7 100644 --- a/src/api/auth/usernameLogin.ts +++ b/src/api/auth/usernameLogin.ts @@ -8,13 +8,12 @@ export async function usernameLogin(username: string, password: string): Promise }, body: JSON.stringify({ "username": username, "password": password }) }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - if ("auth" in data) { - return data.auth.client_token; - } else if ("errors" in data) { - throw new Error(data.errors[0]); - } - }); + + const resp = await fetch(request); + const data = await resp.json() as { auth?: { client_token: string }; errors?: string[] }; + if ("auth" in data) { + return data.auth.client_token; + } else if ("errors" in data) { + throw new Error(data.errors[0]); + } } diff --git a/src/api/kv/createOrUpdateSecret.ts b/src/api/kv/createOrUpdateSecret.ts index 0fbb7ad..2641ce0 100644 --- a/src/api/kv/createOrUpdateSecret.ts +++ b/src/api/kv/createOrUpdateSecret.ts @@ -30,7 +30,7 @@ export async function createOrUpdateSecret( }); const response = await fetch(request); if (!response.ok) { - const json = await response.json(); + const json = await response.json() as {errors: string[]}; throw new Error(json.errors[0]); } } diff --git a/src/api/kv/deleteSecret.ts b/src/api/kv/deleteSecret.ts index 15dac21..dae7fe2 100644 --- a/src/api/kv/deleteSecret.ts +++ b/src/api/kv/deleteSecret.ts @@ -32,12 +32,12 @@ export async function deleteSecret( secretURL = removeDoubleSlash(secretURL).replace(/\/$/, ""); request = new Request(appendAPIURL(secretURL), { method: "DELETE", - headers: (getHeaders() as any), + headers: getHeaders(), }); } const response = await fetch(request); if (!response.ok) { - const json = await response.json(); + const json = await response.json() as {errors: string[]}; throw new Error(json.errors[0]); } } diff --git a/src/api/kv/getSecret.ts b/src/api/kv/getSecret.ts index 85dbd52..34be9d2 100644 --- a/src/api/kv/getSecret.ts +++ b/src/api/kv/getSecret.ts @@ -6,7 +6,7 @@ export async function getSecret( secretPath: string[], name: string, version: string|null = null -): Promise> { +): Promise> { let secretURL = ""; if (mountType == "kv-v2") { secretURL = `/v1/${baseMount}/data/${secretPath.join("")}/${name}`; @@ -16,12 +16,14 @@ export async function getSecret( secretURL = `/v1/${baseMount}/${secretPath.join("")}/${name}`; } const request = new Request(appendAPIURL(secretURL), { - headers: (getHeaders() as any), + headers: getHeaders(), }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - return mountType == "kv-v2" ? data.data.data : data.data; - }); + const resp = await fetch(request); + const data = await resp.json() as unknown; + if (mountType == "kv-v2") { + return (data as {data: {data: Record}}).data.data; + } else { + return (data as {data: Record}).data; + } } diff --git a/src/api/kv/getSecretMetadata.ts b/src/api/kv/getSecretMetadata.ts index 0491039..051ce14 100644 --- a/src/api/kv/getSecretMetadata.ts +++ b/src/api/kv/getSecretMetadata.ts @@ -1,7 +1,7 @@ import { appendAPIURL, getHeaders } from "../apiUtils"; type SecretMetadataType = { - versions: Record> + versions: Record } export async function getSecretMetadata( @@ -10,12 +10,10 @@ export async function getSecretMetadata( name: string ): Promise { const request = new Request(appendAPIURL(`/v1/${baseMount}/metadata/${secretPath.join("")}/${name}`), { - headers: (getHeaders() as any), + headers: getHeaders(), }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - return data.data; - }); + const resp = await fetch(request); + const data = await resp.json() as {data: SecretMetadataType}; + return data.data; } diff --git a/src/api/kv/getSecrets.ts b/src/api/kv/getSecrets.ts index 783c5ee..bfab3ba 100644 --- a/src/api/kv/getSecrets.ts +++ b/src/api/kv/getSecrets.ts @@ -2,8 +2,8 @@ import { DoesNotExistError } from "../../types/internalErrors"; import { appendAPIURL, getHeaders } from "../apiUtils"; export async function getSecrets( - baseMount: string, - mountType: string, + baseMount: string, + mountType: string, secretPath: string[] ): Promise { let secretURL = ""; @@ -14,14 +14,12 @@ export async function getSecrets( secretURL = `/v1/${baseMount}/${secretPath.join("")}?list=true`; } const request = new Request(appendAPIURL(secretURL), { - headers: (getHeaders() as any), - }); - return fetch(request).then(response => { - if (response.status == 404) { - throw DoesNotExistError; - } - return response.json(); - }).then(data => { - return data.data.keys; + headers: getHeaders(), }); + const resp = await fetch(request); + if (resp.status == 404) { + throw DoesNotExistError; + } + const data = await resp.json() as { data: { keys: string[] } }; + return data.data.keys; } diff --git a/src/api/kv/undeleteSecret.ts b/src/api/kv/undeleteSecret.ts index 2f84034..0cdd7bf 100644 --- a/src/api/kv/undeleteSecret.ts +++ b/src/api/kv/undeleteSecret.ts @@ -30,7 +30,7 @@ export async function undeleteSecret( }); const response = await fetch(request); if (!response.ok) { - const json = await response.json(); + const json = await response.json() as {errors: string[]}; throw new Error(json.errors[0]); } } diff --git a/src/api/sys/getCapabilities.ts b/src/api/sys/getCapabilities.ts index fd9d2fa..cb814bc 100644 --- a/src/api/sys/getCapabilities.ts +++ b/src/api/sys/getCapabilities.ts @@ -15,11 +15,9 @@ export async function getCapabilitiesPath(path: string): Promise { } ) }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - return data.capabilities; - }); + const response = await fetch(request); + const data = await response.json() as {capabilities: string[]}; + return data.capabilities; } export async function getCapabilities( diff --git a/src/api/sys/getMounts.ts b/src/api/sys/getMounts.ts index fb4b22a..dfe8e07 100644 --- a/src/api/sys/getMounts.ts +++ b/src/api/sys/getMounts.ts @@ -1,21 +1,21 @@ import { appendAPIURL, getHeaders } from "../apiUtils"; -type MountsType = { - [key: string]: { +export type MountType = { type: string options: { version: string } - } +} + +export type MountsType = { + [key: string]: MountType; } export async function getMounts(): Promise { const request = new Request(appendAPIURL("/v1/sys/internal/ui/mounts"), { - headers: (getHeaders() as any), - }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - return data.data.secret; + headers: getHeaders(), }); + const resp = await fetch(request); + const data = await resp.json() as {data: {secret: MountsType}}; + return data.data.secret; } diff --git a/src/api/sys/getSealStatus.ts b/src/api/sys/getSealStatus.ts index 119f51b..ca4591c 100644 --- a/src/api/sys/getSealStatus.ts +++ b/src/api/sys/getSealStatus.ts @@ -8,9 +8,7 @@ export type SealStatusType = { export async function getSealStatus(): Promise { const request = new Request(appendAPIURL("/v1/sys/seal-status")); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - return data; - }); + const resp = await fetch(request) + const data = await resp.json() as SealStatusType; + return data; } diff --git a/src/api/sys/lookupSelf.ts b/src/api/sys/lookupSelf.ts index 7891083..fad482c 100644 --- a/src/api/sys/lookupSelf.ts +++ b/src/api/sys/lookupSelf.ts @@ -1,17 +1,15 @@ -import { appendAPIURL, getHeaders } from "../apiUtils"; import { TokenInfo } from "../types/token"; +import { appendAPIURL, getHeaders } from "../apiUtils"; export async function lookupSelf(): Promise { const request = new Request(appendAPIURL("/v1/auth/token/lookup-self"), { headers: getHeaders(), }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - if ("data" in data) { - return data.data; - } else if ("errors" in data) { - throw new Error(data.errors[0]); - } - }); + const resp = await fetch(request); + const data = await resp.json() as { data?: TokenInfo; errors?: string[] }; + if ("data" in data) { + return data.data; + } else if ("errors" in data) { + throw new Error(data.errors[0]); + } } diff --git a/src/api/sys/renewSelf.ts b/src/api/sys/renewSelf.ts index b55784f..e8fb802 100644 --- a/src/api/sys/renewSelf.ts +++ b/src/api/sys/renewSelf.ts @@ -9,11 +9,9 @@ export async function renewSelf(): Promise { }, body: JSON.stringify({}) }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - if ("errors" in data) { - throw new Error(data.errors[0]); - } - }); + const resp = await fetch(request) + const data = await resp.json() as { errors?: string[] }; + if ("errors" in data) { + throw new Error(data.errors[0]); + } } diff --git a/src/api/sys/sealVault.ts b/src/api/sys/sealVault.ts index 264f439..0964c66 100644 --- a/src/api/sys/sealVault.ts +++ b/src/api/sys/sealVault.ts @@ -6,11 +6,9 @@ export async function sealVault(): Promise { method: 'PUT', headers: getHeaders(), }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - if ("errors" in data) { - throw new Error(data.errors[0]); - } - }); + const resp = await fetch(request) + const data = await resp.json() as { errors?: string[] }; + if ("errors" in data) { + throw new Error(data.errors[0]); + } } diff --git a/src/api/sys/submitUnsealKey.ts b/src/api/sys/submitUnsealKey.ts index cda94aa..dcd23b6 100644 --- a/src/api/sys/submitUnsealKey.ts +++ b/src/api/sys/submitUnsealKey.ts @@ -10,9 +10,11 @@ export async function submitUnsealKey(key: string): Promise { "key": key }) }); - const response = await fetch(request); - if (!response.ok) { - const json = await response.json(); - throw new Error(json.errors[0]); + const resp = await fetch(request) + if (!resp.ok) { + const data = await resp.json() as { errors?: string[] }; + if ("errors" in data) { + throw new Error(data.errors[0]); + } } } diff --git a/src/api/totp/addNewTOTP.ts b/src/api/totp/addNewTOTP.ts index 3f836c1..3c914a3 100644 --- a/src/api/totp/addNewTOTP.ts +++ b/src/api/totp/addNewTOTP.ts @@ -1,7 +1,6 @@ import { appendAPIURL, getHeaders } from "../apiUtils"; import { removeDoubleSlash } from "../../utils"; - export async function addNewTOTP(baseMount: string, parms: {name: string}): Promise { const request = new Request(appendAPIURL(removeDoubleSlash(`/v1/${baseMount}/keys/${parms.name}`)), { method: 'POST', @@ -11,9 +10,11 @@ export async function addNewTOTP(baseMount: string, parms: {name: string}): Prom }, body: JSON.stringify(parms) }); - const response = await fetch(request); - if (!response.ok) { - const json = await response.json(); - throw new Error(json.errors[0]); + const resp = await fetch(request) + if (!resp.ok) { + const data = await resp.json() as { errors?: string[] }; + if ("errors" in data) { + throw new Error(data.errors[0]); + } } } diff --git a/src/api/totp/getTOTPCode.ts b/src/api/totp/getTOTPCode.ts index 70eb660..2056a47 100644 --- a/src/api/totp/getTOTPCode.ts +++ b/src/api/totp/getTOTPCode.ts @@ -5,9 +5,7 @@ export async function getTOTPCode(baseMount: string, name: string): Promise { - return response.json(); - }).then(data => { - return data.data.code; - }); + const resp = await fetch(request) + const data = await resp.json() as {data: {code: string}}; + return data.data.code; } diff --git a/src/api/totp/getTOTPKeys.ts b/src/api/totp/getTOTPKeys.ts index 6b654cc..8b08144 100644 --- a/src/api/totp/getTOTPKeys.ts +++ b/src/api/totp/getTOTPKeys.ts @@ -1,17 +1,15 @@ import { DoesNotExistError } from "../../types/internalErrors"; import { appendAPIURL, getHeaders } from "../apiUtils"; - export async function getTOTPKeys(baseMount: string): Promise { const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), { headers: getHeaders(), }); - return fetch(request).then(response => { - if (response.status == 404) { - throw DoesNotExistError; - } - return response.json(); - }).then(data => { - return data.data.keys; - }); + + const resp = await fetch(request); + if (resp.status == 404) { + throw DoesNotExistError; + } + const data = await resp.json() as {data: {keys: string[] }}; + return data.data.keys; } diff --git a/src/api/transit/getTransitKey.ts b/src/api/transit/getTransitKey.ts index 470f268..7f0ce3a 100644 --- a/src/api/transit/getTransitKey.ts +++ b/src/api/transit/getTransitKey.ts @@ -1,17 +1,16 @@ import { DoesNotExistError } from "../../types/internalErrors"; -import { appendAPIURL, getHeaders } from "../apiUtils"; import { TransitKeyType } from "../types/transit"; +import { appendAPIURL, getHeaders } from "../apiUtils"; export async function getTransitKey(baseMount: string, name: string): Promise { const request = new Request(appendAPIURL(`/v1/${baseMount}/keys/${name}`), { headers: getHeaders(), }); - return fetch(request).then(response => { - if (response.status == 404) { - throw DoesNotExistError; - } - return response.json(); - }).then(data => { - return data.data; - }); + + const resp = await fetch(request); + if (resp.status == 404) { + throw DoesNotExistError; + } + const data = await resp.json() as { data: TransitKeyType }; + return data.data; } diff --git a/src/api/transit/getTransitKeys.ts b/src/api/transit/getTransitKeys.ts index 8bc8c2f..aa08cf3 100644 --- a/src/api/transit/getTransitKeys.ts +++ b/src/api/transit/getTransitKeys.ts @@ -5,12 +5,10 @@ export async function getTransitKeys(baseMount: string): Promise { const request = new Request(appendAPIURL(`/v1/${baseMount}/keys?list=true`), { headers: getHeaders(), }); - return fetch(request).then(response => { - if (response.status == 404) { - throw DoesNotExistError; - } - return response.json(); - }).then(data => { - return data.data.keys; - }); + const resp = await fetch(request); + if (resp.status == 404) { + throw DoesNotExistError; + } + const data = await resp.json() as { data: string[] }; + return data.data; } diff --git a/src/api/transit/transitDecrypt.ts b/src/api/transit/transitDecrypt.ts index 0ea48f8..6e42198 100644 --- a/src/api/transit/transitDecrypt.ts +++ b/src/api/transit/transitDecrypt.ts @@ -22,12 +22,12 @@ export async function transitDecrypt( }, body: JSON.stringify(payload) }); + const response = await fetch(request); + const data = await response.json() as { errors?: string[]; data?: DecryptionResult; }; if (!response.ok) { - const json = await response.json(); - throw new Error(json.errors[0]); + throw new Error(data.errors[0]); } else { - const json = await response.json(); - return json.data; + return data.data; } } diff --git a/src/api/transit/transitEncrypt.ts b/src/api/transit/transitEncrypt.ts index 82f9c17..2b97342 100644 --- a/src/api/transit/transitEncrypt.ts +++ b/src/api/transit/transitEncrypt.ts @@ -22,12 +22,12 @@ export async function transitEncrypt( }, body: JSON.stringify(payload) }); + const response = await fetch(request); + const data = await response.json() as { errors?: string[]; data?: EncryptionResult; }; if (!response.ok) { - const json = await response.json(); - throw new Error(json.errors[0]); + throw new Error(data.errors[0]); } else { - const json = await response.json(); - return json.data; + return data.data; } } diff --git a/src/api/transit/transitRewrap.ts b/src/api/transit/transitRewrap.ts index 5175578..da8662b 100644 --- a/src/api/transit/transitRewrap.ts +++ b/src/api/transit/transitRewrap.ts @@ -23,12 +23,12 @@ export async function transitRewrap( }, body: JSON.stringify(payload) }); + const response = await fetch(request); + const data = await response.json() as { errors?: string[]; data?: RewrapResult; }; if (!response.ok) { - const json = await response.json(); - throw new Error(json.errors[0]); + throw new Error(data.errors[0]); } else { - const json = await response.json(); - return json.data; + return data.data; } } diff --git a/src/api/types/token.ts b/src/api/types/token.ts index 2215496..8541a3a 100644 --- a/src/api/types/token.ts +++ b/src/api/types/token.ts @@ -9,11 +9,11 @@ export type TokenInfo = { id: string; identity_policies: string[]; issue_time: string; - meta: any; + meta: Record; num_uses: number; - orphan: Boolean; + orphan: boolean; path: string; policies: string[]; - renewable: Boolean; + renewable: boolean; ttl: number; } \ No newline at end of file diff --git a/src/api/types/transit.ts b/src/api/types/transit.ts index 6004787..05c9ea1 100644 --- a/src/api/types/transit.ts +++ b/src/api/types/transit.ts @@ -14,10 +14,10 @@ export const enum TransitKeyTypes { // Type when used to make new transit keys. export type TransitKeyBaseType = { name: string; - convergent_encryption: Boolean; - derived: Boolean; - exportable: Boolean; - allow_plaintext_backup: Boolean; + convergent_encryption: boolean; + derived: boolean; + exportable: boolean; + allow_plaintext_backup: boolean; type: keyof typeof TransitKeyTypes; } @@ -28,8 +28,8 @@ export type TransitKeyType = TransitKeyBaseType & { }; min_decryption_version: number; min_encryption_version: number; - supports_encryption: Boolean; - supports_decryption: Boolean; - supports_derivation: Boolean; - supports_signing: Boolean; + supports_encryption: boolean; + supports_decryption: boolean; + supports_derivation: boolean; + supports_signing: boolean; } \ No newline at end of file diff --git a/src/elements/CopyableInputBox.ts b/src/elements/CopyableInputBox.ts index 7acf92f..caf678a 100644 --- a/src/elements/CopyableInputBox.ts +++ b/src/elements/CopyableInputBox.ts @@ -10,7 +10,7 @@ export interface CopyableInputBoxType extends HTMLElement { export function CopyableInputBox(text: string, copyable = true): CopyableInputBoxType { const inputBoxDiv = (makeElement({ tag: "div" }) as CopyableInputBoxType); - let inputBoxCopyButton = null; + let inputBoxCopyButton: HTMLElement = null; if (copyable) { inputBoxCopyButton = makeElement({ tag: "a", @@ -30,8 +30,8 @@ export function CopyableInputBox(text: string, copyable = true): CopyableInputBo const inputBoxInput = makeElement({ tag: "input", class: ["uk-input", "uk-input-copyable"], - attributes: { "readonly": true, "type": "text" }, - }); + attributes: { "readonly": "true", "type": "text" }, + }) as HTMLInputElement; const inputBoxInner = MarginInline([ inputBoxCopyButton, @@ -40,7 +40,7 @@ export function CopyableInputBox(text: string, copyable = true): CopyableInputBo inputBoxDiv.appendChild(inputBoxInner); inputBoxDiv.setText = function (text) { - (inputBoxInput as HTMLInputElement).value = `${text}`; + inputBoxInput.value = `${text}`; if (copyable) { inputBoxCopyButton.dataset.clipboardText = `${text}`; } diff --git a/src/elements/CopyableModal.ts b/src/elements/CopyableModal.ts index ba86db6..fa5ec71 100644 --- a/src/elements/CopyableModal.ts +++ b/src/elements/CopyableModal.ts @@ -2,10 +2,19 @@ import { addClipboardNotifications } from "../pageUtils"; import { makeElement } from "../htmlUtils"; import ClipboardJS from "clipboard"; import FileSaver from 'file-saver'; +import UIkit from 'uikit/dist/js/uikit.min.js'; import i18next from 'i18next'; -export function CopyableModal(name: string, contentString: string): Element { - return makeElement({ +type FileSaverType = { + saveAs: (blob: Blob, name: string) => void; +} + +type ModalType = HTMLElement & { + show: () => void; +} + +export function CopyableModal(name: string, contentString: string): ModalType { + const modal = makeElement({ tag: "div", class: "modal-sections", attributes: { @@ -53,9 +62,9 @@ export function CopyableModal(name: string, contentString: string): Element { "data-clipboard-text": contentString }, text: i18next.t("copy_modal_download_btn"), - onclick: _ => { - const blob = new Blob([contentString], {type: "text/plain;charset=utf-8"}); - FileSaver.saveAs(blob, "result.txt"); + onclick: () => { + const blob = new Blob([contentString], { type: "text/plain;charset=utf-8" }); + (FileSaver as FileSaverType).saveAs(blob, "result.txt"); } }), 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; } diff --git a/src/elements/QRScanner.ts b/src/elements/QRScanner.ts index 5aeb269..87af665 100644 --- a/src/elements/QRScanner.ts +++ b/src/elements/QRScanner.ts @@ -35,7 +35,7 @@ export async function QRScanner(onScan: (code: string) => void): Promise { try { diff --git a/src/elements/Tile.ts b/src/elements/Tile.ts index b4425c0..842c3cb 100644 --- a/src/elements/Tile.ts +++ b/src/elements/Tile.ts @@ -1,7 +1,7 @@ import { makeElement } from "../htmlUtils"; type TileParams = { - condition: Boolean; + condition: boolean; title: string; description: string; icon: string; diff --git a/src/elements/renewSelf.ts b/src/elements/renewSelf.ts deleted file mode 100644 index 06751f4..0000000 --- a/src/elements/renewSelf.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { appendAPIURL, getHeaders } from "../api/apiUtils"; - -export async function renewSelf(): Promise { - const request = new Request(appendAPIURL("/v1/auth/token/renew-self"), { - method: 'POST', - headers: { - ...getHeaders(), - 'Content-Type': 'application/json' - }, - body: JSON.stringify({}) - }); - return fetch(request).then(response => { - return response.json(); - }).then(data => { - if ("errors" in data) { - throw new Error(data.errors[0]); - } - }); -} diff --git a/src/formatDistance.ts b/src/formatDistance.ts index 7dfb796..de787f4 100644 --- a/src/formatDistance.ts +++ b/src/formatDistance.ts @@ -2,7 +2,7 @@ import { de, enGB, fr, it, nl, ru } from 'date-fns/locale' import { formatDistance as formatDistanceReal} from 'date-fns'; import { pageState } from "./globalPageState"; -function getLocale(): any { +function getLocale(): Locale { return { "en": enGB, "fr": fr, diff --git a/src/htmlUtils.ts b/src/htmlUtils.ts index 1384d87..b149160 100644 --- a/src/htmlUtils.ts +++ b/src/htmlUtils.ts @@ -1,7 +1,7 @@ import { getObjectKeys } from "./utils"; type optionsFunctionsObject = { - [key: string]: (e: any, arg: any) => void + [key: string]: (e: Element, arg: unknown) => void } const optionsFunctions: optionsFunctionsObject = { @@ -13,9 +13,9 @@ const optionsFunctions: optionsFunctionsObject = { }, "id": (e: Element, arg: string) => e.id = 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, - "text": (e: HTMLParagraphElement, arg: string) => e.innerText = arg, + "text": (e: Element, arg: string) => (e as HTMLParagraphElement).innerText = arg, "children": (e: Element, arg: Element | Element[]) => { if (Array.isArray(arg)) { arg.forEach(child => { @@ -34,13 +34,12 @@ interface ElementInfo { class?: string | string[]; id?: string; html?: string; - attributes?: { - [propName: string]: any - }; + attributes?: Record; children?: Element | Element[]; text?: string; thenRun?: (e: Element) => void; - [propName: string]: any; + onclick?: () => void; + [propName: string]: unknown; } export function makeElement(elementInfo: ElementInfo): HTMLElement { @@ -49,14 +48,14 @@ export function makeElement(elementInfo: ElementInfo): HTMLElement { for (const key of Object.getOwnPropertyNames(elementInfo)) { if (getObjectKeys(optionsFunctions).includes(key)) { - (optionsFunctions as any)[key](element, elementInfo[key]); + optionsFunctions[key](element, elementInfo[key]); } } return element; } -export function setElementAttributes(element: Element, attributes: { [propName: string]: any }): void { +export function setElementAttributes(element: Element, attributes: Record): void { for (const key of Object.getOwnPropertyNames(attributes)) { element.setAttribute(key, attributes[key]); } diff --git a/src/main.ts b/src/main.ts index 7d0957b..c282e3d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,14 +2,16 @@ // JS & CSS +/* eslint-disable */ import "./scss/main.scss"; import Icons from 'uikit/dist/js/uikit-icons.min.js'; import UIkit from 'uikit/dist/js/uikit.min.js'; +// @ts-ignore UIkit.use(Icons); -/* eslint-disable */ import Prism from "prismjs"; import "prismjs/components/prism-json"; +// @ts-ignore Prism.highlightAll(); /* eslint-enable */ @@ -29,14 +31,19 @@ import i18next from 'i18next'; // @ts-ignore import translations from './translations/index.mjs' -function ListItem(children) { +function ListItem(children: Element[] | Element): HTMLElement { return makeElement({ tag: "li", children: children }); } -async function onLoad() { +declare global { + interface Window { pageContent: Element; } +} + + +function onLoad(): void { document.body.innerHTML = ""; document.body.appendChild(makeElement({ tag: "nav", @@ -52,17 +59,17 @@ async function onLoad() { ListItem(makeElement({ tag: "a", text: i18next.t("home_btn"), - onclick: _ => { changePage("HOME"); } + onclick: () => { changePage("HOME"); } })), ListItem(makeElement({ tag: "a", text: i18next.t("back_btn"), - onclick: _ => { (pageState.currentPage as Page).goBack(); } + onclick: () => { (pageState.currentPage as Page).goBack(); } })), ListItem(makeElement({ tag: "a", text: i18next.t("refresh_btn"), - onclick: _ => { changePage(pageState.currentPageString); } + onclick: () => { changePage(pageState.currentPageString); } })), ] }) @@ -77,7 +84,7 @@ async function onLoad() { ListItem(makeElement({ tag: "a", 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") { - await playground(); + playground(); } renderPage(); - setInterval(async () => { + setInterval(() => { if (pageState.currentPageString != "UNSEAL") { if (pageState.apiURL.length != 0) { return; } - const sealStatus = await getSealStatus(); - if (sealStatus.sealed) { - changePage("UNSEAL"); - return; - } + void getSealStatus().then((sealStatus) => { + if (sealStatus.sealed) { + changePage("UNSEAL"); + return; + } + }); } }, 5000); } -document.addEventListener('DOMContentLoaded', async function () { +document.addEventListener('DOMContentLoaded', function () { console.log("Loading..."); // @ts-expect-error console.log("Build Data:", BUILD_STRING); - i18next.init({ + void i18next.init({ lng: pageState.language, fallbackLng: 'en', debug: true, // @ts-ignore resources: Object.fromEntries(Object.entries(translations).map(([k, v]) => [k, { translation: v }])), 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)); - return value; + return value as string; } } - }).then(async function (_) { - await onLoad(); + }).then(function (_) { + onLoad(); }); }, false); diff --git a/src/pageUtils.ts b/src/pageUtils.ts index e390a5e..2a20b8d 100644 --- a/src/pageUtils.ts +++ b/src/pageUtils.ts @@ -46,13 +46,13 @@ export async function prePageChecks(): Promise { export function addClipboardNotifications(clipboard: ClipboardJS, timeout = 1000): void { 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', timeout: timeout }); }); 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 }), { status: 'danger', @@ -64,9 +64,9 @@ export function addClipboardNotifications(clipboard: ClipboardJS, timeout = 1000 export function setErrorText(text: string): void { const errorTextElement = document.querySelector("#errorText"); 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}`, status: 'danger', pos: 'top-center', @@ -87,13 +87,13 @@ export function changePage(page: string, shouldSwitch = true): void { export function renderPage(): void { document.documentElement.dir = pageState.pageDirection; 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); (pageState.currentPage as Page).render(); } export function setPageTitle(title: string | HTMLElement): void { - const pageTitle = (document.getElementById("pageTitle") as HTMLElement); + const pageTitle = (document.getElementById("pageTitle") ); pageTitle.innerHTML = ""; if (typeof title === "string") { pageTitle.innerText = title.toString(); @@ -154,7 +154,7 @@ export function setTitleElement(pageState: PageState): void { } export function setPageContent(content: string | HTMLElement): void { - const pageContent = (document.getElementById("pageContent") as HTMLElement); + const pageContent = (document.getElementById("pageContent") ); if (typeof content === "string") { pageContent.innerHTML = content; } else { diff --git a/src/pages/Home.ts b/src/pages/Home.ts index f6c009f..dbdda78 100644 --- a/src/pages/Home.ts +++ b/src/pages/Home.ts @@ -1,6 +1,6 @@ +import { MountType, getMounts } from "../api/sys/getMounts"; import { Page } from "../types/Page"; import { changePage, prePageChecks, setErrorText, setPageContent } from "../pageUtils"; -import { getMounts } from "../api/sys/getMounts"; import { lookupSelf } from "../api/sys/lookupSelf"; import { makeElement } from "../htmlUtils"; import { pageState } from "../globalPageState"; @@ -48,9 +48,10 @@ export class HomePage extends Page { tag: "li", text: i18next.t("your_token_expires_in", {"date": new Date(selfTokenInfo.expire_time)}) })); - } catch (e) { - setErrorText(e.message); - if (e.message == "permission denied") { + } catch (e: unknown) { + const error = e as Error; + setErrorText(error.message); + if (error.message == "permission denied") { pageState.token = ""; changePage("LOGIN"); } @@ -68,7 +69,7 @@ export class HomePage extends Page { // sort it by secretPath so it's in alphabetical order consistantly. const mountsMap = sortedObjectMap(mounts); - mountsMap.forEach(function (mount, baseMount) { + mountsMap.forEach(function (mount: MountType, baseMount) { if (typeof mount != 'object') return; if (mount == null) return; if (!("type" in mount)) return; @@ -97,7 +98,7 @@ export class HomePage extends Page { children: makeElement({ tag: "a", text: linkText, - onclick: _ => { + onclick: () => { pageState.currentBaseMount = baseMount; pageState.currentMountType = mountType; changePage(linkPage); diff --git a/src/pages/KeyValue/KeyValueDelete.ts b/src/pages/KeyValue/KeyValueDelete.ts index f198b84..3d26fa6 100644 --- a/src/pages/KeyValue/KeyValueDelete.ts +++ b/src/pages/KeyValue/KeyValueDelete.ts @@ -31,8 +31,8 @@ export class KeyValueDeletePage extends Page { tag: "button", class: ["uk-button", "uk-button-danger"], text: i18next.t("kv_delete_btn"), - onclick: _ => { - deleteSecret( + onclick: () => { + void deleteSecret( pageState.currentBaseMount, pageState.currentMountType, pageState.currentSecretPath, diff --git a/src/pages/KeyValue/KeyValueNew.ts b/src/pages/KeyValue/KeyValueNew.ts index 75ebcbb..7d72f7b 100644 --- a/src/pages/KeyValue/KeyValueNew.ts +++ b/src/pages/KeyValue/KeyValueNew.ts @@ -29,7 +29,7 @@ export class KeyValueNewPage extends Page { tag: "input", class: ["uk-input", "uk-form-width-medium"], attributes: { - required: true, + required: "true", type: "text", placeholder: i18next.t("kv_new_path"), name: "path" @@ -53,9 +53,9 @@ export class KeyValueNewPage extends Page { }) as HTMLFormElement; setPageContent(this.addKVNewForm); - this.addKVNewForm.addEventListener("submit", function (e) { + this.addKVNewForm.addEventListener("submit", function (e: Event) { e.preventDefault(); - this.newKVSecretHandleForm(); + (this as KeyValueNewPage).newKVSecretHandleForm(); }.bind(this)); } @@ -77,7 +77,7 @@ export class KeyValueNewPage extends Page { ).then(_ => { changePage("KEY_VALUE_VIEW"); return; - }).catch(e => { + }).catch((e: Error) => { setErrorText(e.message); }); } diff --git a/src/pages/KeyValue/KeyValueSecret.ts b/src/pages/KeyValue/KeyValueSecret.ts index a7c5197..37004b4 100644 --- a/src/pages/KeyValue/KeyValueSecret.ts +++ b/src/pages/KeyValue/KeyValueSecret.ts @@ -66,7 +66,7 @@ export class KeyValueSecretPage extends Page { tag: "button", id: "deleteButton", class: ["uk-button", "uk-button-danger"], - onclick: _ => { changePage("KEY_VALUE_DELETE"); }, + onclick: () => { changePage("KEY_VALUE_DELETE"); }, text: deleteButtonText })); } @@ -76,7 +76,7 @@ export class KeyValueSecretPage extends Page { tag: "button", id: "editButton", 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") })); } @@ -86,12 +86,12 @@ export class KeyValueSecretPage extends Page { tag: "button", id: "versionsButton", class: ["uk-button", "uk-button-secondary"], - onclick: _ => { changePage("KEY_VALUE_VERSIONS"); }, + onclick: () => { changePage("KEY_VALUE_VERSIONS"); }, text: i18next.t("kv_secret_versions_btn") })); } - getSecret( + void getSecret( pageState.currentBaseMount, pageState.currentMountType, pageState.currentSecretPath, @@ -113,7 +113,7 @@ export class KeyValueSecretPage extends Page { id: "restoreButton", class: ["uk-button", "uk-button-primary"], onclick: () => { - undeleteSecret( + void undeleteSecret( pageState.currentBaseMount, pageState.currentSecretPath, pageState.currentSecret, @@ -133,14 +133,18 @@ export class KeyValueSecretPage extends Page { } if (isSecretNestedJson) { - const jsonText = JSON.stringify(sortedObjectMap(secretsMap as Record), null, 4); + const jsonText = JSON.stringify( + sortedObjectMap(secretsMap as unknown as Record), + null, + 4 + ); kvList.appendChild(makeElement({ tag: "pre", 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 { - secretsMap.forEach((value, key) => { + secretsMap.forEach((value: string, key: string) => { const kvListElement = this.makeKVListElement(key, value); kvList.appendChild(kvListElement); }, this); diff --git a/src/pages/KeyValue/KeyValueSecretsEdit.ts b/src/pages/KeyValue/KeyValueSecretsEdit.ts index b4bb3f5..95798c5 100644 --- a/src/pages/KeyValue/KeyValueSecretsEdit.ts +++ b/src/pages/KeyValue/KeyValueSecretsEdit.ts @@ -43,7 +43,7 @@ export class KeyValueSecretEditPage extends Page { saveButton ] })); - getSecret( + void getSecret( pageState.currentBaseMount, pageState.currentMountType, pageState.currentSecretPath, @@ -70,7 +70,7 @@ export class KeyValueSecretEditPage extends Page { ).then(_ => { changePage("KEY_VALUE_SECRET"); return; - }).catch(e => { + }).catch((e: Error) => { setErrorText(e.message); }); }; diff --git a/src/pages/KeyValue/KeyValueVersions.ts b/src/pages/KeyValue/KeyValueVersions.ts index 1209ce2..627b83e 100644 --- a/src/pages/KeyValue/KeyValueVersions.ts +++ b/src/pages/KeyValue/KeyValueVersions.ts @@ -39,7 +39,7 @@ export class KeyValueVersionsPage extends Page { children: makeElement({ tag: "a", text: `v${ver}`, - onclick: _ => { + onclick: () => { pageState.currentSecretVersion = ver; changePage("KEY_VALUE_SECRET"); } diff --git a/src/pages/KeyValue/KeyValueView.ts b/src/pages/KeyValue/KeyValueView.ts index 96b634b..10892da 100644 --- a/src/pages/KeyValue/KeyValueView.ts +++ b/src/pages/KeyValue/KeyValueView.ts @@ -61,7 +61,7 @@ export class KeyValueViewPage extends Page { children: makeElement({ tag: "a", text: secret, - onclick: _ => { + onclick: () => { if (secret.endsWith("/")) { pageState.pushCurrentSecretPath(secret); changePage("KEY_VALUE_VIEW"); @@ -75,8 +75,9 @@ export class KeyValueViewPage extends Page { }) ] })); - } catch (e) { - if (e == DoesNotExistError) { + } catch (e: unknown) { + const error = e as Error; + if (error == DoesNotExistError) { // getSecrets also 404's on no keys so dont go all the way back. if (pageState.currentSecretPath.length != 0) { return this.goBack(); @@ -87,7 +88,7 @@ export class KeyValueViewPage extends Page { })); } } else { - setErrorText(e.message); + setErrorText(error.message); } } } diff --git a/src/pages/Login.ts b/src/pages/Login.ts index 46c57fe..8451e96 100644 --- a/src/pages/Login.ts +++ b/src/pages/Login.ts @@ -20,7 +20,7 @@ export class LoginPage extends Page { tag: "input", class: ["uk-input", "uk-form-width-medium"], attributes: { - required: true, + required: "true", type: "password", placeholder: i18next.t("token_input"), name: "token" @@ -45,7 +45,7 @@ export class LoginPage extends Page { id: "usernameInput", class: ["uk-input", "uk-form-width-medium"], attributes: { - required: true, + required: "true", type: "text", placeholder: i18next.t("username_input"), name: "username" @@ -56,7 +56,7 @@ export class LoginPage extends Page { id: "passwordInput", class: ["uk-input", "uk-form-width-medium"], attributes: { - required: true, + required: "true", type: "password", placeholder: i18next.t("password_input"), name: "password" @@ -127,7 +127,7 @@ export class LoginPage extends Page { pageState.token = token as string; lookupSelf().then(_ => { changePage("HOME"); - }).catch(e => { + }).catch((e: Error) => { document.getElementById("tokenInput").classList.add("uk-form-danger"); if (e.message == "permission denied") { setErrorText(i18next.t("token_login_error")); @@ -145,7 +145,7 @@ export class LoginPage extends Page { ).then(res => { pageState.token = res; changePage("HOME"); - }).catch(e => { + }).catch((e: Error) => { document.getElementById("usernameInput").classList.add("uk-form-danger"); document.getElementById("passwordInput").classList.add("uk-form-danger"); setErrorText(e.message); diff --git a/src/pages/Me.ts b/src/pages/Me.ts index fd525eb..a5fc400 100644 --- a/src/pages/Me.ts +++ b/src/pages/Me.ts @@ -53,7 +53,7 @@ export class MePage extends Page { onclick: () => { renewSelf().then(() => { changePage("HOME"); - }).catch(e => { + }).catch((e: Error) => { setErrorText(e.message); }); } diff --git a/src/pages/PwGen.ts b/src/pages/PwGen.ts index f0c72c3..46158fc 100644 --- a/src/pages/PwGen.ts +++ b/src/pages/PwGen.ts @@ -1,10 +1,10 @@ import { CopyableInputBox, CopyableInputBoxType } from "../elements/CopyableInputBox"; import { Margin } from "../elements/Margin"; +import { Option } from "../elements/Option"; import { Page } from "../types/Page"; import { makeElement } from "../htmlUtils"; import { setPageContent } from "../pageUtils"; import i18next from 'i18next'; -import { Option } from "../elements/Option"; const passwordLengthMin = 1; const passwordLengthMax = 64; @@ -55,7 +55,7 @@ export class PwGenPage extends Page { passwordAlphabet: HTMLSelectElement; passwordForm: HTMLFormElement; - async render(): Promise { + render(): void { setPageContent(""); this.passwordBox = CopyableInputBox(genPassword(passwordOptionsDefault)) ; @@ -70,9 +70,9 @@ export class PwGenPage extends Page { class: ["uk-range", "uk-width-1-2"], attributes: { type: "range", - value: passwordLengthDefault, - max: passwordLengthMax, - min: passwordLengthMin, + value: passwordLengthDefault.toString(), + max: passwordLengthMax.toString(), + min: passwordLengthMin.toString(), }, }) as HTMLInputElement; @@ -124,7 +124,7 @@ export class PwGenPage extends Page { this.passwordLengthTitle.innerText = this.getPasswordLengthText(); this.passwordBox.setText(genPassword({ length: (this.passwordLengthRange.value as unknown) as number, - alphabet: this.passwordAlphabet.value as string, + alphabet: this.passwordAlphabet.value , })); } diff --git a/src/pages/SetLanguage.ts b/src/pages/SetLanguage.ts index 00c5cde..8f7084e 100644 --- a/src/pages/SetLanguage.ts +++ b/src/pages/SetLanguage.ts @@ -55,7 +55,7 @@ export class SetLanguagePage extends Page { const language = formData.get("language") as string; pageState.language = language; console.log(pageState.language); - i18next.changeLanguage(language).then((t) => { + void i18next.changeLanguage(language).then((t) => { changePage("HOME", false); pageState.pageDirection = t("language_direction"); location.reload(); diff --git a/src/pages/SetVaultURL.ts b/src/pages/SetVaultURL.ts index 1ab06b3..586fa4c 100644 --- a/src/pages/SetVaultURL.ts +++ b/src/pages/SetVaultURL.ts @@ -19,7 +19,7 @@ export class SetVaultURLPage extends Page { tag: "input", class: ["uk-input", "uk-form-width-medium"], attributes: { - required: true, + required: "true", type: "text", placeholder: "Vault URL", name: "vaultURL" diff --git a/src/pages/TOTP/NewTOTP.ts b/src/pages/TOTP/NewTOTP.ts index ec55b13..dbf8158 100644 --- a/src/pages/TOTP/NewTOTP.ts +++ b/src/pages/TOTP/NewTOTP.ts @@ -33,7 +33,7 @@ export class NewTOTPPage extends Page { tag: "input", class: ["uk-input", "uk-form-width-medium"], attributes: { - required: true, + required: "true", type: "text", placeholder: i18next.t("totp_new_name_text"), name: "name" @@ -89,7 +89,7 @@ export class NewTOTPPage extends Page { }; addNewTOTP(pageState.currentBaseMount, parms).then(_ => { changePage("TOTP"); - }).catch(e => { + }).catch((e: Error) => { setErrorText(`API Error: ${e.message}`); }); }); diff --git a/src/pages/TOTP/TOTPView.ts b/src/pages/TOTP/TOTPView.ts index ebdc226..e5a25bf 100644 --- a/src/pages/TOTP/TOTPView.ts +++ b/src/pages/TOTP/TOTPView.ts @@ -24,7 +24,7 @@ export class TOTPViewPage extends Page { refresher: number; totpListElements: Record; - async render(): Promise { + render(): void { setTitleElement(pageState); const totpList = makeElement({ tag: "div" }); setPageContent(makeElement({ @@ -33,7 +33,7 @@ export class TOTPViewPage extends Page { makeElement({ tag: "a", text: i18next.t("totp_view_new_btn"), - onclick: _ => { changePage("NEW_TOTP"); } + onclick: () => { changePage("NEW_TOTP"); } }), makeElement({ tag: "p", @@ -48,14 +48,14 @@ export class TOTPViewPage extends Page { getTOTPKeys(pageState.currentBaseMount).then(res => { - res.forEach(async function (totpKeyName) { - const totpListElement = this.makeTOTPListElement(totpKeyName); + res.forEach(function (totpKeyName) { + const totpListElement = (this as TOTPViewPage).makeTOTPListElement(totpKeyName); totpList.appendChild(totpListElement); - this.totpListElements[totpKeyName] = totpListElement; - await this.updateTOTPElement(totpKeyName, totpListElement); + (this as TOTPViewPage).totpListElements[totpKeyName] = totpListElement; + void (this as TOTPViewPage).updateTOTPElement(totpKeyName, totpListElement); }, this); document.getElementById("loadingText").remove(); - }).catch(e => { + }).catch((e: Error) => { if (e == DoesNotExistError) { const loadingText = document.getElementById("loadingText"); loadingText.innerText = i18next.t("totp_view_empty"); @@ -64,12 +64,12 @@ export class TOTPViewPage extends Page { } }); - const totpRefresher = async () => { - await Promise.all(Array.from(objectToMap(this.totpListElements)).map((kv) => { + const totpRefresher = () => { + void Promise.all(Array.from(objectToMap(this.totpListElements)).map((kv: [string, TOTPListElement]) => { return this.updateTOTPElement(...kv); })) } - await totpRefresher(); + void totpRefresher(); this.refresher = setInterval(totpRefresher, 3000) as unknown as number; } @@ -92,7 +92,7 @@ export class TOTPViewPage extends Page { children: [totpKeyBox, totpValueBox] }) as TOTPListElement; - gridElement.setCode = totpValueBox.setText; + gridElement.setCode = (code: string) => totpValueBox.setText(code); return gridElement; } diff --git a/src/pages/Transit/TransitDecrypt.ts b/src/pages/Transit/TransitDecrypt.ts index f5e9313..1a4d559 100644 --- a/src/pages/Transit/TransitDecrypt.ts +++ b/src/pages/Transit/TransitDecrypt.ts @@ -6,7 +6,6 @@ import { changePage, setErrorText, setPageContent, setTitleElement } from "../.. import { fileToBase64, makeElement } from "../../htmlUtils"; import { pageState } from "../../globalPageState"; import { transitDecrypt } from "../../api/transit/transitDecrypt"; -import UIkit from 'uikit/dist/js/uikit.min.js'; import i18next from "i18next"; export class TransitDecryptPage extends Page { @@ -20,7 +19,7 @@ export class TransitDecryptPage extends Page { transitDecryptForm: HTMLFormElement; - async render(): Promise { + render(): void { setTitleElement(pageState); setPageContent(makeElement({ tag: "div" @@ -74,7 +73,7 @@ export class TransitDecryptPage extends Page { setPageContent(this.transitDecryptForm); this.transitDecryptForm.addEventListener("submit", async function (e: Event) { e.preventDefault(); - await this.transitDecryptFormHandler(); + await (this as TransitDecryptPage).transitDecryptFormHandler(); }.bind(this)); } @@ -87,11 +86,11 @@ export class TransitDecryptPage extends Page { const ciphertext_file = formData.get("ciphertext_file") as File; 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 { - let res = await transitDecrypt( + const res = await transitDecrypt( pageState.currentBaseMount, pageState.currentSecret, { ciphertext: ciphertext }, @@ -102,9 +101,10 @@ export class TransitDecryptPage extends Page { } const modal = CopyableModal(i18next.t("transit_decrypt_decryption_result_modal_title"), plaintext); document.body.querySelector("#pageContent").appendChild(modal); - UIkit.modal(modal).show(); - } catch (e) { - setErrorText(`API Error: ${e.message}`); + modal.show(); + } catch (e: unknown) { + const error = e as Error; + setErrorText(`API Error: ${error.message}`); } } diff --git a/src/pages/Transit/TransitEncrypt.ts b/src/pages/Transit/TransitEncrypt.ts index 2ba028e..2684161 100644 --- a/src/pages/Transit/TransitEncrypt.ts +++ b/src/pages/Transit/TransitEncrypt.ts @@ -6,7 +6,6 @@ import { changePage, setErrorText, setPageContent, setTitleElement } from "../.. import { fileToBase64, makeElement } from "../../htmlUtils"; import { pageState } from "../../globalPageState"; import { transitEncrypt } from "../../api/transit/transitEncrypt"; -import UIkit from 'uikit/dist/js/uikit.min.js'; import i18next from "i18next"; @@ -22,7 +21,7 @@ export class TransitEncryptPage extends Page { transitEncryptForm: HTMLFormElement; - async render(): Promise { + render(): void { setTitleElement(pageState); setPageContent(makeElement({ tag: "div" @@ -75,9 +74,9 @@ export class TransitEncryptPage extends Page { }) as HTMLFormElement; setPageContent(this.transitEncryptForm); - this.transitEncryptForm.addEventListener("submit", async function (e) { + this.transitEncryptForm.addEventListener("submit", async function (e: Event) { e.preventDefault(); - await this.transitEncryptFormHandler(); + await (this as TransitEncryptPage).transitEncryptFormHandler(); }.bind(this)); } @@ -90,23 +89,24 @@ export class TransitEncryptPage extends Page { const plaintext_file = formData.get("plaintext_file") as File; 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; } else { plaintext = base64Checkbox == "on" ? plaintext : btoa(plaintext); } try { - let res = await transitEncrypt( + const res = await transitEncrypt( pageState.currentBaseMount, pageState.currentSecret, { plaintext: plaintext } ); const modal = CopyableModal(i18next.t("transit_encrypt_encryption_result_modal_title"), res.ciphertext); document.body.querySelector("#pageContent").appendChild(modal); - UIkit.modal(modal).show(); - } catch (e) { - setErrorText(`API Error: ${e.message}`); + modal.show(); + } catch (e: unknown) { + const error = e as Error; + setErrorText(`API Error: ${error.message}`); } } diff --git a/src/pages/Transit/TransitRewrap.ts b/src/pages/Transit/TransitRewrap.ts index 19fa709..aa53edc 100644 --- a/src/pages/Transit/TransitRewrap.ts +++ b/src/pages/Transit/TransitRewrap.ts @@ -1,16 +1,14 @@ import { CopyableModal } from "../../elements/CopyableModal"; -import { FileUploadInput } from "../../elements/FileUploadInput"; import { Margin } from "../../elements/Margin"; +import { Option } from "../../elements/Option"; import { Page } from "../../types/Page"; 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 { makeElement } from "../../htmlUtils"; import { objectToMap } from "../../utils"; -import { Option } from "../../elements/Option"; +import { pageState } from "../../globalPageState"; import { transitRewrap } from "../../api/transit/transitRewrap"; +import i18next from "i18next"; type versionOption = { version: string; label: string } @@ -27,17 +25,17 @@ export class TransitRewrapPage extends Page { async render(): Promise { 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[]; - let versions = stringVersions.map((val) => parseInt(val, 10)) as any as number[]; + const stringVersions = Array.from(objectToMap(transitKey.keys).keys()).reverse() as unknown as string[]; + const versions = stringVersions.map((val): number => parseInt(val, 10)); // get the selectable version options in the same // format the official UI uses. // e.g: ["2 (latest)", "1"] - let options: versionOption[] = versions.map((val): versionOption => { - let i18nkey = val == Math.max(...versions) ? + const options: versionOption[] = versions.map((val): versionOption => { + const i18nkey = val == Math.max(...versions) ? "transit_rewrap_latest_version_option_text" : "transit_rewrap_version_option_text"; @@ -83,15 +81,14 @@ export class TransitRewrapPage extends Page { setPageContent(this.transitRewrapForm); this.transitRewrapForm.addEventListener("submit", async function (e: Event) { e.preventDefault(); - await this.transitRewrapFormHandler(); + await (this as TransitRewrapPage).transitRewrapFormHandler(); }.bind(this)); } async transitRewrapFormHandler(): Promise { const formData = new FormData(this.transitRewrapForm); - const ciphertext = formData.get("ciphertext") as string; try { - let res = await transitRewrap( + const res = await transitRewrap( pageState.currentBaseMount, pageState.currentSecret, { @@ -101,9 +98,10 @@ export class TransitRewrapPage extends Page { ); const modal = CopyableModal(i18next.t("transit_rewrap_result_modal_title"), res.ciphertext); document.body.querySelector("#pageContent").appendChild(modal); - UIkit.modal(modal).show(); - } catch (e) { - setErrorText(`API Error: ${e.message}`); + modal.show(); + } catch (e: unknown) { + const error = e as Error; + setErrorText(`API Error: ${error.message}`); } } diff --git a/src/pages/Transit/TransitView.ts b/src/pages/Transit/TransitView.ts index c2da5cb..2d8da32 100644 --- a/src/pages/Transit/TransitView.ts +++ b/src/pages/Transit/TransitView.ts @@ -46,7 +46,7 @@ export class TransitViewPage extends Page { children: makeElement({ tag: "a", text: secret, - onclick: _ => { + onclick: () => { pageState.currentSecret = secret; changePage("TRANSIT_VIEW_SECRET"); } @@ -55,14 +55,15 @@ export class TransitViewPage extends Page { }) ] })); - } catch (e) { - if (e == DoesNotExistError) { + } catch (e: unknown) { + const error = e as Error; + if (error == DoesNotExistError) { transitViewContent.appendChild(makeElement({ tag: "p", text: i18next.t("transit_view_none_here_text") })); } else { - setErrorText(e.message); + setErrorText(error.message); } } } diff --git a/src/pages/Transit/TransitViewSecret.ts b/src/pages/Transit/TransitViewSecret.ts index 60498f6..17369af 100644 --- a/src/pages/Transit/TransitViewSecret.ts +++ b/src/pages/Transit/TransitViewSecret.ts @@ -1,10 +1,10 @@ import { Page } from "../../types/Page"; +import { Tile } from "../../elements/Tile"; import { changePage, setPageContent, setTitleElement } from "../../pageUtils"; +import { getTransitKey } from "../../api/transit/getTransitKey"; import { makeElement } from "../../htmlUtils"; import { pageState } from "../../globalPageState"; import i18next from 'i18next'; -import { getTransitKey } from "../../api/transit/getTransitKey"; -import { Tile } from "../../elements/Tile"; export class TransitViewSecretPage extends Page { constructor() { @@ -18,7 +18,7 @@ export class TransitViewSecretPage extends Page { async render(): Promise { setTitleElement(pageState); - let transitKey = await getTransitKey(pageState.currentBaseMount, pageState.currentSecret); + const transitKey = await getTransitKey(pageState.currentBaseMount, pageState.currentSecret); setPageContent(makeElement({ tag: "div", diff --git a/src/pages/Unseal.ts b/src/pages/Unseal.ts index b7351e3..2c85380 100644 --- a/src/pages/Unseal.ts +++ b/src/pages/Unseal.ts @@ -41,9 +41,16 @@ export class UnsealPage extends Page { } makeRefresher(): void { - this.refresher = setInterval(async function () { - this.updateSealProgress(await getSealStatus()); - }.bind(this), 1000) as unknown as number; + const id = setInterval(() => { + void (this as UnsealPage).doRefresh().then(() => {}); + return; + }, 1000); + this.refresher = id as unknown as number; + } + + async doRefresh(): Promise { + const status = await getSealStatus(); + this.updateSealProgress(status); } async render(): Promise { @@ -58,7 +65,7 @@ export class UnsealPage extends Page { }) as HTMLParagraphElement; this.unsealInputContent = makeElement({ tag: "div" - }) as HTMLElement; + }); setPageContent(makeElement({ tag: "div", children: [ @@ -103,7 +110,7 @@ export class UnsealPage extends Page { this.deinitWebcam(); this.unsealInputContent.querySelectorAll('*').forEach(n => n.remove()) 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); } @@ -115,7 +122,7 @@ export class UnsealPage extends Page { tag: "input", class: ["uk-input", "uk-form-width-medium"], attributes: { - required: true, + required: "true", type: "password", placeholder: i18next.t("key_input_placeholder"), name: "key" @@ -129,15 +136,15 @@ export class UnsealPage extends Page { ] }) as HTMLFormElement; this.unsealInputContent.appendChild(this.unsealKeyForm); - this.unsealKeyForm.addEventListener("submit", function (e) { + this.unsealKeyForm.addEventListener("submit", function (e: Event) { e.preventDefault(); - this.handleKeySubmit(); + void (this as UnsealPage).handleKeySubmit(); }.bind(this)); } async makeQRInput(): Promise { this.qrScanner = await QRScanner(function (code: string) { - this.submitKey(code); + (this as UnsealPage).submitKey(code); console.log('decoded qr code:', code) }.bind(this)); this.unsealInputContent.appendChild(this.qrScanner); @@ -162,15 +169,15 @@ export class UnsealPage extends Page { submitKey(key: string): void { submitUnsealKey(key).then(_ => { - getSealStatus().then(data => { - this.updateSealProgress(data); + void getSealStatus().then(data => { + void this.updateSealProgress(data); }); - }).catch(e => { + }).catch((e: Error) => { setErrorText(e.message); }); } - async handleKeySubmit(): Promise { + handleKeySubmit(): void { const formData = new FormData(this.unsealKeyForm); this.submitKey(formData.get("key") as string) diff --git a/src/playground.ts b/src/playground.ts index ee43e7a..c66cc3b 100644 --- a/src/playground.ts +++ b/src/playground.ts @@ -1,3 +1,4 @@ +import { PageState } from "./PageState"; import { pageState } from "./globalPageState"; import i18next from 'i18next'; @@ -6,9 +7,13 @@ import i18next from 'i18next'; // before rendering. // Also it only runs when process.env.NODE_ENV == "development" -// Please empty this function before committing. -export async function playground(): Promise { - console.log("Welcome to Playground!"); - (window as any).pageState = pageState; - (window as any).i18next = i18next; +declare global { + interface Window { pageState: PageState; i18next: unknown; } +} + +// Please empty this function before committing. +export function playground(): void { + console.log("Welcome to Playground!"); + window.pageState = pageState; + window.i18next = i18next; } diff --git a/src/types/Page.ts b/src/types/Page.ts index 2e60583..b7be66e 100644 --- a/src/types/Page.ts +++ b/src/types/Page.ts @@ -4,8 +4,9 @@ export class Page { constructor() { // Do Nothing } - render(): any { + render(): unknown { // Do Nothing + return null; } get name(): string { return "Page"; diff --git a/src/utils.ts b/src/utils.ts index 4fda6c1..f5b5845 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -5,13 +5,13 @@ export function removeDoubleSlash(str: string): string { export const getObjectKeys = (obj: Record): string[] => Object.getOwnPropertyNames(obj); export const objectToMap = - (obj: Record): Map => new Map(Object.entries(obj)); + (obj: Record): Map => new Map(Object.entries(obj)); export const sortedObjectMap = - (obj: Record): Map => new Map(Object.entries(obj).sort()); + (obj: Record): Map => new Map(Object.entries(obj).sort()); export function getKeyByObjectPropertyValue(map: Record, searchValue: unknown): string { for (const key of getObjectKeys(map)) { - if ((map as any)[key] === searchValue) + if (map[key] === searchValue) return key; } }