import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { docLink } from "@goauthentik/common/global"; import { groupBy } from "@goauthentik/common/utils"; import "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider"; import { DataProvider, DualSelectPair } from "@goauthentik/elements/ak-dual-select/types"; import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/forms/SearchSelect"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import YAML from "yaml"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; import { map } from "lit/directives/map.js"; import { Outpost, OutpostDefaultConfig, OutpostTypeEnum, OutpostsApi, OutpostsServiceConnectionsAllListRequest, ProvidersApi, ServiceConnection, } from "@goauthentik/api"; interface ProviderBase { pk: number; name: string; assignedBackchannelApplicationName?: string; assignedApplicationName?: string; } const api = () => new ProvidersApi(DEFAULT_CONFIG); const providerListArgs = (page: number, search = "") => ({ ordering: "name", applicationIsnull: false, pageSize: 20, search: search.trim(), page, }); const dualSelectPairMaker = (item: ProviderBase): DualSelectPair => { const label = item.assignedBackchannelApplicationName ? item.assignedBackchannelApplicationName : item.assignedApplicationName; return [ `${item.pk}`, html`
${label}
${item.name}
`, label, ]; }; const provisionMaker = (results: PaginatedResponse) => ({ pagination: results.pagination, options: results.results.map(dualSelectPairMaker), }); const proxyListFetch = async (page: number, search = "") => provisionMaker(await api().providersProxyList(providerListArgs(page, search))); const ldapListFetch = async (page: number, search = "") => provisionMaker(await api().providersLdapList(providerListArgs(page, search))); const radiusListFetch = async (page: number, search = "") => provisionMaker(await api().providersRadiusList(providerListArgs(page, search))); const racListProvider = async (page: number, search = "") => provisionMaker(await api().providersRacList(providerListArgs(page, search))); function providerProvider(type: OutpostTypeEnum): DataProvider { switch (type) { case OutpostTypeEnum.Proxy: return proxyListFetch; case OutpostTypeEnum.Ldap: return ldapListFetch; case OutpostTypeEnum.Radius: return radiusListFetch; case OutpostTypeEnum.Rac: return racListProvider; default: throw new Error(`Unrecognized OutputType: ${type}`); } } @customElement("ak-outpost-form") export class OutpostForm extends ModelForm { @property() type: OutpostTypeEnum = OutpostTypeEnum.Proxy; @property({ type: Boolean }) embedded = false; @state() providers?: DataProvider; defaultConfig?: OutpostDefaultConfig; async loadInstance(pk: string): Promise { const o = await new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesRetrieve({ uuid: pk, }); this.type = o.type || OutpostTypeEnum.Proxy; this.providers = providerProvider(o.type); return o; } async load(): Promise { this.defaultConfig = await new OutpostsApi( DEFAULT_CONFIG, ).outpostsInstancesDefaultSettingsRetrieve(); } getSuccessMessage(): string { return this.instance ? msg("Successfully updated outpost.") : msg("Successfully created outpost."); } async send(data: Outpost): Promise { if (this.instance) { return new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesUpdate({ uuid: this.instance.pk || "", outpostRequest: data, }); } else { return new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesCreate({ outpostRequest: data, }); } } renderForm(): TemplateResult { const typeOptions = [ [OutpostTypeEnum.Proxy, msg("Proxy")], [OutpostTypeEnum.Ldap, msg("LDAP")], [OutpostTypeEnum.Radius, msg("Radius")], [OutpostTypeEnum.Rac, msg("RAC")], ]; return html` => { const args: OutpostsServiceConnectionsAllListRequest = { ordering: "name", }; if (query !== undefined) { args.search = query; } const items = await new OutpostsApi( DEFAULT_CONFIG, ).outpostsServiceConnectionsAllList(args); return items.results; }} .renderElement=${(item: ServiceConnection): string => { return item.name; }} .value=${(item: ServiceConnection | undefined): string | undefined => { return item?.pk; }} .groupBy=${(items: ServiceConnection[]) => { return groupBy(items, (item) => item.verboseName); }} .selected=${(item: ServiceConnection, items: ServiceConnection[]): boolean => { let selected = this.instance?.serviceConnection === item.pk; if (items.length === 1 && !this.instance) { selected = true; } return selected; }} ?blankable=${true} >

${msg( "Selecting an integration enables the management of the outpost by authentik.", )}

${msg("See documentation")}.

${msg("Advanced settings")}

${msg("Set custom attributes using YAML or JSON.")}

${msg("See more here:")}  ${msg("Documentation")}

`; } } declare global { interface HTMLElementTagNameMap { "ak-outpost-form": OutpostForm; } }