import { RenderFlowOption } from "@goauthentik/admin/flows/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { first } from "@goauthentik/common/utils"; import { rootInterface } from "@goauthentik/elements/Base"; import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/SearchSelect"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; import { customElement } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; import { CertificateKeyPair, CoreApi, CoreGroupsListRequest, CryptoApi, CryptoCertificatekeypairsListRequest, Flow, FlowsApi, FlowsInstancesListDesignationEnum, FlowsInstancesListRequest, Group, LDAPAPIAccessMode, LDAPProvider, ProvidersApi, } from "@goauthentik/api"; @customElement("ak-provider-ldap-form") export class LDAPProviderFormPage extends ModelForm { async loadInstance(pk: number): Promise { return new ProvidersApi(DEFAULT_CONFIG).providersLdapRetrieve({ id: pk, }); } getSuccessMessage(): string { if (this.instance) { return msg("Successfully updated provider."); } else { return msg("Successfully created provider."); } } async send(data: LDAPProvider): Promise { if (this.instance) { return new ProvidersApi(DEFAULT_CONFIG).providersLdapUpdate({ id: this.instance.pk || 0, lDAPProviderRequest: data, }); } else { return new ProvidersApi(DEFAULT_CONFIG).providersLdapCreate({ lDAPProviderRequest: data, }); } } renderForm(): TemplateResult { return html`
=> { const args: FlowsInstancesListRequest = { ordering: "slug", designation: FlowsInstancesListDesignationEnum.Authentication, }; if (query !== undefined) { args.search = query; } const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList(args); return flows.results; }} .renderElement=${(flow: Flow): string => { return RenderFlowOption(flow); }} .renderDescription=${(flow: Flow): TemplateResult => { return html`${flow.slug}`; }} .value=${(flow: Flow | undefined): string | undefined => { return flow?.pk; }} .selected=${(flow: Flow): boolean => { let selected = flow.pk === rootInterface()?.tenant?.flowAuthentication; if (this.instance?.authorizationFlow === flow.pk) { selected = true; } return selected; }} >

${msg("Flow used for users to authenticate.")}

=> { const args: CoreGroupsListRequest = { ordering: "name", }; if (query !== undefined) { args.search = query; } const groups = await new CoreApi(DEFAULT_CONFIG).coreGroupsList(args); return groups.results; }} .renderElement=${(group: Group): string => { return group.name; }} .value=${(group: Group | undefined): string | undefined => { return group?.pk; }} .selected=${(group: Group): boolean => { return group.pk === this.instance?.searchGroup; }} ?blankable=${true} >

${msg( "Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed.", )}

${msg("Configure how the outpost authenticates requests.")}

${msg("Configure how the outpost queries the core authentik server's users.")}

${msg( "When enabled, code-based multi-factor authentication can be used by appending a semicolon and the TOTP code to the password. This should only be enabled if all users that will bind to this provider have a TOTP device configured, as otherwise a password may incorrectly be rejected if it contains a semicolon.", )}

${msg("Protocol settings")}

${msg( "LDAP DN under which bind requests and search requests can be made.", )}

=> { const args: CryptoCertificatekeypairsListRequest = { ordering: "name", hasKey: true, includeDetails: false, }; if (query !== undefined) { args.search = query; } const certificates = await new CryptoApi( DEFAULT_CONFIG, ).cryptoCertificatekeypairsList(args); return certificates.results; }} .renderElement=${(item: CertificateKeyPair): string => { return item.name; }} .value=${(item: CertificateKeyPair | undefined): string | undefined => { return item?.pk; }} .selected=${(item: CertificateKeyPair): boolean => { return item.pk === this.instance?.certificate; }} ?blankable=${true} >

${msg( "The certificate for the above configured Base DN. As a fallback, the provider uses a self-signed certificate.", )}

${msg( "DNS name for which the above configured certificate should be used. The certificate cannot be detected based on the base DN, as the SSL/TLS negotiation happens before such data is exchanged.", )}

${msg( "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber", )}

${msg( "The start for gidNumbers, this number is added to a number generated from the group.Pk to make sure that the numbers aren't too low for POSIX groups. Default is 4000 to ensure that we don't collide with local groups or users primary groups gidNumber", )}

`; } }