wip: rename to authentik (#361)
* root: initial rename * web: rename custom element prefix * root: rename external functions with pb_ prefix * root: fix formatting * root: replace domain with goauthentik.io * proxy: update path * root: rename remaining prefixes * flows: rename file extension * root: pbadmin -> akadmin * docs: fix image filenames * lifecycle: ignore migration files * ci: copy default config from current source before loading last tagged * *: new sentry dsn * tests: fix missing python3.9-dev package * root: add additional migrations for service accounts created by outposts * core: mark system-created service accounts with attribute * policies/expression: fix pb_ replacement not working * web: fix last linting errors, add lit-analyse * policies/expressions: fix lint errors * web: fix sidebar display on screens where not all items fit * proxy: attempt to fix proxy pipeline * proxy: use go env GOPATH to get gopath * lib: fix user_default naming inconsistency * docs: add upgrade docs * docs: update screenshots to use authentik * admin: fix create button on empty-state of outpost * web: fix modal submit not refreshing SiteShell and Table * web: fix height of app-card and height of generic icon * web: fix rendering of subtext * admin: fix version check error not being caught * web: fix worker count not being shown * docs: update screenshots * root: new icon * web: fix lint error * admin: fix linting error * root: migrate coverage config to pyproject
|
Before Width: | Height: | Size: 284 B After Width: | Height: | Size: 284 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 351 B After Width: | Height: | Size: 351 B |
|
Before Width: | Height: | Size: 402 B After Width: | Height: | Size: 402 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 543 B After Width: | Height: | Size: 543 B |
|
Before Width: | Height: | Size: 368 B After Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 878 B After Width: | Height: | Size: 878 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@ -10,7 +10,7 @@ variables:
|
||||
stages:
|
||||
- stage: lint
|
||||
jobs:
|
||||
- job: lint
|
||||
- job: eslint
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
steps:
|
||||
@ -27,6 +27,23 @@ stages:
|
||||
command: 'custom'
|
||||
workingDir: 'web/'
|
||||
customCommand: 'run lint'
|
||||
- job: lit_analyse
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: '12.x'
|
||||
displayName: 'Install Node.js'
|
||||
- task: Npm@1
|
||||
inputs:
|
||||
command: 'install'
|
||||
workingDir: 'web/'
|
||||
- task: Npm@1
|
||||
inputs:
|
||||
command: 'custom'
|
||||
workingDir: 'web/'
|
||||
customCommand: 'run lit-analyse'
|
||||
- stage: build_local
|
||||
jobs:
|
||||
- job: build
|
||||
@ -55,7 +72,7 @@ stages:
|
||||
- task: Docker@2
|
||||
inputs:
|
||||
containerRegistry: 'dockerhub'
|
||||
repository: 'beryju/passbook-static'
|
||||
repository: 'beryju/authentik-static'
|
||||
command: 'buildAndPush'
|
||||
Dockerfile: 'web/Dockerfile'
|
||||
tags: "gh-${{ variables.branchName }}"
|
||||
|
||||
@ -14,8 +14,9 @@ const resources = [
|
||||
{ src: "node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css", dest: "dist/" },
|
||||
{ src: "node_modules/@patternfly/patternfly/assets/*", dest: "dist/assets/" },
|
||||
{ src: "src/index.html", dest: "dist" },
|
||||
{ src: "src/passbook.css", dest: "dist" },
|
||||
{ src: "src/authentik.css", dest: "dist" },
|
||||
{ src: "src/assets/*", dest: "dist/assets" },
|
||||
{ src: "../icons/*", dest: "dist/assets/icons" },
|
||||
];
|
||||
|
||||
export default [
|
||||
|
||||
@ -19,13 +19,13 @@ export class Config {
|
||||
return DefaultClient.fetch<Config>(["root", "config"]).then((config) => {
|
||||
if (config.error_reporting_enabled) {
|
||||
Sentry.init({
|
||||
dsn: "https://33cdbcb23f8b436dbe0ee06847410b67@sentry.beryju.org/3",
|
||||
release: `passbook@${VERSION}`,
|
||||
dsn: "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8",
|
||||
release: `authentik@${VERSION}`,
|
||||
integrations: [new Integrations.BrowserTracing()],
|
||||
tracesSampleRate: 1.0,
|
||||
environment: config.error_reporting_environment,
|
||||
});
|
||||
console.debug("passbook/config: Sentry enabled.");
|
||||
console.debug("authentik/config: Sentry enabled.");
|
||||
}
|
||||
return config;
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB |
@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<path style="fill:#57565C;" d="M407,512H105C47.103,512,0,464.897,0,407V105C0,47.103,47.103,0,105,0h302
|
||||
c57.897,0,105,47.103,105,105v302C512,464.897,464.897,512,407,512z"/>
|
||||
<path style="fill:#3E3D42;" d="M407,0H256v512h151c57.897,0,105-47.103,105-105V105C512,47.103,464.897,0,407,0z"/>
|
||||
<rect x="91" y="141" style="fill:#00C3FF;" width="330" height="44"/>
|
||||
<rect x="256" y="141" style="fill:#00AAF0;" width="165" height="44"/>
|
||||
<rect x="91" y="176" style="fill:#FFDC40;" width="330" height="44"/>
|
||||
<rect x="256" y="176" style="fill:#FFAB15;" width="165" height="44"/>
|
||||
<rect x="91" y="206" style="fill:#87E694;" width="330" height="44"/>
|
||||
<rect x="256" y="206" style="fill:#66CC70;" width="165" height="44"/>
|
||||
<path style="fill:#F2F2F2;" d="M421,381c0,8.284-6.716,15-15,15H106c-8.284,0-15-6.716-15-15v-85h89.997
|
||||
c9.31,0,17.688,4.938,21.868,12.888C213.277,328.695,233.638,341,256,341s42.723-12.305,53.135-32.111
|
||||
c4.18-7.95,12.559-12.889,21.868-12.889H421V381z"/>
|
||||
<path style="fill:#FF6849;" d="M421,266h-89.997c-20.487,0-39.041,11.085-48.423,28.929C277.369,304.842,267.185,311,256,311
|
||||
s-21.369-6.158-26.58-16.071C220.038,277.085,201.484,266,180.997,266H91v-30h330V266z"/>
|
||||
<path style="fill:#F2F2F2;" d="M421,146H91v-15c0-8.284,6.716-15,15-15h300c8.284,0,15,6.716,15,15V146z"/>
|
||||
<path style="fill:#E5E5E5;" d="M331.003,296c-9.31,0-17.688,4.938-21.868,12.889C298.723,328.695,278.362,341,256,341v55h150
|
||||
c8.284,0,15-6.716,15-15v-85H331.003z"/>
|
||||
<path style="fill:#FD4B2D;" d="M256,236v75c11.185,0,21.369-6.158,26.58-16.071C291.962,277.085,310.516,266,331.003,266H421v-30
|
||||
H256z"/>
|
||||
<path style="fill:#E5E5E5;" d="M406,116H256v30h165v-15C421,122.716,414.284,116,406,116z"/>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
@ -1,12 +1,3 @@
|
||||
@font-face {
|
||||
font-family: "DIN 1451 Std";
|
||||
src: url("assets/fonts/DINEngschriftStd.woff2") format("woff2"),
|
||||
url("assets/fonts/DINEngschriftStd.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
html {
|
||||
--pf-c-nav__link--PaddingTop: 0.5rem;
|
||||
--pf-c-nav__link--PaddingRight: 0.5rem;
|
||||
@ -14,25 +5,6 @@ html {
|
||||
--pf-c-nav__link--PaddingLeft: 0.5rem;
|
||||
}
|
||||
|
||||
.pb-brand {
|
||||
font-family: "DIN 1451 Std";
|
||||
font-size: 4em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-right: 0.5em;
|
||||
color: var(--pf-global--Color--light-200);
|
||||
}
|
||||
|
||||
.pb-brand > a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.pb-brand > img {
|
||||
max-height: 68px;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
/* Fix patternfly sidebar and header with open Modal */
|
||||
.pf-c-page__sidebar {
|
||||
z-index: 0;
|
||||
@ -81,15 +53,15 @@ select[multiple] {
|
||||
line-height: var(--pf-global--spacer--xl);
|
||||
}
|
||||
|
||||
/* Static OTP Tokens, passbook.stages.otp_static */
|
||||
.pb-otp-tokens {
|
||||
/* Static OTP Tokens, authentik.stages.otp_static */
|
||||
.ak-otp-tokens {
|
||||
list-style: circle;
|
||||
columns: 2;
|
||||
-webkit-columns: 2;
|
||||
-moz-columns: 2;
|
||||
margin-left: var(--pf-global--spacer--xs);
|
||||
}
|
||||
.pb-otp-tokens li {
|
||||
.ak-otp-tokens li {
|
||||
font-size: var(--pf-global--FontSize--2xl);
|
||||
font-family: monospace;
|
||||
}
|
||||
@ -109,3 +81,7 @@ select[multiple] {
|
||||
.pf-c-content h1 :first-child {
|
||||
margin-right: var(--pf-global--spacer--sm);
|
||||
}
|
||||
|
||||
.subtext {
|
||||
font-size: var(--pf-global--FontSize--sm);
|
||||
}
|
||||
@ -5,7 +5,7 @@ import PFAddons from "@patternfly/patternfly/patternfly-addons.css";
|
||||
// @ts-ignore
|
||||
import FA from "@fortawesome/fontawesome-free/css/fontawesome.css";
|
||||
// @ts-ignore
|
||||
import PBGlobal from "../passbook.css";
|
||||
import PBGlobal from "../authentik.css";
|
||||
import { CSSResult } from "lit-element";
|
||||
|
||||
export const COMMON_STYLES: CSSResult[] = [PF, PFAddons, FA, PBGlobal];
|
||||
|
||||
@ -6,7 +6,7 @@ interface TickValue {
|
||||
major: boolean;
|
||||
}
|
||||
|
||||
@customElement("pb-admin-logins-chart")
|
||||
@customElement("ak-admin-logins-chart")
|
||||
export class AdminLoginsChart extends LitElement {
|
||||
@property()
|
||||
url = "";
|
||||
|
||||
@ -7,7 +7,7 @@ import "codemirror/mode/xml/xml.js";
|
||||
import "codemirror/mode/yaml/yaml.js";
|
||||
import "codemirror/mode/python/python.js";
|
||||
|
||||
@customElement("pb-codemirror")
|
||||
@customElement("ak-codemirror")
|
||||
export class CodeMirrorTextarea extends LitElement {
|
||||
@property({type: Boolean})
|
||||
readOnly = false;
|
||||
|
||||
@ -18,7 +18,7 @@ interface Message {
|
||||
message: string;
|
||||
}
|
||||
|
||||
@customElement("pb-messages")
|
||||
@customElement("ak-messages")
|
||||
export class Messages extends LitElement {
|
||||
url = DefaultClient.makeUrl(["root", "messages"]);
|
||||
|
||||
@ -34,7 +34,7 @@ export class Messages extends LitElement {
|
||||
try {
|
||||
this.connect();
|
||||
} catch (error) {
|
||||
console.warn(`passbook/messages: failed to connect to ws ${error}`);
|
||||
console.warn(`authentik/messages: failed to connect to ws ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,12 +48,12 @@ export class Messages extends LitElement {
|
||||
}/ws/client/`;
|
||||
this.messageSocket = new WebSocket(wsUrl);
|
||||
this.messageSocket.addEventListener("open", () => {
|
||||
console.debug(`passbook/messages: connected to ${wsUrl}`);
|
||||
console.debug(`authentik/messages: connected to ${wsUrl}`);
|
||||
});
|
||||
this.messageSocket.addEventListener("close", (e) => {
|
||||
console.debug(`passbook/messages: closed ws connection: ${e}`);
|
||||
console.debug(`authentik/messages: closed ws connection: ${e}`);
|
||||
setTimeout(() => {
|
||||
console.debug(`passbook/messages: reconnecting ws in ${this.retryDelay}ms`);
|
||||
console.debug(`authentik/messages: reconnecting ws in ${this.retryDelay}ms`);
|
||||
this.connect();
|
||||
}, this.retryDelay);
|
||||
this.retryDelay = this.retryDelay * 2;
|
||||
@ -63,7 +63,7 @@ export class Messages extends LitElement {
|
||||
this.renderMessage(data);
|
||||
});
|
||||
this.messageSocket.addEventListener("error", (e) => {
|
||||
console.warn(`passbook/messages: error ${e}`);
|
||||
console.warn(`authentik/messages: error ${e}`);
|
||||
this.retryDelay = this.retryDelay * 2;
|
||||
});
|
||||
}
|
||||
@ -72,7 +72,7 @@ export class Messages extends LitElement {
|
||||
* This mostly gets messages which were created when the user arrives/leaves the site
|
||||
* and especially the login flow */
|
||||
fetchMessages(): Promise<void> {
|
||||
console.debug("passbook/messages: fetching messages over direct api");
|
||||
console.debug("authentik/messages: fetching messages over direct api");
|
||||
return fetch(this.url)
|
||||
.then((r) => r.json())
|
||||
.then((r: Message[]) => {
|
||||
@ -85,10 +85,10 @@ export class Messages extends LitElement {
|
||||
renderMessage(message: Message): void {
|
||||
const container = <HTMLElement>this.querySelector(".pf-c-alert-group");
|
||||
if (!container) {
|
||||
console.warn("passbook/messages: failed to find container");
|
||||
console.warn("authentik/messages: failed to find container");
|
||||
return;
|
||||
}
|
||||
const id = ID("pb-message");
|
||||
const id = ID("ak-message");
|
||||
const el = document.createElement("template");
|
||||
el.innerHTML = `<li id=${id} class="pf-c-alert-group__item">
|
||||
<div class="pf-c-alert pf-m-${message.level_tag} ${message.level_tag === "error" ? "pf-m-danger" : ""}">
|
||||
|
||||
@ -10,7 +10,7 @@ export enum SpinnerSize {
|
||||
XLarge = "pf-m-xl",
|
||||
}
|
||||
|
||||
@customElement("pb-spinner")
|
||||
@customElement("ak-spinner")
|
||||
export class Spinner extends LitElement {
|
||||
@property()
|
||||
size: SpinnerSize = SpinnerSize.Medium;
|
||||
|
||||
@ -5,8 +5,9 @@ import TabsStyle from "@patternfly/patternfly/components/Tabs/tabs.css";
|
||||
// @ts-ignore
|
||||
import GlobalsStyle from "@patternfly/patternfly/base/patternfly-globals.css";
|
||||
import { CURRENT_CLASS } from "../constants";
|
||||
import { gettext } from "django";
|
||||
|
||||
@customElement("pb-tabs")
|
||||
@customElement("ak-tabs")
|
||||
export class Tabs extends LitElement {
|
||||
@property()
|
||||
currentPage?: string;
|
||||
@ -20,7 +21,7 @@ export class Tabs extends LitElement {
|
||||
return html` <li class="pf-c-tabs__item ${slot === this.currentPage ? CURRENT_CLASS : ""}">
|
||||
<button class="pf-c-tabs__link" @click=${() => { this.currentPage = slot; }}>
|
||||
<span class="pf-c-tabs__item-text">
|
||||
${page.attributes.getNamedItem("tab-title")?.value}
|
||||
${page.getAttribute("data-tab-title")}
|
||||
</span>
|
||||
</button>
|
||||
</li>`;
|
||||
@ -30,7 +31,7 @@ export class Tabs extends LitElement {
|
||||
const pages = Array.from(this.querySelectorAll("[slot]"));
|
||||
if (!this.currentPage) {
|
||||
if (pages.length < 1) {
|
||||
return html`<h1>no tabs defined</h1>`;
|
||||
return html`<h1>${gettext("no tabs defined")}</h1>`;
|
||||
}
|
||||
this.currentPage = pages[0].attributes.getNamedItem("slot")?.value;
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ import { customElement, property } from "lit-element";
|
||||
import { ERROR_CLASS, SUCCESS_CLASS } from "../../constants";
|
||||
import { SpinnerButton } from "./SpinnerButton";
|
||||
|
||||
@customElement("pb-action-button")
|
||||
@customElement("ak-action-button")
|
||||
export class ActionButton extends SpinnerButton {
|
||||
@property()
|
||||
url = "";
|
||||
@ -13,7 +13,7 @@ export class ActionButton extends SpinnerButton {
|
||||
return;
|
||||
}
|
||||
this.setLoading();
|
||||
const csrftoken = getCookie("passbook_csrf");
|
||||
const csrftoken = getCookie("authentik_csrf");
|
||||
if (!csrftoken) {
|
||||
console.debug("No csrf token in cookie");
|
||||
this.setDone(ERROR_CLASS);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { customElement, html, LitElement, TemplateResult } from "lit-element";
|
||||
|
||||
@customElement("pb-dropdown")
|
||||
@customElement("ak-dropdown")
|
||||
export class DropdownButton extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@ -14,7 +14,7 @@ import { convertToSlug } from "../../utils";
|
||||
import { SpinnerButton } from "./SpinnerButton";
|
||||
import { PRIMARY_CLASS } from "../../constants";
|
||||
|
||||
@customElement("pb-modal-button")
|
||||
@customElement("ak-modal-button")
|
||||
export class ModalButton extends LitElement {
|
||||
@property()
|
||||
href?: string;
|
||||
@ -92,17 +92,17 @@ export class ModalButton extends LitElement {
|
||||
if (data.indexOf("csrfmiddlewaretoken") !== -1) {
|
||||
const modalSlot = this.querySelector("[slot=modal]");
|
||||
if (!modalSlot) {
|
||||
console.debug("passbook/modalbutton: modal slot not found?");
|
||||
console.debug("authentik/modalbutton: modal slot not found?");
|
||||
return;
|
||||
}
|
||||
modalSlot.innerHTML = data;
|
||||
console.debug("passbook/modalbutton: re-showing form");
|
||||
console.debug("authentik/modalbutton: re-showing form");
|
||||
this.updateHandlers();
|
||||
} else {
|
||||
this.open = false;
|
||||
console.debug("passbook/modalbutton: successful submit");
|
||||
console.debug("authentik/modalbutton: successful submit");
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("hashchange", {
|
||||
new CustomEvent("ak-refresh", {
|
||||
bubbles: true,
|
||||
})
|
||||
);
|
||||
@ -133,7 +133,7 @@ export class ModalButton extends LitElement {
|
||||
modalSlot.innerHTML = t;
|
||||
this.updateHandlers();
|
||||
this.open = true;
|
||||
this.querySelectorAll<SpinnerButton>("pb-spinner-button").forEach((sb) => {
|
||||
this.querySelectorAll<SpinnerButton>("ak-spinner-button").forEach((sb) => {
|
||||
sb.setDone(PRIMARY_CLASS);
|
||||
});
|
||||
})
|
||||
|
||||
@ -7,7 +7,7 @@ import ButtonStyle from "@patternfly/patternfly/components/Button/button.css";
|
||||
import SpinnerStyle from "@patternfly/patternfly/components/Spinner/spinner.css";
|
||||
import { ColorStyles, PRIMARY_CLASS, PROGRESS_CLASS } from "../../constants";
|
||||
|
||||
@customElement("pb-spinner-button")
|
||||
@customElement("ak-spinner-button")
|
||||
export class SpinnerButton extends LitElement {
|
||||
@property({type: Boolean})
|
||||
isRunning = false;
|
||||
|
||||
@ -6,7 +6,7 @@ import ButtonStyle from "@patternfly/patternfly/components/Button/button.css";
|
||||
import { tokenByIdentifier } from "../../api/token";
|
||||
import { ColorStyles, ERROR_CLASS, PRIMARY_CLASS, SUCCESS_CLASS } from "../../constants";
|
||||
|
||||
@customElement("pb-token-copy-button")
|
||||
@customElement("ak-token-copy-button")
|
||||
export class TokenCopyButton extends LitElement {
|
||||
@property()
|
||||
identifier?: string;
|
||||
|
||||
@ -3,7 +3,7 @@ import { css, CSSResult, customElement, html, LitElement, property, TemplateResu
|
||||
import { ifDefined } from "lit-html/directives/if-defined";
|
||||
import { COMMON_STYLES } from "../../common/styles";
|
||||
|
||||
@customElement("pb-aggregate-card")
|
||||
@customElement("ak-aggregate-card")
|
||||
export class AggregateCard extends LitElement {
|
||||
@property()
|
||||
icon?: string;
|
||||
@ -20,9 +20,6 @@ export class AggregateCard extends LitElement {
|
||||
font-size: var(--pf-global--icon--FontSize--lg);
|
||||
text-align: center;
|
||||
}
|
||||
.subtext {
|
||||
font-size: var(--pf-global--FontSize--sm);
|
||||
}
|
||||
`]);
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import { AggregateCard } from "./AggregateCard";
|
||||
import "../Spinner";
|
||||
import { SpinnerSize } from "../Spinner";
|
||||
|
||||
@customElement("pb-aggregate-card-promise")
|
||||
@customElement("ak-aggregate-card-promise")
|
||||
export class AggregatePromiseCard extends AggregateCard {
|
||||
@property({attribute: false})
|
||||
promise?: Promise<Record<string, unknown>>;
|
||||
@ -20,7 +20,7 @@ export class AggregatePromiseCard extends AggregateCard {
|
||||
|
||||
renderInner(): TemplateResult {
|
||||
return html`<p class="center-value">
|
||||
${until(this.promiseProxy(), html`<pb-spinner size="${SpinnerSize.Large}"></pb-spinner>`)}
|
||||
${until(this.promiseProxy(), html`<ak-spinner size="${SpinnerSize.Large}"></ak-spinner>`)}
|
||||
</p>`;
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ export interface SidebarItem {
|
||||
condition?: () => Promise<boolean>;
|
||||
}
|
||||
|
||||
@customElement("pb-sidebar")
|
||||
@customElement("ak-sidebar")
|
||||
export class Sidebar extends LitElement {
|
||||
@property({attribute: false})
|
||||
items: SidebarItem[] = [];
|
||||
@ -36,6 +36,18 @@ export class Sidebar extends LitElement {
|
||||
max-height: 82px;
|
||||
margin-bottom: -0.5rem;
|
||||
}
|
||||
nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 100vh;
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.pf-c-nav__list {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.pf-c-nav__link {
|
||||
--pf-c-nav__link--PaddingTop: 0.5rem;
|
||||
--pf-c-nav__link--PaddingRight: 0.5rem;
|
||||
@ -44,12 +56,6 @@ export class Sidebar extends LitElement {
|
||||
.pf-c-nav__subnav {
|
||||
--pf-c-nav__subnav--PaddingBottom: 0px;
|
||||
}
|
||||
|
||||
.pf-c-nav__item-bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
@ -89,18 +95,12 @@ export class Sidebar extends LitElement {
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<div class="pf-c-page__sidebar-body">
|
||||
<nav class="pf-c-nav" aria-label="Global">
|
||||
<ul class="pf-c-nav__list">
|
||||
<li class="pf-c-nav__item sidebar-brand">
|
||||
<pb-sidebar-brand></pb-sidebar-brand>
|
||||
</li>
|
||||
${this.items.map((i) => until(this.renderItem(i), html``))}
|
||||
<li class="pf-c-nav__item pf-c-nav__item-bottom">
|
||||
<pb-sidebar-user></pb-sidebar-user>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>`;
|
||||
return html`<nav class="pf-c-nav" aria-label="Global">
|
||||
<ak-sidebar-brand></ak-sidebar-brand>
|
||||
<ul class="pf-c-nav__list">
|
||||
${this.items.map((i) => until(this.renderItem(i), html``))}
|
||||
</ul>
|
||||
<ak-sidebar-user></ak-sidebar-user>
|
||||
</nav>`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,15 +6,15 @@ import GlobalsStyle from "@patternfly/patternfly/base/patternfly-globals.css";
|
||||
import { Config } from "../../api/config";
|
||||
|
||||
export const DefaultConfig: Config = {
|
||||
branding_logo: " /static/dist/assets/images/logo.svg",
|
||||
branding_title: "passbook",
|
||||
branding_logo: " /static/dist/assets/icons/icon_left_brand.svg",
|
||||
branding_title: "authentik",
|
||||
|
||||
error_reporting_enabled: false,
|
||||
error_reporting_environment: "",
|
||||
error_reporting_send_pii: false,
|
||||
};
|
||||
|
||||
@customElement("pb-sidebar-brand")
|
||||
@customElement("ak-sidebar-brand")
|
||||
export class SidebarBrand extends LitElement {
|
||||
@property({attribute: false})
|
||||
config: Config = DefaultConfig;
|
||||
@ -24,41 +24,28 @@ export class SidebarBrand extends LitElement {
|
||||
GlobalsStyle,
|
||||
PageStyle,
|
||||
css`
|
||||
.pf-c-brand {
|
||||
font-family: "DIN 1451 Std";
|
||||
line-height: 60px;
|
||||
font-size: 3rem;
|
||||
color: var(--pf-c-nav__link--m-current--Color);
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin: 0 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
height: 82px;
|
||||
}
|
||||
.pf-c-brand img {
|
||||
max-height: 60px;
|
||||
margin-right: 8px;
|
||||
width: 100%;
|
||||
padding: 0 .5rem;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
firstUpdated(): void {
|
||||
Config.get().then((c) => (this.config = c));
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
if (!this.config) {
|
||||
return html``;
|
||||
}
|
||||
return html` <a href="#/" class="pf-c-page__header-brand-link">
|
||||
<div class="pf-c-brand pb-brand">
|
||||
<img src="${this.config.branding_logo}" alt="passbook icon" loading="lazy" />
|
||||
${this.config.branding_title
|
||||
? html`<span>${this.config.branding_title}</span>`
|
||||
: ""}
|
||||
<div class="pf-c-brand ak-brand">
|
||||
<img src="${this.config.branding_logo}" alt="authentik icon" loading="lazy" />
|
||||
</div>
|
||||
</a>`;
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import AvatarStyle from "@patternfly/patternfly/components/Avatar/avatar.css";
|
||||
import { User } from "../../api/user";
|
||||
import { until } from "lit-html/directives/until";
|
||||
|
||||
@customElement("pb-sidebar-user")
|
||||
@customElement("ak-sidebar-user")
|
||||
export class SidebarUser extends LitElement {
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
|
||||
@ -21,6 +21,13 @@ export abstract class Table<T> extends LitElement {
|
||||
return COMMON_STYLES;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.addEventListener("ak-refresh", () => {
|
||||
this.fetch();
|
||||
});
|
||||
}
|
||||
|
||||
public fetch(): void {
|
||||
this.apiEndpoint(this.page).then((r) => {
|
||||
this.data = r;
|
||||
@ -74,15 +81,15 @@ export abstract class Table<T> extends LitElement {
|
||||
<slot name="create-button"></slot>
|
||||
<button
|
||||
@click=${() => {this.fetch();}}
|
||||
class="pf-c-button pf-m-primary"
|
||||
>
|
||||
class="pf-c-button pf-m-primary">
|
||||
${gettext("Refresh")}
|
||||
</button>
|
||||
</div>
|
||||
<pb-table-pagination
|
||||
<ak-table-pagination
|
||||
class="pf-c-toolbar__item pf-m-pagination"
|
||||
.table=${this}
|
||||
></pb-table-pagination>
|
||||
.pages=${this.data?.pagination}
|
||||
.pageChangeHandler=${(page: number) => {this.page = page; }}>
|
||||
</ak-table-pagination>
|
||||
</div>
|
||||
</div>
|
||||
<table class="pf-c-table pf-m-compact pf-m-grid-md">
|
||||
@ -96,10 +103,11 @@ export abstract class Table<T> extends LitElement {
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="pf-c-pagination pf-m-bottom">
|
||||
<pb-table-pagination
|
||||
<ak-table-pagination
|
||||
class="pf-c-toolbar__item pf-m-pagination"
|
||||
.table=${this}
|
||||
></pb-table-pagination>
|
||||
.pages=${this.data?.pagination}
|
||||
.pageChangeHandler=${(page: number) => { this.page = page; }}>
|
||||
</ak-table-pagination>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
|
||||
@ -1,41 +1,29 @@
|
||||
import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
|
||||
import { Table } from "./Table";
|
||||
import { COMMON_STYLES } from "../../common/styles";
|
||||
import { PBPagination } from "../../api/client";
|
||||
|
||||
@customElement("pb-table-pagination")
|
||||
@customElement("ak-table-pagination")
|
||||
export class TablePagination extends LitElement {
|
||||
@property({attribute: false})
|
||||
table?: Table<unknown>;
|
||||
pages?: PBPagination;
|
||||
|
||||
@property({attribute: false})
|
||||
// eslint-disable-next-line
|
||||
pageChangeHandler: (page: number) => void = (page: number) => {}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return COMMON_STYLES;
|
||||
}
|
||||
|
||||
previousHandler(): void {
|
||||
if (!this.table?.data?.pagination.previous) {
|
||||
console.debug("passbook/tables: no previous");
|
||||
return;
|
||||
}
|
||||
this.table.page = this.table?.data?.pagination.previous;
|
||||
}
|
||||
|
||||
nextHandler(): void {
|
||||
if (!this.table?.data?.pagination.next) {
|
||||
console.debug("passbook/tables: no next");
|
||||
return;
|
||||
}
|
||||
this.table.page = this.table?.data?.pagination.next;
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html` <div class="pf-c-pagination pf-m-compact pf-m-hidden pf-m-visible-on-md">
|
||||
<div class="pf-c-pagination pf-m-compact pf-m-compact pf-m-hidden pf-m-visible-on-md">
|
||||
<div class="pf-c-options-menu">
|
||||
<div class="pf-c-options-menu__toggle pf-m-text pf-m-plain">
|
||||
<span class="pf-c-options-menu__toggle-text">
|
||||
${this.table?.data?.pagination.start_index} -
|
||||
${this.table?.data?.pagination.end_index} of
|
||||
${this.table?.data?.pagination.count}
|
||||
${this.pages?.start_index} -
|
||||
${this.pages?.end_index} of
|
||||
${this.pages?.count}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -43,8 +31,8 @@ export class TablePagination extends LitElement {
|
||||
<div class="pf-c-pagination__nav-control pf-m-prev">
|
||||
<button
|
||||
class="pf-c-button pf-m-plain"
|
||||
@click=${() => {this.previousHandler();}}
|
||||
?disabled="${(this.table?.data?.pagination.previous || 0) > 0}"
|
||||
@click=${() => { this.pageChangeHandler(this.pages?.previous || 0); }}
|
||||
?disabled="${(this.pages?.previous || 0) > 0}"
|
||||
aria-label="{% trans 'Go to previous page' %}"
|
||||
>
|
||||
<i class="fas fa-angle-left" aria-hidden="true"></i>
|
||||
@ -53,8 +41,8 @@ export class TablePagination extends LitElement {
|
||||
<div class="pf-c-pagination__nav-control pf-m-next">
|
||||
<button
|
||||
class="pf-c-button pf-m-plain"
|
||||
@click=${() => {this.nextHandler();}}
|
||||
?disabled="${(this.table?.data?.pagination.next || 0) > 0}"
|
||||
@click=${() => { this.pageChangeHandler(this.pages?.next || 0); }}
|
||||
?disabled="${(this.pages?.next || 0) > 0}"
|
||||
aria-label="{% trans 'Go to next page' %}"
|
||||
>
|
||||
<i class="fas fa-angle-right" aria-hidden="true"></i>
|
||||
|
||||
@ -3,23 +3,23 @@
|
||||
<head>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/static/passbook/fonts/DINEngschriftStd.woff2"
|
||||
href="/static/authentik/fonts/DINEngschriftStd.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/static/passbook/fonts/DINEngschriftStd.woff"
|
||||
href="/static/authentik/fonts/DINEngschriftStd.woff"
|
||||
as="font"
|
||||
type="font/woff"
|
||||
crossorigin
|
||||
/>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
<title>passbook</title>
|
||||
<link rel="icon" type="image/png" href="/static/dist/assets/images/logo.png" />
|
||||
<link rel="shortcut icon" type="image/png" href="/static/dist/assets/images/logo.png" />
|
||||
<title>authentik</title>
|
||||
<link rel="icon" type="image/png" href="/static/dist/assets/icons/icon.png" />
|
||||
<link rel="shortcut icon" type="image/png" href="/static/dist/assets/icons/icon.png" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
@ -35,24 +35,24 @@
|
||||
type="text/css"
|
||||
href="/static/node_modules/%40fortawesome/fontawesome-free/css/fontawesome.min.css"
|
||||
/>
|
||||
<link rel="stylesheet" type="text/css" href="/static/passbook/passbook.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/static/authentik/authentik.css" />
|
||||
<script src="/static/dist/main.js" type="module"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pb-messages url="/api/v2beta/root/messages/"></pb-messages>
|
||||
<ak-messages url="/api/v2beta/root/messages/"></ak-messages>
|
||||
<div class="pf-c-page">
|
||||
<a class="pf-c-skip-to-content pf-c-button pf-m-primary" href="#main-content"
|
||||
>Skip to content</a
|
||||
>
|
||||
<pb-sidebar class="pf-c-page__sidebar"> </pb-sidebar>
|
||||
<pb-router-outlet
|
||||
<ak-sidebar class="pf-c-page__sidebar"> </ak-sidebar>
|
||||
<ak-router-outlet
|
||||
role="main"
|
||||
class="pf-c-page__main"
|
||||
tabindex="-1"
|
||||
id="main-content"
|
||||
defaultUrl="/library/"
|
||||
>
|
||||
</pb-router-outlet>
|
||||
</ak-router-outlet>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -117,7 +117,7 @@ export const SIDEBAR_ITEMS: SidebarItem[] = [
|
||||
},
|
||||
];
|
||||
|
||||
@customElement("pb-interface-admin")
|
||||
@customElement("ak-interface-admin")
|
||||
export class AdminInterface extends Interface {
|
||||
|
||||
get sidebar(): SidebarItem[] {
|
||||
|
||||
@ -14,14 +14,14 @@ export abstract class Interface extends LitElement {
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<pb-messages></pb-messages>
|
||||
return html`<ak-messages></ak-messages>
|
||||
<div class="pf-c-page">
|
||||
<a class="pf-c-skip-to-content pf-c-button pf-m-primary" href="#main-content">${gettext("Skip to content")}</a>
|
||||
<pb-sidebar class="pf-c-page__sidebar" .items=${this.sidebar}>
|
||||
</pb-sidebar>
|
||||
<ak-sidebar class="pf-c-page__sidebar" .items=${this.sidebar}>
|
||||
</ak-sidebar>
|
||||
<main class="pf-c-page__main">
|
||||
<pb-router-outlet role="main" class="pf-c-page__main" tabindex="-1" id="main-content" defaultUrl="/library/">
|
||||
</pb-router-outlet>
|
||||
<ak-router-outlet role="main" class="pf-c-page__main" tabindex="-1" id="main-content" defaultUrl="/library/">
|
||||
</ak-router-outlet>
|
||||
</main>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import { PBResponse } from "../api/client";
|
||||
import { COMMON_STYLES } from "../common/styles";
|
||||
import { loading, truncate } from "../utils";
|
||||
|
||||
@customElement("ak-library-app")
|
||||
export class LibraryApplication extends LitElement {
|
||||
@property({attribute: false})
|
||||
application?: Application;
|
||||
@ -13,8 +14,11 @@ export class LibraryApplication extends LitElement {
|
||||
static get styles(): CSSResult[] {
|
||||
return COMMON_STYLES.concat(
|
||||
css`
|
||||
img.pf-icon {
|
||||
max-height: 24px;
|
||||
a {
|
||||
height: 100%;
|
||||
}
|
||||
i.pf-icon {
|
||||
height: 36px;
|
||||
}
|
||||
.pf-c-avatar {
|
||||
--pf-c-avatar--BorderRadius: 0;
|
||||
@ -25,7 +29,7 @@ export class LibraryApplication extends LitElement {
|
||||
|
||||
render(): TemplateResult {
|
||||
if (!this.application) {
|
||||
return html`<pb-spinner></pb-spinner>`;
|
||||
return html`<ak-spinner></ak-spinner>`;
|
||||
}
|
||||
return html` <a href="${this.application.launch_url}" class="pf-c-card pf-m-hoverable pf-m-compact">
|
||||
<div class="pf-c-card__header">
|
||||
@ -45,7 +49,7 @@ export class LibraryApplication extends LitElement {
|
||||
|
||||
}
|
||||
|
||||
@customElement("pb-library")
|
||||
@customElement("ak-library")
|
||||
export class LibraryPage extends LitElement {
|
||||
@property({attribute: false})
|
||||
apps?: PBResponse<Application>;
|
||||
@ -72,7 +76,7 @@ export class LibraryPage extends LitElement {
|
||||
|
||||
renderApps(): TemplateResult {
|
||||
return html`<div class="pf-l-gallery pf-m-gutter">
|
||||
${this.apps?.results.map((app) => html`<pb-library-app application=${app}></pb-library-app>`)}
|
||||
${this.apps?.results.map((app) => html`<ak-library-app .application=${app}></ak-library-app>`)}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import { SpinnerSize } from "../../elements/Spinner";
|
||||
import "../../elements/AdminLoginsChart";
|
||||
import "./TopApplicationsTable";
|
||||
|
||||
@customElement("pb-admin-status-card")
|
||||
@customElement("ak-admin-status-card")
|
||||
export class AdminStatusCard extends AggregatePromiseCard {
|
||||
|
||||
@property({type: Number})
|
||||
@ -23,17 +23,17 @@ export class AdminStatusCard extends AggregatePromiseCard {
|
||||
lessThanThreshold?: number;
|
||||
|
||||
renderNone(): TemplateResult {
|
||||
return html`<pb-spinner size=${SpinnerSize.Large}></pb-spinner>`;
|
||||
return html`<ak-spinner size=${SpinnerSize.Large}></ak-spinner>`;
|
||||
}
|
||||
|
||||
renderGood(): TemplateResult {
|
||||
return html`<p class="pb-aggregate-card">
|
||||
return html`<p class="ak-aggregate-card">
|
||||
<i class="fa fa-check-circle"></i> ${this.value}
|
||||
</p>`;
|
||||
}
|
||||
|
||||
renderBad(): TemplateResult {
|
||||
return html`<p class="pb-aggregate-card">
|
||||
return html`<p class="ak-aggregate-card">
|
||||
<i class="fa fa-exclamation-triangle"></i> ${this.value}
|
||||
</p>
|
||||
<p class="subtext">${this.warningText ? gettext(this.warningText) : ""}</p>`;
|
||||
@ -49,7 +49,7 @@ export class AdminStatusCard extends AggregatePromiseCard {
|
||||
|
||||
}
|
||||
|
||||
@customElement("pb-admin-overview")
|
||||
@customElement("ak-admin-overview")
|
||||
export class AdminOverviewPage extends LitElement {
|
||||
@property({attribute: false})
|
||||
data?: AdminOverview;
|
||||
@ -74,45 +74,54 @@ export class AdminOverviewPage extends LitElement {
|
||||
</section>
|
||||
<section class="pf-c-page__main-section">
|
||||
<div class="pf-l-gallery pf-m-gutter">
|
||||
<pb-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;">
|
||||
<pb-admin-logins-chart url="${DefaultClient.makeUrl(["admin", "metrics"])}"></pb-admin-logins-chart>
|
||||
</pb-aggregate-card>
|
||||
<pb-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;">
|
||||
<pb-top-applications-table></pb-top-applications-table>
|
||||
</pb-aggregate-card>
|
||||
<pb-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header="Workers">
|
||||
|
||||
</pb-aggregate-card>
|
||||
<pb-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header="Providers" headerLink="#/administration/providers/">
|
||||
<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-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>
|
||||
</ak-aggregate-card>
|
||||
<ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header="Workers">
|
||||
${this.data ?
|
||||
this.data?.worker_count < 1 ?
|
||||
html`<p class="ak-aggregate-card">
|
||||
<i class="fa fa-exclamation-triangle"></i> ${this.data?.worker_count}
|
||||
</p>
|
||||
<p class="subtext">${gettext("No workers connected.")}</p>` :
|
||||
html`<p class="ak-aggregate-card">
|
||||
<i class="fa fa-check-circle"></i> ${this.data?.worker_count}
|
||||
</p>`
|
||||
: html`<ak-spinner size=${SpinnerSize.Large}></ak-spinner>`}
|
||||
</ak-aggregate-card>
|
||||
<ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header="Providers" headerLink="#/administration/providers/">
|
||||
${this.data ?
|
||||
this.data?.providers_without_application > 1 ?
|
||||
html`<p class="pb-aggregate-card">
|
||||
html`<p class="ak-aggregate-card">
|
||||
<i class="fa fa-exclamation-triangle"></i> 0
|
||||
</p>
|
||||
<p class="subtext">${gettext("At least one Provider has no application assigned.")}</p>` :
|
||||
html`<p class="pb-aggregate-card">
|
||||
html`<p class="ak-aggregate-card">
|
||||
<i class="fa fa-check-circle"></i> 0
|
||||
</p>`
|
||||
: html`<pb-spinner size=${SpinnerSize.Large}></pb-spinner>`}
|
||||
</pb-aggregate-card>
|
||||
<pb-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header="Policies" headerLink="#/administration/policies/">
|
||||
: html`<ak-spinner size=${SpinnerSize.Large}></ak-spinner>`}
|
||||
</ak-aggregate-card>
|
||||
<ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header="Policies" headerLink="#/administration/policies/">
|
||||
${this.data ?
|
||||
this.data?.policies_without_binding > 1 ?
|
||||
html`<p class="pb-aggregate-card">
|
||||
html`<p class="ak-aggregate-card">
|
||||
<i class="fa fa-exclamation-triangle"></i> 0
|
||||
</p>
|
||||
<p class="subtext">${gettext("Policies without binding exist.")}</p>` :
|
||||
html`<p class="pb-aggregate-card">
|
||||
html`<p class="ak-aggregate-card">
|
||||
<i class="fa fa-check-circle"></i> 0
|
||||
</p>`
|
||||
: html`<pb-spinner size=${SpinnerSize.Large}></pb-spinner>`}
|
||||
</pb-aggregate-card>
|
||||
<pb-aggregate-card-promise
|
||||
: html`<ak-spinner size=${SpinnerSize.Large}></ak-spinner>`}
|
||||
</ak-aggregate-card>
|
||||
<ak-aggregate-card-promise
|
||||
icon="pf-icon pf-icon-user"
|
||||
header="Users"
|
||||
headerLink="#/administration/users/"
|
||||
.promise=${this.users}>
|
||||
</pb-aggregate-card-promise>
|
||||
</ak-aggregate-card-promise>
|
||||
</div>
|
||||
</section>`;
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import { COMMON_STYLES } from "../../common/styles";
|
||||
|
||||
import "../../elements/Spinner";
|
||||
|
||||
@customElement("pb-top-applications-table")
|
||||
@customElement("ak-top-applications-table")
|
||||
export class TopApplicationsTable extends LitElement {
|
||||
|
||||
@property({attribute: false})
|
||||
@ -43,7 +43,7 @@ export class TopApplicationsTable extends LitElement {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody role="rowgroup">
|
||||
${this.topN ? this.topN.map((e) => this.renderRow(e)) : html`<pb-spinner></pb-spinner>`}
|
||||
${this.topN ? this.topN.map((e) => this.renderRow(e)) : html`<ak-spinner></ak-spinner>`}
|
||||
</tbody>
|
||||
</table>`;
|
||||
}
|
||||
|
||||
@ -4,13 +4,13 @@ import { Application } from "../../api/application";
|
||||
import { PBResponse } from "../../api/client";
|
||||
import { TablePage } from "../../elements/table/TablePage";
|
||||
|
||||
@customElement("pb-application-list")
|
||||
@customElement("ak-application-list")
|
||||
export class ApplicationList extends TablePage<Application> {
|
||||
pageTitle(): string {
|
||||
return gettext("Applications");
|
||||
}
|
||||
pageDescription(): string {
|
||||
return gettext("External Applications which use passbook as Identity-Provider, utilizing protocols like OAuth2 and SAML.");
|
||||
return gettext("External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML.");
|
||||
}
|
||||
pageIcon(): string {
|
||||
return gettext("pf-icon pf-icon-applications");
|
||||
@ -34,18 +34,18 @@ export class ApplicationList extends TablePage<Application> {
|
||||
item.provider.toString(),
|
||||
item.provider.toString(),
|
||||
`
|
||||
<pb-modal-button href="administration/policies/bindings/${item.pk}/update/">
|
||||
<pb-spinner-button slot="trigger" class="pf-m-secondary">
|
||||
<ak-modal-button href="administration/policies/bindings/${item.pk}/update/">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-secondary">
|
||||
Edit
|
||||
</pb-spinner-button>
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</pb-modal-button>
|
||||
<pb-modal-button href="administration/policies/bindings/${item.pk}/delete/">
|
||||
<pb-spinner-button slot="trigger" class="pf-m-danger">
|
||||
</ak-modal-button>
|
||||
<ak-modal-button href="administration/policies/bindings/${item.pk}/delete/">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-danger">
|
||||
Delete
|
||||
</pb-spinner-button>
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</pb-modal-button>
|
||||
</ak-modal-button>
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ import { Table } from "../../elements/table/Table";
|
||||
import "../../elements/Tabs";
|
||||
import "../../elements/AdminLoginsChart";
|
||||
|
||||
@customElement("pb-bound-policies-list")
|
||||
@customElement("ak-bound-policies-list")
|
||||
export class BoundPoliciesList extends Table<PolicyBinding> {
|
||||
@property()
|
||||
target?: string;
|
||||
@ -33,24 +33,24 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
|
||||
item.order.toString(),
|
||||
item.timeout.toString(),
|
||||
`
|
||||
<pb-modal-button href="administration/policies/bindings/${item.pk}/update/">
|
||||
<pb-spinner-button slot="trigger" class="pf-m-secondary">
|
||||
<ak-modal-button href="administration/policies/bindings/${item.pk}/update/">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-secondary">
|
||||
Edit
|
||||
</pb-spinner-button>
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</pb-modal-button>
|
||||
<pb-modal-button href="administration/policies/bindings/${item.pk}/delete/">
|
||||
<pb-spinner-button slot="trigger" class="pf-m-danger">
|
||||
</ak-modal-button>
|
||||
<ak-modal-button href="administration/policies/bindings/${item.pk}/delete/">
|
||||
<ak-spinner-button slot="trigger" class="pf-m-danger">
|
||||
Delete
|
||||
</pb-spinner-button>
|
||||
</ak-spinner-button>
|
||||
<div slot="modal"></div>
|
||||
</pb-modal-button>
|
||||
</ak-modal-button>
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@customElement("pb-application-view")
|
||||
@customElement("ak-application-view")
|
||||
export class ApplicationViewPage extends LitElement {
|
||||
@property()
|
||||
set args(value: { [key: string]: string }) {
|
||||
@ -88,8 +88,8 @@ export class ApplicationViewPage extends LitElement {
|
||||
<p>${this.application?.meta_publisher}</p>
|
||||
</div>
|
||||
</section>
|
||||
<pb-tabs>
|
||||
<section slot="page-1" tab-title="Users" class="pf-c-page__main-section pf-m-no-padding-mobile">
|
||||
<ak-tabs>
|
||||
<section slot="page-1" data-tab-title="Users" class="pf-c-page__main-section pf-m-no-padding-mobile">
|
||||
<div class="pf-l-gallery pf-m-gutter">
|
||||
<div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-4-col" style="grid-column-end: span 3;grid-row-end: span 2;">
|
||||
<div class="pf-c-card__header">
|
||||
@ -99,18 +99,18 @@ export class ApplicationViewPage extends LitElement {
|
||||
</div>
|
||||
<div class="pf-c-card__body">
|
||||
${this.application ? html`
|
||||
<pb-admin-logins-chart
|
||||
<ak-admin-logins-chart
|
||||
url="${DefaultClient.makeUrl(["core", "applications", this.application?.slug, "metrics"])}">
|
||||
</pb-admin-logins-chart>`: ""}
|
||||
</ak-admin-logins-chart>`: ""}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div slot="page-2" tab-title="Policy Bindings" class="pf-c-page__main-section pf-m-no-padding-mobile">
|
||||
<div slot="page-2" data-tab-title="Policy Bindings" class="pf-c-page__main-section pf-m-no-padding-mobile">
|
||||
<div class="pf-c-card">
|
||||
<pb-bound-policies-list .target=${this.application.pk}></pb-bound-policies-list>
|
||||
<ak-bound-policies-list .target=${this.application.pk}></ak-bound-policies-list>
|
||||
</div>
|
||||
</div>
|
||||
</pb-tabs>`;
|
||||
</ak-tabs>`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ interface Response {
|
||||
body?: string;
|
||||
}
|
||||
|
||||
@customElement("pb-flow-shell-card")
|
||||
@customElement("ak-flow-shell-card")
|
||||
export class FlowShellCard extends LitElement {
|
||||
@property()
|
||||
flowBodyUrl = "";
|
||||
@ -59,7 +59,7 @@ export class FlowShellCard extends LitElement {
|
||||
this.setFormSubmitHandlers();
|
||||
break;
|
||||
default:
|
||||
console.debug(`passbook/flows: unexpected data type ${data.type}`);
|
||||
console.debug(`authentik/flows: unexpected data type ${data.type}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -84,13 +84,13 @@ export class FlowShellCard extends LitElement {
|
||||
const element = <HTMLInputElement>form.elements[index];
|
||||
if (element.value === form.action) {
|
||||
console.debug(
|
||||
"passbook/flows: Found Form action URL in form elements, not changing form action."
|
||||
"authentik/flows: Found Form action URL in form elements, not changing form action."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
form.action = this.flowBodyUrl;
|
||||
console.debug(`passbook/flows: updated form.action ${this.flowBodyUrl}`);
|
||||
console.debug(`authentik/flows: updated form.action ${this.flowBodyUrl}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -102,11 +102,11 @@ export class FlowShellCard extends LitElement {
|
||||
|
||||
setFormSubmitHandlers(): void {
|
||||
this.querySelectorAll("form").forEach((form) => {
|
||||
console.debug(`passbook/flows: Checking for autosubmit attribute ${form}`);
|
||||
console.debug(`authentik/flows: Checking for autosubmit attribute ${form}`);
|
||||
this.checkAutosubmit(form);
|
||||
console.debug(`passbook/flows: Setting action for form ${form}`);
|
||||
console.debug(`authentik/flows: Setting action for form ${form}`);
|
||||
this.updateFormAction(form);
|
||||
console.debug(`passbook/flows: Adding handler for form ${form}`);
|
||||
console.debug(`authentik/flows: Adding handler for form ${form}`);
|
||||
form.addEventListener("submit", (e) => {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(form);
|
||||
@ -125,14 +125,14 @@ export class FlowShellCard extends LitElement {
|
||||
this.errorMessage(e);
|
||||
});
|
||||
});
|
||||
form.classList.add("pb-flow-wrapped");
|
||||
form.classList.add("ak-flow-wrapped");
|
||||
});
|
||||
}
|
||||
|
||||
errorMessage(error: string): void {
|
||||
this.flowBody = `
|
||||
<style>
|
||||
.pb-exception {
|
||||
.ak-exception {
|
||||
font-family: monospace;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
@ -146,12 +146,12 @@ export class FlowShellCard extends LitElement {
|
||||
<h3>
|
||||
Something went wrong! Please try again later.
|
||||
</h3>
|
||||
<pre class="pb-exception">${error}</pre>
|
||||
<pre class="ak-exception">${error}</pre>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
loading(): TemplateResult {
|
||||
return html` <div class="pf-c-login__main-body pb-loading">
|
||||
return html` <div class="pf-c-login__main-body ak-loading">
|
||||
<span class="pf-c-spinner" role="progressbar" aria-valuetext="Loading...">
|
||||
<span class="pf-c-spinner__clipper"></span>
|
||||
<span class="pf-c-spinner__lead-ball"></span>
|
||||
|
||||
@ -7,7 +7,7 @@ import SpinnerStyle from "@patternfly/patternfly/components/Spinner/spinner.css"
|
||||
import BackdropStyle from "@patternfly/patternfly/components/Backdrop/backdrop.css";
|
||||
import { SpinnerSize } from "../../elements/Spinner";
|
||||
|
||||
@customElement("pb-site-shell")
|
||||
@customElement("ak-site-shell")
|
||||
export class SiteShell extends LitElement {
|
||||
@property()
|
||||
set url(value: string) {
|
||||
@ -45,6 +45,13 @@ export class SiteShell extends LitElement {
|
||||
];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.addEventListener("ak-refresh", () => {
|
||||
this.loadContent();
|
||||
});
|
||||
}
|
||||
|
||||
loadContent(): void {
|
||||
if (!this._url) {
|
||||
return;
|
||||
@ -55,7 +62,7 @@ export class SiteShell extends LitElement {
|
||||
if (r.ok) {
|
||||
return r;
|
||||
}
|
||||
console.debug(`passbook/site-shell: Request failed ${this._url}`);
|
||||
console.debug(`authentik/site-shell: Request failed ${this._url}`);
|
||||
window.location.hash = "#/";
|
||||
throw new Error("Request failed");
|
||||
})
|
||||
@ -69,7 +76,7 @@ export class SiteShell extends LitElement {
|
||||
})
|
||||
.then(() => {
|
||||
// Ensure anchors only change the hash
|
||||
this.querySelectorAll<HTMLAnchorElement>("a:not(.pb-root-link)").forEach((a) => {
|
||||
this.querySelectorAll<HTMLAnchorElement>("a:not(.ak-root-link)").forEach((a) => {
|
||||
if (a.href === "") {
|
||||
return;
|
||||
}
|
||||
@ -78,12 +85,12 @@ export class SiteShell extends LitElement {
|
||||
const qs = url.search || "";
|
||||
a.href = `#${url.pathname}${qs}`;
|
||||
} catch (e) {
|
||||
console.debug(`passbook/site-shell: error ${e}`);
|
||||
console.debug(`authentik/site-shell: error ${e}`);
|
||||
a.href = `#${a.href}`;
|
||||
}
|
||||
});
|
||||
// Create refresh buttons
|
||||
this.querySelectorAll("[role=pb-refresh]").forEach((rt) => {
|
||||
this.querySelectorAll("[role=ak-refresh]").forEach((rt) => {
|
||||
rt.addEventListener("click", () => {
|
||||
this.loadContent();
|
||||
});
|
||||
@ -108,7 +115,7 @@ export class SiteShell extends LitElement {
|
||||
html`<div class="pf-c-backdrop">
|
||||
<div class="pf-l-bullseye">
|
||||
<div class="pf-l-bullseye__item">
|
||||
<pb-spinner size=${SpinnerSize.Large}></pb-spinner>
|
||||
<ak-spinner size=${SpinnerSize.Large}></ak-spinner>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
@ -15,7 +15,7 @@ export class Route {
|
||||
|
||||
redirect(to: string): Route {
|
||||
this.callback = () => {
|
||||
console.debug(`passbook/router: redirecting ${to}`);
|
||||
console.debug(`authentik/router: redirecting ${to}`);
|
||||
window.location.hash = `#${to}`;
|
||||
return html``;
|
||||
};
|
||||
|
||||
@ -11,7 +11,7 @@ import { RouteMatch } from "./RouteMatch";
|
||||
|
||||
import "../generic/SiteShell";
|
||||
|
||||
@customElement("pb-router-outlet")
|
||||
@customElement("ak-router-outlet")
|
||||
export class RouterOutlet extends LitElement {
|
||||
@property({attribute: false})
|
||||
current?: RouteMatch;
|
||||
@ -46,28 +46,28 @@ export class RouterOutlet extends LitElement {
|
||||
if (activeUrl === "") {
|
||||
activeUrl = this.defaultUrl || "/";
|
||||
window.location.hash = `#${activeUrl}`;
|
||||
console.debug(`passbook/router: set to ${window.location.hash}`);
|
||||
console.debug(`authentik/router: set to ${window.location.hash}`);
|
||||
return;
|
||||
}
|
||||
let matchedRoute: RouteMatch | null = null;
|
||||
ROUTES.some((route) => {
|
||||
console.debug(`passbook/router: matching ${activeUrl} against ${route.url}`);
|
||||
console.debug(`authentik/router: matching ${activeUrl} against ${route.url}`);
|
||||
const match = route.url.exec(activeUrl);
|
||||
if (match != null) {
|
||||
matchedRoute = new RouteMatch(route);
|
||||
matchedRoute.arguments = match.groups || {};
|
||||
matchedRoute.fullUrl = activeUrl;
|
||||
console.debug(`passbook/router: found match ${matchedRoute}`);
|
||||
console.debug(`authentik/router: found match ${matchedRoute}`);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!matchedRoute) {
|
||||
console.debug(`passbook/router: route "${activeUrl}" not defined, defaulting to shell`);
|
||||
console.debug(`authentik/router: route "${activeUrl}" not defined, defaulting to shell`);
|
||||
const route = new Route(
|
||||
RegExp(""),
|
||||
html`<pb-site-shell url=${activeUrl}>
|
||||
html`<ak-site-shell url=${activeUrl}>
|
||||
<div slot="body"></div>
|
||||
</pb-site-shell>`
|
||||
</ak-site-shell>`
|
||||
);
|
||||
matchedRoute = new RouteMatch(route);
|
||||
matchedRoute.arguments = route.url.exec(activeUrl)?.groups || {};
|
||||
|
||||
@ -10,10 +10,10 @@ export const ROUTES: Route[] = [
|
||||
// Prevent infinite Shell loops
|
||||
new Route(new RegExp("^/$")).redirect("/library/"),
|
||||
new Route(new RegExp("^#.*")).redirect("/library/"),
|
||||
new Route(new RegExp("^/library/$"), html`<pb-library></pb-library>`),
|
||||
new Route(new RegExp("^/administration/overview-ng/$"), html`<pb-admin-overview></pb-admin-overview>`),
|
||||
new Route(new RegExp("^/applications/$"), html`<pb-application-list></pb-application-list>`),
|
||||
new Route(new RegExp("^/library/$"), html`<ak-library></ak-library>`),
|
||||
new Route(new RegExp("^/administration/overview-ng/$"), html`<ak-admin-overview></ak-admin-overview>`),
|
||||
new Route(new RegExp("^/applications/$"), html`<ak-application-list></ak-application-list>`),
|
||||
new Route(new RegExp(`^/applications/(?<slug>${SLUG_REGEX})/$`)).then((args) => {
|
||||
return html`<pb-application-view .args=${args}></pb-application-view>`;
|
||||
return html`<ak-application-view .args=${args}></ak-application-view>`;
|
||||
}),
|
||||
];
|
||||
|
||||
@ -42,7 +42,7 @@ export function loading<T>(v: T, actual: TemplateResult): TemplateResult {
|
||||
<div class="pf-c-empty-state__content">
|
||||
<div class="pf-l-bullseye">
|
||||
<div class="pf-l-bullseye__item">
|
||||
<pb-spinner size="${SpinnerSize.Large}"></pb-spinner>
|
||||
<ak-spinner size="${SpinnerSize.Large}"></ak-spinner>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||