import { gettext } from "django"; import { LitElement, html, customElement, property, TemplateResult, CSSResult, css } from "lit-element"; import { unsafeHTML } from "lit-html/directives/unsafe-html"; import { getCookie } from "../../utils"; import "../../elements/stages/identification/IdentificationStage"; import "../../elements/stages/password/PasswordStage"; import "../../elements/stages/consent/ConsentStage"; import "../../elements/stages/email/EmailStage"; import "../../elements/stages/autosubmit/AutosubmitStage"; import "../../elements/stages/prompt/PromptStage"; import "../../elements/stages/authenticator_totp/AuthenticatorTOTPStage"; import "../../elements/stages/authenticator_static/AuthenticatorStaticStage"; import "../../elements/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage"; import "../../elements/stages/authenticator_validate/AuthenticatorValidateStage"; import { ShellChallenge, Challenge, ChallengeTypes, Flow, RedirectChallenge } from "../../api/Flows"; import { DefaultClient } from "../../api/Client"; import { IdentificationChallenge } from "../../elements/stages/identification/IdentificationStage"; import { PasswordChallenge } from "../../elements/stages/password/PasswordStage"; import { ConsentChallenge } from "../../elements/stages/consent/ConsentStage"; import { EmailChallenge } from "../../elements/stages/email/EmailStage"; import { AutosubmitChallenge } from "../../elements/stages/autosubmit/AutosubmitStage"; import { PromptChallenge } from "../../elements/stages/prompt/PromptStage"; import { AuthenticatorTOTPChallenge } from "../../elements/stages/authenticator_totp/AuthenticatorTOTPStage"; import { AuthenticatorStaticChallenge } from "../../elements/stages/authenticator_static/AuthenticatorStaticStage"; import { AuthenticatorValidateStageChallenge } from "../../elements/stages/authenticator_validate/AuthenticatorValidateStage"; import { WebAuthnAuthenticatorRegisterChallenge } from "../../elements/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage"; import { COMMON_STYLES } from "../../common/styles"; import { SpinnerSize } from "../../elements/Spinner"; import { StageHost } from "../../elements/stages/base"; @customElement("ak-flow-executor") export class FlowExecutor extends LitElement implements StageHost { @property() flowSlug = ""; @property({attribute: false}) challenge?: Challenge; @property({type: Boolean}) loading = false; static get styles(): CSSResult[] { return COMMON_STYLES.concat(css` .ak-loading { display: flex; height: 100%; width: 100%; justify-content: center; align-items: center; position: absolute; background-color: #0303039e; } .ak-hidden { display: none; } :host { position: relative; } `); } constructor() { super(); this.addEventListener("ak-flow-submit", () => { this.submit(); }); } submit(formData?: FormData): Promise { const csrftoken = getCookie("authentik_csrf"); const request = new Request(DefaultClient.makeUrl(["flows", "executor", this.flowSlug]), { headers: { "X-CSRFToken": csrftoken, }, }); this.loading = true; return fetch(request, { method: "POST", mode: "same-origin", body: formData, }) .then((response) => { return response.json(); }) .then((data) => { this.challenge = data; }) .catch((e) => { this.errorMessage(e); }) .finally(() => { this.loading = false; }); } firstUpdated(): void { this.loading = true; Flow.executor(this.flowSlug).then((challenge) => { this.challenge = challenge; }).catch((e) => { // Catch JSON or Update errors this.errorMessage(e); }).finally(() => { this.loading = false; }); } errorMessage(error: string): void { this.challenge = { type: ChallengeTypes.shell, body: ` ` }; } renderLoading(): TemplateResult { return html`
`; } renderChallenge(): TemplateResult { if (!this.challenge) { return html``; } switch (this.challenge.type) { case ChallengeTypes.redirect: console.debug(`authentik/flows: redirecting to ${(this.challenge as RedirectChallenge).to}`); window.location.assign((this.challenge as RedirectChallenge).to); break; case ChallengeTypes.shell: return html`${unsafeHTML((this.challenge as ShellChallenge).body)}`; case ChallengeTypes.native: switch (this.challenge.component) { case "ak-stage-identification": return html``; case "ak-stage-password": return html``; case "ak-stage-consent": return html``; case "ak-stage-email": return html``; case "ak-stage-autosubmit": return html``; case "ak-stage-prompt": return html``; case "ak-stage-authenticator-totp": return html``; case "ak-stage-authenticator-static": return html``; case "ak-stage-authenticator-webauthn": return html``; case "ak-stage-authenticator-validate": return html``; default: break; } break; default: console.debug(`authentik/flows: unexpected data type ${this.challenge.type}`); break; } return html``; } render(): TemplateResult { if (!this.challenge) { return this.renderLoading(); } return html` ${this.loading ? this.renderLoading() : html``} ${this.renderChallenge()} `; } }