web: Replace calls to `rootInterface()?.tenant?` with a contextual `this.tenant` object (#7778)
* This commit abstracts access to the object `rootInterface()?.config?` into a single accessor, `authentikConfig`, that can be mixed into any AKElement object that requires access to it. Since access to `rootInterface()?.config?` is _universally_ used for a single (and repetitive) boolean check, a separate accessor has been provided that converts all calls of the form: ``` javascript rootInterface()?.config?.capabilities.includes(CapabilitiesEnum.CanImpersonate) ``` into: ``` javascript this.can(CapabilitiesEnum.CanImpersonate) ``` It does this via a Mixin, `WithCapabilitiesConfig`, which understands that these calls only make sense in the context of a running, fully configured authentik instance, and that their purpose is to inform authentik components of a user’s capabilities. The latter is why I don’t feel uncomfortable turning a function call into a method; we should make it explicit that this is a relationship between components. The mixin has a single single field, `[WCC.capabilitiesConfig]`, where its association with the upper-level configuration is made. If that syntax looks peculiar to you, good! I’ve used an explict unique symbol as the field name; it is inaccessable an innumerable in the object list. The debugger shows it only as: Symbol(): { cacheTimeout: 300 cacheTimeoutFlows: 300 cacheTimeoutPolicies: 300 cacheTimeoutReputation: 300 capabilities: (5) ['can_save_media', 'can_geo_ip', 'can_impersonate', 'can_debug', 'is_enterprise'] } Since you can’t reference it by identity, you can’t write to it. Until every browser supports actual private fields, this is the best we can do; it does guarantee that field name collisions are impossible, which is a win. The mixin takes a second optional boolean; setting this to true will cause any web component using the mixin to automatically schedule a re-render if the capabilities list changes. The mixin is also generic; despite the "...into a Lit-Context" in the title, the internals of the Mixin can be replaced with anything so long as the signature of `.can()` is preserved. Because this work builds off the work I did to give the Sidebar access to the configuration without ad-hoc retrieval or prop-drilling, it wasn’t necessary to create a new context for it. That will be necessary for the following: TODO: ``` javascript rootInterface()?.uiConfig; rootInterface()?.tenant; me(); ``` * This commit abstracts access to the object `rootInterface()?.tenant?` into a single accessor, `tenant`, that can be mixed into any AKElement object that requires access to it. Like `WithCapabilitiesConfig` and `WithAuthentikConfig`, this one is named `WithTenantConfig`. TODO: ``` javascript rootInterface()?.uiConfig; me(); ``` * web: Added a README with a description of the applications' "mental model," essentially an architectural description. * web: prettier did a thing * web: prettier had opinions about the README * web: Jens requested that subscription be by default, and it's the right call. * web: Jens requested that the default subscription state for contexts be , and it's the right call. * web: prettier having opinions after merging with dependent branch * web: prettier still having opinions.
This commit is contained in:
parent
d555c0db41
commit
a2dce3fb63
|
@ -7,7 +7,7 @@ import "@goauthentik/components/ak-number-input";
|
||||||
import "@goauthentik/components/ak-radio-input";
|
import "@goauthentik/components/ak-radio-input";
|
||||||
import "@goauthentik/components/ak-switch-input";
|
import "@goauthentik/components/ak-switch-input";
|
||||||
import "@goauthentik/components/ak-text-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/FormGroup";
|
||||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ import {
|
||||||
} from "./LDAPOptionsAndHelp";
|
} from "./LDAPOptionsAndHelp";
|
||||||
|
|
||||||
@customElement("ak-application-wizard-authentication-by-ldap")
|
@customElement("ak-application-wizard-authentication-by-ldap")
|
||||||
export class ApplicationWizardApplicationDetails extends BaseProviderPanel {
|
export class ApplicationWizardApplicationDetails extends WithTenantConfig(BaseProviderPanel) {
|
||||||
render() {
|
render() {
|
||||||
const provider = this.wizard.provider as LDAPProvider | undefined;
|
const provider = this.wizard.provider as LDAPProvider | undefined;
|
||||||
const errors = this.wizard.errors.provider;
|
const errors = this.wizard.errors.provider;
|
||||||
|
@ -57,7 +57,7 @@ export class ApplicationWizardApplicationDetails extends BaseProviderPanel {
|
||||||
<ak-tenanted-flow-search
|
<ak-tenanted-flow-search
|
||||||
flowType=${FlowsInstancesListDesignationEnum.Authentication}
|
flowType=${FlowsInstancesListDesignationEnum.Authentication}
|
||||||
.currentFlow=${provider?.authorizationFlow}
|
.currentFlow=${provider?.authorizationFlow}
|
||||||
.tenantFlow=${rootInterface()?.tenant?.flowAuthentication}
|
.tenantFlow=${this.tenant.flowAuthentication}
|
||||||
required
|
required
|
||||||
></ak-tenanted-flow-search>
|
></ak-tenanted-flow-search>
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
|
|
|
@ -3,7 +3,7 @@ import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||||
import "@goauthentik/admin/common/ak-flow-search/ak-tenanted-flow-search";
|
import "@goauthentik/admin/common/ak-flow-search/ak-tenanted-flow-search";
|
||||||
import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
|
import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
|
||||||
import "@goauthentik/components/ak-text-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/FormGroup";
|
||||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import { FlowsInstancesListDesignationEnum, RadiusProvider } from "@goauthentik/
|
||||||
import BaseProviderPanel from "../BaseProviderPanel";
|
import BaseProviderPanel from "../BaseProviderPanel";
|
||||||
|
|
||||||
@customElement("ak-application-wizard-authentication-by-radius")
|
@customElement("ak-application-wizard-authentication-by-radius")
|
||||||
export class ApplicationWizardAuthenticationByRadius extends BaseProviderPanel {
|
export class ApplicationWizardAuthenticationByRadius extends WithTenantConfig(BaseProviderPanel) {
|
||||||
render() {
|
render() {
|
||||||
const provider = this.wizard.provider as RadiusProvider | undefined;
|
const provider = this.wizard.provider as RadiusProvider | undefined;
|
||||||
const errors = this.wizard.errors.provider;
|
const errors = this.wizard.errors.provider;
|
||||||
|
@ -42,7 +42,7 @@ export class ApplicationWizardAuthenticationByRadius extends BaseProviderPanel {
|
||||||
<ak-tenanted-flow-search
|
<ak-tenanted-flow-search
|
||||||
flowType=${FlowsInstancesListDesignationEnum.Authentication}
|
flowType=${FlowsInstancesListDesignationEnum.Authentication}
|
||||||
.currentFlow=${provider?.authorizationFlow}
|
.currentFlow=${provider?.authorizationFlow}
|
||||||
.tenantFlow=${rootInterface()?.tenant?.flowAuthentication}
|
.tenantFlow=${this.tenant.flowAuthentication}
|
||||||
required
|
required
|
||||||
></ak-tenanted-flow-search>
|
></ak-tenanted-flow-search>
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
|
|
|
@ -9,11 +9,11 @@ import { MessageLevel } from "@goauthentik/common/messages";
|
||||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||||
import { first } from "@goauthentik/common/utils";
|
import { first } from "@goauthentik/common/utils";
|
||||||
import "@goauthentik/components/ak-status-label";
|
import "@goauthentik/components/ak-status-label";
|
||||||
import { rootInterface } from "@goauthentik/elements/Base";
|
|
||||||
import {
|
import {
|
||||||
CapabilitiesEnum,
|
CapabilitiesEnum,
|
||||||
WithCapabilitiesConfig,
|
WithCapabilitiesConfig,
|
||||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||||
|
import { WithTenantConfig } from "@goauthentik/elements/Interface/tenantProvider";
|
||||||
import "@goauthentik/elements/buttons/ActionButton";
|
import "@goauthentik/elements/buttons/ActionButton";
|
||||||
import "@goauthentik/elements/buttons/Dropdown";
|
import "@goauthentik/elements/buttons/Dropdown";
|
||||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||||
|
@ -110,7 +110,7 @@ export class RelatedUserAdd extends Form<{ users: number[] }> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@customElement("ak-user-related-list")
|
@customElement("ak-user-related-list")
|
||||||
export class RelatedUserList extends WithCapabilitiesConfig(Table<User>) {
|
export class RelatedUserList extends WithTenantConfig(WithCapabilitiesConfig(Table<User>)) {
|
||||||
expandable = true;
|
expandable = true;
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ export class RelatedUserList extends WithCapabilitiesConfig(Table<User>) {
|
||||||
${msg("Set password")}
|
${msg("Set password")}
|
||||||
</button>
|
</button>
|
||||||
</ak-forms-modal>
|
</ak-forms-modal>
|
||||||
${rootInterface()?.tenant?.flowRecovery
|
${this.tenant?.flowRecovery
|
||||||
? html`
|
? html`
|
||||||
<ak-action-button
|
<ak-action-button
|
||||||
class="pf-m-secondary"
|
class="pf-m-secondary"
|
||||||
|
|
|
@ -3,7 +3,7 @@ import "@goauthentik/admin/common/ak-flow-search/ak-tenanted-flow-search";
|
||||||
import { BaseProviderForm } from "@goauthentik/admin/providers/BaseProviderForm";
|
import { BaseProviderForm } from "@goauthentik/admin/providers/BaseProviderForm";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { first } from "@goauthentik/common/utils";
|
import { first } 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/FormGroup";
|
||||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
import "@goauthentik/elements/forms/Radio";
|
import "@goauthentik/elements/forms/Radio";
|
||||||
|
@ -25,7 +25,7 @@ import {
|
||||||
} from "@goauthentik/api";
|
} from "@goauthentik/api";
|
||||||
|
|
||||||
@customElement("ak-provider-ldap-form")
|
@customElement("ak-provider-ldap-form")
|
||||||
export class LDAPProviderFormPage extends BaseProviderForm<LDAPProvider> {
|
export class LDAPProviderFormPage extends WithTenantConfig(BaseProviderForm<LDAPProvider>) {
|
||||||
async loadInstance(pk: number): Promise<LDAPProvider> {
|
async loadInstance(pk: number): Promise<LDAPProvider> {
|
||||||
return new ProvidersApi(DEFAULT_CONFIG).providersLdapRetrieve({
|
return new ProvidersApi(DEFAULT_CONFIG).providersLdapRetrieve({
|
||||||
id: pk,
|
id: pk,
|
||||||
|
@ -68,7 +68,7 @@ export class LDAPProviderFormPage extends BaseProviderForm<LDAPProvider> {
|
||||||
<ak-tenanted-flow-search
|
<ak-tenanted-flow-search
|
||||||
flowType=${FlowsInstancesListDesignationEnum.Authentication}
|
flowType=${FlowsInstancesListDesignationEnum.Authentication}
|
||||||
.currentFlow=${this.instance?.authorizationFlow}
|
.currentFlow=${this.instance?.authorizationFlow}
|
||||||
.tenantFlow=${rootInterface()?.tenant?.flowAuthentication}
|
.tenantFlow=${this.tenant?.flowAuthentication}
|
||||||
required
|
required
|
||||||
></ak-tenanted-flow-search>
|
></ak-tenanted-flow-search>
|
||||||
<p class="pf-c-form__helper-text">${msg("Flow used for users to authenticate.")}</p>
|
<p class="pf-c-form__helper-text">${msg("Flow used for users to authenticate.")}</p>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { BaseProviderForm } from "@goauthentik/admin/providers/BaseProviderForm";
|
import { BaseProviderForm } from "@goauthentik/admin/providers/BaseProviderForm";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
|
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/FormGroup";
|
||||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
import "@goauthentik/elements/forms/SearchSelect";
|
import "@goauthentik/elements/forms/SearchSelect";
|
||||||
|
@ -14,7 +14,7 @@ import { customElement } from "lit/decorators.js";
|
||||||
import { FlowsInstancesListDesignationEnum, ProvidersApi, RadiusProvider } from "@goauthentik/api";
|
import { FlowsInstancesListDesignationEnum, ProvidersApi, RadiusProvider } from "@goauthentik/api";
|
||||||
|
|
||||||
@customElement("ak-provider-radius-form")
|
@customElement("ak-provider-radius-form")
|
||||||
export class RadiusProviderFormPage extends BaseProviderForm<RadiusProvider> {
|
export class RadiusProviderFormPage extends WithTenantConfig(BaseProviderForm<RadiusProvider>) {
|
||||||
loadInstance(pk: number): Promise<RadiusProvider> {
|
loadInstance(pk: number): Promise<RadiusProvider> {
|
||||||
return new ProvidersApi(DEFAULT_CONFIG).providersRadiusRetrieve({
|
return new ProvidersApi(DEFAULT_CONFIG).providersRadiusRetrieve({
|
||||||
id: pk,
|
id: pk,
|
||||||
|
@ -57,7 +57,7 @@ export class RadiusProviderFormPage extends BaseProviderForm<RadiusProvider> {
|
||||||
<ak-tenanted-flow-search
|
<ak-tenanted-flow-search
|
||||||
flowType=${FlowsInstancesListDesignationEnum.Authentication}
|
flowType=${FlowsInstancesListDesignationEnum.Authentication}
|
||||||
.currentFlow=${this.instance?.authorizationFlow}
|
.currentFlow=${this.instance?.authorizationFlow}
|
||||||
.tenantFlow=${rootInterface()?.tenant?.flowAuthentication}
|
.tenantFlow=${this.tenant?.flowAuthentication}
|
||||||
required
|
required
|
||||||
></ak-tenanted-flow-search>
|
></ak-tenanted-flow-search>
|
||||||
<p class="pf-c-form__helper-text">${msg("Flow used for users to authenticate.")}</p>
|
<p class="pf-c-form__helper-text">${msg("Flow used for users to authenticate.")}</p>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
CapabilitiesEnum,
|
CapabilitiesEnum,
|
||||||
WithCapabilitiesConfig,
|
WithCapabilitiesConfig,
|
||||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||||
|
import { WithTenantConfig } from "@goauthentik/elements/Interface/tenantProvider";
|
||||||
import { PFSize } from "@goauthentik/elements/Spinner";
|
import { PFSize } from "@goauthentik/elements/Spinner";
|
||||||
import "@goauthentik/elements/TreeView";
|
import "@goauthentik/elements/TreeView";
|
||||||
import "@goauthentik/elements/buttons/ActionButton";
|
import "@goauthentik/elements/buttons/ActionButton";
|
||||||
|
@ -90,7 +91,7 @@ const recoveryButtonStyles = css`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@customElement("ak-user-list")
|
@customElement("ak-user-list")
|
||||||
export class UserListPage extends WithCapabilitiesConfig(TablePage<User>) {
|
export class UserListPage extends WithTenantConfig(WithCapabilitiesConfig(TablePage<User>)) {
|
||||||
expandable = true;
|
expandable = true;
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
|
||||||
|
@ -351,7 +352,7 @@ export class UserListPage extends WithCapabilitiesConfig(TablePage<User>) {
|
||||||
${msg("Set password")}
|
${msg("Set password")}
|
||||||
</button>
|
</button>
|
||||||
</ak-forms-modal>
|
</ak-forms-modal>
|
||||||
${rootInterface()?.tenant?.flowRecovery
|
${this.tenant.flowRecovery
|
||||||
? html`
|
? html`
|
||||||
<ak-action-button
|
<ak-action-button
|
||||||
class="pf-m-secondary"
|
class="pf-m-secondary"
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import { createContext } from "@lit-labs/context";
|
import { createContext } from "@lit-labs/context";
|
||||||
|
|
||||||
import { type Config } from "@goauthentik/api";
|
import type { Config, CurrentTenant } from "@goauthentik/api";
|
||||||
|
|
||||||
export const authentikConfigContext = createContext<Config>(Symbol("authentik-config-context"));
|
export const authentikConfigContext = createContext<Config>(Symbol("authentik-config-context"));
|
||||||
|
|
||||||
|
export const authentikTenantContext = createContext<CurrentTenant>(
|
||||||
|
Symbol("authentik-tenant-context"),
|
||||||
|
);
|
||||||
|
|
||||||
export default authentikConfigContext;
|
export default authentikConfigContext;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { config, tenant } from "@goauthentik/common/api/config";
|
import { config, tenant } from "@goauthentik/common/api/config";
|
||||||
import { UIConfig, uiConfig } from "@goauthentik/common/ui/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 type { AdoptedStyleSheetsElement } from "@goauthentik/elements/types";
|
||||||
import { ensureCSSStyleSheet } from "@goauthentik/elements/utils/ensureCSSStyleSheet";
|
import { ensureCSSStyleSheet } from "@goauthentik/elements/utils/ensureCSSStyleSheet";
|
||||||
|
|
||||||
|
@ -21,9 +24,6 @@ type AkInterface = HTMLElement & {
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Interface extends AKElement implements AkInterface {
|
export class Interface extends AKElement implements AkInterface {
|
||||||
@state()
|
|
||||||
tenant?: CurrentTenant;
|
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
uiConfig?: UIConfig;
|
uiConfig?: UIConfig;
|
||||||
|
|
||||||
|
@ -45,6 +45,24 @@ export class Interface extends AKElement implements AkInterface {
|
||||||
return this._config;
|
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() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
document.adoptedStyleSheets = [...document.adoptedStyleSheets, ensureCSSStyleSheet(PFBase)];
|
document.adoptedStyleSheets = [...document.adoptedStyleSheets, ensureCSSStyleSheet(PFBase)];
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function WithAuthentikConfig<T extends Constructor<LitElement>>(
|
||||||
superclass: T,
|
superclass: T,
|
||||||
subscribe = true,
|
subscribe = true,
|
||||||
) {
|
) {
|
||||||
class WithAkConfigProvider extends superclass {
|
abstract class WithAkConfigProvider extends superclass {
|
||||||
@consume({ context: authentikConfigContext, subscribe })
|
@consume({ context: authentikConfigContext, subscribe })
|
||||||
public authentikConfig!: Config;
|
public authentikConfig!: Config;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<T = object> = abstract new (...args: any[]) => T;
|
||||||
|
|
||||||
|
export function WithTenantConfig<T extends Constructor<LitElement>>(
|
||||||
|
superclass: T,
|
||||||
|
subscribe = true,
|
||||||
|
) {
|
||||||
|
abstract class WithTenantProvider extends superclass {
|
||||||
|
@consume({ context: authentikTenantContext, subscribe })
|
||||||
|
public tenant!: CurrentTenant;
|
||||||
|
}
|
||||||
|
return WithTenantProvider;
|
||||||
|
}
|
|
@ -8,7 +8,8 @@ import {
|
||||||
} from "@goauthentik/common/constants";
|
} from "@goauthentik/common/constants";
|
||||||
import { currentInterface } from "@goauthentik/common/sentry";
|
import { currentInterface } from "@goauthentik/common/sentry";
|
||||||
import { me } from "@goauthentik/common/users";
|
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 "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
|
@ -23,7 +24,7 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||||
import { EventsApi } from "@goauthentik/api";
|
import { EventsApi } from "@goauthentik/api";
|
||||||
|
|
||||||
@customElement("ak-page-header")
|
@customElement("ak-page-header")
|
||||||
export class PageHeader extends AKElement {
|
export class PageHeader extends WithTenantConfig(AKElement) {
|
||||||
@property()
|
@property()
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
|
||||||
|
@ -35,9 +36,8 @@ export class PageHeader extends AKElement {
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
set header(value: string) {
|
set header(value: string) {
|
||||||
const tenant = rootInterface()?.tenant;
|
|
||||||
const currentIf = currentInterface();
|
const currentIf = currentInterface();
|
||||||
let title = tenant?.brandingTitle || TITLE_DEFAULT;
|
let title = this.tenant?.brandingTitle || TITLE_DEFAULT;
|
||||||
if (currentIf === "admin") {
|
if (currentIf === "admin") {
|
||||||
title = `${msg("Admin")} - ${title}`;
|
title = `${msg("Admin")} - ${title}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { EVENT_SIDEBAR_TOGGLE } from "@goauthentik/common/constants";
|
import { EVENT_SIDEBAR_TOGGLE } from "@goauthentik/common/constants";
|
||||||
import { first } from "@goauthentik/common/utils";
|
import { AKElement } from "@goauthentik/elements/Base";
|
||||||
import { AKElement, rootInterface } from "@goauthentik/elements/Base";
|
import { WithTenantConfig } from "@goauthentik/elements/Interface/tenantProvider";
|
||||||
|
|
||||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||||
import { customElement } from "lit/decorators.js";
|
import { customElement } from "lit/decorators.js";
|
||||||
|
@ -27,7 +27,7 @@ export const DefaultTenant: CurrentTenant = {
|
||||||
};
|
};
|
||||||
|
|
||||||
@customElement("ak-sidebar-brand")
|
@customElement("ak-sidebar-brand")
|
||||||
export class SidebarBrand extends AKElement {
|
export class SidebarBrand extends WithTenantConfig(AKElement) {
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
PFBase,
|
PFBase,
|
||||||
|
@ -85,10 +85,7 @@ export class SidebarBrand extends AKElement {
|
||||||
<a href="#/" class="pf-c-page__header-brand-link">
|
<a href="#/" class="pf-c-page__header-brand-link">
|
||||||
<div class="pf-c-brand ak-brand">
|
<div class="pf-c-brand ak-brand">
|
||||||
<img
|
<img
|
||||||
src="${first(
|
src=${this.tenant?.brandingLogo ?? DefaultTenant.brandingLogo}
|
||||||
rootInterface()?.tenant?.brandingLogo,
|
|
||||||
DefaultTenant.brandingLogo,
|
|
||||||
)}"
|
|
||||||
alt="authentik Logo"
|
alt="authentik Logo"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,14 +2,15 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||||
import { MessageLevel } from "@goauthentik/common/messages";
|
import { MessageLevel } from "@goauthentik/common/messages";
|
||||||
import { refreshMe } from "@goauthentik/common/users";
|
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 { showMessage } from "@goauthentik/elements/messages/MessageContainer";
|
||||||
import { StageHost } from "@goauthentik/flow/stages/base";
|
import { StageHost } from "@goauthentik/flow/stages/base";
|
||||||
import "@goauthentik/user/user-settings/details/stages/prompt/PromptStage";
|
import "@goauthentik/user/user-settings/details/stages/prompt/PromptStage";
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { CSSResult, TemplateResult, html } from "lit";
|
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 { unsafeHTML } from "lit/directives/unsafe-html.js";
|
||||||
|
|
||||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||||
|
@ -21,7 +22,6 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||||
import {
|
import {
|
||||||
ChallengeChoices,
|
ChallengeChoices,
|
||||||
ChallengeTypes,
|
ChallengeTypes,
|
||||||
CurrentTenant,
|
|
||||||
FlowChallengeResponseRequest,
|
FlowChallengeResponseRequest,
|
||||||
FlowErrorChallenge,
|
FlowErrorChallenge,
|
||||||
FlowsApi,
|
FlowsApi,
|
||||||
|
@ -31,13 +31,13 @@ import {
|
||||||
} from "@goauthentik/api";
|
} from "@goauthentik/api";
|
||||||
|
|
||||||
@customElement("ak-user-settings-flow-executor")
|
@customElement("ak-user-settings-flow-executor")
|
||||||
export class UserSettingsFlowExecutor extends AKElement implements StageHost {
|
export class UserSettingsFlowExecutor
|
||||||
|
extends WithTenantConfig(AKElement, true)
|
||||||
|
implements StageHost
|
||||||
|
{
|
||||||
@property()
|
@property()
|
||||||
flowSlug?: string;
|
flowSlug?: string;
|
||||||
|
|
||||||
@state()
|
|
||||||
tenant?: CurrentTenant;
|
|
||||||
|
|
||||||
private _challenge?: ChallengeTypes;
|
private _challenge?: ChallengeTypes;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
|
@ -87,7 +87,6 @@ export class UserSettingsFlowExecutor extends AKElement implements StageHost {
|
||||||
}
|
}
|
||||||
|
|
||||||
firstUpdated(): void {
|
firstUpdated(): void {
|
||||||
this.tenant = rootInterface()?.tenant;
|
|
||||||
this.flowSlug = this.tenant?.flowUserSettings;
|
this.flowSlug = this.tenant?.flowUserSettings;
|
||||||
if (!this.flowSlug) {
|
if (!this.flowSlug) {
|
||||||
return;
|
return;
|
||||||
|
|
Reference in New Issue