From 1149a619869a77260c39d1230cbeeb14df9deaa8 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 29 Dec 2022 11:56:54 +0100 Subject: [PATCH] web/admin: replace certificate selection with ak-search-select Signed-off-by: Jens Langhammer --- .../admin/providers/ldap/LDAPProviderForm.ts | 62 ++++----- .../providers/oauth2/OAuth2ProviderForm.ts | 71 +++++----- .../providers/proxy/ProxyProviderForm.ts | 61 ++++----- .../admin/providers/saml/SAMLProviderForm.ts | 121 +++++++++--------- web/src/admin/sources/ldap/LDAPSourceForm.ts | 64 +++++---- web/src/admin/sources/saml/SAMLSourceForm.ts | 59 +++++---- web/src/admin/tenants/TenantForm.ts | 66 +++++----- web/src/elements/SearchSelect.ts | 4 +- 8 files changed, 258 insertions(+), 250 deletions(-) diff --git a/web/src/admin/providers/ldap/LDAPProviderForm.ts b/web/src/admin/providers/ldap/LDAPProviderForm.ts index c1e4d5629..945eb9dec 100644 --- a/web/src/admin/providers/ldap/LDAPProviderForm.ts +++ b/web/src/admin/providers/ldap/LDAPProviderForm.ts @@ -13,9 +13,11 @@ import { ifDefined } from "lit/directives/if-defined.js"; import { until } from "lit/directives/until.js"; import { + CertificateKeyPair, CoreApi, CoreGroupsListRequest, CryptoApi, + CryptoCertificatekeypairsListRequest, FlowsApi, FlowsInstancesListDesignationEnum, Group, @@ -181,37 +183,37 @@ export class LDAPProviderFormPage extends ModelForm {

- + => { + 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} + > +

- ${t`Due to protocol limitations, this certificate is only used when the outpost has a single provider.`} + ${t`Due to protocol limitations, this certificate is only used when the outpost has a single provider, or all providers use the same certificate.`}

${t`If multiple providers share an outpost, a self-signed certificate is used.`} diff --git a/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts b/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts index 107ef5b2a..57da744f4 100644 --- a/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts +++ b/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts @@ -14,8 +14,10 @@ import { ifDefined } from "lit/directives/if-defined.js"; import { until } from "lit/directives/until.js"; import { + CertificateKeyPair, ClientTypeEnum, CryptoApi, + CryptoCertificatekeypairsListRequest, Flow, FlowsApi, FlowsInstancesListDesignationEnum, @@ -186,39 +188,42 @@ ${this.instance?.redirectUris} - + => { + 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, + items: CertificateKeyPair[], + ): boolean => { + let selected = this.instance?.signingKey === item.pk; + if (!this.instance && items.length === 1) { + selected = true; + } + return selected; + }} + ?blankable=${true} + > +

${t`Key used to sign the tokens.`}

diff --git a/web/src/admin/providers/proxy/ProxyProviderForm.ts b/web/src/admin/providers/proxy/ProxyProviderForm.ts index d55de90a5..8e9c0b449 100644 --- a/web/src/admin/providers/proxy/ProxyProviderForm.ts +++ b/web/src/admin/providers/proxy/ProxyProviderForm.ts @@ -1,6 +1,7 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { first } from "@goauthentik/common/utils"; import "@goauthentik/elements/SearchSelect"; +import "@goauthentik/elements/SearchSelect"; import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; @@ -20,7 +21,9 @@ import PFToggleGroup from "@patternfly/patternfly/components/ToggleGroup/toggle- import PFSpacing from "@patternfly/patternfly/utilities/Spacing/spacing.css"; import { + CertificateKeyPair, CryptoApi, + CryptoCertificatekeypairsListRequest, Flow, FlowsApi, FlowsInstancesListDesignationEnum, @@ -346,35 +349,35 @@ export class ProxyProviderFormPage extends ModelForm { ${t`Advanced protocol settings`}
- + => { + 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} + > + - - ${until( - new CryptoApi(DEFAULT_CONFIG) - .cryptoCertificatekeypairsList({ - ordering: "name", - hasKey: true, - includeDetails: false, - }) - .then((keys) => { - return keys.results.map((key) => { - return html``; - }); - }), - html``, - )} - + => { + 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?.signingKp; + }} + ?blankable=${true} + > +

${t`Certificate used to sign outgoing Responses going to the Service Provider.`}

@@ -195,38 +197,35 @@ export class SAMLProviderFormPage extends ModelForm { label=${t`Verification Certificate`} name="verificationKp" > - + => { + 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?.verificationKp; + }} + ?blankable=${true} + > +

${t`When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.`}

diff --git a/web/src/admin/sources/ldap/LDAPSourceForm.ts b/web/src/admin/sources/ldap/LDAPSourceForm.ts index f83d9d26e..a3b3520df 100644 --- a/web/src/admin/sources/ldap/LDAPSourceForm.ts +++ b/web/src/admin/sources/ldap/LDAPSourceForm.ts @@ -13,9 +13,11 @@ import { ifDefined } from "lit/directives/if-defined.js"; import { until } from "lit/directives/until.js"; import { + CertificateKeyPair, CoreApi, CoreGroupsListRequest, CryptoApi, + CryptoCertificatekeypairsListRequest, Group, LDAPSource, LDAPSourceRequest, @@ -149,39 +151,35 @@ export class LDAPSourceForm extends ModelForm { label=${t`TLS Verification Certificate`} name="peerCertificate" > - + => { + 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?.peerCertificate; + }} + ?blankable=${true} + > +

${t`When connecting to an LDAP Server with TLS, certificates are not checked by default. Specify a keypair to validate the remote certificate.`}

diff --git a/web/src/admin/sources/saml/SAMLSourceForm.ts b/web/src/admin/sources/saml/SAMLSourceForm.ts index 21d422efb..a8e1ad1a8 100644 --- a/web/src/admin/sources/saml/SAMLSourceForm.ts +++ b/web/src/admin/sources/saml/SAMLSourceForm.ts @@ -16,7 +16,9 @@ import { until } from "lit/directives/until.js"; import { BindingTypeEnum, CapabilitiesEnum, + CertificateKeyPair, CryptoApi, + CryptoCertificatekeypairsListRequest, DigestAlgorithmEnum, FlowsApi, FlowsInstancesListDesignationEnum, @@ -260,34 +262,35 @@ export class SAMLSourceForm extends ModelForm {
- + => { + 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?.signingKp; + }} + ?blankable=${true} + > +

${t`Keypair which is used to sign outgoing requests. Leave empty to disable signing.`}

diff --git a/web/src/admin/tenants/TenantForm.ts b/web/src/admin/tenants/TenantForm.ts index f1675509f..aebe6e8f7 100644 --- a/web/src/admin/tenants/TenantForm.ts +++ b/web/src/admin/tenants/TenantForm.ts @@ -1,6 +1,7 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { first } from "@goauthentik/common/utils"; import "@goauthentik/elements/CodeMirror"; +import "@goauthentik/elements/SearchSelect"; import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; @@ -11,12 +12,13 @@ import { t } from "@lingui/macro"; import { TemplateResult, html } from "lit"; import { customElement } from "lit/decorators.js"; -import { ifDefined } from "lit/directives/if-defined.js"; import { until } from "lit/directives/until.js"; import { + CertificateKeyPair, CoreApi, CryptoApi, + CryptoCertificatekeypairsListRequest, FlowsApi, FlowsInstancesListDesignationEnum, Tenant, @@ -388,39 +390,35 @@ export class TenantForm extends ModelForm {

- + => { + 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?.webCertificate; + }} + ?blankable=${true} + > +
diff --git a/web/src/elements/SearchSelect.ts b/web/src/elements/SearchSelect.ts index a32977f08..49d9eb06c 100644 --- a/web/src/elements/SearchSelect.ts +++ b/web/src/elements/SearchSelect.ts @@ -52,13 +52,13 @@ export class SearchSelect extends AKElement { value!: (element: T | undefined) => unknown; @property({ attribute: false }) - selected?: (element: T) => boolean; + selected?: (element: T, elements: T[]) => boolean; firstUpdated(): void { this.fetchObjects(this.query).then((objects) => { this.objects = objects; this.objects.forEach((obj) => { - if (this.selected && this.selected(obj)) { + if (this.selected && this.selected(obj, this.objects)) { this.selectedObject = obj; } });