Merge branch 'web/config-provider' into web/config-provider-2-tenant

* web/config-provider:
  web/flows: show logo in card (#7824)
This commit is contained in:
Ken Sternberg 2023-12-08 13:02:50 -08:00
commit 284c2327c6
2 changed files with 80 additions and 105 deletions

View file

@ -27,7 +27,7 @@ window.authentik.flow = {
{% block body %} {% block body %}
<ak-message-container></ak-message-container> <ak-message-container></ak-message-container>
<ak-flow-executor> <ak-flow-executor flowSlug="{{ flow.slug }}">
<ak-loading></ak-loading> <ak-loading></ak-loading>
</ak-flow-executor> </ak-flow-executor>
{% endblock %} {% endblock %}

View file

@ -18,7 +18,7 @@ import "@goauthentik/flow/stages/RedirectStage";
import { StageHost } from "@goauthentik/flow/stages/base"; import { StageHost } from "@goauthentik/flow/stages/base";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html, render } from "lit"; import { CSSResult, TemplateResult, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators.js"; import { customElement, property, state } from "lit/decorators.js";
import { unsafeHTML } from "lit/directives/unsafe-html.js"; import { unsafeHTML } from "lit/directives/unsafe-html.js";
import { until } from "lit/directives/until.js"; import { until } from "lit/directives/until.js";
@ -46,7 +46,8 @@ import {
@customElement("ak-flow-executor") @customElement("ak-flow-executor")
export class FlowExecutor extends Interface implements StageHost { export class FlowExecutor extends Interface implements StageHost {
flowSlug?: string; @property()
flowSlug: string = window.location.pathname.split("/")[3];
private _challenge?: ChallengeTypes; private _challenge?: ChallengeTypes;
@ -94,6 +95,9 @@ export class FlowExecutor extends Interface implements StageHost {
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [PFBase, PFLogin, PFDrawer, PFButton, PFTitle, PFList, PFBackgroundImage].concat(css` return [PFBase, PFLogin, PFDrawer, PFButton, PFTitle, PFList, PFBackgroundImage].concat(css`
:host {
--pf-c-login__main-body--PaddingBottom: var(--pf-global--spacer--2xl);
}
.pf-c-background-image::before { .pf-c-background-image::before {
--pf-c-background-image--BackgroundImage: var(--ak-flow-background); --pf-c-background-image--BackgroundImage: var(--ak-flow-background);
--pf-c-background-image--BackgroundImage-2x: var(--ak-flow-background); --pf-c-background-image--BackgroundImage-2x: var(--ak-flow-background);
@ -111,6 +115,9 @@ export class FlowExecutor extends Interface implements StageHost {
background-color: transparent; background-color: transparent;
} }
/* layouts */ /* layouts */
.pf-c-login.stacked .pf-c-login__main {
margin-top: 13rem;
}
.pf-c-login__container.content-right { .pf-c-login__container.content-right {
grid-template-areas: grid-template-areas:
"header main" "header main"
@ -146,13 +153,27 @@ export class FlowExecutor extends Interface implements StageHost {
:host([theme="dark"]) .pf-c-login.sidebar_right .pf-c-list { :host([theme="dark"]) .pf-c-login.sidebar_right .pf-c-list {
color: var(--ak-dark-foreground); color: var(--ak-dark-foreground);
} }
.pf-c-brand {
padding-top: calc(
var(--pf-c-login__main-footer-links--PaddingTop) +
var(--pf-c-login__main-footer-links--PaddingBottom) +
var(--pf-c-login__main-body--PaddingBottom)
);
max-height: 9rem;
}
.ak-brand {
display: flex;
justify-content: center;
}
.ak-brand img {
padding: 0 2rem;
}
`); `);
} }
constructor() { constructor() {
super(); super();
this.ws = new WebsocketClient(); this.ws = new WebsocketClient();
this.flowSlug = window.location.pathname.split("/")[3];
if (window.location.search.includes("inspector")) { if (window.location.search.includes("inspector")) {
this.inspectorOpen = !this.inspectorOpen; this.inspectorOpen = !this.inspectorOpen;
} }
@ -165,75 +186,68 @@ export class FlowExecutor extends Interface implements StageHost {
return globalAK()?.tenant.uiTheme || UiThemeEnum.Automatic; return globalAK()?.tenant.uiTheme || UiThemeEnum.Automatic;
} }
submit(payload?: FlowChallengeResponseRequest): Promise<boolean> { async submit(payload?: FlowChallengeResponseRequest): Promise<boolean> {
if (!payload) return Promise.reject(); if (!payload) return Promise.reject();
if (!this.challenge) return Promise.reject(); if (!this.challenge) return Promise.reject();
// @ts-ignore // @ts-ignore
payload.component = this.challenge.component; payload.component = this.challenge.component;
this.loading = true; this.loading = true;
return new FlowsApi(DEFAULT_CONFIG) try {
.flowsExecutorSolve({ const challenge = await new FlowsApi(DEFAULT_CONFIG).flowsExecutorSolve({
flowSlug: this.flowSlug || "", flowSlug: this.flowSlug,
query: window.location.search.substring(1), query: window.location.search.substring(1),
flowChallengeResponseRequest: payload, flowChallengeResponseRequest: payload,
})
.then((data) => {
if (this.inspectorOpen) {
window.dispatchEvent(
new CustomEvent(EVENT_FLOW_ADVANCE, {
bubbles: true,
composed: true,
}),
);
}
this.challenge = data;
if (this.challenge.flowInfo) {
this.flowInfo = this.challenge.flowInfo;
}
if (this.challenge.responseErrors) {
return false;
}
return true;
})
.catch((e: Error | ResponseError) => {
this.errorMessage(e);
return false;
})
.finally(() => {
this.loading = false;
return false;
}); });
if (this.inspectorOpen) {
window.dispatchEvent(
new CustomEvent(EVENT_FLOW_ADVANCE, {
bubbles: true,
composed: true,
}),
);
}
this.challenge = challenge;
if (this.challenge.flowInfo) {
this.flowInfo = this.challenge.flowInfo;
}
if (this.challenge.responseErrors) {
return false;
}
return true;
} catch (exc: unknown) {
this.errorMessage(exc as Error | ResponseError);
return false;
} finally {
this.loading = false;
}
} }
firstUpdated(): void { async firstUpdated(): Promise<void> {
configureSentry(); configureSentry();
this.loading = true; this.loading = true;
new FlowsApi(DEFAULT_CONFIG) try {
.flowsExecutorGet({ const challenge = await new FlowsApi(DEFAULT_CONFIG).flowsExecutorGet({
flowSlug: this.flowSlug || "", flowSlug: this.flowSlug,
query: window.location.search.substring(1), query: window.location.search.substring(1),
})
.then((challenge) => {
if (this.inspectorOpen) {
window.dispatchEvent(
new CustomEvent(EVENT_FLOW_ADVANCE, {
bubbles: true,
composed: true,
}),
);
}
this.challenge = challenge;
if (this.challenge.flowInfo) {
this.flowInfo = this.challenge.flowInfo;
}
})
.catch((e: Error | ResponseError) => {
// Catch JSON or Update errors
this.errorMessage(e);
})
.finally(() => {
this.loading = false;
}); });
if (this.inspectorOpen) {
window.dispatchEvent(
new CustomEvent(EVENT_FLOW_ADVANCE, {
bubbles: true,
composed: true,
}),
);
}
this.challenge = challenge;
if (this.challenge.flowInfo) {
this.flowInfo = this.challenge.flowInfo;
}
} catch (exc: unknown) {
// Catch JSON or Update errors
this.errorMessage(exc as Error | ResponseError);
} finally {
this.loading = false;
}
} }
async errorMessage(error: Error | ResponseError): Promise<void> { async errorMessage(error: Error | ResponseError): Promise<void> {
@ -412,12 +426,15 @@ export class FlowExecutor extends Interface implements StageHost {
} }
renderChallengeWrapper(): TemplateResult { renderChallengeWrapper(): TemplateResult {
const logo = html`<div class="pf-c-login__main-header pf-c-brand ak-brand">
<img src="${first(this.tenant?.brandingLogo, "")}" alt="authentik Logo" />
</div>`;
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state ?loading=${true} header=${msg("Loading")}> return html`${logo}<ak-empty-state ?loading=${true} header=${msg("Loading")}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html` return html`
${this.loading ? html`<ak-loading-overlay></ak-loading-overlay>` : html``} ${this.loading ? html`<ak-loading-overlay></ak-loading-overlay>` : nothing} ${logo}
${until(this.renderChallenge())} ${until(this.renderChallenge())}
`; `;
} }
@ -453,43 +470,9 @@ export class FlowExecutor extends Interface implements StageHost {
} }
} }
renderBackgroundOverlay(): TemplateResult {
const overlaySVG = html`<svg
xmlns="http://www.w3.org/2000/svg"
class="pf-c-background-image__filter"
width="0"
height="0"
>
<filter id="image_overlay">
<feColorMatrix
in="SourceGraphic"
type="matrix"
values="1.3 0 0 0 0 0 1.3 0 0 0 0 0 1.3 0 0 0 0 0 1 0"
/>
<feComponentTransfer color-interpolation-filters="sRGB" result="duotone">
<feFuncR
type="table"
tableValues="0.086274509803922 0.43921568627451"
></feFuncR>
<feFuncG
type="table"
tableValues="0.086274509803922 0.43921568627451"
></feFuncG>
<feFuncB
type="table"
tableValues="0.086274509803922 0.43921568627451"
></feFuncB>
<feFuncA type="table" tableValues="0 1"></feFuncA>
</feComponentTransfer>
</filter>
</svg>`;
render(overlaySVG, document.body);
return overlaySVG;
}
render(): TemplateResult { render(): TemplateResult {
return html` <ak-locale-context> return html` <ak-locale-context>
<div class="pf-c-background-image">${this.renderBackgroundOverlay()}</div> <div class="pf-c-background-image"></div>
<div class="pf-c-page__drawer"> <div class="pf-c-page__drawer">
<div class="pf-c-drawer ${this.inspectorOpen ? "pf-m-expanded" : "pf-m-collapsed"}"> <div class="pf-c-drawer ${this.inspectorOpen ? "pf-m-expanded" : "pf-m-collapsed"}">
<div class="pf-c-drawer__main"> <div class="pf-c-drawer__main">
@ -497,14 +480,6 @@ export class FlowExecutor extends Interface implements StageHost {
<div class="pf-c-drawer__body"> <div class="pf-c-drawer__body">
<div class="pf-c-login ${this.getLayout()}"> <div class="pf-c-login ${this.getLayout()}">
<div class="${this.getLayoutClass()}"> <div class="${this.getLayoutClass()}">
<header class="pf-c-login__header">
<div class="pf-c-brand ak-brand">
<img
src="${first(this.tenant?.brandingLogo, "")}"
alt="authentik Logo"
/>
</div>
</header>
<div class="pf-c-login__main"> <div class="pf-c-login__main">
${this.renderChallengeWrapper()} ${this.renderChallengeWrapper()}
</div> </div>