diff --git a/web/src/admin/applications/wizard/methods/ldap/ak-application-wizard-authentication-by-ldap.ts b/web/src/admin/applications/wizard/methods/ldap/ak-application-wizard-authentication-by-ldap.ts
index a99384171..6e1554196 100644
--- a/web/src/admin/applications/wizard/methods/ldap/ak-application-wizard-authentication-by-ldap.ts
+++ b/web/src/admin/applications/wizard/methods/ldap/ak-application-wizard-authentication-by-ldap.ts
@@ -7,7 +7,7 @@ import "@goauthentik/components/ak-number-input";
import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-switch-input";
import "@goauthentik/components/ak-text-input";
-import { rootInterface } from "@goauthentik/elements/Base";
+import { WithTenantConfig } from "@goauthentik/elements/Interface/tenantProvider";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
@@ -32,7 +32,7 @@ import {
} from "./LDAPOptionsAndHelp";
@customElement("ak-application-wizard-authentication-by-ldap")
-export class ApplicationWizardApplicationDetails extends BaseProviderPanel {
+export class ApplicationWizardApplicationDetails extends WithTenantConfig(BaseProviderPanel) {
render() {
const provider = this.wizard.provider as LDAPProvider | undefined;
const errors = this.wizard.errors.provider;
@@ -57,7 +57,7 @@ export class ApplicationWizardApplicationDetails extends BaseProviderPanel {
diff --git a/web/src/admin/applications/wizard/methods/radius/ak-application-wizard-authentication-by-radius.ts b/web/src/admin/applications/wizard/methods/radius/ak-application-wizard-authentication-by-radius.ts
index cadbd94ad..44f452037 100644
--- a/web/src/admin/applications/wizard/methods/radius/ak-application-wizard-authentication-by-radius.ts
+++ b/web/src/admin/applications/wizard/methods/radius/ak-application-wizard-authentication-by-radius.ts
@@ -3,7 +3,7 @@ import "@goauthentik/admin/common/ak-crypto-certificate-search";
import "@goauthentik/admin/common/ak-flow-search/ak-tenanted-flow-search";
import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-text-input";
-import { rootInterface } from "@goauthentik/elements/Base";
+import { WithTenantConfig } from "@goauthentik/elements/Interface/tenantProvider";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
@@ -17,7 +17,7 @@ import { FlowsInstancesListDesignationEnum, RadiusProvider } from "@goauthentik/
import BaseProviderPanel from "../BaseProviderPanel";
@customElement("ak-application-wizard-authentication-by-radius")
-export class ApplicationWizardAuthenticationByRadius extends BaseProviderPanel {
+export class ApplicationWizardAuthenticationByRadius extends WithTenantConfig(BaseProviderPanel) {
render() {
const provider = this.wizard.provider as RadiusProvider | undefined;
const errors = this.wizard.errors.provider;
@@ -42,7 +42,7 @@ export class ApplicationWizardAuthenticationByRadius extends BaseProviderPanel {
diff --git a/web/src/admin/groups/RelatedUserList.ts b/web/src/admin/groups/RelatedUserList.ts
index 27450fb82..5e2c6b952 100644
--- a/web/src/admin/groups/RelatedUserList.ts
+++ b/web/src/admin/groups/RelatedUserList.ts
@@ -9,11 +9,11 @@ import { MessageLevel } from "@goauthentik/common/messages";
import { uiConfig } from "@goauthentik/common/ui/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-status-label";
-import { rootInterface } from "@goauthentik/elements/Base";
import {
CapabilitiesEnum,
WithCapabilitiesConfig,
} from "@goauthentik/elements/Interface/capabilitiesProvider";
+import { WithTenantConfig } from "@goauthentik/elements/Interface/tenantProvider";
import "@goauthentik/elements/buttons/ActionButton";
import "@goauthentik/elements/buttons/Dropdown";
import "@goauthentik/elements/forms/DeleteBulkForm";
@@ -110,7 +110,7 @@ export class RelatedUserAdd extends Form<{ users: number[] }> {
}
@customElement("ak-user-related-list")
-export class RelatedUserList extends WithCapabilitiesConfig(Table) {
+export class RelatedUserList extends WithTenantConfig(WithCapabilitiesConfig(Table)) {
expandable = true;
checkbox = true;
@@ -295,7 +295,7 @@ export class RelatedUserList extends WithCapabilitiesConfig(Table) {
${msg("Set password")}
- ${rootInterface()?.tenant?.flowRecovery
+ ${this.tenant?.flowRecovery
? html`
{
+export class LDAPProviderFormPage extends WithTenantConfig(BaseProviderForm) {
async loadInstance(pk: number): Promise {
return new ProvidersApi(DEFAULT_CONFIG).providersLdapRetrieve({
id: pk,
@@ -68,7 +68,7 @@ export class LDAPProviderFormPage extends BaseProviderForm {
${msg("Flow used for users to authenticate.")}
diff --git a/web/src/admin/providers/radius/RadiusProviderForm.ts b/web/src/admin/providers/radius/RadiusProviderForm.ts
index 269a5ee95..f37c865d5 100644
--- a/web/src/admin/providers/radius/RadiusProviderForm.ts
+++ b/web/src/admin/providers/radius/RadiusProviderForm.ts
@@ -1,7 +1,7 @@
import { BaseProviderForm } from "@goauthentik/admin/providers/BaseProviderForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
-import { rootInterface } from "@goauthentik/elements/Base";
+import { WithTenantConfig } from "@goauthentik/elements/Interface/tenantProvider";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect";
@@ -14,7 +14,7 @@ import { customElement } from "lit/decorators.js";
import { FlowsInstancesListDesignationEnum, ProvidersApi, RadiusProvider } from "@goauthentik/api";
@customElement("ak-provider-radius-form")
-export class RadiusProviderFormPage extends BaseProviderForm {
+export class RadiusProviderFormPage extends WithTenantConfig(BaseProviderForm) {
loadInstance(pk: number): Promise {
return new ProvidersApi(DEFAULT_CONFIG).providersRadiusRetrieve({
id: pk,
@@ -57,7 +57,7 @@ export class RadiusProviderFormPage extends BaseProviderForm {
${msg("Flow used for users to authenticate.")}
diff --git a/web/src/admin/users/UserListPage.ts b/web/src/admin/users/UserListPage.ts
index e9d0c6f09..afb88f3f6 100644
--- a/web/src/admin/users/UserListPage.ts
+++ b/web/src/admin/users/UserListPage.ts
@@ -16,6 +16,7 @@ import {
CapabilitiesEnum,
WithCapabilitiesConfig,
} from "@goauthentik/elements/Interface/capabilitiesProvider";
+import { WithTenantConfig } from "@goauthentik/elements/Interface/tenantProvider";
import { PFSize } from "@goauthentik/elements/Spinner";
import "@goauthentik/elements/TreeView";
import "@goauthentik/elements/buttons/ActionButton";
@@ -90,7 +91,7 @@ const recoveryButtonStyles = css`
`;
@customElement("ak-user-list")
-export class UserListPage extends WithCapabilitiesConfig(TablePage) {
+export class UserListPage extends WithTenantConfig(WithCapabilitiesConfig(TablePage)) {
expandable = true;
checkbox = true;
@@ -351,7 +352,7 @@ export class UserListPage extends WithCapabilitiesConfig(TablePage) {
${msg("Set password")}
- ${rootInterface()?.tenant?.flowRecovery
+ ${this.tenant.flowRecovery
? html`
(Symbol("authentik-config-context"));
+export const authentikTenantContext = createContext(
+ Symbol("authentik-tenant-context"),
+);
+
export default authentikConfigContext;
diff --git a/web/src/elements/Interface/Interface.ts b/web/src/elements/Interface/Interface.ts
index 744a16095..b2470cfd2 100644
--- a/web/src/elements/Interface/Interface.ts
+++ b/web/src/elements/Interface/Interface.ts
@@ -1,6 +1,9 @@
import { config, tenant } from "@goauthentik/common/api/config";
import { UIConfig, uiConfig } from "@goauthentik/common/ui/config";
-import { authentikConfigContext } from "@goauthentik/elements/AuthentikContexts";
+import {
+ authentikConfigContext,
+ authentikTenantContext,
+} from "@goauthentik/elements/AuthentikContexts";
import type { AdoptedStyleSheetsElement } from "@goauthentik/elements/types";
import { ensureCSSStyleSheet } from "@goauthentik/elements/utils/ensureCSSStyleSheet";
@@ -21,9 +24,6 @@ type AkInterface = HTMLElement & {
};
export class Interface extends AKElement implements AkInterface {
- @state()
- tenant?: CurrentTenant;
-
@state()
uiConfig?: UIConfig;
@@ -45,6 +45,24 @@ export class Interface extends AKElement implements AkInterface {
return this._config;
}
+ _tenantContext = new ContextProvider(this, {
+ context: authentikTenantContext,
+ initialValue: undefined,
+ });
+
+ _tenant?: CurrentTenant;
+
+ @state()
+ set tenant(c: CurrentTenant) {
+ this._tenant = c;
+ this._tenantContext.setValue(c);
+ this.requestUpdate();
+ }
+
+ get tenant(): CurrentTenant | undefined {
+ return this._tenant;
+ }
+
constructor() {
super();
document.adoptedStyleSheets = [...document.adoptedStyleSheets, ensureCSSStyleSheet(PFBase)];
diff --git a/web/src/elements/Interface/authentikConfigProvider.ts b/web/src/elements/Interface/authentikConfigProvider.ts
index 2f2bbcf43..5b2027fd0 100644
--- a/web/src/elements/Interface/authentikConfigProvider.ts
+++ b/web/src/elements/Interface/authentikConfigProvider.ts
@@ -12,7 +12,7 @@ export function WithAuthentikConfig>(
superclass: T,
subscribe = true,
) {
- class WithAkConfigProvider extends superclass {
+ abstract class WithAkConfigProvider extends superclass {
@consume({ context: authentikConfigContext, subscribe })
public authentikConfig!: Config;
}
diff --git a/web/src/elements/Interface/tenantProvider.ts b/web/src/elements/Interface/tenantProvider.ts
new file mode 100644
index 000000000..63d389048
--- /dev/null
+++ b/web/src/elements/Interface/tenantProvider.ts
@@ -0,0 +1,20 @@
+import { authentikTenantContext } from "@goauthentik/elements/AuthentikContexts";
+
+import { consume } from "@lit-labs/context";
+import type { LitElement } from "lit";
+
+import type { CurrentTenant } from "@goauthentik/api";
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+type Constructor = abstract new (...args: any[]) => T;
+
+export function WithTenantConfig>(
+ superclass: T,
+ subscribe = true,
+) {
+ abstract class WithTenantProvider extends superclass {
+ @consume({ context: authentikTenantContext, subscribe })
+ public tenant!: CurrentTenant;
+ }
+ return WithTenantProvider;
+}
diff --git a/web/src/elements/PageHeader.ts b/web/src/elements/PageHeader.ts
index fcdbbeffc..7be55996d 100644
--- a/web/src/elements/PageHeader.ts
+++ b/web/src/elements/PageHeader.ts
@@ -8,7 +8,8 @@ import {
} from "@goauthentik/common/constants";
import { currentInterface } from "@goauthentik/common/sentry";
import { me } from "@goauthentik/common/users";
-import { AKElement, rootInterface } from "@goauthentik/elements/Base";
+import { AKElement } from "@goauthentik/elements/Base";
+import { WithTenantConfig } from "@goauthentik/elements/Interface/tenantProvider";
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
import { msg } from "@lit/localize";
@@ -23,7 +24,7 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { EventsApi } from "@goauthentik/api";
@customElement("ak-page-header")
-export class PageHeader extends AKElement {
+export class PageHeader extends WithTenantConfig(AKElement) {
@property()
icon?: string;
@@ -35,9 +36,8 @@ export class PageHeader extends AKElement {
@property()
set header(value: string) {
- const tenant = rootInterface()?.tenant;
const currentIf = currentInterface();
- let title = tenant?.brandingTitle || TITLE_DEFAULT;
+ let title = this.tenant?.brandingTitle || TITLE_DEFAULT;
if (currentIf === "admin") {
title = `${msg("Admin")} - ${title}`;
}
diff --git a/web/src/elements/sidebar/SidebarBrand.ts b/web/src/elements/sidebar/SidebarBrand.ts
index fa442b36c..b57d336f7 100644
--- a/web/src/elements/sidebar/SidebarBrand.ts
+++ b/web/src/elements/sidebar/SidebarBrand.ts
@@ -1,6 +1,6 @@
import { EVENT_SIDEBAR_TOGGLE } from "@goauthentik/common/constants";
-import { first } from "@goauthentik/common/utils";
-import { AKElement, rootInterface } from "@goauthentik/elements/Base";
+import { AKElement } from "@goauthentik/elements/Base";
+import { WithTenantConfig } from "@goauthentik/elements/Interface/tenantProvider";
import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement } from "lit/decorators.js";
@@ -27,7 +27,7 @@ export const DefaultTenant: CurrentTenant = {
};
@customElement("ak-sidebar-brand")
-export class SidebarBrand extends AKElement {
+export class SidebarBrand extends WithTenantConfig(AKElement) {
static get styles(): CSSResult[] {
return [
PFBase,
@@ -85,10 +85,7 @@ export class SidebarBrand extends AKElement {
diff --git a/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts b/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts
index e7aa36343..f4252f58b 100644
--- a/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts
+++ b/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts
@@ -2,14 +2,15 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EVENT_REFRESH } from "@goauthentik/common/constants";
import { MessageLevel } from "@goauthentik/common/messages";
import { refreshMe } from "@goauthentik/common/users";
-import { AKElement, rootInterface } from "@goauthentik/elements/Base";
+import { AKElement } from "@goauthentik/elements/Base";
+import { WithTenantConfig } from "@goauthentik/elements/Interface/tenantProvider";
import { showMessage } from "@goauthentik/elements/messages/MessageContainer";
import { StageHost } from "@goauthentik/flow/stages/base";
import "@goauthentik/user/user-settings/details/stages/prompt/PromptStage";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit";
-import { customElement, property, state } from "lit/decorators.js";
+import { customElement, property } from "lit/decorators.js";
import { unsafeHTML } from "lit/directives/unsafe-html.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css";
@@ -21,7 +22,6 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css";
import {
ChallengeChoices,
ChallengeTypes,
- CurrentTenant,
FlowChallengeResponseRequest,
FlowErrorChallenge,
FlowsApi,
@@ -31,13 +31,13 @@ import {
} from "@goauthentik/api";
@customElement("ak-user-settings-flow-executor")
-export class UserSettingsFlowExecutor extends AKElement implements StageHost {
+export class UserSettingsFlowExecutor
+ extends WithTenantConfig(AKElement, true)
+ implements StageHost
+{
@property()
flowSlug?: string;
- @state()
- tenant?: CurrentTenant;
-
private _challenge?: ChallengeTypes;
@property({ attribute: false })
@@ -87,7 +87,6 @@ export class UserSettingsFlowExecutor extends AKElement implements StageHost {
}
firstUpdated(): void {
- this.tenant = rootInterface()?.tenant;
this.flowSlug = this.tenant?.flowUserSettings;
if (!this.flowSlug) {
return;