Merge branch 'master' into version-2021.3

This commit is contained in:
Jens Langhammer
2021-03-03 20:48:02 +01:00
65 changed files with 2287 additions and 1200 deletions

View File

@ -78,8 +78,8 @@ stages:
python ./scripts/az_do_set_branch.py
- task: Docker@2
inputs:
containerRegistry: 'GHCR'
repository: 'beryju/authentik-static'
containerRegistry: 'beryjuorg-harbor'
repository: 'authentik/static'
command: 'buildAndPush'
Dockerfile: 'web/Dockerfile'
tags: "gh-$(branchName)"

View File

@ -1,3 +1,5 @@
import { gettext } from "django";
import { showMessage } from "../elements/messages/MessageContainer";
import { getCookie } from "../utils";
import { NotFoundError, RequestError } from "./Error";
@ -47,6 +49,13 @@ export class Client {
}
return r;
})
.catch((e) => {
showMessage({
level_tag: "error",
message: gettext(`Unexpected error while fetching: ${e.toString()}`),
});
return e;
})
.then((r) => r.json())
.then((r) => <T>r);
}

View File

@ -1,16 +1,21 @@
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import Chart from "chart.js";
import { showMessage } from "./messages/MessageContainer";
import { DefaultClient } from "../api/Client";
interface TickValue {
value: number;
major: boolean;
}
export interface LoginMetrics {
logins_failed_per_1h: { x: number, y: number }[];
logins_per_1h: { x: number, y: number }[];
}
@customElement("ak-admin-logins-chart")
export class AdminLoginsChart extends LitElement {
@property()
url = "";
@property({type: Array})
url: string[] = [];
chart?: Chart;
@ -40,15 +45,7 @@ export class AdminLoginsChart extends LitElement {
}
firstUpdated(): void {
fetch(this.url)
.then((r) => r.json())
.catch((e) => {
showMessage({
level_tag: "error",
message: "Unexpected error"
});
console.error(e);
})
DefaultClient.fetch<LoginMetrics>(this.url)
.then((r) => {
const canvas = <HTMLCanvasElement>this.shadowRoot?.querySelector("canvas");
if (!canvas) {

View File

@ -12,10 +12,17 @@ export class Tabs extends LitElement {
@property()
currentPage?: string;
@property({type: Boolean})
vertical = false;
static get styles(): CSSResult[] {
return [GlobalsStyle, TabsStyle, css`
::slotted(*) {
height: 100%;
flex-grow: 2;
}
:host([vertical]) {
display: flex;
}
`];
}
@ -39,7 +46,7 @@ export class Tabs extends LitElement {
}
this.currentPage = pages[0].attributes.getNamedItem("slot")?.value;
}
return html`<div class="pf-c-tabs">
return html`<div class="pf-c-tabs ${this.vertical ? "pf-m-vertical pf-m-box" : ""}">
<ul class="pf-c-tabs__list">
${pages.map((page) => this.renderTab(page))}
</ul>

View File

@ -1,6 +1,5 @@
import { gettext } from "django";
import { LitElement, html, customElement, TemplateResult, property } from "lit-element";
import { DefaultClient } from "../../api/Client";
import "./Message";
import { APIMessage } from "./Message";
@ -15,7 +14,6 @@ export function showMessage(message: APIMessage): void {
@customElement("ak-message-container")
export class MessageContainer extends LitElement {
url = DefaultClient.makeUrl(["root", "messages"]);
@property({attribute: false})
messages: APIMessage[] = [];
@ -36,10 +34,6 @@ export class MessageContainer extends LitElement {
}
}
firstUpdated(): void {
this.fetchMessages();
}
connect(): void {
const wsUrl = `${window.location.protocol.replace("http", "ws")}//${
window.location.host
@ -74,21 +68,6 @@ export class MessageContainer extends LitElement {
});
}
/* Fetch messages which were stored in the session.
* This mostly gets messages which were created when the user arrives/leaves the site
* and especially the login flow */
fetchMessages(): Promise<void> {
console.debug("authentik/messages: fetching messages over direct api");
return fetch(this.url)
.then((r) => r.json())
.then((r: APIMessage[]) => {
r.forEach((m: APIMessage) => {
this.messages.push(m);
this.requestUpdate();
});
});
}
render(): TemplateResult {
return html`<ul class="pf-c-alert-group pf-m-toast">
${this.messages.map((m) => {

View File

@ -119,13 +119,15 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
return html`<ak-stage-authenticator-validate-code
.host=${this}
.challenge=${this.challenge}
.deviceChallenge=${this.selectedDeviceChallenge}>
.deviceChallenge=${this.selectedDeviceChallenge}
.showBackButton=${(this.challenge?.device_challenges.length || []) > 1}>
</ak-stage-authenticator-validate-code>`;
case DeviceClasses.WEBAUTHN:
return html`<ak-stage-authenticator-validate-webauthn
.host=${this}
.challenge=${this.challenge}
.deviceChallenge=${this.selectedDeviceChallenge}>
.deviceChallenge=${this.selectedDeviceChallenge}
.showBackButton=${(this.challenge?.device_challenges.length || []) > 1}>
</ak-stage-authenticator-validate-webauthn>`;
}
}

View File

@ -14,6 +14,9 @@ export class AuthenticatorValidateStageWebCode extends BaseStage {
@property({ attribute: false })
deviceChallenge?: DeviceChallenge;
@property({ type: Boolean })
showBackButton = false;
static get styles(): CSSResult[] {
return COMMON_STYLES;
}
@ -61,14 +64,16 @@ export class AuthenticatorValidateStageWebCode extends BaseStage {
</div>
<footer class="pf-c-login__main-footer">
<ul class="pf-c-login__main-footer-links">
<li class="pf-c-login__main-footer-links-item">
<button class="pf-c-button pf-m-secondary pf-m-block" @click=${() => {
if (!this.host) return;
(this.host as AuthenticatorValidateStage).selectedDeviceChallenge = undefined;
}}>
${gettext("Return to device picker")}
</button>
</li>
${this.showBackButton ?
html`<li class="pf-c-login__main-footer-links-item">
<button class="pf-c-button pf-m-secondary pf-m-block" @click=${() => {
if (!this.host) return;
(this.host as AuthenticatorValidateStage).selectedDeviceChallenge = undefined;
}}>
${gettext("Return to device picker")}
</button>
</li>`:
html``}
</ul>
</footer>`;
}

View File

@ -21,6 +21,9 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage {
@property()
authenticateMessage = "";
@property({type: Boolean})
showBackButton = false;
static get styles(): CSSResult[] {
return COMMON_STYLES;
}
@ -98,14 +101,16 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage {
</div>
<footer class="pf-c-login__main-footer">
<ul class="pf-c-login__main-footer-links">
<li class="pf-c-login__main-footer-links-item">
<button class="pf-c-button pf-m-secondary pf-m-block" @click=${() => {
if (!this.host) return;
(this.host as AuthenticatorValidateStage).selectedDeviceChallenge = undefined;
}}>
${gettext("Return to device picker")}
</button>
</li>
${this.showBackButton ?
html`<li class="pf-c-login__main-footer-links-item">
<button class="pf-c-button pf-m-secondary pf-m-block" @click=${() => {
if (!this.host) return;
(this.host as AuthenticatorValidateStage).selectedDeviceChallenge = undefined;
}}>
${gettext("Return to device picker")}
</button>
</li>`:
html``}
</ul>
</footer>`;
}

View File

@ -1,6 +1,5 @@
import { gettext } from "django";
import { CSSResult, customElement, html, LitElement, TemplateResult } from "lit-element";
import { DefaultClient } from "../../api/Client";
import { COMMON_STYLES } from "../../common/styles";
import "../../elements/AdminLoginsChart";
@ -31,7 +30,7 @@ export class AdminOverviewPage extends LitElement {
<section class="pf-c-page__main-section">
<div class="pf-l-gallery pf-m-gutter">
<ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header="Logins over the last 24 hours" style="grid-column-end: span 3;grid-row-end: span 2;">
<ak-admin-logins-chart url="${DefaultClient.makeUrl(["admin", "metrics"])}"></ak-admin-logins-chart>
<ak-admin-logins-chart .url="${["admin", "metrics"]}"></ak-admin-logins-chart>
</ak-aggregate-card>
<ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header="Apps with most usage" style="grid-column-end: span 2;grid-row-end: span 3;">
<ak-top-applications-table></ak-top-applications-table>

View File

@ -1,7 +1,6 @@
import { gettext } from "django";
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import { Application } from "../../api/Applications";
import { DefaultClient } from "../../api/Client";
import { COMMON_STYLES } from "../../common/styles";
import "../../elements/Tabs";
@ -71,7 +70,7 @@ export class ApplicationViewPage extends LitElement {
<div class="pf-c-card__body">
${this.application ? html`
<ak-admin-logins-chart
url="${DefaultClient.makeUrl(["core", "applications", this.application?.slug, "metrics"])}">
.url="${["core", "applications", this.application?.slug, "metrics"]}">
</ak-admin-logins-chart>`: ""}
</div>
</div>