changed to use ui-shared (#27705)

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
This commit is contained in:
Erik Jan de Wit 2024-03-11 15:48:49 +01:00 committed by GitHub
parent 6967f57f39
commit 131aeedb98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 395 additions and 874 deletions

View file

@ -1,3 +1,4 @@
import Select from "../../../../forms/Select";
import LegacyKeyValueInput from "../LegacyKeyValueInput"; import LegacyKeyValueInput from "../LegacyKeyValueInput";
export default class AddMapperPage { export default class AddMapperPage {
@ -7,7 +8,7 @@ export default class AddMapperPage {
#idpMapperSelect = "idp-mapper-select"; #idpMapperSelect = "idp-mapper-select";
#addMapperButton = "#add-mapper-button"; #addMapperButton = "#add-mapper-button";
#mapperNameInput = "#kc-name"; #mapperNameInput = "name";
#attribute = "config.user🍺attribute"; #attribute = "config.user🍺attribute";
#attributeName = "attribute.name"; #attributeName = "attribute.name";
#attributeFriendlyName = "attribute.friendly.name"; #attributeFriendlyName = "attribute.friendly.name";
@ -64,15 +65,15 @@ export default class AddMapperPage {
return this; return this;
} }
typeName(name: string) {
cy.findByTestId(this.#mapperNameInput).clear();
cy.findByTestId(this.#mapperNameInput).type(name);
}
fillSocialMapper(name: string) { fillSocialMapper(name: string) {
cy.get(this.#mapperNameInput).clear(); this.typeName(name);
cy.get(this.#mapperNameInput).clear().type(name);
cy.get(this.#syncmodeSelectToggle).click();
cy.findByTestId("legacy").click();
Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Legacy");
cy.get(this.#idpMapperSelectToggle).click(); cy.get(this.#idpMapperSelectToggle).click();
cy.findByTestId(this.#idpMapperSelect) cy.findByTestId(this.#idpMapperSelect)
@ -101,13 +102,8 @@ export default class AddMapperPage {
} }
addAdvancedAttrToRoleMapper(name: string) { addAdvancedAttrToRoleMapper(name: string) {
cy.get(this.#mapperNameInput).clear(); this.typeName(name);
Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.get(this.#mapperNameInput).clear().type(name);
cy.get(this.#syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.#idpMapperSelectToggle).click(); cy.get(this.#idpMapperSelectToggle).click();
@ -132,13 +128,8 @@ export default class AddMapperPage {
} }
addUsernameTemplateImporterMapper(name: string) { addUsernameTemplateImporterMapper(name: string) {
cy.get(this.#mapperNameInput).clear(); this.typeName(name);
Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.get(this.#mapperNameInput).clear().type(name);
cy.get(this.#syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.#idpMapperSelectToggle).click(); cy.get(this.#idpMapperSelectToggle).click();
@ -157,13 +148,8 @@ export default class AddMapperPage {
} }
addHardcodedUserSessionAttrMapper(name: string) { addHardcodedUserSessionAttrMapper(name: string) {
cy.get(this.#mapperNameInput).clear(); this.typeName(name);
Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.get(this.#mapperNameInput).clear().type(name);
cy.get(this.#syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.#idpMapperSelectToggle).click(); cy.get(this.#idpMapperSelectToggle).click();
@ -185,13 +171,9 @@ export default class AddMapperPage {
} }
addSAMLAttrImporterMapper(name: string) { addSAMLAttrImporterMapper(name: string) {
cy.get(this.#mapperNameInput).clear(); this.typeName(name);
cy.get(this.#mapperNameInput).clear().type(name); Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.get(this.#syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.#idpMapperSelectToggle).click(); cy.get(this.#idpMapperSelectToggle).click();
@ -215,14 +197,9 @@ export default class AddMapperPage {
} }
addOIDCAttrImporterMapper(name: string) { addOIDCAttrImporterMapper(name: string) {
cy.get(this.#mapperNameInput).clear(); this.typeName(name);
cy.get(this.#mapperNameInput).clear().type(name);
cy.get(this.#syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.get(this.#idpMapperSelectToggle).click(); cy.get(this.#idpMapperSelectToggle).click();
cy.findByTestId(this.#idpMapperSelect) cy.findByTestId(this.#idpMapperSelect)
@ -238,13 +215,8 @@ export default class AddMapperPage {
} }
addHardcodedRoleMapper(name: string) { addHardcodedRoleMapper(name: string) {
cy.get(this.#mapperNameInput).clear(); this.typeName(name);
Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.get(this.#mapperNameInput).clear().type(name);
cy.get(this.#syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.#idpMapperSelectToggle).click(); cy.get(this.#idpMapperSelectToggle).click();
@ -257,13 +229,8 @@ export default class AddMapperPage {
} }
addHardcodedAttrMapper(name: string) { addHardcodedAttrMapper(name: string) {
cy.get(this.#mapperNameInput).clear(); this.typeName(name);
Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.get(this.#mapperNameInput).clear().type(name);
cy.get(this.#syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.#idpMapperSelectToggle).click(); cy.get(this.#idpMapperSelectToggle).click();
@ -283,13 +250,9 @@ export default class AddMapperPage {
} }
addSAMLAttributeToRoleMapper(name: string) { addSAMLAttributeToRoleMapper(name: string) {
cy.get(this.#mapperNameInput).clear(); this.typeName(name);
cy.get(this.#mapperNameInput).clear().type(name); Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.get(this.#syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.#idpMapperSelectToggle).click(); cy.get(this.#idpMapperSelectToggle).click();
@ -305,9 +268,7 @@ export default class AddMapperPage {
} }
editUsernameTemplateImporterMapper() { editUsernameTemplateImporterMapper() {
cy.get(this.#syncmodeSelectToggle).click(); Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Legacy");
cy.findByTestId("legacy").click();
cy.findByTestId(this.#template).type("_edited"); cy.findByTestId(this.#template).type("_edited");
@ -319,9 +280,7 @@ export default class AddMapperPage {
} }
editSocialMapper() { editSocialMapper() {
cy.get(this.#syncmodeSelectToggle).click(); Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.findByTestId("inherit").click();
cy.findByTestId(this.#socialProfileJSONfieldPath).clear(); cy.findByTestId(this.#socialProfileJSONfieldPath).clear();
@ -339,9 +298,7 @@ export default class AddMapperPage {
} }
editSAMLorOIDCMapper() { editSAMLorOIDCMapper() {
cy.get(this.#syncmodeSelectToggle).click(); Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.findByTestId("legacy").click();
cy.get(this.#attributesKeyInput).clear(); cy.get(this.#attributesKeyInput).clear();
cy.get(this.#attributesKeyInput).type("key_edited"); cy.get(this.#attributesKeyInput).type("key_edited");
@ -357,14 +314,9 @@ export default class AddMapperPage {
} }
addOIDCAttributeImporterMapper(name: string) { addOIDCAttributeImporterMapper(name: string) {
cy.get(this.#mapperNameInput).clear(); this.typeName(name);
cy.get(this.#mapperNameInput).clear().type(name);
cy.get(this.#syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.get(this.#idpMapperSelectToggle).click(); cy.get(this.#idpMapperSelectToggle).click();
cy.findByTestId(this.#idpMapperSelect) cy.findByTestId(this.#idpMapperSelect)
@ -383,13 +335,9 @@ export default class AddMapperPage {
} }
addOIDCClaimToRoleMapper(name: string) { addOIDCClaimToRoleMapper(name: string) {
cy.get(this.#mapperNameInput).clear(); this.typeName(name);
cy.get(this.#mapperNameInput).clear().type(name); Select.selectItem(cy.get(this.#syncmodeSelectToggle), "Inherit");
cy.get(this.#syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.#idpMapperSelectToggle).click(); cy.get(this.#idpMapperSelectToggle).click();

View file

@ -1,3 +1,4 @@
import Select from "../../../../../forms/Select";
import PageObject from "../../../components/PageObject"; import PageObject from "../../../components/PageObject";
import Masthead from "../../../Masthead"; import Masthead from "../../../Masthead";
@ -6,44 +7,32 @@ const masthead = new Masthead();
export default class ProviderSAMLSettings extends PageObject { export default class ProviderSAMLSettings extends PageObject {
#samlSwitch = "Saml-switch"; #samlSwitch = "Saml-switch";
#modalConfirm = "#modal-confirm"; #modalConfirm = "#modal-confirm";
#serviceProviderEntityID = "serviceProviderEntityId"; #serviceProviderEntityID = "config.entityId";
#identityProviderEntityId = "identityProviderEntityId"; #identityProviderEntityId = "identityProviderEntityId";
#ssoServiceUrl = "sso-service-url"; #ssoServiceUrl = "config.singleSignOnServiceUrl";
#singleLogoutServiceUrl = "single-logout-service-url"; #singleLogoutServiceUrl = "config.singleLogoutServiceUrl";
#nameIdPolicyFormat = "#kc-nameIdPolicyFormat"; #nameIdPolicyFormat = "#nameIDPolicyFormat";
#principalType = "#kc-principalType"; #principalType = "#principalType";
#principalAttribute = "principalAttribute";
#principalSubjectNameId = "subjectNameId-option";
#principalAttributeName = "attributeName-option";
#principalFriendlyAttribute = "attributeFriendlyName-option";
#transientPolicy = "transient-option"; #allowCreate = "config.allowCreate";
#emailPolicy = "email-option"; #httpPostBindingResponse = "config.postBindingResponse";
#kerberosPolicy = "kerberos-option"; #httpPostBindingAuthnRequest = "config.postBindingAuthnRequest";
#x509Policy = "x509-option"; #httpPostBindingLogout = "config.postBindingLogout";
#windowsDomainQNPolicy = "windowsDomainQN-option"; #wantAuthnRequestsSigned = "config.wantAuthnRequestsSigned";
#unspecifiedPolicy = "unspecified-option";
#persistentPolicy = "persistent-option";
#allowCreate = "#allowCreate"; #signatureAlgorithm = "#signatureAlgorithm";
#httpPostBindingResponse = "#httpPostBindingResponse"; #samlSignatureKeyName = "#xmlSigKeyInfoKeyNameTransformer";
#httpPostBindingAuthnRequest = "#httpPostBindingAuthnRequest";
#httpPostBindingLogout = "#httpPostBindingLogout";
#wantAuthnRequestsSigned = "#wantAuthnRequestsSigned";
#signatureAlgorithm = "#kc-signatureAlgorithm"; #wantAssertionsSigned = "config.wantAssertionsSigned";
#samlSignatureKeyName = "#kc-samlSignatureKeyName"; #wantAssertionsEncrypted = "config.wantAssertionsEncrypted";
#forceAuthentication = "config.forceAuthn";
#wantAssertionsSigned = "#wantAssertionsSigned"; #validateSignature = "config.validateSignature";
#wantAssertionsEncrypted = "#wantAssertionsEncrypted"; #validatingX509Certs = "config.signingCertificate";
#forceAuthentication = "#forceAuthentication"; #signServiceProviderMetadata = "config.signSpMetadata";
#validateSignature = "#validateSignature"; #passSubject = "config.loginHint";
#validatingX509Certs = "validatingX509Certs"; #allowedClockSkew = "#config\\.allowedClockSkew";
#signServiceProviderMetadata = "#signServiceProviderMetadata"; #attributeConsumingServiceIndex = "#config\\.attributeConsumingServiceIndex";
#passSubject = "#passSubject"; #attributeConsumingServiceName = "config.attributeConsumingServiceName";
#allowedClockSkew = "allowedClockSkew";
#attributeConsumingServiceIndex = "attributeConsumingServiceIndex";
#attributeConsumingServiceName = "attributeConsumingServiceName";
#comparison = "#comparison"; #comparison = "#comparison";
#saveBtn = "idp-details-save"; #saveBtn = "idp-details-save";
@ -95,26 +84,33 @@ export default class ProviderSAMLSettings extends PageObject {
} }
public typeX509Certs(cert: string) { public typeX509Certs(cert: string) {
cy.findByTestId(this.#validatingX509Certs).clear().type(cert); cy.findByTestId(this.#validatingX509Certs).clear();
cy.findByTestId(this.#validatingX509Certs).type(cert);
return this; return this;
} }
public selectNamePolicyIdFormat() { public selectNamePolicyIdFormat(option: string) {
cy.get(this.#nameIdPolicyFormat).scrollIntoView().click(); cy.get(this.#nameIdPolicyFormat).scrollIntoView();
Select.selectItem(cy.get(this.#nameIdPolicyFormat), option);
Select.assertSelectedItem(cy.get(this.#nameIdPolicyFormat), option);
return this;
} }
public selectPrincipalFormat() { public selectPrincipalFormat(option: string) {
cy.get(this.#principalType).scrollIntoView().click(); cy.get(this.#principalType).scrollIntoView();
Select.selectItem(cy.get(this.#principalType), option);
Select.assertSelectedItem(cy.get(this.#principalType), option);
return this;
} }
public selectSignatureAlgorithm(algorithm: string) { public selectSignatureAlgorithm(algorithm: string) {
cy.get(this.#signatureAlgorithm).scrollIntoView().click(); cy.get(this.#signatureAlgorithm).scrollIntoView();
cy.findByText(algorithm).click(); Select.selectItem(cy.get(this.#signatureAlgorithm), algorithm);
} }
public selectSAMLSignature(key: string) { public selectSAMLSignature(key: string) {
cy.get(this.#samlSignatureKeyName).scrollIntoView().click(); cy.get(this.#samlSignatureKeyName).scrollIntoView();
cy.findByText(key).click(); Select.selectItem(cy.get(this.#samlSignatureKeyName), key);
} }
public selectComparison(comparison: string) { public selectComparison(comparison: string) {
@ -143,25 +139,18 @@ export default class ProviderSAMLSettings extends PageObject {
} }
public assertNameIdPolicyFormat() { public assertNameIdPolicyFormat() {
this.selectNamePolicyIdFormat(); this.selectNamePolicyIdFormat("Transient");
cy.findByTestId(this.#transientPolicy).click(); this.selectNamePolicyIdFormat("Email");
this.selectNamePolicyIdFormat(); this.selectNamePolicyIdFormat("Kerberos");
cy.findByTestId(this.#emailPolicy).click(); this.selectNamePolicyIdFormat("X.509 Subject Name");
this.selectNamePolicyIdFormat(); this.selectNamePolicyIdFormat("Windows Domain Qualified Name");
cy.findByTestId(this.#kerberosPolicy).click(); this.selectNamePolicyIdFormat("Unspecified");
this.selectNamePolicyIdFormat(); this.selectNamePolicyIdFormat("Persistent");
cy.findByTestId(this.#x509Policy).click();
this.selectNamePolicyIdFormat();
cy.findByTestId(this.#windowsDomainQNPolicy).click();
this.selectNamePolicyIdFormat();
cy.findByTestId(this.#unspecifiedPolicy).click();
this.selectNamePolicyIdFormat();
cy.findByTestId(this.#persistentPolicy).click();
return this; return this;
} }
public assertSignatureAlgorithm() { public assertSignatureAlgorithm() {
cy.get(this.#wantAuthnRequestsSigned).parent().click(); cy.findByTestId(this.#wantAuthnRequestsSigned).parent().click();
cy.get(this.#signatureAlgorithm).should("not.exist"); cy.get(this.#signatureAlgorithm).should("not.exist");
cy.get(this.#samlSignatureKeyName).should("not.exist"); cy.get(this.#samlSignatureKeyName).should("not.exist");
this.clickRevertBtn(); this.clickRevertBtn();
@ -183,38 +172,32 @@ export default class ProviderSAMLSettings extends PageObject {
} }
public assertPrincipalType() { public assertPrincipalType() {
this.selectPrincipalFormat(); this.selectPrincipalFormat("Subject NameID");
cy.findByTestId(this.#principalAttributeName).click(); this.selectPrincipalFormat("Attribute [Name]");
cy.findByTestId(this.#principalAttribute).should("exist").scrollIntoView(); this.selectPrincipalFormat("Attribute [Friendly Name]");
this.selectPrincipalFormat();
cy.findByTestId(this.#principalFriendlyAttribute).click();
cy.findByTestId(this.#principalAttribute).should("exist");
this.selectPrincipalFormat();
cy.findByTestId(this.#principalSubjectNameId).click();
cy.findByTestId(this.#principalAttribute).should("not.exist");
return this; return this;
} }
public assertSAMLSwitches() { public assertSAMLSwitches() {
cy.get(this.#allowCreate).parent().click(); cy.findByTestId(this.#allowCreate).parent().click();
cy.get(this.#httpPostBindingResponse).parent().click(); cy.findByTestId(this.#httpPostBindingResponse).parent().click();
cy.get(this.#httpPostBindingLogout).parent().click(); cy.findByTestId(this.#httpPostBindingLogout).parent().click();
cy.get(this.#httpPostBindingAuthnRequest).parent().click(); cy.findByTestId(this.#httpPostBindingAuthnRequest).parent().click();
cy.get(this.#wantAssertionsSigned).parent().click(); cy.findByTestId(this.#wantAssertionsSigned).parent().click();
cy.get(this.#wantAssertionsEncrypted).parent().click(); cy.findByTestId(this.#wantAssertionsEncrypted).parent().click();
cy.get(this.#forceAuthentication).parent().click(); cy.findByTestId(this.#forceAuthentication).parent().click();
cy.get(this.#signServiceProviderMetadata).parent().click(); cy.findByTestId(this.#signServiceProviderMetadata).parent().click();
cy.get(this.#passSubject).parent().click(); cy.findByTestId(this.#passSubject).parent().click();
return this; return this;
} }
public assertValidateSignatures() { public assertValidateSignatures() {
cy.get(this.#validateSignature).parent().click(); cy.findByTestId(this.#validateSignature).parent().click();
cy.findByTestId(this.#validatingX509Certs).should("not.exist"); cy.findByTestId(this.#validatingX509Certs).should("not.exist");
cy.get(this.#validateSignature).parent().click(); cy.findByTestId(this.#validateSignature).parent().click();
this.typeX509Certs("X509 Certificate"); this.typeX509Certs("X509 Certificate");
this.clickRevertBtn(); this.clickRevertBtn();
cy.findByTestId(this.#validatingX509Certs); cy.findByTestId(this.#validatingX509Certs);
@ -223,13 +206,13 @@ export default class ProviderSAMLSettings extends PageObject {
} }
public assertTextFields() { public assertTextFields() {
cy.findByTestId(this.#allowedClockSkew) cy.get(this.#allowedClockSkew)
.find("input") .find("input")
.should("have.value", 0) .should("have.value", 0)
.clear() .clear()
.type("111"); .type("111");
cy.findByTestId(this.#attributeConsumingServiceIndex) cy.get(this.#attributeConsumingServiceIndex)
.find("input") .find("input")
.should("have.value", 0) .should("have.value", 0)
.clear() .clear()

View file

@ -7,15 +7,14 @@ import {
Button, Button,
ButtonVariant, ButtonVariant,
DropdownItem, DropdownItem,
FormGroup,
PageSection, PageSection,
ValidatedOptions,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { useState } from "react"; import { useState } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { TextControl } from "ui-shared";
import { adminClient } from "../../admin-client"; import { adminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
@ -23,7 +22,6 @@ import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import type { AttributeForm } from "../../components/key-value-form/AttributeForm"; import type { AttributeForm } from "../../components/key-value-form/AttributeForm";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { convertFormValuesToObject, convertToFormValues } from "../../util"; import { convertFormValuesToObject, convertToFormValues } from "../../util";
@ -50,11 +48,7 @@ export default function AddMapper() {
const form = useForm<IdPMapperRepresentationWithAttributes>({ const form = useForm<IdPMapperRepresentationWithAttributes>({
shouldUnregister: true, shouldUnregister: true,
}); });
const { const { handleSubmit } = form;
handleSubmit,
register,
formState: { errors },
} = form;
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const navigate = useNavigate(); const navigate = useNavigate();
const localeSort = useLocaleSort(); const localeSort = useLocaleSort();
@ -202,41 +196,31 @@ export default function AddMapper() {
onSubmit={handleSubmit(save)} onSubmit={handleSubmit(save)}
className="pf-u-mt-lg" className="pf-u-mt-lg"
> >
{id && ( <FormProvider {...form}>
<FormGroup {id && (
label={t("id")} <TextControl
fieldId="kc-name" name="id"
validated={ label={t("id")}
errors.name ? ValidatedOptions.error : ValidatedOptions.default readOnly
} rules={{
helperTextInvalid={t("required")} required: t("required"),
> }}
<KeycloakTextInput
value={currentMapper.id}
id="kc-name"
isDisabled={!!id}
validated={
errors.name ? ValidatedOptions.error : ValidatedOptions.default
}
{...register("name")}
/> />
</FormGroup> )}
)} {currentMapper.properties && (
{currentMapper.properties && ( <>
<> <AddMapperForm
<AddMapperForm form={form}
form={form} id={id}
id={id} mapperTypes={mapperTypes}
mapperTypes={mapperTypes} updateMapperType={setCurrentMapper}
updateMapperType={setCurrentMapper} mapperType={currentMapper}
mapperType={currentMapper} />
/>
<FormProvider {...form}>
<DynamicComponents properties={currentMapper.properties!} />
</FormProvider>
</>
)}
<DynamicComponents properties={currentMapper.properties!} />
</>
)}
</FormProvider>
<ActionGroup> <ActionGroup>
<Button <Button
data-testid="new-mapper-save-button" data-testid="new-mapper-save-button"

View file

@ -5,14 +5,11 @@ import {
Select, Select,
SelectOption, SelectOption,
SelectVariant, SelectVariant,
ValidatedOptions,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { useState } from "react"; import { useState } from "react";
import { Controller, UseFormReturn } from "react-hook-form"; import { Controller, UseFormReturn } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem, SelectControl, TextControl } from "ui-shared";
import { HelpItem } from "ui-shared";
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
import type { IdPMapperRepresentationWithAttributes } from "./AddMapper"; import type { IdPMapperRepresentationWithAttributes } from "./AddMapper";
type AddMapperFormProps = { type AddMapperFormProps = {
@ -34,85 +31,33 @@ export const AddMapperForm = ({
}: AddMapperFormProps) => { }: AddMapperFormProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { const { control } = form;
control,
register,
formState: { errors },
} = form;
const [mapperTypeOpen, setMapperTypeOpen] = useState(false); const [mapperTypeOpen, setMapperTypeOpen] = useState(false);
const syncModes = ["inherit", "import", "legacy", "force"]; const syncModes = ["inherit", "import", "legacy", "force"];
const [syncModeOpen, setSyncModeOpen] = useState(false);
return ( return (
<> <>
<FormGroup <TextControl
name="name"
label={t("name")} label={t("name")}
labelIcon={ labelIcon={t("addIdpMapperNameHelp")}
<HelpItem helpText={t("addIdpMapperNameHelp")} fieldLabelId="name" /> readOnly={!!id}
} rules={{
fieldId="kc-name" required: t("required"),
isRequired }}
validated={ />
errors.name ? ValidatedOptions.error : ValidatedOptions.default <SelectControl
} name="config.syncMode"
helperTextInvalid={t("required")}
>
<KeycloakTextInput
id="kc-name"
isDisabled={!!id}
validated={
errors.name ? ValidatedOptions.error : ValidatedOptions.default
}
{...register("name", { required: true })}
/>
</FormGroup>
<FormGroup
label={t("syncModeOverride")} label={t("syncModeOverride")}
isRequired labelIcon={t("syncModeOverrideHelp")}
labelIcon={ options={syncModes.map((option) => ({
<HelpItem key: option.toUpperCase(),
helpText={t("syncModeOverrideHelp")} value: t(`syncModes.${option}`),
fieldLabelId="syncModeOverride" }))}
/> controller={{ defaultValue: syncModes[0].toUpperCase() }}
} />
fieldId="syncMode"
>
<Controller
name="config.syncMode"
defaultValue={syncModes[0].toUpperCase()}
control={control}
render={({ field }) => (
<Select
toggleId="syncMode"
datatest-id="syncmode-select"
required
direction="down"
onToggle={() => setSyncModeOpen(!syncModeOpen)}
onSelect={(_, value) => {
field.onChange(value.toString().toUpperCase());
setSyncModeOpen(false);
}}
selections={t(`syncModes.${field.value.toLowerCase()}`)}
variant={SelectVariant.single}
aria-label={t("syncMode")}
isOpen={syncModeOpen}
>
{syncModes.map((option) => (
<SelectOption
selected={option === field.value}
key={option}
data-testid={option}
value={option.toUpperCase()}
>
{t(`syncModes.${option}`)}
</SelectOption>
))}
</Select>
)}
/>
</FormGroup>
<FormGroup <FormGroup
label={t("mapperType")} label={t("mapperType")}
labelIcon={ labelIcon={

View file

@ -1,22 +1,10 @@
import IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation"; import IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation";
import { import { ExpandableSection } from "@patternfly/react-core";
ExpandableSection,
FormGroup,
NumberInput,
Select,
SelectOption,
SelectVariant,
ValidatedOptions,
} from "@patternfly/react-core";
import { useState } from "react"; import { useState } from "react";
import { Controller, useFormContext, useWatch } from "react-hook-form"; import { FormProvider, useFormContext, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { NumberControl, SelectControl, TextControl } from "ui-shared";
import { HelpItem } from "ui-shared"; import { DefaultSwitchControl } from "../../components/SwitchControl";
import { KeycloakTextArea } from "../../components/keycloak-text-area/KeycloakTextArea";
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
import { FormGroupField } from "../component/FormGroupField";
import { SwitchField } from "../component/SwitchField";
import "./discovery-settings.css"; import "./discovery-settings.css";
@ -27,22 +15,8 @@ type DescriptorSettingsProps = {
const Fields = ({ readOnly }: DescriptorSettingsProps) => { const Fields = ({ readOnly }: DescriptorSettingsProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { const form = useFormContext<IdentityProviderRepresentation>();
register, const { control } = form;
control,
formState: { errors },
} = useFormContext<IdentityProviderRepresentation>();
const [namedPolicyDropdownOpen, setNamedPolicyDropdownOpen] = useState(false);
const [principalTypeDropdownOpen, setPrincipalTypeDropdownOpen] =
useState(false);
const [signatureAlgorithmDropdownOpen, setSignatureAlgorithmDropdownOpen] =
useState(false);
const [encryptionAlgorithmDropdownOpen, setEncryptionAlgorithmDropdownOpen] =
useState(false);
const [
samlSignatureKeyNameDropdownOpen,
setSamlSignatureKeyNameDropdownOpen,
] = useState(false);
const wantAuthnSigned = useWatch({ const wantAuthnSigned = useWatch({
control, control,
@ -71,595 +45,282 @@ const Fields = ({ readOnly }: DescriptorSettingsProps) => {
return ( return (
<div className="pf-c-form pf-m-horizontal"> <div className="pf-c-form pf-m-horizontal">
<FormGroup <FormProvider {...form}>
label={t("serviceProviderEntityId")} <TextControl
fieldId="kc-saml-service-provider-entity-id" name="config.entityId"
labelIcon={ label={t("serviceProviderEntityId")}
<HelpItem labelIcon={t("serviceProviderEntityIdHelp")}
helpText={t("serviceProviderEntityIdHelp")}
fieldLabelId="serviceProviderEntityId"
/>
}
>
<KeycloakTextInput
data-testid="serviceProviderEntityId"
id="kc-saml-service-provider-entity-id"
{...register("config.entityId")}
/> />
</FormGroup> <TextControl
<FormGroup name="config.idpEntityId"
label={t("identityProviderEntityId")} label={t("identityProviderEntityId")}
fieldId="kc-identity-provider-entity-id" labelIcon={t("identityProviderEntityIdHelp")}
labelIcon={
<HelpItem
helpText={t("identityProviderEntityIdHelp")}
fieldLabelId="identityProviderEntityId"
/>
}
>
<KeycloakTextInput
data-testid="identityProviderEntityId" data-testid="identityProviderEntityId"
id="kc-identity-provider-entity-id" id="kc-identity-provider-entity-id"
{...register("config.idpEntityId")}
/> />
</FormGroup> <TextControl
<FormGroup name="config.singleSignOnServiceUrl"
label={t("ssoServiceUrl")} label={t("ssoServiceUrl")}
labelIcon={ labelIcon={t("ssoServiceUrlHelp")}
<HelpItem
helpText={t("ssoServiceUrlHelp")}
fieldLabelId="ssoServiceUrl"
/>
}
fieldId="kc-sso-service-url"
isRequired
validated={
errors.config?.singleSignOnServiceUrl
? ValidatedOptions.error
: ValidatedOptions.default
}
helperTextInvalid={t("required")}
>
<KeycloakTextInput
type="url" type="url"
data-testid="sso-service-url" readOnly={readOnly}
id="kc-sso-service-url" rules={{ required: t("required") }}
validated={
errors.config?.singleSignOnServiceUrl
? ValidatedOptions.error
: ValidatedOptions.default
}
isReadOnly={readOnly}
{...register("config.singleSignOnServiceUrl", { required: true })}
/> />
</FormGroup> <TextControl
<FormGroup name="config.singleLogoutServiceUrl"
label={t("singleLogoutServiceUrl")} label={t("singleLogoutServiceUrl")}
labelIcon={ labelIcon={t("singleLogoutServiceUrlHelp")}
<HelpItem
helpText={t("singleLogoutServiceUrlHelp")}
fieldLabelId="singleLogoutServiceUrl"
/>
}
fieldId="single-logout-service-url"
data-testid="single-logout-service-url"
validated={
errors.config?.singleLogoutServiceUrl
? ValidatedOptions.error
: ValidatedOptions.default
}
helperTextInvalid={t("required")}
>
<KeycloakTextInput
type="url" type="url"
id="single-logout-service-url" readOnly={readOnly}
isReadOnly={readOnly} rules={{ required: t("required") }}
{...register("config.singleLogoutServiceUrl")}
/> />
</FormGroup> <DefaultSwitchControl
<SwitchField name="config.backchannelSupported"
field="config.backchannelSupported" label={t("backchannelLogout")}
label="backchannelLogout" isDisabled={readOnly}
data-testid="backchannelLogout" stringify
isReadOnly={readOnly} />
/> <DefaultSwitchControl
<SwitchField name="config.sendIdTokenOnLogout"
field="config.sendIdTokenOnLogout" label={t("sendIdTokenOnLogout")}
label="sendIdTokenOnLogout" defaultValue={"true"}
data-testid="sendIdTokenOnLogout" isDisabled={readOnly}
defaultValue={"true"} stringify
isReadOnly={readOnly} />
/> <DefaultSwitchControl
<SwitchField name="config.sendClientIdOnLogout"
field="config.sendClientIdOnLogout" label={t("sendClientIdOnLogout")}
label="sendClientIdOnLogout" isDisabled={readOnly}
data-testid="sendClientIdOnLogout" stringify
isReadOnly={readOnly} />
/> <SelectControl
<FormGroup
label={t("nameIdPolicyFormat")}
labelIcon={
<HelpItem
helpText={t("nameIdPolicyFormatHelp")}
fieldLabelId="nameIdPolicyFormat"
/>
}
fieldId="kc-nameIdPolicyFormat"
helperTextInvalid={t("required")}
>
<Controller
name="config.nameIDPolicyFormat" name="config.nameIDPolicyFormat"
defaultValue={"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"} label={t("nameIdPolicyFormat")}
control={control} labelIcon={t("nameIdPolicyFormatHelp")}
render={({ field }) => ( controller={{
<Select defaultValue:
toggleId="kc-nameIdPolicyFormat" "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
onToggle={(isExpanded) => setNamedPolicyDropdownOpen(isExpanded)} }}
isOpen={namedPolicyDropdownOpen} isDisabled={readOnly}
onSelect={(_, value) => { options={[
field.onChange(value as string); {
setNamedPolicyDropdownOpen(false); key: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
}} value: t("persistent"),
selections={field.value} },
variant={SelectVariant.single} {
isDisabled={readOnly} key: "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
> value: t("transient"),
<SelectOption },
data-testid="persistent-option" {
value={"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"} key: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
isPlaceholder value: t("email"),
> },
{t("persistent")} {
</SelectOption> key: "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos",
<SelectOption value: t("kerberos"),
data-testid="transient-option" },
value="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" {
> key: "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName",
{t("transient")} value: t("x509"),
</SelectOption> },
<SelectOption {
data-testid="email-option" key: "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName",
value="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" value: t("windowsDomainQN"),
> },
{t("email")} {
</SelectOption> key: "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
<SelectOption value: t("unspecified"),
data-testid="kerberos-option" },
value="urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos" ]}
> />
{t("kerberos")} <SelectControl
</SelectOption>
<SelectOption
data-testid="x509-option"
value="urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName"
>
{t("x509")}
</SelectOption>
<SelectOption
data-testid="windowsDomainQN-option"
value="urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName"
>
{t("windowsDomainQN")}
</SelectOption>
<SelectOption
data-testid="unspecified-option"
value={"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"}
>
{t("unspecified")}
</SelectOption>
</Select>
)}
></Controller>
</FormGroup>
<FormGroup
label={t("principalType")}
labelIcon={
<HelpItem
helpText={t("principalTypeHelp")}
fieldLabelId="principalType"
/>
}
fieldId="kc-principalType"
helperTextInvalid={t("required")}
>
<Controller
name="config.principalType" name="config.principalType"
defaultValue={t("subjectNameId")} label={t("principalType")}
control={control} labelIcon={t("principalTypeHelp")}
render={({ field }) => ( controller={{
<Select defaultValue: "SUBJECT",
toggleId="kc-principalType" }}
onToggle={(isExpanded) => isDisabled={readOnly}
setPrincipalTypeDropdownOpen(isExpanded) options={[
} { key: "SUBJECT", value: t("subjectNameId") },
isOpen={principalTypeDropdownOpen} { key: "ATTRIBUTE", value: t("attributeName") },
onSelect={(_, value) => { { key: "FRIENDLY_ATTRIBUTE", value: t("attributeFriendlyName") },
field.onChange(value.toString()); ]}
setPrincipalTypeDropdownOpen(false); />
}}
selections={field.value}
variant={SelectVariant.single}
isDisabled={readOnly}
>
<SelectOption
data-testid="subjectNameId-option"
value="SUBJECT"
isPlaceholder
>
{t("subjectNameId")}
</SelectOption>
<SelectOption
data-testid="attributeName-option"
value="ATTRIBUTE"
>
{t("attributeName")}
</SelectOption>
<SelectOption
data-testid="attributeFriendlyName-option"
value="FRIENDLY_ATTRIBUTE"
>
{t("attributeFriendlyName")}
</SelectOption>
</Select>
)}
></Controller>
</FormGroup>
{principalType?.includes("ATTRIBUTE") && ( {principalType?.includes("ATTRIBUTE") && (
<FormGroup <TextControl
label={t("principalAttribute")} name="config.principalAttribute"
labelIcon={ label={t("principalAttribute")}
<HelpItem labelIcon={t("principalAttributeHelp")}
helpText={t("principalAttributeHelp")} readOnly={readOnly}
fieldLabelId="principalAttribute"
/>
}
fieldId="principalAttribute"
>
<KeycloakTextInput
id="principalAttribute"
data-testid="principalAttribute"
isReadOnly={readOnly}
{...register("config.principalAttribute")}
/> />
</FormGroup> )}
)} <DefaultSwitchControl
<SwitchField name="config.allowCreate"
field="config.allowCreate" label={t("allowCreate")}
label="allowCreate" isDisabled={readOnly}
isReadOnly={readOnly} stringify
/> />
<SwitchField <DefaultSwitchControl
field="config.postBindingResponse" name="config.postBindingResponse"
label="httpPostBindingResponse" label={t("httpPostBindingResponse")}
isReadOnly={readOnly} isDisabled={readOnly}
/> stringify
/>
<SwitchField <DefaultSwitchControl
field="config.postBindingAuthnRequest" name="config.postBindingAuthnRequest"
label="httpPostBindingAuthnRequest" label={t("httpPostBindingAuthnRequest")}
isReadOnly={readOnly} isDisabled={readOnly}
/> stringify
/>
<SwitchField <DefaultSwitchControl
field="config.postBindingLogout" name="config.postBindingLogout"
label="httpPostBindingLogout" label={t("httpPostBindingLogout")}
isReadOnly={readOnly} isDisabled={readOnly}
/> stringify
/>
<SwitchField <DefaultSwitchControl
field="config.wantAuthnRequestsSigned" name="config.wantAuthnRequestsSigned"
label="wantAuthnRequestsSigned" label={t("wantAuthnRequestsSigned")}
isReadOnly={readOnly} isDisabled={readOnly}
/> stringify
/>
{wantAuthnSigned === "true" && ( {wantAuthnSigned === "true" && (
<> <>
<FormGroup <SelectControl
label={t("signatureAlgorithm")}
labelIcon={
<HelpItem
helpText={t("signatureAlgorithmHelp")}
fieldLabelId="signatureAlgorithm"
/>
}
fieldId="kc-signatureAlgorithm"
>
<Controller
name="config.signatureAlgorithm" name="config.signatureAlgorithm"
defaultValue="RSA_SHA256" label={t("signatureAlgorithm")}
control={control} labelIcon={t("signatureAlgorithmHelp")}
render={({ field }) => ( isDisabled={readOnly}
<Select controller={{
toggleId="kc-signatureAlgorithm" defaultValue: "RSA_SHA256",
onToggle={(isExpanded) => }}
setSignatureAlgorithmDropdownOpen(isExpanded) options={[
} "RSA_SHA1",
isOpen={signatureAlgorithmDropdownOpen} "RSA_SHA256",
onSelect={(_, value) => { "RSA_SHA256_MGF1",
field.onChange(value.toString()); "RSA_SHA512",
setSignatureAlgorithmDropdownOpen(false); "RSA_SHA512_MGF1",
}} "DSA_SHA1",
selections={field.value} ]}
variant={SelectVariant.single} />
isDisabled={readOnly} <SelectControl
>
<SelectOption value="RSA_SHA1" />
<SelectOption value="RSA_SHA256" isPlaceholder />
<SelectOption value="RSA_SHA256_MGF1" />
<SelectOption value="RSA_SHA512" />
<SelectOption value="RSA_SHA512_MGF1" />
<SelectOption value="DSA_SHA1" />
</Select>
)}
></Controller>
</FormGroup>
<FormGroup
label={t("samlSignatureKeyName")}
labelIcon={
<HelpItem
helpText={t("samlSignatureKeyNameHelp")}
fieldLabelId="samlSignatureKeyName"
/>
}
fieldId="kc-samlSignatureKeyName"
>
<Controller
name="config.xmlSigKeyInfoKeyNameTransformer" name="config.xmlSigKeyInfoKeyNameTransformer"
defaultValue={t("keyID")} label={t("samlSignatureKeyName")}
control={control} labelIcon={t("samlSignatureKeyNameHelp")}
render={({ field }) => ( isDisabled={readOnly}
<Select controller={{
toggleId="kc-samlSignatureKeyName" defaultValue: t("keyID"),
onToggle={(isExpanded) => }}
setSamlSignatureKeyNameDropdownOpen(isExpanded) options={["NONE", t("keyID"), t("certSubject")]}
}
isOpen={samlSignatureKeyNameDropdownOpen}
onSelect={(_, value) => {
field.onChange(value.toString());
setSamlSignatureKeyNameDropdownOpen(false);
}}
selections={field.value}
variant={SelectVariant.single}
isDisabled={readOnly}
>
<SelectOption value="NONE" />
<SelectOption value={t("keyID")} isPlaceholder />
<SelectOption value={t("certSubject")} />
</Select>
)}
></Controller>
</FormGroup>
</>
)}
<SwitchField
field="config.wantAssertionsSigned"
label="wantAssertionsSigned"
isReadOnly={readOnly}
/>
<SwitchField
field="config.wantAssertionsEncrypted"
label="wantAssertionsEncrypted"
isReadOnly={readOnly}
/>
{wantAssertionsEncrypted === "true" && (
<FormGroup
label={t("encryptionAlgorithm")}
labelIcon={
<HelpItem
helpText={t("encryptionAlgorithmHelp")}
fieldLabelId="encryptionAlgorithm"
/> />
} </>
fieldId="kc-encryptionAlgorithm" )}
> <DefaultSwitchControl
<Controller name="config.wantAssertionsSigned"
label={t("wantAssertionsSigned")}
isDisabled={readOnly}
stringify
/>
<DefaultSwitchControl
name="config.wantAssertionsEncrypted"
label={t("wantAssertionsEncrypted")}
isDisabled={readOnly}
stringify
/>
{wantAssertionsEncrypted === "true" && (
<SelectControl
name="config.encryptionAlgorithm" name="config.encryptionAlgorithm"
defaultValue="RSA-OAEP" label={t("encryptionAlgorithm")}
control={control} labelIcon={t("encryptionAlgorithmHelp")}
render={({ field }) => ( isDisabled={readOnly}
<Select controller={{
toggleId="kc-encryptionAlgorithm" defaultValue: "RSA-OAEP",
onToggle={(isExpanded) => }}
setEncryptionAlgorithmDropdownOpen(isExpanded) options={["RSA-OAEP", "RSA1_5"]}
} />
isOpen={encryptionAlgorithmDropdownOpen} )}
onSelect={(_, value) => {
field.onChange(value.toString());
setEncryptionAlgorithmDropdownOpen(false);
}}
selections={field.value}
variant={SelectVariant.single}
isDisabled={readOnly}
>
<SelectOption value="RSA-OAEP" />
<SelectOption value="RSA1_5" />
</Select>
)}
></Controller>
</FormGroup>
)}
<SwitchField <DefaultSwitchControl
field="config.forceAuthn" name="config.forceAuthn"
label="forceAuthentication" label={t("forceAuthentication")}
isReadOnly={readOnly} isDisabled={readOnly}
/> stringify
/>
<SwitchField <DefaultSwitchControl
field="config.validateSignature" name="config.validateSignature"
label="validateSignature" label={t("validateSignature")}
isReadOnly={readOnly} isDisabled={readOnly}
/> stringify
{validateSignature === "true" && ( />
<> {validateSignature === "true" && (
<FormGroup <>
label={t("metadataDescriptorUrl")} <TextControl
labelIcon={ name="config.metadataDescriptorUrl"
<HelpItem label={t("metadataDescriptorUrl")}
helpText={t("metadataDescriptorUrlHelp")} labelIcon={t("metadataDescriptorUrlHelp")}
fieldLabelId="metadataDescriptorUrl"
/>
}
isRequired={useMetadataDescriptorUrl === "true"}
validated={
errors.config?.metadataDescriptorUrl
? ValidatedOptions.error
: ValidatedOptions.default
}
fieldId="metadataDescriptorUrl"
helperTextInvalid={t("required")}
>
<KeycloakTextInput
type="url" type="url"
id="metadataDescriptorUrl" readOnly={readOnly}
data-testid="metadataDescriptorUrl" rules={{
isReadOnly={readOnly} required: {
validated={ value: useMetadataDescriptorUrl === "true",
errors.config?.metadataDescriptorUrl message: t("required"),
? ValidatedOptions.error },
: ValidatedOptions.default }}
}
{...register("config.metadataDescriptorUrl", {
required: useMetadataDescriptorUrl === "true",
})}
/> />
</FormGroup> <DefaultSwitchControl
<SwitchField name="config.useMetadataDescriptorUrl"
field="config.useMetadataDescriptorUrl" label={t("useMetadataDescriptorUrl")}
label="useMetadataDescriptorUrl" isDisabled={readOnly}
data-testid="useMetadataDescriptorUrl" />
isReadOnly={readOnly} {useMetadataDescriptorUrl !== "true" && (
/> <TextControl
{useMetadataDescriptorUrl !== "true" && ( name="config.signingCertificate"
<FormGroupField label="validatingX509Certs"> label="validatingX509Certs"
<KeycloakTextArea readOnly={readOnly}
id="validatingX509Certs" />
data-testid="validatingX509Certs" )}
isReadOnly={readOnly} </>
{...register("config.signingCertificate")} )}
></KeycloakTextArea> <DefaultSwitchControl
</FormGroupField> name="config.signSpMetadata"
)} label={t("signServiceProviderMetadata")}
</> isDisabled={readOnly}
)} stringify
<SwitchField />
field="config.signSpMetadata" <DefaultSwitchControl
label="signServiceProviderMetadata" name="config.loginHint"
data-testid="signServiceProviderMetadata" label={t("passSubject")}
isReadOnly={readOnly} isDisabled={readOnly}
/> stringify
<SwitchField />
field="config.loginHint" <NumberControl
label="passSubject"
data-testid="passSubject"
isReadOnly={readOnly}
/>
<FormGroup
label={t("allowedClockSkew")}
labelIcon={
<HelpItem
helpText={t("allowedClockSkewHelp")}
fieldLabelId="allowedClockSkew"
/>
}
fieldId="allowedClockSkew"
helperTextInvalid={t("required")}
>
<Controller
name="config.allowedClockSkew" name="config.allowedClockSkew"
defaultValue={0} label={t("allowedClockSkew")}
control={control} labelIcon={t("allowedClockSkewHelp")}
render={({ field }) => { controller={{ defaultValue: 0, rules: { min: 0, max: 2147483 } }}
const v = Number(field.value); isDisabled={readOnly}
return (
<NumberInput
data-testid="allowedClockSkew"
inputName="allowedClockSkew"
min={0}
max={2147483}
value={v}
readOnly
onPlus={() => field.onChange(v + 1)}
onMinus={() => field.onChange(v - 1)}
onChange={(event) => {
const value = Number(
(event.target as HTMLInputElement).value,
);
field.onChange(value < 0 ? 0 : value);
}}
/>
);
}}
/> />
</FormGroup> <NumberControl
<FormGroup
label={t("attributeConsumingServiceIndex")}
labelIcon={
<HelpItem
helpText={t("attributeConsumingServiceIndexHelp")}
fieldLabelId="attributeConsumingServiceIndex"
/>
}
fieldId="attributeConsumingServiceIndex"
helperTextInvalid={t("required")}
>
<Controller
name="config.attributeConsumingServiceIndex" name="config.attributeConsumingServiceIndex"
defaultValue={0} label={t("attributeConsumingServiceIndex")}
control={control} labelIcon={t("attributeConsumingServiceIndexHelp")}
render={({ field }) => { controller={{ defaultValue: 0, rules: { min: 0, max: 2147483 } }}
const v = Number(field.value); isDisabled={readOnly}
return (
<NumberInput
data-testid="attributeConsumingServiceIndex"
inputName="attributeConsumingServiceIndex"
min={0}
max={2147483}
value={v}
readOnly
onPlus={() => field.onChange(v + 1)}
onMinus={() => field.onChange(v - 1)}
onChange={(event) => {
const value = Number(
(event.target as HTMLInputElement).value,
);
field.onChange(value < 0 ? 0 : value);
}}
/>
);
}}
/> />
</FormGroup> <TextControl
name="config.attributeConsumingServiceName"
<FormGroup label={t("attributeConsumingServiceName")}
label={t("attributeConsumingServiceName")} labelIcon={t("attributeConsumingServiceNameHelp")}
labelIcon={ readOnly={readOnly}
<HelpItem
helpText={t("attributeConsumingServiceNameHelp")}
fieldLabelId="attributeConsumingServiceName"
/>
}
fieldId="attributeConsumingServiceName"
helperTextInvalid={t("required")}
>
<KeycloakTextInput
id="attributeConsumingServiceName"
data-testid="attributeConsumingServiceName"
isReadOnly={readOnly}
{...register("config.attributeConsumingServiceName")}
/> />
</FormGroup> </FormProvider>
</div> </div>
); );
}; };

View file

@ -73,7 +73,7 @@ export const SelectControl = <
selections={ selections={
typeof options[0] !== "string" typeof options[0] !== "string"
? (options as SelectControlOption[]) ? (options as SelectControlOption[])
.filter((o) => value.includes(o.key)) .filter((o) => value === o.key)
.map((o) => o.value) .map((o) => o.value)
: value : value
} }

View file

@ -12,7 +12,7 @@ import { FormLabel } from "./FormLabel";
export type SwitchControlProps< export type SwitchControlProps<
T extends FieldValues, T extends FieldValues,
P extends FieldPath<T> = FieldPath<T>, P extends FieldPath<T> = FieldPath<T>,
> = Omit<SwitchProps, "name" | "defaultValue"> & > = Omit<SwitchProps, "name" | "defaultValue" | "ref"> &
UseControllerProps<T, P> & { UseControllerProps<T, P> & {
name: string; name: string;
label?: string; label?: string;
@ -45,10 +45,10 @@ export const SwitchControl = <
defaultValue={defaultValue} defaultValue={defaultValue}
render={({ field: { onChange, value } }) => ( render={({ field: { onChange, value } }) => (
<Switch <Switch
{...props}
id={props.name} id={props.name}
data-testid={props.name} data-testid={props.name}
label={props.labelOn} label={props.labelOn}
labelOff={props.labelOff}
isChecked={props.stringify ? value === "true" : value} isChecked={props.stringify ? value === "true" : value}
onChange={(checked, e) => { onChange={(checked, e) => {
const value = props.stringify ? checked.toString() : checked; const value = props.stringify ? checked.toString() : checked;