diff --git a/web/src/admin/AdminInterface/AboutModal.ts b/web/src/admin/AdminInterface/AboutModal.ts index a519ee535991..0edd6fdf57cc 100644 --- a/web/src/admin/AdminInterface/AboutModal.ts +++ b/web/src/admin/AdminInterface/AboutModal.ts @@ -1,6 +1,6 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { VERSION } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { BrandConfig, ServerConfig } from "@goauthentik/common/global"; import "@goauthentik/elements/EmptyState"; import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider"; import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider"; @@ -33,7 +33,7 @@ export class AboutModal extends WithLicenseSummary(WithBrandConfig(ModalButton)) const status = await new AdminApi(DEFAULT_CONFIG).adminSystemRetrieve(); const version = await new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve(); let build: string | TemplateResult = msg("Release"); - if (globalAK().config.capabilities.includes(CapabilitiesEnum.CanDebug)) { + if (ServerConfig.capabilities.includes(CapabilitiesEnum.CanDebug)) { build = msg("Development"); } else if (version.buildHash !== "") { build = html` { impersonationRequest: data, }) .then(() => { - window.location.href = globalAK().api.base; + window.location.href = APIConfig.base; }); } diff --git a/web/src/common/api/config.ts b/web/src/common/api/config.ts index 7464564bd43b..a05e04a13fc1 100644 --- a/web/src/common/api/config.ts +++ b/web/src/common/api/config.ts @@ -3,79 +3,40 @@ import { EventMiddleware, LoggingMiddleware, } from "@goauthentik/common/api/middleware"; -import { EVENT_LOCALE_REQUEST, VERSION } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { VERSION } from "@goauthentik/common/constants"; +import { APIConfig, BrandConfig } from "@goauthentik/common/global"; -import { Config, Configuration, CoreApi, CurrentBrand, RootApi } from "@goauthentik/api"; +import { Configuration as ApiConfiguration } from "@goauthentik/api"; -let globalConfigPromise: Promise | undefined = Promise.resolve(globalAK().config); -export function config(): Promise { - if (!globalConfigPromise) { - globalConfigPromise = new RootApi(DEFAULT_CONFIG).rootConfigRetrieve(); - } - return globalConfigPromise; -} - -export function brandSetFavicon(brand: CurrentBrand) { - /** - * - * - */ - const rels = ["icon", "shortcut icon"]; - rels.forEach((rel) => { - let relIcon = document.head.querySelector(`link[rel='${rel}']`); - if (!relIcon) { - relIcon = document.createElement("link"); - relIcon.rel = rel; - document.getElementsByTagName("head")[0].appendChild(relIcon); - } - relIcon.href = brand.brandingFavicon; - }); -} - -export function brandSetLocale(brand: CurrentBrand) { - if (brand.defaultLocale === "") { - return; - } - console.debug("authentik/locale: setting locale from brand default"); - window.dispatchEvent( - new CustomEvent(EVENT_LOCALE_REQUEST, { - composed: true, - bubbles: true, - detail: { locale: brand.defaultLocale }, - }), - ); -} - -let globalBrandPromise: Promise | undefined = Promise.resolve(globalAK().brand); -export function brand(): Promise { - if (!globalBrandPromise) { - globalBrandPromise = new CoreApi(DEFAULT_CONFIG) - .coreBrandsCurrentRetrieve() - .then((brand) => { - brandSetFavicon(brand); - brandSetLocale(brand); - return brand; - }); - } - return globalBrandPromise; -} +/** + * Extract the content of a meta tag by name. + * + * @todo Can we memoize this? + */ +function extractMetaContent(name: string): string { + const metaEl = document.querySelector(`meta[name=${name}]`); -export function getMetaContent(key: string): string { - const metaEl = document.querySelector(`meta[name=${key}]`); if (!metaEl) return ""; + return metaEl.content; } -export const DEFAULT_CONFIG = new Configuration({ - basePath: `${globalAK().api.base}api/v3`, +/** + * Default API Configuration. + * + * @todo This is a frequent source of duplication when working with the API. + * We should consider moving this to a more central location. + */ +export const DEFAULT_CONFIG = new ApiConfiguration({ + basePath: `${APIConfig.base}api/v3`, headers: { - "sentry-trace": getMetaContent("sentry-trace"), + "sentry-trace": extractMetaContent("sentry-trace"), }, middleware: [ + // --- new CSRFMiddleware(), new EventMiddleware(), - new LoggingMiddleware(globalAK().brand), + new LoggingMiddleware(BrandConfig), ], }); diff --git a/web/src/common/global.ts b/web/src/common/global.ts index 8b29b8150f3f..7045a7485664 100644 --- a/web/src/common/global.ts +++ b/web/src/common/global.ts @@ -1,59 +1,142 @@ import { Config, ConfigFromJSON, CurrentBrand, CurrentBrandFromJSON } from "@goauthentik/api"; -export interface GlobalAuthentik { - _converted?: boolean; +export interface APIConfig { + /** + * Absolute base path to the API. + */ + base: string; + /** + * Relative base path to the API. + */ + relBase: string; +} + +export interface FlowConfig { + /** + * The current flow ID. + */ + layout: string; +} + +export interface SerializedClientState { + /** + * The BCP47 language tag. + */ locale?: string; - flow?: { - layout: string; - }; - config: Config; - brand: CurrentBrand; + /** + * Current flow state. + */ + flow?: FlowConfig; + /** + * Server configuration. + */ + config: unknown; + /** + * Branding information. + */ + brand: unknown; + /** + * The major and minor components of the current version. + */ versionFamily: string; + /** + * A subdomain compatible SemVer. + */ versionSubdomain: string; + /** + * The current build hash. + */ build: string; - api: { - base: string; - relBase: string; - }; + + /** + * The API configuration. + */ + api: APIConfig; } -export interface AuthentikWindow { - authentik: GlobalAuthentik; +type ClientConfigRealm = T & { + readonly authentik: Readonly; +}; + +function isClientConfigRealm(namespace: object): namespace is ClientConfigRealm { + return typeof namespace === "object" && "authentik" in namespace; } -export function globalAK(): GlobalAuthentik { - const ak = (window as unknown as AuthentikWindow).authentik; - if (ak && !ak._converted) { - ak._converted = true; - ak.brand = CurrentBrandFromJSON(ak.brand); - ak.config = ConfigFromJSON(ak.config); - } - const apiBase = new URL(process.env.AK_API_BASE_PATH || window.location.origin); - if (!ak) { - return { - config: ConfigFromJSON({ - capabilities: [], - }), - brand: CurrentBrandFromJSON({ - ui_footer_links: [], - }), - versionFamily: "", - versionSubdomain: "", - build: "", - api: { - base: apiBase.toString(), - relBase: apiBase.pathname, - }, - }; - } - return ak; +/** + * The current locale as defined by the server. + * + * @format BCP47 + */ +export let ServerLocale = ""; + +export let FlowConfig: FlowConfig | undefined; + +/** + * The current build hash. + */ +export let BuildHash = ""; + +/** + * The major and minor components of the SemVer. + */ +export let VersionFamily = ""; + +/** + * A subdomain compatible SemVer. + */ +export let VersionSubdomain = ""; + +/** + * The parsed API configuration extracted from the global scope. + */ +export let APIConfig: Readonly; + +/** + * The parsed server configuration extracted from the global scope. + */ +export let ServerConfig: Readonly; + +/** + * The parsed brand configuration extracted from the global scope. + */ +export let BrandConfig: Readonly; + +if (!isClientConfigRealm(self)) { + const apiOrigin = new URL(process.env.AK_API_BASE_PATH || window.location.origin); + + APIConfig = { + base: apiOrigin.toString(), + relBase: apiOrigin.pathname, + }; + + BrandConfig = CurrentBrandFromJSON({ + ui_footer_links: [], + }); +} else { + ServerLocale = self.authentik.locale || ""; + FlowConfig = self.authentik.flow; + + BuildHash = self.authentik.build; + + VersionFamily = self.authentik.versionFamily; + VersionSubdomain = self.authentik.versionSubdomain; + + ServerConfig = ConfigFromJSON(self.authentik.config); + BrandConfig = CurrentBrandFromJSON(self.authentik.brand); + APIConfig = self.authentik.api; } -export function docLink(path: string): string { - const ak = globalAK(); - // Default case or beta build which should always point to latest - if (!ak || ak.build !== "") { - return `https://goauthentik.io${path}`; - } - return `https://${ak.versionSubdomain}.goauthentik.io${path}`; +/** + * Generate a link to the documentation. + */ +export function docLink(documentationPath: string): string { + const origin = + // Default case or beta build which should always point to latest + BuildHash || !VersionSubdomain + ? "https://goauthentik.io" + : `https://${VersionSubdomain}.goauthentik.io`; + + const docsURL = new URL(documentationPath, origin); + + return docsURL.toString(); } diff --git a/web/src/common/sentry.ts b/web/src/common/sentry.ts index 3699ba5d6bc3..e84b4c59db92 100644 --- a/web/src/common/sentry.ts +++ b/web/src/common/sentry.ts @@ -1,98 +1,106 @@ -import { config } from "@goauthentik/common/api/config"; import { VERSION } from "@goauthentik/common/constants"; +import { SentryIgnoredError } from "@goauthentik/common/errors"; +import { ServerConfig } from "@goauthentik/common/global"; import { me } from "@goauthentik/common/users"; -import { - ErrorEvent, - EventHint, - browserTracingIntegration, - init, - setTag, - setUser, -} from "@sentry/browser"; +import { browserTracingIntegration, init, setTag, setUser } from "@sentry/browser"; -import { CapabilitiesEnum, Config, ResponseError } from "@goauthentik/api"; +import { CapabilitiesEnum, ResponseError } from "@goauthentik/api"; + +export const TAG_SENTRY_COMPONENT = "authentik.component"; +export const TAG_SENTRY_CAPABILITIES = "authentik.capabilities"; /** - * A generic error that can be thrown without triggering Sentry's reporting. + * Configure Sentry with the given configuration. + * + * @param canSendPII Whether the user can send personally identifiable information. */ -export class SentryIgnoredError extends Error {} +export async function configureSentry(canSendPII?: boolean): Promise { + if (!ServerConfig.errorReporting.enabled) return; + const { capabilities, errorReporting } = ServerConfig; -export const TAG_SENTRY_COMPONENT = "authentik.component"; -export const TAG_SENTRY_CAPABILITIES = "authentik.capabilities"; + init({ + dsn: 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({ + shouldCreateSpanForRequest: (url: string) => { + return url.startsWith(window.location.host); + }, + }), + ], + tracesSampleRate: errorReporting.tracesSampleRate, + environment: errorReporting.environment, + beforeSend: (event, hint) => { + if (!hint) return event; -export async function configureSentry(canDoPpi = false): Promise { - const cfg = await config(); - - 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}`, - integrations: [ - browserTracingIntegration({ - shouldCreateSpanForRequest: (url: string) => { - return url.startsWith(window.location.host); - }, - }), - ], - tracesSampleRate: cfg.errorReporting.tracesSampleRate, - environment: cfg.errorReporting.environment, - beforeSend: ( - event: ErrorEvent, - hint: EventHint, - ): ErrorEvent | PromiseLike | 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/${currentInterface()}`); - } - if (cfg.capabilities.includes(CapabilitiesEnum.CanDebug)) { - const Spotlight = await import("@spotlightjs/spotlight"); + const { originalException } = hint; - 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."); + if (originalException instanceof SentryIgnoredError) { + return null; + } + + if (originalException instanceof ResponseError) return null; + if (originalException instanceof DOMException) return null; + + return event; + }, + }); + + setTag(TAG_SENTRY_CAPABILITIES, capabilities.join(",")); + + if (window.location.pathname.includes("if/")) { + setTag(TAG_SENTRY_COMPONENT, `web/${currentInterface()}`); + } + + if ( + // Retain this predicate order to allow ESBuild to tree-shake the import in production. + process.env.NODE_ENV === "development" && + capabilities.includes(CapabilitiesEnum.CanDebug) + ) { + await import("@spotlightjs/spotlight") + .then((Spotlight) => { + return Spotlight.init({ + injectImmediately: true, + }); + }) + .catch((error) => { + console.error("Failed to init Spotlight", error); }); - } else { - console.debug("authentik/config: Sentry enabled."); + } + + if (errorReporting.sendPii && canSendPII) { + const session = await me().catch(() => null); + + if (session) { + setUser({ email: session.user.email }); + console.debug("authentik/config: Sentry PII enabled."); } } - return cfg; + + console.debug("authentik/config: Sentry enabled."); } -// Get the interface name from URL +/** + * Get the current interface from the URL. + */ export function currentInterface(): string { const pathMatches = window.location.pathname.match(/.+if\/(\w+)\//); let currentInterface = "unknown"; + if (pathMatches && pathMatches.length >= 2) { currentInterface = pathMatches[1]; } + return currentInterface.toLowerCase(); } diff --git a/web/src/common/ws.ts b/web/src/common/ws.ts index 8c6c9b26eb21..71f49176be30 100644 --- a/web/src/common/ws.ts +++ b/web/src/common/ws.ts @@ -1,5 +1,5 @@ import { EVENT_MESSAGE, EVENT_WS_MESSAGE } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import { MessageLevel } from "@goauthentik/common/messages"; import { msg } from "@lit/localize"; @@ -22,7 +22,8 @@ export class WebsocketClient { connect(): void { if (navigator.webdriver) return; - const apiURL = new URL(globalAK().api.base); + + const apiURL = new URL(APIConfig.base); const wsUrl = `${window.location.protocol.replace("http", "ws")}//${apiURL.host}${apiURL.pathname}ws/client/`; this.messageSocket = new WebSocket(wsUrl); this.messageSocket.addEventListener("open", () => { diff --git a/web/src/components/ak-nav-buttons.ts b/web/src/components/ak-nav-buttons.ts index e5111b32203b..ba9109f98b13 100644 --- a/web/src/components/ak-nav-buttons.ts +++ b/web/src/components/ak-nav-buttons.ts @@ -3,7 +3,7 @@ import { EVENT_API_DRAWER_TOGGLE, EVENT_NOTIFICATION_DRAWER_TOGGLE, } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import { UIConfig, UserDisplay, uiConfig } from "@goauthentik/common/ui/config"; import { me } from "@goauthentik/common/users"; import { AKElement } from "@goauthentik/elements/Base"; @@ -146,7 +146,7 @@ export class NavigationButtons extends AKElement { @@ -194,7 +194,7 @@ export class NavigationButtons extends AKElement { ${this.renderSettings()}
diff --git a/web/src/elements/Base.ts b/web/src/elements/Base.ts index 658aa75f03f5..5acf0f2ab96c 100644 --- a/web/src/elements/Base.ts +++ b/web/src/elements/Base.ts @@ -1,5 +1,5 @@ import { EVENT_THEME_CHANGE } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { BrandConfig } from "@goauthentik/common/global"; import { UIConfig } from "@goauthentik/common/ui/config"; import { adaptCSS } from "@goauthentik/common/utils"; import { ensureCSSStyleSheet } from "@goauthentik/elements/utils/ensureCSSStyleSheet"; @@ -78,7 +78,7 @@ export class AKElement extends LitElement { async _initTheme(root: DocumentOrShadowRoot): Promise { // Early activate theme based on media query to prevent light flash // when dark is preferred - this._applyTheme(root, globalAK().brand.uiTheme); + this._applyTheme(root, BrandConfig.uiTheme); this._applyTheme(root, await this.getTheme()); } diff --git a/web/src/elements/Interface/ConfigContextController.ts b/web/src/elements/Interface/ConfigContextController.ts index c626a7a9c995..233ca3656050 100644 --- a/web/src/elements/Interface/ConfigContextController.ts +++ b/web/src/elements/Interface/ConfigContextController.ts @@ -1,6 +1,6 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_REFRESH } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { ServerConfig } from "@goauthentik/common/global"; import { authentikConfigContext } from "@goauthentik/elements/AuthentikContexts"; import type { ReactiveElementHost } from "@goauthentik/elements/types.js"; @@ -24,8 +24,8 @@ export class ConfigContextController implements ReactiveController { initialValue: undefined, }); // Pre-hydrate from template-embedded config - this.context.setValue(globalAK().config); - this.host.config = globalAK().config; + this.context.setValue(ServerConfig); + this.host.config = ServerConfig; this.fetch = this.fetch.bind(this); this.fetch(); } diff --git a/web/src/elements/PageHeader.ts b/web/src/elements/PageHeader.ts index d0ec119cd592..6069c5ae04b3 100644 --- a/web/src/elements/PageHeader.ts +++ b/web/src/elements/PageHeader.ts @@ -3,7 +3,7 @@ import { EVENT_WS_MESSAGE, TITLE_DEFAULT, } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import { currentInterface } from "@goauthentik/common/sentry"; import { UIConfig, UserDisplay, uiConfig } from "@goauthentik/common/ui/config"; import { me } from "@goauthentik/common/users"; @@ -186,7 +186,7 @@ export class PageHeader extends WithBrandConfig(AKElement) { ${msg("User interface")} diff --git a/web/src/elements/ak-locale-context/helpers.ts b/web/src/elements/ak-locale-context/helpers.ts index 751371485a8c..71eb327aa356 100644 --- a/web/src/elements/ak-locale-context/helpers.ts +++ b/web/src/elements/ak-locale-context/helpers.ts @@ -1,4 +1,4 @@ -import { globalAK } from "@goauthentik/common/global"; +import { ServerLocale } from "@goauthentik/common/global"; import { LOCALES as RAW_LOCALES, enLocale } from "./definitions"; import { AkLocale } from "./types"; @@ -51,7 +51,7 @@ export function autoDetectLanguage(userReq = TOMBSTONE, brandReq = TOMBSTONE): s userReq, window.navigator?.language ?? TOMBSTONE, brandReq, - globalAK()?.locale ?? TOMBSTONE, + ServerLocale ?? TOMBSTONE, DEFAULT_LOCALE, ].filter(isLocaleCandidate); diff --git a/web/src/elements/banner/EnterpriseStatusBanner.ts b/web/src/elements/banner/EnterpriseStatusBanner.ts index 7a7d36208ac7..81e299dd3d42 100644 --- a/web/src/elements/banner/EnterpriseStatusBanner.ts +++ b/web/src/elements/banner/EnterpriseStatusBanner.ts @@ -1,4 +1,4 @@ -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import { AKElement } from "@goauthentik/elements/Base"; import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider"; @@ -76,7 +76,7 @@ export class EnterpriseStatusBanner extends WithLicenseSummary(AKElement) { : "pf-m-gold"}" > ${message} - ${msg("Click here for more info.")}
`; diff --git a/web/src/elements/notifications/APIDrawer.ts b/web/src/elements/notifications/APIDrawer.ts index 8e3c1ce89809..3f38ed2b866b 100644 --- a/web/src/elements/notifications/APIDrawer.ts +++ b/web/src/elements/notifications/APIDrawer.ts @@ -1,6 +1,6 @@ import { RequestInfo } from "@goauthentik/common/api/middleware"; import { EVENT_API_DRAWER_TOGGLE, EVENT_REQUEST_POST } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import { formatElapsedTime } from "@goauthentik/common/temporal"; import { AKElement } from "@goauthentik/elements/Base"; @@ -92,7 +92,7 @@ export class APIDrawer extends AKElement {

${msg("API Requests")}

- ${msg("Open API Browser")} diff --git a/web/src/elements/notifications/NotificationDrawer.ts b/web/src/elements/notifications/NotificationDrawer.ts index cfa58d819b9f..03cf381d6cac 100644 --- a/web/src/elements/notifications/NotificationDrawer.ts +++ b/web/src/elements/notifications/NotificationDrawer.ts @@ -1,6 +1,6 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_NOTIFICATION_DRAWER_TOGGLE, EVENT_REFRESH } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import { actionToLabel } from "@goauthentik/common/labels"; import { MessageLevel } from "@goauthentik/common/messages"; import { formatElapsedTime } from "@goauthentik/common/temporal"; @@ -99,7 +99,7 @@ export class NotificationDrawer extends AKElement { html` diff --git a/web/src/elements/sidebar/SidebarVersion.ts b/web/src/elements/sidebar/SidebarVersion.ts index f5e0fbed0527..b9c896b7ad5d 100644 --- a/web/src/elements/sidebar/SidebarVersion.ts +++ b/web/src/elements/sidebar/SidebarVersion.ts @@ -1,5 +1,5 @@ import type { AdminInterface } from "@goauthentik/admin/AdminInterface/AdminInterface"; -import { globalAK } from "@goauthentik/common/global"; +import { BrandConfig } from "@goauthentik/common/global"; import { AKElement, rootInterface } from "@goauthentik/elements/Base"; import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider"; import { WithVersion } from "@goauthentik/elements/Interface/versionProvider"; @@ -45,7 +45,7 @@ export class SidebarVersion extends WithLicenseSummary(WithVersion(AKElement)) { if (!this.version || !this.licenseSummary) { return nothing; } - let product = globalAK().brand.brandingTitle || DefaultBrand.brandingTitle; + let product = BrandConfig.brandingTitle || DefaultBrand.brandingTitle; if (this.licenseSummary.status != LicenseSummaryStatusEnum.Unlicensed) { product += ` ${msg("Enterprise")}`; } diff --git a/web/src/flow/FlowExecutor.ts b/web/src/flow/FlowExecutor.ts index 6eb2e0ed8599..dd1953b9d975 100644 --- a/web/src/flow/FlowExecutor.ts +++ b/web/src/flow/FlowExecutor.ts @@ -4,7 +4,7 @@ import { EVENT_FLOW_INSPECTOR_TOGGLE, TITLE_DEFAULT, } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { BrandConfig, FlowConfig } from "@goauthentik/common/global"; import { configureSentry } from "@goauthentik/common/sentry"; import { first } from "@goauthentik/common/utils"; import { WebsocketClient } from "@goauthentik/common/ws"; @@ -201,7 +201,7 @@ export class FlowExecutor extends Interface implements StageHost { } async getTheme(): Promise { - return globalAK()?.brand.uiTheme || UiThemeEnum.Automatic; + return BrandConfig.uiTheme || UiThemeEnum.Automatic; } async submit( @@ -487,7 +487,7 @@ export class FlowExecutor extends Interface implements StageHost { } getLayout(): string { - const prefilledFlow = globalAK()?.flow?.layout || FlowLayoutEnum.Stacked; + const prefilledFlow = FlowConfig?.layout || FlowLayoutEnum.Stacked; if (this.challenge) { return this.challenge?.flowInfo?.layout || prefilledFlow; } @@ -528,7 +528,7 @@ export class FlowExecutor extends Interface implements StageHost { src="${themeImage( first( this.brand?.brandingLogo, - globalAK()?.brand.brandingLogo, + BrandConfig.brandingLogo, DefaultBrand.brandingLogo, ), )}" diff --git a/web/src/flow/providers/SessionEnd.ts b/web/src/flow/providers/SessionEnd.ts index 3e58d70d0129..56566b2946e5 100644 --- a/web/src/flow/providers/SessionEnd.ts +++ b/web/src/flow/providers/SessionEnd.ts @@ -1,4 +1,4 @@ -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import "@goauthentik/flow/FormStatic"; import { BaseStage } from "@goauthentik/flow/stages/base"; @@ -48,7 +48,7 @@ export class SessionEnd extends BaseStage { str`You've logged out of ${this.challenge.applicationName}. You can go back to the overview to launch another application, or log out of your authentik account.`, )}

-
+ ${msg("Go back to overview")} ${this.challenge.invalidationFlowUrl diff --git a/web/src/standalone/api-browser/index.ts b/web/src/standalone/api-browser/index.ts index 7d0e113f7c26..b97582e7de44 100644 --- a/web/src/standalone/api-browser/index.ts +++ b/web/src/standalone/api-browser/index.ts @@ -1,6 +1,6 @@ import { CSRFHeaderName } from "@goauthentik/common/api/middleware"; import { EVENT_THEME_CHANGE } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { BrandConfig } from "@goauthentik/common/global"; import { first, getCookie } from "@goauthentik/common/utils"; import { Interface } from "@goauthentik/elements/Interface"; import "@goauthentik/elements/ak-locale-context"; @@ -61,7 +61,7 @@ export class APIBrowser extends Interface { } async getTheme(): Promise { - return globalAK()?.brand.uiTheme || UiThemeEnum.Automatic; + return BrandConfig.uiTheme || UiThemeEnum.Automatic; } render(): TemplateResult { diff --git a/web/src/standalone/loading/index.ts b/web/src/standalone/loading/index.ts index 76cdff5a262d..cca3991a5376 100644 --- a/web/src/standalone/loading/index.ts +++ b/web/src/standalone/loading/index.ts @@ -1,4 +1,4 @@ -import { globalAK } from "@goauthentik/common/global"; +import { BrandConfig } from "@goauthentik/common/global"; import { Interface } from "@goauthentik/elements/Interface"; import { msg } from "@lit/localize"; @@ -39,7 +39,7 @@ export class Loading extends Interface { } async getTheme(): Promise { - return globalAK()?.brand.uiTheme || UiThemeEnum.Automatic; + return BrandConfig.uiTheme || UiThemeEnum.Automatic; } render(): TemplateResult { diff --git a/web/src/user/LibraryApplication/index.ts b/web/src/user/LibraryApplication/index.ts index 2f672882bc0e..4ad340a8ed06 100644 --- a/web/src/user/LibraryApplication/index.ts +++ b/web/src/user/LibraryApplication/index.ts @@ -1,5 +1,5 @@ import { PFSize } from "@goauthentik/common/enums.js"; -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import { truncateWords } from "@goauthentik/common/utils"; import "@goauthentik/elements/AppIcon"; import { AKElement, rootInterface } from "@goauthentik/elements/Base"; @@ -82,8 +82,7 @@ export class LibraryApplication extends AKElement { ? html`  ${msg("Edit")} diff --git a/web/src/user/LibraryPage/ak-library-application-empty-list.ts b/web/src/user/LibraryPage/ak-library-application-empty-list.ts index 170eff0a8fe0..dedcbffcb0ae 100644 --- a/web/src/user/LibraryPage/ak-library-application-empty-list.ts +++ b/web/src/user/LibraryPage/ak-library-application-empty-list.ts @@ -1,4 +1,4 @@ -import { docLink, globalAK } from "@goauthentik/common/global"; +import { APIConfig, docLink } from "@goauthentik/common/global"; import { AKElement } from "@goauthentik/elements/Base"; import { paramURL } from "@goauthentik/elements/router/RouterOutlet"; @@ -49,7 +49,7 @@ export class LibraryPageApplicationEmptyList extends AKElement { ${msg("Create a new application")} diff --git a/web/src/user/UserInterface.ts b/web/src/user/UserInterface.ts index d418a6ace901..b4812179eff4 100644 --- a/web/src/user/UserInterface.ts +++ b/web/src/user/UserInterface.ts @@ -4,7 +4,7 @@ import { EVENT_NOTIFICATION_DRAWER_TOGGLE, EVENT_WS_MESSAGE, } from "@goauthentik/common/constants"; -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import { configureSentry } from "@goauthentik/common/sentry"; import { UIConfig } from "@goauthentik/common/ui/config"; import { me } from "@goauthentik/common/users"; @@ -166,14 +166,14 @@ class UserInterfacePresentation extends AKElement { return html` ${msg("Admin interface")} ${msg("Admin")} diff --git a/web/src/user/user-settings/details/UserPassword.ts b/web/src/user/user-settings/details/UserPassword.ts index 1a971116dcaf..c74b6039b1a6 100644 --- a/web/src/user/user-settings/details/UserPassword.ts +++ b/web/src/user/user-settings/details/UserPassword.ts @@ -1,5 +1,5 @@ import { AndNext } from "@goauthentik/common/api/config"; -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import { AKElement } from "@goauthentik/elements/Base"; import { msg } from "@lit/localize"; @@ -32,7 +32,7 @@ export class UserSettingsPassword extends AKElement {
diff --git a/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts b/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts index 1ddd2d44db3e..b39c81c31475 100644 --- a/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts +++ b/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts @@ -5,7 +5,7 @@ import { parseAPIResponseError, pluckErrorDetail, } from "@goauthentik/common/errors/network"; -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import { MessageLevel } from "@goauthentik/common/messages"; import { refreshMe } from "@goauthentik/common/users"; import { AKElement } from "@goauthentik/elements/Base"; @@ -181,7 +181,7 @@ export class UserSettingsFlowExecutor ); return html` ${msg("Open settings")} diff --git a/web/src/user/user-settings/details/stages/prompt/PromptStage.ts b/web/src/user/user-settings/details/stages/prompt/PromptStage.ts index 1c06efb89fba..d85a7ae91758 100644 --- a/web/src/user/user-settings/details/stages/prompt/PromptStage.ts +++ b/web/src/user/user-settings/details/stages/prompt/PromptStage.ts @@ -1,4 +1,4 @@ -import { globalAK } from "@goauthentik/common/global"; +import { APIConfig } from "@goauthentik/common/global"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { PromptStage } from "@goauthentik/flow/stages/prompt/PromptStage"; @@ -51,8 +51,7 @@ export class UserSettingsPromptStage extends PromptStage { ${this.host.brand?.flowUnenrollment ? html` ${msg("Delete account")} ` diff --git a/web/src/user/user-settings/mfa/MFADevicesPage.ts b/web/src/user/user-settings/mfa/MFADevicesPage.ts index 7cb8ee2f6f18..632aa556b930 100644 --- a/web/src/user/user-settings/mfa/MFADevicesPage.ts +++ b/web/src/user/user-settings/mfa/MFADevicesPage.ts @@ -1,7 +1,7 @@ import { AndNext, DEFAULT_CONFIG } from "@goauthentik/common/api/config"; -import { globalAK } from "@goauthentik/common/global"; +import { SentryIgnoredError } from "@goauthentik/common/errors"; +import { APIConfig } from "@goauthentik/common/global"; import { deviceTypeName } from "@goauthentik/common/labels"; -import { SentryIgnoredError } from "@goauthentik/common/sentry"; import { formatElapsedTime } from "@goauthentik/common/temporal"; import "@goauthentik/elements/buttons/Dropdown"; import "@goauthentik/elements/buttons/ModalButton"; @@ -74,7 +74,7 @@ export class MFADevicesPage extends Table { return html`