Merge branch 'next' into new-forms
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> # Conflicts: # web/src/api/legacy.ts # web/src/main.ts # web/src/pages/users/UserSettingsPage.ts
This commit is contained in:
		@ -9,6 +9,7 @@ import PFList from "@patternfly/patternfly/components/List/list.css";
 | 
			
		||||
import AKGlobal from "../authentik.css";
 | 
			
		||||
 | 
			
		||||
import { unsafeHTML } from "lit-html/directives/unsafe-html";
 | 
			
		||||
import "./access_denied/FlowAccessDenied";
 | 
			
		||||
import "./stages/authenticator_static/AuthenticatorStaticStage";
 | 
			
		||||
import "./stages/authenticator_totp/AuthenticatorTOTPStage";
 | 
			
		||||
import "./stages/authenticator_validate/AuthenticatorValidateStage";
 | 
			
		||||
@ -16,11 +17,11 @@ import "./stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage";
 | 
			
		||||
import "./stages/autosubmit/AutosubmitStage";
 | 
			
		||||
import "./stages/captcha/CaptchaStage";
 | 
			
		||||
import "./stages/consent/ConsentStage";
 | 
			
		||||
import "./stages/dummy/DummyStage";
 | 
			
		||||
import "./stages/email/EmailStage";
 | 
			
		||||
import "./stages/identification/IdentificationStage";
 | 
			
		||||
import "./stages/password/PasswordStage";
 | 
			
		||||
import "./stages/prompt/PromptStage";
 | 
			
		||||
import "./access_denied/FlowAccessDenied";
 | 
			
		||||
import { ShellChallenge, RedirectChallenge } from "../api/Flows";
 | 
			
		||||
import { IdentificationChallenge } from "./stages/identification/IdentificationStage";
 | 
			
		||||
import { PasswordChallenge } from "./stages/password/PasswordStage";
 | 
			
		||||
