web: Replace ad-hoc search for CryptoCertificateKeyPairs with ak-crypto-certeficate-search
This commit replaces various ad-hoc implementations of `search-select` for CryptoCertificateKeyPairs with a web component that encapsulates all of the needed behavior and exposes a single API. The results are: Lots of visual clutter is eliminated. A single search of: ```HTML <ak-search-select .fetchObjects=${async (query?: string): Promise<CertificateKeyPair[]> => { 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 this.instance?.tlsVerification === item.pk; }} ?blankable=${true} > </ak-search-select> ``` Now looks like: ```HTML <ak-crypto-certificate-search certificate=${this.instance?.tlsVerification}> </ak-crypto-certificate-search> ``` There are three searches that do not require there to be a valid key with the certificate; these are supported with the boolean property `nokey`; likewise, there is one search (in SAMLProviderForm) that states that if there is no current certificate in the SAMLProvider and only one certificate can be found in the Authentik database, use that one; this is supported with the boolean property `singleton`. These changes replace 382 lines of object-oriented invocations with 36 lines of declarative configuration, and 98 lines for the class. Overall, the code for "find a crypto certificate" has been reduced by 46%. Suggestions for a better word than `singleton` are welcome!
This commit is contained in:
parent
134c6976fa
commit
911f8e49cc
129
web/src/admin/common/ak-crypto-certificate-search.ts
Normal file
129
web/src/admin/common/ak-crypto-certificate-search.ts
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
|
import { AKElement } from "@goauthentik/elements/Base";
|
||||||
|
import { SearchSelect } from "@goauthentik/elements/forms/SearchSelect";
|
||||||
|
import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter";
|
||||||
|
|
||||||
|
import { html } from "lit";
|
||||||
|
import { customElement } from "lit/decorators.js";
|
||||||
|
import { property, query } from "lit/decorators.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
CertificateKeyPair,
|
||||||
|
CryptoApi,
|
||||||
|
CryptoCertificatekeypairsListRequest,
|
||||||
|
} from "@goauthentik/api";
|
||||||
|
|
||||||
|
const renderElement = (item: CertificateKeyPair): string => item.name;
|
||||||
|
|
||||||
|
const renderValue = (item: CertificateKeyPair | undefined): string | undefined => item?.pk;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cryptographic Certificate Search
|
||||||
|
*
|
||||||
|
* @element ak-crypto-certificate-search
|
||||||
|
*
|
||||||
|
* A wrapper around SearchSelect for the many searches of cryptographic key-pairs used throughout our
|
||||||
|
* code base. This is another one of those "If it's not error-free, at least it's localized to one
|
||||||
|
* place" issues.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
@customElement("ak-crypto-certificate-search")
|
||||||
|
export class CryptoCertificateSearch extends CustomListenerElement(AKElement) {
|
||||||
|
@property({ type: String, reflect: true })
|
||||||
|
certificate?: string;
|
||||||
|
|
||||||
|
@query("ak-search-select")
|
||||||
|
search!: SearchSelect<CertificateKeyPair>;
|
||||||
|
|
||||||
|
@property({ type: String })
|
||||||
|
name: string | null | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to `true` if you want to find pairs that don't have a valid key. Of our 14 searches, 11
|
||||||
|
* require the key, 3 do not (as of 2023-08-01).
|
||||||
|
*
|
||||||
|
* @attr
|
||||||
|
*/
|
||||||
|
@property({ type: Boolean, attribute: "nokey" })
|
||||||
|
noKey = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this to true if, should there be only one certificate available, you want the system to
|
||||||
|
* use it by default.
|
||||||
|
*
|
||||||
|
* @attr
|
||||||
|
*/
|
||||||
|
@property({ type: Boolean, attribute: "singleton" })
|
||||||
|
singleton = false;
|
||||||
|
|
||||||
|
selectedKeypair?: CertificateKeyPair;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.selected = this.selected.bind(this);
|
||||||
|
this.fetchObjects = this.fetchObjects.bind(this);
|
||||||
|
this.handleSearchUpdate = this.handleSearchUpdate.bind(this);
|
||||||
|
this.addCustomListener("ak-change", this.handleSearchUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.selectedKeypair ? renderValue(this.selectedKeypair) : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
const horizontalContainer = this.closest("ak-form-element-horizontal[name]");
|
||||||
|
if (!horizontalContainer) {
|
||||||
|
throw new Error("This search can only be used in a named ak-form-element-horizontal");
|
||||||
|
}
|
||||||
|
const name = horizontalContainer.getAttribute("name");
|
||||||
|
const myName = this.getAttribute("name");
|
||||||
|
if (name !== null && name !== myName) {
|
||||||
|
this.setAttribute("name", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSearchUpdate(ev: CustomEvent) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this.selectedKeypair = ev.detail.value;
|
||||||
|
this.dispatchEvent(new InputEvent("input", { bubbles: true, composed: true }));
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchObjects(query?: string): Promise<CertificateKeyPair[]> {
|
||||||
|
const args: CryptoCertificatekeypairsListRequest = {
|
||||||
|
ordering: "name",
|
||||||
|
hasKey: !this.noKey,
|
||||||
|
includeDetails: false,
|
||||||
|
};
|
||||||
|
if (query !== undefined) {
|
||||||
|
args.search = query;
|
||||||
|
}
|
||||||
|
const certificates = await new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList(
|
||||||
|
args,
|
||||||
|
);
|
||||||
|
return certificates.results;
|
||||||
|
}
|
||||||
|
|
||||||
|
selected(item: CertificateKeyPair, items: CertificateKeyPair[]) {
|
||||||
|
return (
|
||||||
|
(this.singleton && !this.certificate && items.length === 1) ||
|
||||||
|
(!!this.certificate && this.certificate === item.pk)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`
|
||||||
|
<ak-search-select
|
||||||
|
.fetchObjects=${this.fetchObjects}
|
||||||
|
.renderElement=${renderElement}
|
||||||
|
.value=${renderValue}
|
||||||
|
.selected=${this.selected}
|
||||||
|
?blankable=${true}
|
||||||
|
>
|
||||||
|
</ak-search-select>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CryptoCertificateSearch;
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { first } from "@goauthentik/common/utils";
|
import { first } from "@goauthentik/common/utils";
|
||||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
|
@ -9,13 +10,7 @@ import { TemplateResult, html } from "lit";
|
||||||
import { customElement } from "lit/decorators.js";
|
import { customElement } from "lit/decorators.js";
|
||||||
import { ifDefined } from "lit/directives/if-defined.js";
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
|
|
||||||
import {
|
import { DockerServiceConnection, OutpostsApi } from "@goauthentik/api";
|
||||||
CertificateKeyPair,
|
|
||||||
CryptoApi,
|
|
||||||
CryptoCertificatekeypairsListRequest,
|
|
||||||
DockerServiceConnection,
|
|
||||||
OutpostsApi,
|
|
||||||
} from "@goauthentik/api";
|
|
||||||
|
|
||||||
@customElement("ak-service-connection-docker-form")
|
@customElement("ak-service-connection-docker-form")
|
||||||
export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnection, string> {
|
export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnection, string> {
|
||||||
|
@ -93,33 +88,9 @@ export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnecti
|
||||||
label=${msg("TLS Verification Certificate")}
|
label=${msg("TLS Verification Certificate")}
|
||||||
name="tlsVerification"
|
name="tlsVerification"
|
||||||
>
|
>
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (query?: string): Promise<CertificateKeyPair[]> => {
|
certificate=${this.instance?.tlsVerification}
|
||||||
const args: CryptoCertificatekeypairsListRequest = {
|
></ak-crypto-certificate-search>
|
||||||
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 this.instance?.tlsVerification === item.pk;
|
|
||||||
}}
|
|
||||||
?blankable=${true}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${msg(
|
${msg(
|
||||||
"CA which the endpoint's Certificate is verified against. Can be left empty for no validation.",
|
"CA which the endpoint's Certificate is verified against. Can be left empty for no validation.",
|
||||||
|
@ -130,33 +101,9 @@ export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnecti
|
||||||
label=${msg("TLS Authentication Certificate/SSH Keypair")}
|
label=${msg("TLS Authentication Certificate/SSH Keypair")}
|
||||||
name="tlsAuthentication"
|
name="tlsAuthentication"
|
||||||
>
|
>
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (query?: string): Promise<CertificateKeyPair[]> => {
|
certificate=${this.instance?.tlsAuthentication}
|
||||||
const args: CryptoCertificatekeypairsListRequest = {
|
></ak-crypto-certificate-search>
|
||||||
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 this.instance?.tlsAuthentication === item.pk;
|
|
||||||
}}
|
|
||||||
?blankable=${true}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${msg(
|
${msg(
|
||||||
"Certificate/Key used for authentication. Can be left empty for no authentication.",
|
"Certificate/Key used for authentication. Can be left empty for no authentication.",
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||||
import "@goauthentik/admin/common/ak-flow-search/ak-tenanted-flow-search";
|
import "@goauthentik/admin/common/ak-flow-search/ak-tenanted-flow-search";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { first } from "@goauthentik/common/utils";
|
import { first } from "@goauthentik/common/utils";
|
||||||
|
@ -14,11 +15,8 @@ import { customElement } from "lit/decorators.js";
|
||||||
import { ifDefined } from "lit/directives/if-defined.js";
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CertificateKeyPair,
|
|
||||||
CoreApi,
|
CoreApi,
|
||||||
CoreGroupsListRequest,
|
CoreGroupsListRequest,
|
||||||
CryptoApi,
|
|
||||||
CryptoCertificatekeypairsListRequest,
|
|
||||||
FlowsInstancesListDesignationEnum,
|
FlowsInstancesListDesignationEnum,
|
||||||
Group,
|
Group,
|
||||||
LDAPAPIAccessMode,
|
LDAPAPIAccessMode,
|
||||||
|
@ -208,35 +206,9 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
|
||||||
</p>
|
</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal label=${msg("Certificate")} name="certificate">
|
<ak-form-element-horizontal label=${msg("Certificate")} name="certificate">
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (
|
certificate=${this.instance?.certificate}
|
||||||
query?: string,
|
></ak-crypto-certificate-search>
|
||||||
): Promise<CertificateKeyPair[]> => {
|
|
||||||
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}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${msg(
|
${msg(
|
||||||
"The certificate for the above configured Base DN. As a fallback, the provider uses a self-signed certificate.",
|
"The certificate for the above configured Base DN. As a fallback, the provider uses a self-signed certificate.",
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||||
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
|
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
|
import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
|
||||||
|
@ -14,10 +15,7 @@ import { customElement, state } from "lit/decorators.js";
|
||||||
import { ifDefined } from "lit/directives/if-defined.js";
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CertificateKeyPair,
|
|
||||||
ClientTypeEnum,
|
ClientTypeEnum,
|
||||||
CryptoApi,
|
|
||||||
CryptoCertificatekeypairsListRequest,
|
|
||||||
FlowsInstancesListDesignationEnum,
|
FlowsInstancesListDesignationEnum,
|
||||||
IssuerModeEnum,
|
IssuerModeEnum,
|
||||||
OAuth2Provider,
|
OAuth2Provider,
|
||||||
|
@ -206,42 +204,10 @@ ${this.instance?.redirectUris}</textarea
|
||||||
</p>
|
</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal label=${msg("Signing Key")} name="signingKey">
|
<ak-form-element-horizontal label=${msg("Signing Key")} name="signingKey">
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (
|
certificate=${this.instance?.signingKey}
|
||||||
query?: string,
|
singleton
|
||||||
): Promise<CertificateKeyPair[]> => {
|
></ak-crypto-certificate-search>
|
||||||
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}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
<p class="pf-c-form__helper-text">${msg("Key used to sign the tokens.")}</p>
|
<p class="pf-c-form__helper-text">${msg("Key used to sign the tokens.")}</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||||
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
|
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { first } from "@goauthentik/common/utils";
|
import { first } from "@goauthentik/common/utils";
|
||||||
|
@ -19,9 +20,6 @@ import PFList from "@patternfly/patternfly/components/List/list.css";
|
||||||
import PFSpacing from "@patternfly/patternfly/utilities/Spacing/spacing.css";
|
import PFSpacing from "@patternfly/patternfly/utilities/Spacing/spacing.css";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CertificateKeyPair,
|
|
||||||
CryptoApi,
|
|
||||||
CryptoCertificatekeypairsListRequest,
|
|
||||||
FlowsInstancesListDesignationEnum,
|
FlowsInstancesListDesignationEnum,
|
||||||
PaginatedOAuthSourceList,
|
PaginatedOAuthSourceList,
|
||||||
PaginatedScopeMappingList,
|
PaginatedScopeMappingList,
|
||||||
|
@ -338,35 +336,9 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
|
||||||
<span slot="header">${msg("Advanced protocol settings")}</span>
|
<span slot="header">${msg("Advanced protocol settings")}</span>
|
||||||
<div slot="body" class="pf-c-form">
|
<div slot="body" class="pf-c-form">
|
||||||
<ak-form-element-horizontal label=${msg("Certificate")} name="certificate">
|
<ak-form-element-horizontal label=${msg("Certificate")} name="certificate">
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (
|
certificate=${this.instance?.certificate}
|
||||||
query?: string,
|
></ak-crypto-certificate-search>
|
||||||
): Promise<CertificateKeyPair[]> => {
|
|
||||||
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}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
label=${msg("Additional scopes")}
|
label=${msg("Additional scopes")}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||||
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
|
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import "@goauthentik/elements/forms/FormGroup";
|
import "@goauthentik/elements/forms/FormGroup";
|
||||||
|
@ -13,9 +14,6 @@ import { customElement } from "lit/decorators.js";
|
||||||
import { ifDefined } from "lit/directives/if-defined.js";
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CertificateKeyPair,
|
|
||||||
CryptoApi,
|
|
||||||
CryptoCertificatekeypairsListRequest,
|
|
||||||
DigestAlgorithmEnum,
|
DigestAlgorithmEnum,
|
||||||
FlowsInstancesListDesignationEnum,
|
FlowsInstancesListDesignationEnum,
|
||||||
PaginatedSAMLPropertyMappingList,
|
PaginatedSAMLPropertyMappingList,
|
||||||
|
@ -177,35 +175,9 @@ export class SAMLProviderFormPage extends ModelForm<SAMLProvider, number> {
|
||||||
label=${msg("Signing Certificate")}
|
label=${msg("Signing Certificate")}
|
||||||
name="signingKp"
|
name="signingKp"
|
||||||
>
|
>
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (
|
certificate=${this.instance?.signingKp}
|
||||||
query?: string,
|
></ak-crypto-certificate-search>
|
||||||
): Promise<CertificateKeyPair[]> => {
|
|
||||||
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}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${msg(
|
${msg(
|
||||||
"Certificate used to sign outgoing Responses going to the Service Provider.",
|
"Certificate used to sign outgoing Responses going to the Service Provider.",
|
||||||
|
@ -216,41 +188,16 @@ export class SAMLProviderFormPage extends ModelForm<SAMLProvider, number> {
|
||||||
label=${msg("Verification Certificate")}
|
label=${msg("Verification Certificate")}
|
||||||
name="verificationKp"
|
name="verificationKp"
|
||||||
>
|
>
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (
|
certificate=${this.instance?.verificationKp}
|
||||||
query?: string,
|
nokey
|
||||||
): Promise<CertificateKeyPair[]> => {
|
></ak-crypto-certificate-search>
|
||||||
const args: CryptoCertificatekeypairsListRequest = {
|
|
||||||
ordering: "name",
|
|
||||||
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}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${msg(
|
${msg(
|
||||||
"When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.",
|
"When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.",
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
|
|
||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
label=${msg("Property mappings")}
|
label=${msg("Property mappings")}
|
||||||
?required=${true}
|
?required=${true}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||||
import { placeholderHelperText } from "@goauthentik/admin/helperText";
|
import { placeholderHelperText } from "@goauthentik/admin/helperText";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { first } from "@goauthentik/common/utils";
|
import { first } from "@goauthentik/common/utils";
|
||||||
|
@ -12,11 +13,8 @@ import { customElement } from "lit/decorators.js";
|
||||||
import { ifDefined } from "lit/directives/if-defined.js";
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CertificateKeyPair,
|
|
||||||
CoreApi,
|
CoreApi,
|
||||||
CoreGroupsListRequest,
|
CoreGroupsListRequest,
|
||||||
CryptoApi,
|
|
||||||
CryptoCertificatekeypairsListRequest,
|
|
||||||
Group,
|
Group,
|
||||||
LDAPSource,
|
LDAPSource,
|
||||||
LDAPSourceRequest,
|
LDAPSourceRequest,
|
||||||
|
@ -208,34 +206,10 @@ export class LDAPSourceForm extends ModelForm<LDAPSource, string> {
|
||||||
label=${msg("TLS Verification Certificate")}
|
label=${msg("TLS Verification Certificate")}
|
||||||
name="peerCertificate"
|
name="peerCertificate"
|
||||||
>
|
>
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (
|
certificate=${this.instance?.peerCertificate}
|
||||||
query?: string,
|
nokey
|
||||||
): Promise<CertificateKeyPair[]> => {
|
></ak-crypto-certificate-search>
|
||||||
const args: CryptoCertificatekeypairsListRequest = {
|
|
||||||
ordering: "name",
|
|
||||||
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}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${msg(
|
${msg(
|
||||||
"When connecting to an LDAP Server with TLS, certificates are not checked by default. Specify a keypair to validate the remote certificate.",
|
"When connecting to an LDAP Server with TLS, certificates are not checked by default. Specify a keypair to validate the remote certificate.",
|
||||||
|
@ -246,35 +220,9 @@ export class LDAPSourceForm extends ModelForm<LDAPSource, string> {
|
||||||
label=${msg("TLS Client authentication certificate")}
|
label=${msg("TLS Client authentication certificate")}
|
||||||
name="clientCertificate"
|
name="clientCertificate"
|
||||||
>
|
>
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (
|
certificate=${this.instance?.clientCertificate}
|
||||||
query?: string,
|
></ak-crypto-certificate-search>
|
||||||
): Promise<CertificateKeyPair[]> => {
|
|
||||||
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?.clientCertificate;
|
|
||||||
}}
|
|
||||||
?blankable=${true}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${msg(
|
${msg(
|
||||||
"Client certificate keypair to authenticate against the LDAP Server's Certificate.",
|
"Client certificate keypair to authenticate against the LDAP Server's Certificate.",
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||||
import "@goauthentik/admin/common/ak-flow-search/ak-source-flow-search";
|
import "@goauthentik/admin/common/ak-flow-search/ak-source-flow-search";
|
||||||
import { iconHelperText, placeholderHelperText } from "@goauthentik/admin/helperText";
|
import { iconHelperText, placeholderHelperText } from "@goauthentik/admin/helperText";
|
||||||
import { UserMatchingModeToLabel } from "@goauthentik/admin/sources/oauth/utils";
|
import { UserMatchingModeToLabel } from "@goauthentik/admin/sources/oauth/utils";
|
||||||
|
@ -18,9 +19,6 @@ import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
import {
|
import {
|
||||||
BindingTypeEnum,
|
BindingTypeEnum,
|
||||||
CapabilitiesEnum,
|
CapabilitiesEnum,
|
||||||
CertificateKeyPair,
|
|
||||||
CryptoApi,
|
|
||||||
CryptoCertificatekeypairsListRequest,
|
|
||||||
DigestAlgorithmEnum,
|
DigestAlgorithmEnum,
|
||||||
FlowsInstancesListDesignationEnum,
|
FlowsInstancesListDesignationEnum,
|
||||||
NameIdPolicyEnum,
|
NameIdPolicyEnum,
|
||||||
|
@ -274,35 +272,9 @@ export class SAMLSourceForm extends ModelForm<SAMLSource, string> {
|
||||||
</ak-radio>
|
</ak-radio>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal label=${msg("Signing keypair")} name="signingKp">
|
<ak-form-element-horizontal label=${msg("Signing keypair")} name="signingKp">
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (
|
certificate=${this.instance?.signingKp}
|
||||||
query?: string,
|
></ak-crypto-certificate-search>
|
||||||
): Promise<CertificateKeyPair[]> => {
|
|
||||||
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}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${msg(
|
${msg(
|
||||||
"Keypair which is used to sign outgoing requests. Leave empty to disable signing.",
|
"Keypair which is used to sign outgoing requests. Leave empty to disable signing.",
|
||||||
|
@ -313,34 +285,10 @@ export class SAMLSourceForm extends ModelForm<SAMLSource, string> {
|
||||||
label=${msg("Verification Certificate")}
|
label=${msg("Verification Certificate")}
|
||||||
name="verificationKp"
|
name="verificationKp"
|
||||||
>
|
>
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (
|
certificate=${this.instance?.verificationKp}
|
||||||
query?: string,
|
nokey
|
||||||
): Promise<CertificateKeyPair[]> => {
|
></ak-crypto-certificate-search>
|
||||||
const args: CryptoCertificatekeypairsListRequest = {
|
|
||||||
ordering: "name",
|
|
||||||
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}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${msg(
|
${msg(
|
||||||
"When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.",
|
"When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.",
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||||
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
|
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { first } from "@goauthentik/common/utils";
|
import { first } from "@goauthentik/common/utils";
|
||||||
|
@ -13,14 +14,7 @@ import { msg } from "@lit/localize";
|
||||||
import { TemplateResult, html } from "lit";
|
import { TemplateResult, html } from "lit";
|
||||||
import { customElement } from "lit/decorators.js";
|
import { customElement } from "lit/decorators.js";
|
||||||
|
|
||||||
import {
|
import { CoreApi, FlowsInstancesListDesignationEnum, Tenant } from "@goauthentik/api";
|
||||||
CertificateKeyPair,
|
|
||||||
CoreApi,
|
|
||||||
CryptoApi,
|
|
||||||
CryptoCertificatekeypairsListRequest,
|
|
||||||
FlowsInstancesListDesignationEnum,
|
|
||||||
Tenant,
|
|
||||||
} from "@goauthentik/api";
|
|
||||||
|
|
||||||
@customElement("ak-tenant-form")
|
@customElement("ak-tenant-form")
|
||||||
export class TenantForm extends ModelForm<Tenant, string> {
|
export class TenantForm extends ModelForm<Tenant, string> {
|
||||||
|
@ -236,35 +230,9 @@ export class TenantForm extends ModelForm<Tenant, string> {
|
||||||
label=${msg("Web Certificate")}
|
label=${msg("Web Certificate")}
|
||||||
name="webCertificate"
|
name="webCertificate"
|
||||||
>
|
>
|
||||||
<ak-search-select
|
<ak-crypto-certificate-search
|
||||||
.fetchObjects=${async (
|
certificate=${this.instance?.webCertificate}
|
||||||
query?: string,
|
></ak-crypto-certificate-search>
|
||||||
): Promise<CertificateKeyPair[]> => {
|
|
||||||
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}
|
|
||||||
>
|
|
||||||
</ak-search-select>
|
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
label=${msg("Event retention")}
|
label=${msg("Event retention")}
|
||||||
|
|
Reference in a new issue