mirror of
https://github.com/goauthentik/authentik
synced 2026-05-15 03:16:22 +02:00
* Use project relative paths. * Fix tests. * Fix types. * Clean up admin imports. * Move admin import. * Remove or replace references to admin. * Typo fix. * Flesh out ak-modal, about modal. * Flesh out lazy modal. * Fix portal elements not using dialog scope. * Fix url parameters, wizards. * Fix invokers, lazy load. * Fix theming. * Add placeholders, help. * Flesh out command palette. Flesh out styles, command invokers. Continue clean up. Allow slotted content. Flesh out. * Flesh out edit invoker. Prep groups. * Fix odd labeling, legacy situations. * Prepare deprecation of table modal. Clean up serialization. * Tidy types. * Port provider select modal. * Port member select form. * Flesh out role modal. Fix loading state. * Port user group form. * Fix spellcheck. * Fix dialog detection. * Revise types. * Port rac launch modal. * Remove deprecated table modal. * Consistent form action placement. * Consistent casing. * Consistent alignment. * Use more appropriate description. * Flesh out icon. Fix alignment, colors. * Flesh out user search. * Consistent save button. * Clean up labels. * Reduce warning noise. * Clean up label. * Use attribute e2e expects. * Use directive. Fix lifecycle * Fix frequent un-memoized entries. * Fix up closedBy detection. * Tidy alignment. * Fix types, composition. * Fix labels, tests. * Fix up impersonation, labels. * Flesh out. Fix refresh after submit. * Flesh out basic modal test. * Fix ARIA. * Flesh out roles test. * Revise selectors. * Clean up selectors. * Fix impersonation labels, form references. * Fix messages appearing under modals. * Ensure reason is parsed. * Flesh out impersonation test. * Flesh out impersonate test. * Flesh out application tests. Clean up toolbar header, ARIA. * Flesh out wizard test. * Refine weight, order. * Fix up initial values, selectors. * Fix tests. * Fix selector.
203 lines
6.4 KiB
TypeScript
203 lines
6.4 KiB
TypeScript
import { DEFAULT_CONFIG } from "#common/api/config";
|
|
import { type APIResult, isAPIResultReady } from "#common/api/responses";
|
|
import { globalAK } from "#common/global";
|
|
import { applyThemeChoice, formatColorScheme } from "#common/theme";
|
|
import { createUIConfig, DefaultUIConfig } from "#common/ui/config";
|
|
import { autoDetectLanguage } from "#common/ui/locale/utils";
|
|
import { me } from "#common/users";
|
|
|
|
import {
|
|
CommandPaletteState,
|
|
PaletteCommandDefinitionInit,
|
|
PaletteCommandNamespace,
|
|
} from "#elements/commands/shared";
|
|
import { ReactiveContextController } from "#elements/controllers/ReactiveContextController";
|
|
import { AKConfigMixin, kAKConfig } from "#elements/mixins/config";
|
|
import { kAKLocale, type LocaleMixin } from "#elements/mixins/locale";
|
|
import {
|
|
canAccessAdmin,
|
|
SessionContext,
|
|
SessionMixin,
|
|
UIConfigContext,
|
|
} from "#elements/mixins/session";
|
|
import { AKDrawerChangeEvent } from "#elements/notifications/events";
|
|
import type { ReactiveElementHost } from "#elements/types";
|
|
|
|
import { CoreApi, SessionUser } from "@goauthentik/api";
|
|
|
|
import { setUser } from "@sentry/browser";
|
|
|
|
import { ContextProvider } from "@lit/context";
|
|
import { msg } from "@lit/localize";
|
|
|
|
/**
|
|
* A controller that provides the session information to the element.
|
|
*
|
|
* @see {@linkcode SessionMixin}
|
|
*/
|
|
export class SessionContextController extends ReactiveContextController<APIResult<SessionUser>> {
|
|
protected static override logPrefix = "session";
|
|
|
|
public host: ReactiveElementHost<LocaleMixin & SessionMixin & AKConfigMixin>;
|
|
public context: ContextProvider<SessionContext>;
|
|
|
|
protected uiConfigContext: ContextProvider<UIConfigContext>;
|
|
|
|
constructor(
|
|
host: ReactiveElementHost<SessionMixin & AKConfigMixin>,
|
|
initialValue?: APIResult<SessionUser>,
|
|
) {
|
|
super();
|
|
|
|
this.host = host;
|
|
|
|
this.context = new ContextProvider(this.host, {
|
|
context: SessionContext,
|
|
initialValue: initialValue ?? { loading: true, error: null },
|
|
});
|
|
|
|
this.uiConfigContext = new ContextProvider(this.host, {
|
|
context: UIConfigContext,
|
|
initialValue: DefaultUIConfig,
|
|
});
|
|
}
|
|
|
|
protected apiEndpoint(requestInit?: RequestInit) {
|
|
return me(requestInit);
|
|
}
|
|
|
|
#refreshCommandsFrameID = -1;
|
|
|
|
#commands = new CommandPaletteState({
|
|
target: this.host,
|
|
});
|
|
|
|
protected doRefresh(session: APIResult<SessionUser>): void {
|
|
this.context.setValue(session);
|
|
this.host.session = session;
|
|
|
|
if (!isAPIResultReady(session)) return;
|
|
|
|
const localeHint: string | undefined = session.user.settings.locale;
|
|
|
|
if (localeHint) {
|
|
const locale = autoDetectLanguage(localeHint);
|
|
this.logger.info(`Activating user's configured locale '${locale}'`);
|
|
this.host[kAKLocale]?.setLocale(locale);
|
|
}
|
|
|
|
const { settings = {} } = session.user || {};
|
|
|
|
const nextUIConfig = createUIConfig(settings);
|
|
this.uiConfigContext.setValue(nextUIConfig);
|
|
this.host.uiConfig = nextUIConfig;
|
|
const colorScheme = formatColorScheme(nextUIConfig.theme.base);
|
|
|
|
applyThemeChoice(colorScheme, this.host.ownerDocument);
|
|
|
|
const config = this.host[kAKConfig];
|
|
|
|
if (config?.errorReporting.sendPii) {
|
|
this.logger.info("Sentry with PII enabled.");
|
|
|
|
setUser({ email: session.user.email });
|
|
}
|
|
|
|
this.#refreshCommandsFrameID = requestAnimationFrame(this.#refreshCommands);
|
|
}
|
|
|
|
#refreshCommands = (): void => {
|
|
const session = this.context.value;
|
|
|
|
if (!isAPIResultReady(session)) {
|
|
this.#commands.clear();
|
|
return;
|
|
}
|
|
|
|
const base = globalAK().api.base;
|
|
const group = msg("Session");
|
|
const weight = 0.5;
|
|
|
|
const commands: PaletteCommandDefinitionInit[] = [
|
|
{
|
|
namespace: PaletteCommandNamespace.Navigation,
|
|
|
|
label: msg("User settings"),
|
|
prefix: msg("Navigate to", { id: "command-palette.prefix.navigate" }),
|
|
group,
|
|
weight,
|
|
action: () => {
|
|
window.location.assign(`${base}if/user/#/settings`);
|
|
},
|
|
},
|
|
];
|
|
|
|
const { notificationDrawer, apiDrawer } = this.host.uiConfig?.enabledFeatures ?? {};
|
|
const drawerGroup = msg("Interface");
|
|
|
|
if (apiDrawer) {
|
|
commands.push({
|
|
label: msg("API requests drawer", {
|
|
id: "command-palette.label.api-requests-drawer",
|
|
}),
|
|
prefix: msg("Toggle", { id: "command-palette.prefix.toggle" }),
|
|
group: drawerGroup,
|
|
weight,
|
|
action: AKDrawerChangeEvent.dispatchAPIToggle,
|
|
});
|
|
}
|
|
|
|
if (notificationDrawer) {
|
|
commands.push({
|
|
label: msg("Notifications drawer", {
|
|
id: "command-palette.label.notifications-drawer",
|
|
}),
|
|
prefix: msg("Toggle", { id: "command-palette.prefix.toggle" }),
|
|
group: drawerGroup,
|
|
weight,
|
|
|
|
action: AKDrawerChangeEvent.dispatchNotificationsToggle,
|
|
});
|
|
}
|
|
|
|
if (canAccessAdmin(session.user)) {
|
|
commands.push({
|
|
label: msg("Admin interface"),
|
|
prefix: msg("Navigate to", { id: "command-palette.prefix.navigate" }),
|
|
group,
|
|
weight,
|
|
action: () => {
|
|
window.location.assign(`${base}if/admin/`);
|
|
},
|
|
});
|
|
}
|
|
|
|
if (session.original) {
|
|
commands.push({
|
|
label: msg("Stop impersonation"),
|
|
suffix: msg("Reloads page", { id: "command-palette.prefix.reloads-page" }),
|
|
group,
|
|
weight,
|
|
action: async () => {
|
|
await new CoreApi(DEFAULT_CONFIG).coreUsersImpersonateEndRetrieve();
|
|
window.location.reload();
|
|
},
|
|
});
|
|
}
|
|
|
|
this.#commands.set(commands);
|
|
};
|
|
|
|
public override hostConnected() {
|
|
this.logger.debug("Host connected, refreshing session");
|
|
this.refresh();
|
|
}
|
|
|
|
public override hostDisconnected() {
|
|
this.context.clearCallbacks();
|
|
cancelAnimationFrame(this.#refreshCommandsFrameID);
|
|
|
|
super.hostDisconnected();
|
|
}
|
|
}
|