2021-02-17 22:52:49 +00:00
|
|
|
import { gettext } from "django";
|
2020-12-01 08:15:41 +00:00
|
|
|
import { LitElement, html, customElement, property, TemplateResult } from "lit-element";
|
2021-02-17 22:52:49 +00:00
|
|
|
import { unsafeHTML } from "lit-html/directives/unsafe-html";
|
2021-02-17 19:49:58 +00:00
|
|
|
import { getCookie } from "../../utils";
|
2021-02-17 22:52:49 +00:00
|
|
|
import "../../elements/stages/identification/IdentificationStage";
|
2021-02-20 23:14:18 +00:00
|
|
|
import "../../elements/stages/password/PasswordStage";
|
2021-02-21 12:15:45 +00:00
|
|
|
import "../../elements/stages/consent/ConsentStage";
|
2021-02-20 22:19:27 +00:00
|
|
|
import { ShellChallenge, Challenge, ChallengeTypes, Flow, RedirectChallenge } from "../../api/Flows";
|
|
|
|
import { DefaultClient } from "../../api/Client";
|
|
|
|
import { IdentificationChallenge } from "../../elements/stages/identification/IdentificationStage";
|
2021-02-20 23:14:18 +00:00
|
|
|
import { PasswordChallenge } from "../../elements/stages/password/PasswordStage";
|
2021-02-21 12:15:45 +00:00
|
|
|
import { ConsentChallenge } from "../../elements/stages/consent/ConsentStage";
|
2020-11-20 21:08:00 +00:00
|
|
|
|
2021-02-17 22:52:49 +00:00
|
|
|
@customElement("ak-flow-executor")
|
|
|
|
export class FlowExecutor extends LitElement {
|
2020-11-20 21:08:00 +00:00
|
|
|
@property()
|
2021-02-20 22:19:27 +00:00
|
|
|
flowSlug = "";
|
2020-11-20 21:08:00 +00:00
|
|
|
|
2021-02-17 22:52:49 +00:00
|
|
|
@property({attribute: false})
|
2021-02-20 22:19:27 +00:00
|
|
|
challenge?: Challenge;
|
2020-10-16 14:36:18 +00:00
|
|
|
|
2020-12-01 08:15:41 +00:00
|
|
|
createRenderRoot(): Element | ShadowRoot {
|
2020-10-16 14:36:18 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2021-02-17 19:49:58 +00:00
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
this.addEventListener("ak-flow-submit", () => {
|
2021-02-17 22:52:49 +00:00
|
|
|
this.submit();
|
2021-02-17 19:49:58 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-02-17 22:52:49 +00:00
|
|
|
submit(formData?: FormData): void {
|
|
|
|
const csrftoken = getCookie("authentik_csrf");
|
2021-02-20 22:19:27 +00:00
|
|
|
const request = new Request(DefaultClient.makeUrl(["flows", "executor", this.flowSlug]), {
|
2021-02-17 22:52:49 +00:00
|
|
|
headers: {
|
|
|
|
"X-CSRFToken": csrftoken,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
fetch(request, {
|
|
|
|
method: "POST",
|
|
|
|
mode: "same-origin",
|
|
|
|
body: formData,
|
|
|
|
})
|
|
|
|
.then((response) => {
|
|
|
|
return response.json();
|
|
|
|
})
|
|
|
|
.then((data) => {
|
2021-02-20 22:19:27 +00:00
|
|
|
this.challenge = data;
|
2021-02-17 22:52:49 +00:00
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
this.errorMessage(e);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-12-01 08:15:41 +00:00
|
|
|
firstUpdated(): void {
|
2021-02-20 22:19:27 +00:00
|
|
|
Flow.executor(this.flowSlug).then((challenge) => {
|
|
|
|
this.challenge = challenge;
|
|
|
|
}).catch((e) => {
|
|
|
|
// Catch JSON or Update errors
|
|
|
|
this.errorMessage(e);
|
2020-10-16 14:36:18 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-12-01 08:15:41 +00:00
|
|
|
errorMessage(error: string): void {
|
2021-02-20 22:19:27 +00:00
|
|
|
this.challenge = <ShellChallenge>{
|
|
|
|
type: ChallengeTypes.shell,
|
|
|
|
body: `<style>
|
|
|
|
.ak-exception {
|
|
|
|
font-family: monospace;
|
|
|
|
overflow-x: scroll;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
<header class="pf-c-login__main-header">
|
|
|
|
<h1 class="pf-c-title pf-m-3xl">
|
|
|
|
${gettext("Whoops!")}
|
|
|
|
</h1>
|
|
|
|
</header>
|
|
|
|
<div class="pf-c-login__main-body">
|
|
|
|
<h3>${gettext("Something went wrong! Please try again later.")}</h3>
|
|
|
|
<pre class="ak-exception">${error}</pre>
|
|
|
|
</div>`
|
|
|
|
};
|
2020-10-26 09:52:13 +00:00
|
|
|
}
|
|
|
|
|
2020-12-01 08:15:41 +00:00
|
|
|
loading(): TemplateResult {
|
2020-12-05 21:08:42 +00:00
|
|
|
return html` <div class="pf-c-login__main-body ak-loading">
|
2020-11-26 22:35:59 +00:00
|
|
|
<span class="pf-c-spinner" role="progressbar" aria-valuetext="Loading...">
|
2020-11-21 19:48:49 +00:00
|
|
|
<span class="pf-c-spinner__clipper"></span>
|
|
|
|
<span class="pf-c-spinner__lead-ball"></span>
|
|
|
|
<span class="pf-c-spinner__tail-ball"></span>
|
|
|
|
</span>
|
|
|
|
</div>`;
|
2020-10-16 14:36:18 +00:00
|
|
|
}
|
|
|
|
|
2020-12-01 08:15:41 +00:00
|
|
|
render(): TemplateResult {
|
2021-02-20 22:19:27 +00:00
|
|
|
if (!this.challenge) {
|
|
|
|
return this.loading();
|
|
|
|
}
|
|
|
|
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`<ak-stage-identification .host=${this} .challenge=${this.challenge as IdentificationChallenge}></ak-stage-identification>`;
|
2021-02-20 23:14:18 +00:00
|
|
|
case "ak-stage-password":
|
|
|
|
return html`<ak-stage-password .host=${this} .challenge=${this.challenge as PasswordChallenge}></ak-stage-password>`;
|
2021-02-21 12:15:45 +00:00
|
|
|
case "ak-stage-consent":
|
|
|
|
return html`<ak-stage-consent .host=${this} .challenge=${this.challenge as ConsentChallenge}></ak-stage-consent>`;
|
2021-02-20 22:19:27 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
console.debug(`authentik/flows: unexpected data type ${this.challenge.type}`);
|
|
|
|
break;
|
2020-10-16 14:36:18 +00:00
|
|
|
}
|
2021-02-20 22:19:27 +00:00
|
|
|
return html``;
|
2020-10-16 14:36:18 +00:00
|
|
|
}
|
|
|
|
}
|