1
0
Fork 0
VaultUI/src/pages/Unseal.ts

195 lines
5.3 KiB
TypeScript
Raw Normal View History

import { MarginInline } from "../elements/MarginInline";
2021-05-07 23:33:58 +01:00
import { Page } from "../types/Page";
2021-05-08 02:09:08 +01:00
import { QRScanner, QRScannerType } from "../elements/QRScanner";
2021-05-09 11:18:18 +01:00
import { SealStatusType, getSealStatus } from "../api/sys/getSealStatus";
2021-05-07 23:21:38 +01:00
import { changePage, setErrorText, setPageContent } from "../pageUtils";
import { makeElement } from "../htmlUtils";
2021-05-09 11:18:18 +01:00
import { submitUnsealKey } from "../api/sys/submitUnsealKey";
import i18next from "i18next";
const UnsealInputModes = {
FORM_INPUT: "FORM_INPUT",
QR_INPUT: "QR_INPUT",
};
2021-04-15 13:01:58 +01:00
export class UnsealPage extends Page {
constructor() {
super();
this.mode = UnsealInputModes.FORM_INPUT;
}
2021-05-08 02:09:08 +01:00
mode: string;
refresher: number;
qrScanner: QRScannerType;
unsealProgress: HTMLProgressElement;
unsealProgressText: HTMLParagraphElement;
unsealInputContent: HTMLElement;
unsealKeyForm: HTMLFormElement;
2021-05-12 17:37:09 +01:00
async cleanup(): Promise<void> {
2021-05-08 02:09:08 +01:00
this.deinitWebcam();
clearInterval(this.refresher);
}
2021-05-08 02:09:08 +01:00
deinitWebcam(): void {
try {
2021-04-29 12:52:00 +01:00
this.qrScanner.deinit();
2021-04-24 16:26:31 +01:00
} catch (_) {
2021-05-07 23:08:02 +01:00
// Do Nothing
}
2021-04-15 13:01:58 +01:00
}
2021-05-08 02:09:08 +01:00
makeRefresher(): void {
2021-05-10 11:35:14 +01:00
const id = setInterval(() => {
void (this as UnsealPage).doRefresh().then(() => {});
return;
}, 1000);
this.refresher = id as unknown as number;
}
async doRefresh(): Promise<void> {
const status = await getSealStatus();
2021-05-12 18:26:32 +01:00
await this.updateSealProgress(status);
}
2021-05-08 02:09:08 +01:00
async render(): Promise<void> {
this.unsealProgress = makeElement({
tag: "progress",
class: "uk-progress",
attributes: { value: "0", max: "0" },
2021-05-08 02:09:08 +01:00
}) as HTMLProgressElement;
this.unsealProgressText = makeElement({
tag: "p",
text: i18next.t("unseal_keys_progress", {
progress: "0",
keys_needed: "0",
}),
2021-05-08 02:09:08 +01:00
}) as HTMLParagraphElement;
this.unsealInputContent = makeElement({
tag: "div",
});
setPageContent(
makeElement({
tag: "div",
children: [
this.unsealProgress,
makeElement({
tag: "p",
id: "errorText",
class: ["uk-text-danger", "uk-margin-top"],
}),
this.unsealProgressText,
this.unsealInputContent,
],
}),
);
this.switchInputMode(this.mode);
2021-05-12 18:26:32 +01:00
await this.updateSealProgress(await getSealStatus());
this.makeRefresher();
}
2021-05-08 02:09:08 +01:00
setButtons(method: string): void {
const newMethod: string =
method == UnsealInputModes.FORM_INPUT
? UnsealInputModes.QR_INPUT
: UnsealInputModes.FORM_INPUT;
2021-05-08 02:09:08 +01:00
const buttonText: string =
newMethod == UnsealInputModes.FORM_INPUT
? i18next.t("unseal_input_btn")
: i18next.t("unseal_qr_btn");
this.unsealInputContent.appendChild(
makeElement({
tag: "button",
class: ["uk-button", "uk-button-primary"],
text: buttonText,
onclick: () => {
this.switchInputMode(newMethod);
},
}),
);
}
2021-05-08 02:09:08 +01:00
switchInputMode(method: string): void {
this.deinitWebcam();
this.unsealInputContent.querySelectorAll("*").forEach((n) => n.remove());
if (method == UnsealInputModes.FORM_INPUT) this.makeUnsealForm();
2021-05-10 11:35:14 +01:00
if (method == UnsealInputModes.QR_INPUT) void this.makeQRInput();
this.setButtons(method);
}
2021-05-08 02:09:08 +01:00
makeUnsealForm(): void {
2021-04-15 13:01:58 +01:00
this.unsealKeyForm = makeElement({
tag: "form",
children: [
MarginInline(
makeElement({
tag: "input",
class: ["uk-input", "uk-form-width-medium"],
attributes: {
required: "true",
type: "password",
placeholder: i18next.t("key_input_placeholder"),
name: "key",
},
}),
),
MarginInline(
makeElement({
tag: "button",
class: ["uk-button", "uk-button-primary"],
text: i18next.t("submit_key_btn"),
}),
),
],
2021-05-08 02:09:08 +01:00
}) as HTMLFormElement;
this.unsealInputContent.appendChild(this.unsealKeyForm);
this.unsealKeyForm.addEventListener("submit", (e: Event) => {
e.preventDefault();
void this.handleKeySubmit();
});
}
2021-04-15 13:01:58 +01:00
2021-05-08 02:09:08 +01:00
async makeQRInput(): Promise<void> {
2021-05-12 18:26:32 +01:00
this.qrScanner = await QRScanner(async (code: string) => {
await this.submitKey(code);
});
2021-04-29 12:52:00 +01:00
this.unsealInputContent.appendChild(this.qrScanner);
2021-04-15 13:01:58 +01:00
}
2021-05-12 18:26:32 +01:00
async updateSealProgress(data: SealStatusType): Promise<void> {
2021-05-08 02:09:08 +01:00
const progress = data.progress;
const keysNeeded = data.t;
const text = this.unsealProgressText;
2021-04-19 19:45:51 +01:00
text.innerText = i18next.t("unseal_keys_progress", {
progress: String(progress),
keys_needed: String(keysNeeded),
2021-04-19 19:45:51 +01:00
});
2021-05-08 02:09:08 +01:00
const progressBar = this.unsealProgress;
2021-04-15 13:01:58 +01:00
progressBar.value = progress;
progressBar.max = keysNeeded;
if (!data.sealed) {
progressBar.value = keysNeeded;
2021-05-12 18:26:32 +01:00
await changePage("HOME");
2021-04-15 13:01:58 +01:00
}
}
2021-05-12 18:26:32 +01:00
async submitKey(key: string): Promise<void> {
try {
await submitUnsealKey(key);
await this.updateSealProgress(await getSealStatus());
} catch (e: unknown) {
const error = e as Error;
setErrorText(error.message);
}
2021-04-15 13:01:58 +01:00
}
2021-05-12 18:26:32 +01:00
async handleKeySubmit(): Promise<void> {
2021-05-08 02:09:08 +01:00
const formData = new FormData(this.unsealKeyForm);
2021-05-12 18:26:32 +01:00
await this.submitKey(formData.get("key") as string);
}
2021-05-08 02:09:08 +01:00
get name(): string {
2021-04-19 19:45:51 +01:00
return i18next.t("unseal_vault_text");
2021-04-15 13:01:58 +01:00
}
}