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 fca1666d81..5df32e02d6 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 @@ -1,6 +1,7 @@ import "@goauthentik/admin/applications/wizard/ak-wizard-title"; import "@goauthentik/admin/common/ak-crypto-certificate-search"; import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search"; +import { renderForm } from "@goauthentik/admin/providers/radius/RadiusProviderFormForm.js"; import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-text-input"; import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider"; @@ -10,91 +11,21 @@ import "@goauthentik/elements/forms/HorizontalFormElement"; import { msg } from "@lit/localize"; import { customElement } from "@lit/reactive-element/decorators.js"; import { html } from "lit"; -import { ifDefined } from "lit/directives/if-defined.js"; -import { FlowsInstancesListDesignationEnum, RadiusProvider } from "@goauthentik/api"; +import { RadiusProvider } from "@goauthentik/api"; import BaseProviderPanel from "../BaseProviderPanel"; @customElement("ak-application-wizard-authentication-by-radius") export class ApplicationWizardAuthenticationByRadius extends WithBrandConfig(BaseProviderPanel) { render() { - const provider = this.wizard.provider as RadiusProvider | undefined; - const errors = this.wizard.errors.provider; - return html`${msg("Configure Radius Provider")}
- - - - - -

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

-
- - - ${msg("Protocol settings")} -
- - -
-
- - ${msg("Advanced flow settings")} -
- - -

- ${msg("Flow used when logging out of this provider.")} -

-
-
+ ${renderForm( + this.wizard.provider as RadiusProvider | undefined, + this.wizard.errors.provider, + this.brand, + )}
`; } } diff --git a/web/src/admin/providers/radius/RadiusProviderForm.ts b/web/src/admin/providers/radius/RadiusProviderForm.ts index d3280d8013..e1832f7fc7 100644 --- a/web/src/admin/providers/radius/RadiusProviderForm.ts +++ b/web/src/admin/providers/radius/RadiusProviderForm.ts @@ -1,48 +1,12 @@ -import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search"; -import "@goauthentik/admin/common/ak-flow-search/ak-flow-search"; 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 { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider"; -import { DualSelectPair } from "@goauthentik/elements/ak-dual-select/types"; -import "@goauthentik/elements/forms/FormGroup"; -import "@goauthentik/elements/forms/HorizontalFormElement"; -import "@goauthentik/elements/forms/SearchSelect"; -import { msg } from "@lit/localize"; -import { TemplateResult, html } from "lit"; -import { ifDefined } from "lit-html/directives/if-defined.js"; import { customElement } from "lit/decorators.js"; -import { - FlowsInstancesListDesignationEnum, - PropertymappingsApi, - ProvidersApi, - RadiusProvider, - RadiusProviderPropertyMapping, -} from "@goauthentik/api"; +import { ProvidersApi, RadiusProvider } from "@goauthentik/api"; -export async function radiusPropertyMappingsProvider(page = 1, search = "") { - const propertyMappings = await new PropertymappingsApi( - DEFAULT_CONFIG, - ).propertymappingsProviderRadiusList({ - ordering: "name", - pageSize: 20, - search: search.trim(), - page, - }); - return { - pagination: propertyMappings.pagination, - options: propertyMappings.results.map((m) => [m.pk, m.name, m.name, m]), - }; -} - -export function makeRadiusPropertyMappingsSelector(instanceMappings?: string[]) { - const localMappings = instanceMappings ? new Set(instanceMappings) : undefined; - return localMappings - ? ([pk, _]: DualSelectPair) => localMappings.has(pk) - : ([_0, _1, _2, _]: DualSelectPair) => []; -} +import { renderForm } from "./RadiusProviderFormForm.js"; @customElement("ak-provider-radius-form") export class RadiusProviderFormPage extends WithBrandConfig(BaseProviderForm) { @@ -65,127 +29,8 @@ export class RadiusProviderFormPage extends WithBrandConfig(BaseProviderForm - - - - -

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

-
- - -

- ${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(`List of CIDRs (comma-seperated) that clients can connect from. A more specific - CIDR will match before a looser one. Clients connecting from a non-specified CIDR - will be dropped.`)} -

-
- - - -
-
- - ${msg("Advanced flow settings")} -
- - -

- ${msg("Flow used when logging out of this provider.")} -

-
-
- `; + renderForm() { + return renderForm(this.instance ?? {}, [], this.brand); } } diff --git a/web/src/admin/providers/radius/RadiusProviderFormForm.ts b/web/src/admin/providers/radius/RadiusProviderFormForm.ts new file mode 100644 index 0000000000..a88be56afe --- /dev/null +++ b/web/src/admin/providers/radius/RadiusProviderFormForm.ts @@ -0,0 +1,161 @@ +import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search"; +import "@goauthentik/admin/common/ak-flow-search/ak-flow-search"; +import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils"; +import { DualSelectPair } from "@goauthentik/elements/ak-dual-select/types"; +import "@goauthentik/elements/forms/FormGroup"; +import "@goauthentik/elements/forms/HorizontalFormElement"; +import "@goauthentik/elements/forms/SearchSelect"; + +import { msg } from "@lit/localize"; +import { html } from "lit"; +import { ifDefined } from "lit/directives/if-defined.js"; + +import { + FlowsInstancesListDesignationEnum, + PropertymappingsApi, + RadiusProviderPropertyMapping, + ValidationError, +} from "@goauthentik/api"; + +export async function radiusPropertyMappingsProvider(page = 1, search = "") { + const propertyMappings = await new PropertymappingsApi( + DEFAULT_CONFIG, + ).propertymappingsProviderRadiusList({ + ordering: "name", + pageSize: 20, + search: search.trim(), + page, + }); + return { + pagination: propertyMappings.pagination, + options: propertyMappings.results.map((m) => [m.pk, m.name, m.name, m]), + }; +} + +export function makeRadiusPropertyMappingsSelector(instanceMappings?: string[]) { + const localMappings = instanceMappings ? new Set(instanceMappings) : undefined; + return localMappings + ? ([pk, _]: DualSelectPair) => localMappings.has(pk) + : ([_0, _1, _2, _]: DualSelectPair) => []; +} + +const mfaHelp = 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.", +); + +const clientNetworksHelp = msg( + "List of CIDRs (comma-seperated) that clients can connect from. A more specific CIDR will match before a looser one. Clients connecting from a non-specified CIDR will be dropped.", +); + +// All Provider objects have an Authorization flow, but not all providers have an Authentication +// flow. Radius needs only one field, but it is not the Authorization field, it is an +// Authentication field. So, yeah, we're using the authorization field to store the +// authentication information, which is why the ak-branded-flow-search call down there looks so +// weird-- we're looking up Authentication flows, but we're storing them in the Authorization +// field of the target Provider. + +export function renderForm( + provider?: Partial, + errors: ValidationError = {}, + brand?: CurrentBrand, +) { + return html` + + + + + +

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

+
+ + + +

${mfaHelp}

+
+ + + ${msg("Protocol settings")} +
+ + + + + +
+
+ + ${msg("Advanced flow settings")} +
+ + +

+ ${msg("Flow used when logging out of this provider.")} +

+
+
+ `; +}