@ -193,6 +194,8 @@ export class FlowExecutor extends LitElement implements StageHost {
 | 
			
		||||
                        return html`<ak-stage-captcha .host=${this} .challenge=${this.challenge as CaptchaChallenge}></ak-stage-captcha>`;
 | 
			
		||||
                    case "ak-stage-consent":
 | 
			
		||||
                        return html`<ak-stage-consent .host=${this} .challenge=${this.challenge as ConsentChallenge}></ak-stage-consent>`;
 | 
			
		||||
                    case "ak-stage-dummy":
 | 
			
		||||
                        return html`<ak-stage-dummy .host=${this} .challenge=${this.challenge as Challenge}></ak-stage-dummy>`;
 | 
			
		||||
                    case "ak-stage-email":
 | 
			
		||||
                        return html`<ak-stage-email .host=${this} .challenge=${this.challenge as EmailChallenge}></ak-stage-email>`;
 | 
			
		||||
                    case "ak-stage-autosubmit":
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,6 @@ import "../../elements/EmptyState";
 | 
			
		||||
 | 
			
		||||
export interface AccessDeniedChallenge extends Challenge {
 | 
			
		||||
    error_message?: string;
 | 
			
		||||
    policy_result?: Record<string, unknown>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@customElement("ak-stage-access-denied")
 | 
			
		||||
@ -49,27 +48,6 @@ export class FlowAccessDenied extends BaseStage {
 | 
			
		||||
                        ${this.challenge?.error_message &&
 | 
			
		||||
                            html`<hr>
 | 
			
		||||
                            <p>${this.challenge.error_message}</p>`}
 | 
			
		||||
                        ${this.challenge.policy_result &&
 | 
			
		||||
                            html`<hr>
 | 
			
		||||
                            <em>
 | 
			
		||||
                                ${gettext("Explanation:")}
 | 
			
		||||
                            </em>
 | 
			
		||||
                            <ul class="pf-c-list">
 | 
			
		||||
                                {% for source_result in policy_result.source_results %}
 | 
			
		||||
                                <li>
 | 
			
		||||
                                    {% blocktrans with name=source_result.source_policy.name result=source_result.passing %}
 | 
			
		||||
                                    Policy '{{ name }}' returned result '{{ result }}'
 | 
			
		||||
                                    {% endblocktrans %}
 | 
			
		||||
                                    {% if source_result.messages %}
 | 
			
		||||
                                    <ul class="pf-c-list">
 | 
			
		||||
                                        {% for message in source_result.messages %}
 | 
			
		||||
                                            <li>{{ message }}</li>
 | 
			
		||||
                                        {% endfor %}
 | 
			
		||||
                                    </ul>
 | 
			
		||||
                                    {% endif %}
 | 
			
		||||
                                </li>
 | 
			
		||||
                                {% endfor %}
 | 
			
		||||
                            </ul>`}
 | 
			
		||||
                    </div>
 | 
			
		||||
                </form>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,7 @@ import { BaseStage } from "../base";
 | 
			
		||||
import "../../../elements/forms/FormElement";
 | 
			
		||||
import "../../../elements/EmptyState";
 | 
			
		||||
import "../../FormStatic";
 | 
			
		||||
import { FlowURLManager } from "../../../api/legacy";
 | 
			
		||||
 | 
			
		||||
export const STATIC_TOKEN_STYLE = css`
 | 
			
		||||
/* Static OTP Tokens */
 | 
			
		||||
@ -61,7 +62,7 @@ export class AuthenticatorStaticStage extends BaseStage {
 | 
			
		||||
                        userAvatar="${this.challenge.pending_user_avatar}"
 | 
			
		||||
                        user=${this.challenge.pending_user}>
 | 
			
		||||
                        <div slot="link">
 | 
			
		||||
                            <a href="/flows/-/cancel/">${gettext("Not you?")}</a>
 | 
			
		||||
                            <a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </ak-form-static>
 | 
			
		||||
                    <ak-form-element
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,8 @@ import "../../../elements/forms/FormElement";
 | 
			
		||||
import { showMessage } from "../../../elements/messages/MessageContainer";
 | 
			
		||||
import "../../../elements/EmptyState";
 | 
			
		||||
import "../../FormStatic";
 | 
			
		||||
import { MessageLevel } from "../../../elements/messages/Message";
 | 
			
		||||
import { FlowURLManager } from "../../../api/legacy";
 | 
			
		||||
 | 
			
		||||
export interface AuthenticatorTOTPChallenge extends WithUserInfoChallenge {
 | 
			
		||||
    config_url: string;
 | 
			
		||||
@ -48,7 +50,7 @@ export class AuthenticatorTOTPStage extends BaseStage {
 | 
			
		||||
                        userAvatar="${this.challenge.pending_user_avatar}"
 | 
			
		||||
                        user=${this.challenge.pending_user}>
 | 
			
		||||
                        <div slot="link">
 | 
			
		||||
                            <a href="/flows/-/cancel/">${gettext("Not you?")}</a>
 | 
			
		||||
                            <a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </ak-form-static>
 | 
			
		||||
                    <input type="hidden" name="otp_uri" value=${this.challenge.config_url} />
 | 
			
		||||
@ -60,7 +62,7 @@ export class AuthenticatorTOTPStage extends BaseStage {
 | 
			
		||||
                            if (!this.challenge?.config_url) return;
 | 
			
		||||
                            navigator.clipboard.writeText(this.challenge?.config_url).then(() => {
 | 
			
		||||
                                showMessage({
 | 
			
		||||
                                    level_tag: "success",
 | 
			
		||||
                                    level: MessageLevel.success,
 | 
			
		||||
                                    message: gettext("Successfully copied TOTP Config.")
 | 
			
		||||
                                });
 | 
			
		||||
                            });
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,7 @@ import AKGlobal from "../../../authentik.css";
 | 
			
		||||
import { BaseStage, StageHost } from "../base";
 | 
			
		||||
import "./AuthenticatorValidateStageWebAuthn";
 | 
			
		||||
import "./AuthenticatorValidateStageCode";
 | 
			
		||||
import { PasswordManagerPrefill } from "../identification/IdentificationStage";
 | 
			
		||||
 | 
			
		||||
export enum DeviceClasses {
 | 
			
		||||
    STATIC = "static",
 | 
			
		||||
@ -83,6 +84,17 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
 | 
			
		||||
                        <small>${gettext("Use a security key to prove your identity.")}</small>
 | 
			
		||||
                    </div>`;
 | 
			
		||||
            case DeviceClasses.TOTP:
 | 
			
		||||
                // TOTP is a bit special, assuming that TOTP is allowed from the backend,
 | 
			
		||||
                // and we have a pre-filled value from the password manager,
 | 
			
		||||
                // directly set the the TOTP device Challenge as active.
 | 
			
		||||
                if (PasswordManagerPrefill.totp) {
 | 
			
		||||
                    console.debug("authentik/stages/authenticator_validate: found prefill totp code, selecting totp challenge");
 | 
			
		||||
                    this.selectedDeviceChallenge = deviceChallenge;
 | 
			
		||||
                    // Delay the update as a re-render isn't triggered from here
 | 
			
		||||
                    setTimeout(() => {
 | 
			
		||||
                        this.requestUpdate();
 | 
			
		||||
                    }, 100);
 | 
			
		||||
                }
 | 
			
		||||
                return html`<i class="fas fa-clock"></i>
 | 
			
		||||
                    <div class="right">
 | 
			
		||||
                        <p>${gettext("Traditional authenticator")}</p>
 | 
			
		||||
@ -141,9 +153,9 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
 | 
			
		||||
    render(): TemplateResult {
 | 
			
		||||
        if (!this.challenge) {
 | 
			
		||||
            return html`<ak-empty-state
 | 
			
		||||
    ?loading="${true}"
 | 
			
		||||
    header=${gettext("Loading")}>
 | 
			
		||||
</ak-empty-state>`;
 | 
			
		||||
                ?loading="${true}"
 | 
			
		||||
                header=${gettext("Loading")}>
 | 
			
		||||
            </ak-empty-state>`;
 | 
			
		||||
        }
 | 
			
		||||
        // User only has a single device class, so we don't show a picker
 | 
			
		||||
        if (this.challenge?.device_challenges.length === 1) {
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,7 @@ import "../../../elements/forms/FormElement";
 | 
			
		||||
import "../../../elements/EmptyState";
 | 
			
		||||
import { PasswordManagerPrefill } from "../identification/IdentificationStage";
 | 
			
		||||
import "../../FormStatic";
 | 
			
		||||
import { FlowURLManager } from "../../../api/legacy";
 | 
			
		||||
 | 
			
		||||
@customElement("ak-stage-authenticator-validate-code")
 | 
			
		||||
export class AuthenticatorValidateStageWebCode extends BaseStage {
 | 
			
		||||
@ -44,7 +45,7 @@ export class AuthenticatorValidateStageWebCode extends BaseStage {
 | 
			
		||||
                    userAvatar="${this.challenge.pending_user_avatar}"
 | 
			
		||||
                    user=${this.challenge.pending_user}>
 | 
			
		||||
                    <div slot="link">
 | 
			
		||||
                        <a href="/flows/-/cancel/">${gettext("Not you?")}</a>
 | 
			
		||||
                        <a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </ak-form-static>
 | 
			
		||||
                <ak-form-element
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,7 @@ import { BaseStage } from "../base";
 | 
			
		||||
import "../../../elements/forms/FormElement";
 | 
			
		||||
import "../../../elements/EmptyState";
 | 
			
		||||
import "../../FormStatic";
 | 
			
		||||
import { FlowURLManager } from "../../../api/legacy";
 | 
			
		||||
 | 
			
		||||
export interface CaptchaChallenge extends WithUserInfoChallenge {
 | 
			
		||||
    site_key: string;
 | 
			
		||||
@ -78,7 +79,7 @@ export class CaptchaStage extends BaseStage {
 | 
			
		||||
                        userAvatar="${this.challenge.pending_user_avatar}"
 | 
			
		||||
                        user=${this.challenge.pending_user}>
 | 
			
		||||
                        <div slot="link">
 | 
			
		||||
                            <a href="/flows/-/cancel/">${gettext("Not you?")}</a>
 | 
			
		||||
                            <a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </ak-form-static>
 | 
			
		||||
                    <div class="ak-loading">
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,7 @@ import AKGlobal from "../../../authentik.css";
 | 
			
		||||
import { BaseStage } from "../base";
 | 
			
		||||
import "../../../elements/EmptyState";
 | 
			
		||||
import "../../FormStatic";
 | 
			
		||||
import { FlowURLManager } from "../../../api/legacy";
 | 
			
		||||
 | 
			
		||||
export interface Permission {
 | 
			
		||||
    name: string;
 | 
			
		||||
@ -53,7 +54,7 @@ export class ConsentStage extends BaseStage {
 | 
			
		||||
                        userAvatar="${this.challenge.pending_user_avatar}"
 | 
			
		||||
                        user=${this.challenge.pending_user}>
 | 
			
		||||
                        <div slot="link">
 | 
			
		||||
                            <a href="/flows/-/cancel/">${gettext("Not you?")}</a>
 | 
			
		||||
                            <a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </ak-form-static>
 | 
			
		||||
                    <div class="pf-c-form__group">
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										52
									
								
								web/src/flows/stages/dummy/DummyStage.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								web/src/flows/stages/dummy/DummyStage.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
			
		||||
import { gettext } from "django";
 | 
			
		||||
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
 | 
			
		||||
import { Challenge } from "../../../api/Flows";
 | 
			
		||||
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
 | 
			
		||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
 | 
			
		||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
 | 
			
		||||
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 AKGlobal from "../../../authentik.css";
 | 
			
		||||
import { BaseStage } from "../base";
 | 
			
		||||
import "../../../elements/EmptyState";
 | 
			
		||||
import "../../FormStatic";
 | 
			
		||||
 | 
			
		||||
@customElement("ak-stage-dummy")
 | 
			
		||||
export class DummyStage extends BaseStage {
 | 
			
		||||
 | 
			
		||||
    @property({ attribute: false })
 | 
			
		||||
    challenge?: Challenge;
 | 
			
		||||
 | 
			
		||||
    static get styles(): CSSResult[] {
 | 
			
		||||
        return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton, AKGlobal];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(): TemplateResult {
 | 
			
		||||
        if (!this.challenge) {
 | 
			
		||||
            return html`<ak-empty-state
 | 
			
		||||
                ?loading="${true}"
 | 
			
		||||
                header=${gettext("Loading")}>
 | 
			
		||||
            </ak-empty-state>`;
 | 
			
		||||
        }
 | 
			
		||||
        return html`<header class="pf-c-login__main-header">
 | 
			
		||||
                <h1 class="pf-c-title pf-m-3xl">
 | 
			
		||||
                    ${this.challenge.title}
 | 
			
		||||
                </h1>
 | 
			
		||||
            </header>
 | 
			
		||||
            <div class="pf-c-login__main-body">
 | 
			
		||||
                <form class="pf-c-form" @submit=${(e: Event) => { this.submitForm(e); }}>
 | 
			
		||||
                    <div class="pf-c-form__group pf-m-action">
 | 
			
		||||
                        <button type="submit" class="pf-c-button pf-m-primary pf-m-block">
 | 
			
		||||
                            ${gettext("Continue")}
 | 
			
		||||
                        </button>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </form>
 | 
			
		||||
            </div>
 | 
			
		||||
            <footer class="pf-c-login__main-footer">
 | 
			
		||||
                <ul class="pf-c-login__main-footer-links">
 | 
			
		||||
                </ul>
 | 
			
		||||
            </footer>`;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -13,6 +13,7 @@ import "../../../elements/forms/FormElement";
 | 
			
		||||
import "../../../elements/EmptyState";
 | 
			
		||||
import { PasswordManagerPrefill } from "../identification/IdentificationStage";
 | 
			
		||||
import "../../FormStatic";
 | 
			
		||||
import { FlowURLManager } from "../../../api/legacy";
 | 
			
		||||
 | 
			
		||||
export interface PasswordChallenge extends WithUserInfoChallenge {
 | 
			
		||||
    recovery_url?: string;
 | 
			
		||||
@ -47,7 +48,7 @@ export class PasswordStage extends BaseStage {
 | 
			
		||||
                        userAvatar="${this.challenge.pending_user_avatar}"
 | 
			
		||||
                        user=${this.challenge.pending_user}>
 | 
			
		||||
                        <div slot="link">
 | 
			
		||||
                            <a href="/flows/-/cancel/">${gettext("Not you?")}</a>
 | 
			
		||||
                            <a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </ak-form-static>
 | 
			
		||||
                    <input name="username" autocomplete="username" type="hidden" value="${this.challenge.pending_user}">
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user