stages/identification: allow setting of a password stage to check password and identity in a single step

closes #970

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer
2021-06-05 14:02:15 +02:00
parent f996f9d4e3
commit 24da24b5d5
16 changed files with 260 additions and 49 deletions

View File

@ -1,4 +1,5 @@
import { LitElement, property } from "lit-element";
import { ErrorDetail } from "authentik-api";
import { html, LitElement, property, TemplateResult } from "lit-element";
export interface StageHost {
challenge?: unknown;
@ -22,4 +23,23 @@ export class BaseStage<Tin, Tout> extends LitElement {
this.host?.submit(object as unknown as Tout);
}
renderNonFieldErrors(errors: ErrorDetail[]): TemplateResult {
if (!errors) {
return html``;
}
return html`<div class="pf-c-form__alert">
${errors.map(err => {
return html`<div class="pf-c-alert pf-m-inline pf-m-danger">
<div class="pf-c-alert__icon">
<i class="fas fa-exclamation-circle"></i>
</div>
<h4 class="pf-c-alert__title">
${err.string}
</h4>
</div>`;
})}
</div>`;
}
}

View File

@ -7,6 +7,7 @@ import PFFormControl from "@patternfly/patternfly/components/FormControl/form-co
import PFTitle from "@patternfly/patternfly/components/Title/title.css";
import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import PFAlert from "@patternfly/patternfly/components/Alert/alert.css";
import AKGlobal from "../../../authentik.css";
import "../../../elements/forms/FormElement";
import "../../../elements/EmptyState";
@ -25,7 +26,7 @@ export const PasswordManagerPrefill: {
export class IdentificationStage extends BaseStage<IdentificationChallenge, IdentificationChallengeResponseRequest> {
static get styles(): CSSResult[] {
return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton, AKGlobal].concat(
return [PFBase, PFAlert, PFLogin, PFForm, PFFormControl, PFTitle, PFButton, AKGlobal].concat(
css`
/* login page's icons */
.pf-c-login__main-footer-links-item button {
@ -160,7 +161,7 @@ export class IdentificationStage extends BaseStage<IdentificationChallenge, Iden
label=${label}
?required="${true}"
class="pf-c-form__group"
.errors=${(this.challenge?.responseErrors || {})["uid_field"]}>
.errors=${(this.challenge.responseErrors || {})["uid_field"]}>
<!-- @ts-ignore -->
<input type=${type}
name="uidField"
@ -170,6 +171,25 @@ export class IdentificationStage extends BaseStage<IdentificationChallenge, Iden
class="pf-c-form-control"
required>
</ak-form-element>
${this.challenge.passwordFields ? html`
<ak-form-element
label="${t`Password`}"
?required="${true}"
class="pf-c-form__group"
.errors=${(this.challenge.responseErrors || {})["password"]}>
<input type="password"
name="password"
placeholder="${t`Password`}"
autofocus=""
autocomplete="current-password"
class="pf-c-form-control"
required
value=${PasswordManagerPrefill.password || ""}>
</ak-form-element>
`: html``}
${"non_field_errors" in (this.challenge?.responseErrors || {}) ?
this.renderNonFieldErrors(this.challenge?.responseErrors?.non_field_errors || []) :
html``}
<div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${this.challenge.primaryAction}

View File

@ -13,7 +13,6 @@ import { BaseStage } from "../base";
import "../../../elements/forms/FormElement";
import "../../../elements/EmptyState";
import "../../../elements/Divider";
import { Error } from "../../../api/Flows";
import { PromptChallenge, PromptChallengeResponseRequest, StagePrompt } from "authentik-api";
@ -103,24 +102,6 @@ export class PromptStage extends BaseStage<PromptChallenge, PromptChallengeRespo
return "";
}
renderNonFieldErrors(errors: Error[]): TemplateResult {
if (!errors) {
return html``;
}
return html`<div class="pf-c-form__alert">
${errors.map(err => {
return html`<div class="pf-c-alert pf-m-inline pf-m-danger">
<div class="pf-c-alert__icon">
<i class="fas fa-exclamation-circle"></i>
</div>
<h4 class="pf-c-alert__title">
${err.string}
</h4>
</div>`;
})}
</div>`;
}
render(): TemplateResult {
if (!this.challenge) {
return html`<ak-empty-state