From e72097292cb3e3c06a1a149bddc586e2a81458cf Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Sun, 2 Jan 2022 20:03:34 +0100 Subject: [PATCH] web/flows: fix helper form not being removed from identification stage (improve password manager compatibility) Signed-off-by: Jens Langhammer --- web/src/flows/FlowExecutor.ts | 8 +++++++- web/src/flows/stages/base.ts | 16 +++++++++++++--- .../identification/IdentificationStage.ts | 18 +++++++++++++----- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/web/src/flows/FlowExecutor.ts b/web/src/flows/FlowExecutor.ts index 082f4a440..19c95d289 100644 --- a/web/src/flows/FlowExecutor.ts +++ b/web/src/flows/FlowExecutor.ts @@ -131,7 +131,7 @@ export class FlowExecutor extends LitElement implements StageHost { }); } - submit(payload?: FlowChallengeResponseRequest): Promise { + submit(payload?: FlowChallengeResponseRequest): Promise { if (!payload) return Promise.reject(); if (!this.challenge) return Promise.reject(); // @ts-ignore @@ -153,12 +153,18 @@ export class FlowExecutor extends LitElement implements StageHost { ); } this.challenge = data; + if (this.challenge.responseErrors) { + return false; + } + return true; }) .catch((e: Error | Response) => { this.errorMessage(e); + return false; }) .finally(() => { this.loading = false; + return false; }); } diff --git a/web/src/flows/stages/base.ts b/web/src/flows/stages/base.ts index e1f3551d5..d6c97de67 100644 --- a/web/src/flows/stages/base.ts +++ b/web/src/flows/stages/base.ts @@ -7,7 +7,7 @@ export interface StageHost { challenge?: unknown; flowSlug: string; loading: boolean; - submit(payload: unknown): Promise; + submit(payload: unknown): Promise; } export class BaseStage extends LitElement { @@ -16,14 +16,19 @@ export class BaseStage extends LitElement { @property({ attribute: false }) challenge!: Tin; - submitForm(e: Event): void { + async submitForm(e: Event): Promise { e.preventDefault(); const object: { [key: string]: unknown; } = {}; const form = new FormData(this.shadowRoot?.querySelector("form") || undefined); form.forEach((value, key) => (object[key] = value)); - this.host?.submit(object as unknown as Tout); + return this.host?.submit(object as unknown as Tout).then((successful) => { + if (successful) { + this.cleanup(); + } + return successful; + }); } renderNonFieldErrors(errors: ErrorDetail[]): TemplateResult { @@ -41,4 +46,9 @@ export class BaseStage extends LitElement { })} `; } + + cleanup(): void { + // Method that can be overridden by stages + return; + } } diff --git a/web/src/flows/stages/identification/IdentificationStage.ts b/web/src/flows/stages/identification/IdentificationStage.ts index 841aa9b06..51c381df1 100644 --- a/web/src/flows/stages/identification/IdentificationStage.ts +++ b/web/src/flows/stages/identification/IdentificationStage.ts @@ -41,6 +41,8 @@ export class IdentificationStage extends BaseStage< IdentificationChallenge, IdentificationChallengeResponseRequest > { + form?: HTMLFormElement; + static get styles(): CSSResult[] { return [ PFBase, @@ -72,8 +74,8 @@ export class IdentificationStage extends BaseStage< } firstUpdated(): void { - const wrapperForm = document.createElement("form"); - document.documentElement.appendChild(wrapperForm); + this.form = document.createElement("form"); + document.documentElement.appendChild(this.form); // This is a workaround for the fact that we're in a shadow dom // adapted from https://github.com/home-assistant/frontend/issues/3133 const username = document.createElement("input"); @@ -91,7 +93,7 @@ export class IdentificationStage extends BaseStage< input.focus(); }); }; - wrapperForm.appendChild(username); + this.form.appendChild(username); const password = document.createElement("input"); password.setAttribute("type", "password"); password.setAttribute("name", "password"); @@ -115,7 +117,7 @@ export class IdentificationStage extends BaseStage< input.focus(); }); }; - wrapperForm.appendChild(password); + this.form.appendChild(password); const totp = document.createElement("input"); totp.setAttribute("type", "text"); totp.setAttribute("name", "code"); @@ -139,7 +141,13 @@ export class IdentificationStage extends BaseStage< input.focus(); }); }; - wrapperForm.appendChild(totp); + this.form.appendChild(totp); + } + + cleanup(): void { + if (this.form) { + document.documentElement.removeChild(this.form); + } } renderSource(source: LoginSource): TemplateResult {