root: improve sentry distributed tracing (#14468)
* core: include all sentry headers Signed-off-by: Jens Langhammer <jens@goauthentik.io> * remove spotlight patch we dont need anymore Signed-off-by: Jens Langhammer <jens@goauthentik.io> * always trace in debug Signed-off-by: Jens Langhammer <jens@goauthentik.io> * init sentry earlier Signed-off-by: Jens Langhammer <jens@goauthentik.io> * re-add light interface https://github.com/goauthentik/authentik/pull/14331 removes 2 unneeded API calls Signed-off-by: Jens Langhammer <jens@goauthentik.io> * sentry integrated router Signed-off-by: Jens Langhammer <jens@goauthentik.io> * use new Sentry middleware to propagate headers Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix missing baggage Signed-off-by: Jens Langhammer <jens@goauthentik.io> * cleanup logs Signed-off-by: Jens Langhammer <jens@goauthentik.io> * use sanitized URLs for logging/tracing Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
1
web/package-lock.json
generated
1
web/package-lock.json
generated
@ -7,7 +7,6 @@
|
||||
"": {
|
||||
"name": "@goauthentik/web",
|
||||
"version": "0.0.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
".",
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
"lint:precommit": "wireit",
|
||||
"lint:types": "wireit",
|
||||
"lit-analyse": "wireit",
|
||||
"postinstall": "bash scripts/patch-spotlight.sh",
|
||||
"precommit": "wireit",
|
||||
"prettier": "wireit",
|
||||
"prettier-check": "wireit",
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
* @import { Message as ESBuildMessage } from "esbuild";
|
||||
*/
|
||||
|
||||
const logPrefix = "👷 [ESBuild]";
|
||||
const logPrefix = "authentik/dev/web: ";
|
||||
const log = console.debug.bind(console, logPrefix);
|
||||
|
||||
/**
|
||||
@ -76,7 +76,7 @@ export class ESBuildObserver extends EventSource {
|
||||
*/
|
||||
#startListener = () => {
|
||||
this.#trackActivity();
|
||||
log("⏰ Build started...");
|
||||
log("⏰ Build started...");
|
||||
};
|
||||
|
||||
#internalErrorListener = () => {
|
||||
@ -86,7 +86,7 @@ export class ESBuildObserver extends EventSource {
|
||||
clearTimeout(this.#keepAliveInterval);
|
||||
|
||||
this.close();
|
||||
log("⛔️ Closing connection");
|
||||
log("⛔️ Closing connection");
|
||||
}
|
||||
};
|
||||
|
||||
@ -126,13 +126,13 @@ export class ESBuildObserver extends EventSource {
|
||||
this.#trackActivity();
|
||||
|
||||
if (!this.online) {
|
||||
log("🚫 Build finished while offline.");
|
||||
log("🚫 Build finished while offline.");
|
||||
this.deferredReload = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
log("🛎️ Build completed! Reloading...");
|
||||
log("🛎️ Build completed! Reloading...");
|
||||
|
||||
// We use an animation frame to keep the reload from happening before the
|
||||
// event loop has a chance to process the message.
|
||||
@ -189,13 +189,13 @@ export class ESBuildObserver extends EventSource {
|
||||
|
||||
if (!this.deferredReload) return;
|
||||
|
||||
log("🛎️ Reloading after offline build...");
|
||||
log("🛎️ Reloading after offline build...");
|
||||
this.deferredReload = false;
|
||||
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
log("🛎️ Listening for build changes...");
|
||||
log("🛎️ Listening for build changes...");
|
||||
|
||||
this.#keepAliveInterval = setInterval(() => {
|
||||
const now = Date.now();
|
||||
@ -203,7 +203,7 @@ export class ESBuildObserver extends EventSource {
|
||||
if (now - this.lastUpdatedAt < 10_000) return;
|
||||
|
||||
this.alive = false;
|
||||
log("👋 Waiting for build to start...");
|
||||
log("👋 Waiting for build to start...");
|
||||
}, 15_000);
|
||||
}
|
||||
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
TARGET="./node_modules/@spotlightjs/overlay/dist/index-"[0-9a-f]*.js
|
||||
|
||||
if [[ $(grep -L "QX2" "$TARGET" > /dev/null 2> /dev/null) ]]; then
|
||||
patch --forward -V none --no-backup-if-mismatch -p0 $TARGET <<EOF
|
||||
|
||||
TARGET=$(find "./node_modules/@spotlightjs/overlay/dist/" -name "index-[0-9a-f]*.js");
|
||||
|
||||
if ! grep -GL 'QX2 = ' "$TARGET" > /dev/null ; then
|
||||
patch --forward --no-backup-if-mismatch -p0 "$TARGET" <<EOF
|
||||
>>>>>>> main
|
||||
--- a/index-5682ce90.js 2024-06-13 16:19:28
|
||||
+++ b/index-5682ce90.js 2024-06-13 16:20:23
|
||||
@@ -4958,11 +4958,10 @@
|
||||
}
|
||||
);
|
||||
}
|
||||
-const q2 = w.lazy(() => import("./main-3257b7fc.js").then((n) => n.m));
|
||||
+const q2 = w.lazy(() => import("./main-3257b7fc.js").then((n) => n.m)), QX2 = () => {};
|
||||
function Gp({
|
||||
data: n,
|
||||
- onUpdateData: a = () => {
|
||||
- },
|
||||
+ onUpdateData: a = QX2,
|
||||
editingEnabled: s = !1,
|
||||
clipboardEnabled: o = !1,
|
||||
displayDataTypes: c = !1,
|
||||
EOF
|
||||
|
||||
else
|
||||
echo "spotlight overlay.js patch already applied"
|
||||
fi
|
||||
@ -131,9 +131,9 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
|
||||
//#region Lifecycle
|
||||
|
||||
constructor() {
|
||||
configureSentry(true);
|
||||
super();
|
||||
this.ws = new WebsocketClient();
|
||||
|
||||
this.#sidebarMatcher = window.matchMedia("(min-width: 1200px)");
|
||||
this.sidebarOpen = this.#sidebarMatcher.matches;
|
||||
}
|
||||
@ -167,7 +167,6 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
|
||||
}
|
||||
|
||||
async firstUpdated(): Promise<void> {
|
||||
configureSentry(true);
|
||||
this.user = await me();
|
||||
|
||||
const canAccessAdmin =
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
} from "@goauthentik/common/api/middleware";
|
||||
import { EVENT_LOCALE_REQUEST, VERSION } from "@goauthentik/common/constants";
|
||||
import { globalAK } from "@goauthentik/common/global";
|
||||
import { SentryMiddleware } from "@goauthentik/common/sentry";
|
||||
|
||||
import { Config, Configuration, CoreApi, CurrentBrand, RootApi } from "@goauthentik/api";
|
||||
|
||||
@ -66,21 +67,13 @@ export function brand(): Promise<CurrentBrand> {
|
||||
return globalBrandPromise;
|
||||
}
|
||||
|
||||
export function getMetaContent(key: string): string {
|
||||
const metaEl = document.querySelector<HTMLMetaElement>(`meta[name=${key}]`);
|
||||
if (!metaEl) return "";
|
||||
return metaEl.content;
|
||||
}
|
||||
|
||||
export const DEFAULT_CONFIG = new Configuration({
|
||||
basePath: `${globalAK().api.base}api/v3`,
|
||||
headers: {
|
||||
"sentry-trace": getMetaContent("sentry-trace"),
|
||||
},
|
||||
middleware: [
|
||||
new CSRFMiddleware(),
|
||||
new EventMiddleware(),
|
||||
new LoggingMiddleware(globalAK().brand),
|
||||
new SentryMiddleware(),
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { config } from "@goauthentik/common/api/config";
|
||||
import { VERSION } from "@goauthentik/common/constants";
|
||||
import { globalAK } from "@goauthentik/common/global";
|
||||
import { me } from "@goauthentik/common/users";
|
||||
import { readInterfaceRouteParam } from "@goauthentik/elements/router/utils";
|
||||
import {
|
||||
@ -10,8 +10,16 @@ import {
|
||||
setTag,
|
||||
setUser,
|
||||
} from "@sentry/browser";
|
||||
import { getTraceData } from "@sentry/core";
|
||||
import * as Spotlight from "@spotlightjs/spotlight";
|
||||
|
||||
import { CapabilitiesEnum, Config, ResponseError } from "@goauthentik/api";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
FetchParams,
|
||||
Middleware,
|
||||
RequestContext,
|
||||
ResponseError,
|
||||
} from "@goauthentik/api";
|
||||
|
||||
/**
|
||||
* A generic error that can be thrown without triggering Sentry's reporting.
|
||||
@ -21,69 +29,94 @@ export class SentryIgnoredError extends Error {}
|
||||
export const TAG_SENTRY_COMPONENT = "authentik.component";
|
||||
export const TAG_SENTRY_CAPABILITIES = "authentik.capabilities";
|
||||
|
||||
export async function configureSentry(canDoPpi = false): Promise<Config> {
|
||||
const cfg = await config();
|
||||
let _sentryConfigured = false;
|
||||
|
||||
if (cfg.errorReporting.enabled) {
|
||||
init({
|
||||
dsn: cfg.errorReporting.sentryDsn,
|
||||
ignoreErrors: [
|
||||
/network/gi,
|
||||
/fetch/gi,
|
||||
/module/gi,
|
||||
// Error on edge on ios,
|
||||
// https://stackoverflow.com/questions/69261499/what-is-instantsearchsdkjsbridgeclearhighlight
|
||||
/instantSearchSDKJSBridgeClearHighlight/gi,
|
||||
// Seems to be an issue in Safari and Firefox
|
||||
/MutationObserver.observe/gi,
|
||||
/NS_ERROR_FAILURE/gi,
|
||||
],
|
||||
release: `authentik@${VERSION}`,
|
||||
export function configureSentry(canDoPpi = false) {
|
||||
const cfg = globalAK().config;
|
||||
const debug = cfg.capabilities.includes(CapabilitiesEnum.CanDebug);
|
||||
if (!cfg.errorReporting.enabled && !debug) {
|
||||
return cfg;
|
||||
}
|
||||
init({
|
||||
dsn: cfg.errorReporting.sentryDsn,
|
||||
ignoreErrors: [
|
||||
/network/gi,
|
||||
/fetch/gi,
|
||||
/module/gi,
|
||||
// Error on edge on ios,
|
||||
// https://stackoverflow.com/questions/69261499/what-is-instantsearchsdkjsbridgeclearhighlight
|
||||
/instantSearchSDKJSBridgeClearHighlight/gi,
|
||||
// Seems to be an issue in Safari and Firefox
|
||||
/MutationObserver.observe/gi,
|
||||
/NS_ERROR_FAILURE/gi,
|
||||
],
|
||||
release: `authentik@${VERSION}`,
|
||||
integrations: [
|
||||
browserTracingIntegration({
|
||||
// https://docs.sentry.io/platforms/javascript/tracing/instrumentation/automatic-instrumentation/#custom-routing
|
||||
instrumentNavigation: false,
|
||||
instrumentPageLoad: false,
|
||||
traceFetch: false,
|
||||
}),
|
||||
],
|
||||
tracePropagationTargets: [window.location.origin],
|
||||
tracesSampleRate: debug ? 1.0 : cfg.errorReporting.tracesSampleRate,
|
||||
environment: cfg.errorReporting.environment,
|
||||
beforeSend: (
|
||||
event: ErrorEvent,
|
||||
hint: EventHint,
|
||||
): ErrorEvent | PromiseLike<ErrorEvent | null> | null => {
|
||||
if (!hint) {
|
||||
return event;
|
||||
}
|
||||
if (hint.originalException instanceof SentryIgnoredError) {
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
hint.originalException instanceof ResponseError ||
|
||||
hint.originalException instanceof DOMException
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return event;
|
||||
},
|
||||
});
|
||||
setTag(TAG_SENTRY_CAPABILITIES, cfg.capabilities.join(","));
|
||||
if (window.location.pathname.includes("if/")) {
|
||||
setTag(TAG_SENTRY_COMPONENT, `web/${readInterfaceRouteParam()}`);
|
||||
}
|
||||
if (debug) {
|
||||
Spotlight.init({
|
||||
injectImmediately: true,
|
||||
integrations: [
|
||||
browserTracingIntegration({
|
||||
shouldCreateSpanForRequest: (url: string) => {
|
||||
return url.startsWith(window.location.host);
|
||||
},
|
||||
Spotlight.sentry({
|
||||
injectIntoSDK: true,
|
||||
}),
|
||||
],
|
||||
tracesSampleRate: cfg.errorReporting.tracesSampleRate,
|
||||
environment: cfg.errorReporting.environment,
|
||||
beforeSend: (
|
||||
event: ErrorEvent,
|
||||
hint: EventHint,
|
||||
): ErrorEvent | PromiseLike<ErrorEvent | null> | null => {
|
||||
if (!hint) {
|
||||
return event;
|
||||
}
|
||||
if (hint.originalException instanceof SentryIgnoredError) {
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
hint.originalException instanceof ResponseError ||
|
||||
hint.originalException instanceof DOMException
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return event;
|
||||
},
|
||||
});
|
||||
setTag(TAG_SENTRY_CAPABILITIES, cfg.capabilities.join(","));
|
||||
if (window.location.pathname.includes("if/")) {
|
||||
setTag(TAG_SENTRY_COMPONENT, `web/${readInterfaceRouteParam()}`);
|
||||
}
|
||||
if (cfg.capabilities.includes(CapabilitiesEnum.CanDebug)) {
|
||||
const Spotlight = await import("@spotlightjs/spotlight");
|
||||
|
||||
Spotlight.init({ injectImmediately: true });
|
||||
}
|
||||
if (cfg.errorReporting.sendPii && canDoPpi) {
|
||||
me().then((user) => {
|
||||
setUser({ email: user.user.email });
|
||||
console.debug("authentik/config: Sentry with PII enabled.");
|
||||
});
|
||||
} else {
|
||||
console.debug("authentik/config: Sentry enabled.");
|
||||
}
|
||||
console.debug("authentik/config: Enabled Sentry Spotlight");
|
||||
}
|
||||
if (cfg.errorReporting.sendPii && canDoPpi) {
|
||||
me().then((user) => {
|
||||
setUser({ email: user.user.email });
|
||||
console.debug("authentik/config: Sentry with PII enabled.");
|
||||
});
|
||||
} else {
|
||||
console.debug("authentik/config: Sentry enabled.");
|
||||
}
|
||||
_sentryConfigured = true;
|
||||
}
|
||||
|
||||
export class SentryMiddleware implements Middleware {
|
||||
pre?(context: RequestContext): Promise<FetchParams | void> {
|
||||
if (!_sentryConfigured) {
|
||||
return Promise.resolve(context);
|
||||
}
|
||||
const traceData = getTraceData();
|
||||
// @ts-ignore
|
||||
context.init.headers["baggage"] = traceData["baggage"];
|
||||
// @ts-ignore
|
||||
context.init.headers["sentry-trace"] = traceData["sentry-trace"];
|
||||
return Promise.resolve(context);
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
|
||||
@ -23,9 +23,20 @@ const configContext = Symbol("configContext");
|
||||
const modalController = Symbol("modalController");
|
||||
const versionContext = Symbol("versionContext");
|
||||
|
||||
export abstract class Interface extends AKElement implements ThemedElement {
|
||||
export abstract class LightInterface extends AKElement implements ThemedElement {
|
||||
protected static readonly PFBaseStyleSheet = createStyleSheetUnsafe(PFBase);
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const styleParent = resolveStyleSheetParent(document);
|
||||
|
||||
this.dataset.akInterfaceRoot = this.tagName.toLowerCase();
|
||||
|
||||
appendStyleSheet(styleParent, Interface.PFBaseStyleSheet);
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class Interface extends LightInterface implements ThemedElement {
|
||||
[configContext]: ConfigContextController;
|
||||
|
||||
[modalController]: ModalOrchestrationController;
|
||||
@ -38,12 +49,6 @@ export abstract class Interface extends AKElement implements ThemedElement {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const styleParent = resolveStyleSheetParent(document);
|
||||
|
||||
this.dataset.akInterfaceRoot = this.tagName.toLowerCase();
|
||||
|
||||
appendStyleSheet(styleParent, Interface.PFBaseStyleSheet);
|
||||
|
||||
this.addController(new BrandContextController(this));
|
||||
this[configContext] = new ConfigContextController(this);
|
||||
this[modalController] = new ModalOrchestrationController(this);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { AuthenticatedInterface, Interface } from "./Interface";
|
||||
import { AuthenticatedInterface, Interface, LightInterface } from "./Interface";
|
||||
|
||||
export { Interface, AuthenticatedInterface };
|
||||
export { Interface, AuthenticatedInterface, LightInterface };
|
||||
export default Interface;
|
||||
|
||||
@ -6,19 +6,35 @@ import { TemplateResult } from "lit";
|
||||
export class RouteMatch {
|
||||
route: Route;
|
||||
arguments: { [key: string]: string };
|
||||
fullUrl?: string;
|
||||
fullURL: string;
|
||||
|
||||
constructor(route: Route) {
|
||||
constructor(route: Route, fullUrl: string) {
|
||||
this.route = route;
|
||||
this.arguments = {};
|
||||
this.fullURL = fullUrl;
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return this.route.render(this.arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the matched Route's URL regex to a sanitized, readable URL by replacing
|
||||
* all regex values with placeholders according to the name of their regex group.
|
||||
*
|
||||
* @returns The sanitized URL for logging/tracing.
|
||||
*/
|
||||
sanitizedURL() {
|
||||
let cleanedURL = this.fullURL;
|
||||
for (const match of Object.keys(this.arguments)) {
|
||||
const value = this.arguments[match];
|
||||
cleanedURL = cleanedURL?.replace(value, `:${match}`);
|
||||
}
|
||||
return cleanedURL;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<RouteMatch url=${this.fullUrl} route=${this.route} arguments=${JSON.stringify(
|
||||
return `<RouteMatch url=${this.sanitizedURL()} route=${this.route} arguments=${JSON.stringify(
|
||||
this.arguments,
|
||||
)}>`;
|
||||
}
|
||||
|
||||
@ -3,8 +3,15 @@ import { AKElement } from "@goauthentik/elements/Base";
|
||||
import { Route } from "@goauthentik/elements/router/Route";
|
||||
import { RouteMatch } from "@goauthentik/elements/router/RouteMatch";
|
||||
import "@goauthentik/elements/router/Router404";
|
||||
import {
|
||||
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
|
||||
getClient,
|
||||
startBrowserTracingNavigationSpan,
|
||||
startBrowserTracingPageLoadSpan,
|
||||
} from "@sentry/browser";
|
||||
import { Client, Span } from "@sentry/types";
|
||||
|
||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||
import { CSSResult, PropertyValues, TemplateResult, css, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
// Poliyfill for hashchange.newURL,
|
||||
@ -53,6 +60,9 @@ export class RouterOutlet extends AKElement {
|
||||
@property({ attribute: false })
|
||||
routes: Route[] = [];
|
||||
|
||||
private sentryClient?: Client;
|
||||
private pageLoadSpan?: Span;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
css`
|
||||
@ -69,6 +79,15 @@ export class RouterOutlet extends AKElement {
|
||||
constructor() {
|
||||
super();
|
||||
window.addEventListener("hashchange", (ev: HashChangeEvent) => this.navigate(ev));
|
||||
this.sentryClient = getClient();
|
||||
if (this.sentryClient) {
|
||||
this.pageLoadSpan = startBrowserTracingPageLoadSpan(this.sentryClient, {
|
||||
name: window.location.pathname,
|
||||
attributes: {
|
||||
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
firstUpdated(): void {
|
||||
@ -92,9 +111,8 @@ export class RouterOutlet extends AKElement {
|
||||
this.routes.some((route) => {
|
||||
const match = route.url.exec(activeUrl);
|
||||
if (match !== null) {
|
||||
matchedRoute = new RouteMatch(route);
|
||||
matchedRoute = new RouteMatch(route, activeUrl);
|
||||
matchedRoute.arguments = match.groups || {};
|
||||
matchedRoute.fullUrl = activeUrl;
|
||||
console.debug("authentik/router: found match ", matchedRoute);
|
||||
return true;
|
||||
}
|
||||
@ -107,13 +125,31 @@ export class RouterOutlet extends AKElement {
|
||||
<ak-router-404 url=${activeUrl}></ak-router-404>
|
||||
</div>`;
|
||||
});
|
||||
matchedRoute = new RouteMatch(route);
|
||||
matchedRoute = new RouteMatch(route, activeUrl);
|
||||
matchedRoute.arguments = route.url.exec(activeUrl)?.groups || {};
|
||||
matchedRoute.fullUrl = activeUrl;
|
||||
}
|
||||
this.current = matchedRoute;
|
||||
}
|
||||
|
||||
updated(changedProperties: PropertyValues<this>): void {
|
||||
if (!changedProperties.has("current") || !this.current) return;
|
||||
if (!this.sentryClient) return;
|
||||
// https://docs.sentry.io/platforms/javascript/tracing/instrumentation/automatic-instrumentation/#custom-routing
|
||||
if (this.pageLoadSpan) {
|
||||
this.pageLoadSpan.updateName(this.current.sanitizedURL());
|
||||
this.pageLoadSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, "route");
|
||||
this.pageLoadSpan = undefined;
|
||||
} else {
|
||||
startBrowserTracingNavigationSpan(this.sentryClient, {
|
||||
op: "navigation",
|
||||
name: this.current.sanitizedURL(),
|
||||
attributes: {
|
||||
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render(): TemplateResult | undefined {
|
||||
return this.current?.render();
|
||||
}
|
||||
|
||||
@ -171,6 +171,7 @@ export class FlowExecutor extends Interface implements StageHost {
|
||||
}
|
||||
|
||||
constructor() {
|
||||
configureSentry();
|
||||
super();
|
||||
this.ws = new WebsocketClient();
|
||||
const inspector = new URL(window.location.toString()).searchParams.get("inspector");
|
||||
@ -237,7 +238,6 @@ export class FlowExecutor extends Interface implements StageHost {
|
||||
}
|
||||
|
||||
async firstUpdated(): Promise<void> {
|
||||
configureSentry();
|
||||
if (this.config?.capabilities.includes(CapabilitiesEnum.CanDebug)) {
|
||||
this.inspectorAvailable = true;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Interface } from "@goauthentik/elements/Interface";
|
||||
import { LightInterface } from "@goauthentik/elements/Interface";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||
@ -10,7 +10,7 @@ import PFSpinner from "@patternfly/patternfly/components/Spinner/spinner.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
@customElement("ak-loading")
|
||||
export class Loading extends Interface {
|
||||
export class Loading extends LightInterface {
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
PFBase,
|
||||
@ -25,16 +25,6 @@ export class Loading extends Interface {
|
||||
];
|
||||
}
|
||||
|
||||
registerContexts(): void {
|
||||
// Stub function to avoid making API requests for things we don't need. The `Interface` base class loads
|
||||
// a bunch of data that is used globally by various things, however this is an interface that is shown
|
||||
// very briefly and we don't need any of that data.
|
||||
}
|
||||
|
||||
async _initCustomCSS(): Promise<void> {
|
||||
// Stub function to avoid fetching custom CSS.
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html` <section
|
||||
class="ak-static-page pf-c-page__main-section pf-m-no-padding-mobile pf-m-xl"
|
||||
|
||||
@ -281,10 +281,10 @@ export class UserInterface extends AuthenticatedInterface {
|
||||
me?: SessionUser;
|
||||
|
||||
constructor() {
|
||||
configureSentry(true);
|
||||
super();
|
||||
this.ws = new WebsocketClient();
|
||||
this.fetchConfigurationDetails();
|
||||
configureSentry(true);
|
||||
this.toggleNotificationDrawer = this.toggleNotificationDrawer.bind(this);
|
||||
this.toggleApiDrawer = this.toggleApiDrawer.bind(this);
|
||||
this.fetchConfigurationDetails = this.fetchConfigurationDetails.bind(this);
|
||||
|
||||
Reference in New Issue
Block a user