Identity providers(mappers): update "create" form fields for all SAML mapper types (#1282)

This commit is contained in:
Jenny 2021-10-01 11:03:38 -04:00 committed by GitHub
parent ed0949a44f
commit 3b677c6e8e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 586 additions and 175 deletions

View file

@ -142,7 +142,7 @@ describe("Identity provider test", () => {
masthead.checkNotificationMessage(createMapperSuccessMsg); masthead.checkNotificationMessage(createMapperSuccessMsg);
}); });
it("should add SAML mapper", () => { it("should add SAML mapper of type Advanced Attribute to Role", () => {
sidebarPage.goToIdentityProviders(); sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("saml"); listingPage.goToItemDetails("saml");
@ -151,7 +151,7 @@ describe("Identity provider test", () => {
addMapperPage.emptyStateAddMapper(); addMapperPage.emptyStateAddMapper();
addMapperPage.fillSAMLorOIDCMapper("SAML mapper"); addMapperPage.addAdvancedAttrToRoleMapper("SAML mapper");
masthead.checkNotificationMessage(createMapperSuccessMsg); masthead.checkNotificationMessage(createMapperSuccessMsg);
}); });
@ -172,6 +172,78 @@ describe("Identity provider test", () => {
masthead.checkNotificationMessage(createMapperSuccessMsg); masthead.checkNotificationMessage(createMapperSuccessMsg);
}); });
it("should add SAML mapper of type Hardcoded User Session Attribute", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("saml");
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addHardcodedUserSessionAttrMapper(
"Hardcoded User Session Attribute"
);
masthead.checkNotificationMessage(createMapperSuccessMsg);
});
it("should add SAML mapper of type Attribute Importer", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("saml");
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addAttrImporterMapper("Attribute Importer");
masthead.checkNotificationMessage(createMapperSuccessMsg);
});
it("should add SAML mapper of type Hardcoded Role", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("saml");
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addHardcodedRoleMapper("Hardcoded Role");
masthead.checkNotificationMessage(createMapperSuccessMsg);
});
it("should add SAML mapper of type Hardcoded Attribute", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("saml");
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addHardcodedAttrMapper("Hardcoded Attribute");
masthead.checkNotificationMessage(createMapperSuccessMsg);
});
it("should add SAML mapper of type SAML Attribute To Role", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails("saml");
addMapperPage.goToMappersTab();
addMapperPage.addMapper();
addMapperPage.addSAMLAttributeToRoleMapper("SAML Attribute To Role");
masthead.checkNotificationMessage(createMapperSuccessMsg);
});
it("should edit Username Template Importer mapper", () => { it("should edit Username Template Importer mapper", () => {
sidebarPage.goToIdentityProviders(); sidebarPage.goToIdentityProviders();

View file

@ -7,6 +7,12 @@ export default class AddMapperPage {
private mapperNameInput = "#kc-name"; private mapperNameInput = "#kc-name";
private mapperRoleInput = "mapper-role-input"; private mapperRoleInput = "mapper-role-input";
private attributeName = "attribute-name";
private attributeFriendlyName = "attribute-friendly-name";
private attributeValue = "attribute-value";
private userAttribute = "user-attribute";
private userAttributeName = "user-attribute-name";
private userAttributeValue = "user-attribute-value";
private userSessionAttribute = "user-session-attribute"; private userSessionAttribute = "user-session-attribute";
private userSessionAttributeValue = "user-session-attribute-value"; private userSessionAttributeValue = "user-session-attribute-value";
private newMapperSaveButton = "new-mapper-save-button"; private newMapperSaveButton = "new-mapper-save-button";
@ -91,7 +97,7 @@ export default class AddMapperPage {
return this; return this;
} }
fillSAMLorOIDCMapper(name: string) { addAdvancedAttrToRoleMapper(name: string) {
cy.get(this.mapperNameInput).clear(); cy.get(this.mapperNameInput).clear();
cy.get(this.mapperNameInput).clear().type(name); cy.get(this.mapperNameInput).clear().type(name);
@ -150,6 +156,135 @@ export default class AddMapperPage {
return this; return this;
} }
addHardcodedUserSessionAttrMapper(name: string) {
cy.get(this.mapperNameInput).clear();
cy.get(this.mapperNameInput).clear().type(name);
cy.get(this.syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.idpMapperSelectToggle).click();
cy.findByTestId(this.idpMapperSelect)
.contains("Hardcoded User Session Attribute")
.click();
cy.findByTestId(this.userSessionAttribute).clear();
cy.findByTestId(this.userSessionAttribute).type("user session attribute");
cy.findByTestId(this.userSessionAttributeValue).clear();
cy.findByTestId(this.userSessionAttributeValue).type(
"user session attribute value"
);
this.saveNewMapper();
return this;
}
addAttrImporterMapper(name: string) {
cy.get(this.mapperNameInput).clear();
cy.get(this.mapperNameInput).clear().type(name);
cy.get(this.syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.idpMapperSelectToggle).click();
cy.findByTestId(this.idpMapperSelect)
.contains("Attribute Importer")
.click();
cy.findByTestId(this.attributeName).clear();
cy.findByTestId(this.attributeName).type("attribute name");
cy.findByTestId(this.attributeFriendlyName).clear();
cy.findByTestId(this.attributeFriendlyName).type("friendly name");
cy.findByTestId(this.userAttributeName).clear();
cy.findByTestId(this.userAttributeName).type("user attribute name");
this.saveNewMapper();
return this;
}
addHardcodedRoleMapper(name: string) {
cy.get(this.mapperNameInput).clear();
cy.get(this.mapperNameInput).clear().type(name);
cy.get(this.syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.idpMapperSelectToggle).click();
cy.findByTestId(this.idpMapperSelect).contains("Hardcoded Role").click();
cy.findByTestId(this.mapperRoleInput).clear();
cy.findByTestId(this.mapperRoleInput).type("admin");
this.saveNewMapper();
return this;
}
addHardcodedAttrMapper(name: string) {
cy.get(this.mapperNameInput).clear();
cy.get(this.mapperNameInput).clear().type(name);
cy.get(this.syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.idpMapperSelectToggle).click();
cy.findByTestId(this.idpMapperSelect)
.contains("Hardcoded Attribute")
.click();
cy.findByTestId(this.userAttribute).clear();
cy.findByTestId(this.userAttribute).type("user session attribute");
cy.findByTestId(this.userAttributeValue).clear();
cy.findByTestId(this.userAttributeValue).type(
"user session attribute value"
);
this.saveNewMapper();
return this;
}
addSAMLAttributeToRoleMapper(name: string) {
cy.get(this.mapperNameInput).clear();
cy.get(this.mapperNameInput).clear().type(name);
cy.get(this.syncmodeSelectToggle).click();
cy.findByTestId("inherit").click();
cy.get(this.idpMapperSelectToggle).click();
cy.findByTestId(this.idpMapperSelect)
.contains("SAML Attribute To Role")
.click();
cy.findByTestId(this.mapperRoleInput).clear();
cy.findByTestId(this.mapperRoleInput).type("admin");
this.saveNewMapper();
return this;
}
editUsernameTemplateImporterMapper() { editUsernameTemplateImporterMapper() {
cy.get(this.syncmodeSelectToggle).click(); cy.get(this.syncmodeSelectToggle).click();

View file

@ -27,7 +27,6 @@ import {
import { FormAccess } from "../../components/form-access/FormAccess"; import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient"; import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import type { IdentityProviderAddMapperParams } from "../routes/AddMapper"; import type { IdentityProviderAddMapperParams } from "../routes/AddMapper";
import _ from "lodash";
import { AssociatedRolesModal } from "../../realm-roles/AssociatedRolesModal"; import { AssociatedRolesModal } from "../../realm-roles/AssociatedRolesModal";
import type { RoleRepresentation } from "../../model/role-model"; import type { RoleRepresentation } from "../../model/role-model";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
@ -35,8 +34,9 @@ import type { IdentityProviderEditMapperParams } from "../routes/EditMapper";
import { convertToFormValues } from "../../util"; import { convertToFormValues } from "../../util";
import { toIdentityProvider } from "../routes/IdentityProvider"; import { toIdentityProvider } from "../routes/IdentityProvider";
import type IdentityProviderMapperRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderMapperRepresentation"; import type IdentityProviderMapperRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderMapperRepresentation";
import { AddMapperForm } from "./AddMapperForm";
type IdPMapperRepresentationWithAttributes = export type IdPMapperRepresentationWithAttributes =
IdentityProviderMapperRepresentation & { IdentityProviderMapperRepresentation & {
attributes: KeyValueType[]; attributes: KeyValueType[];
}; };
@ -166,19 +166,39 @@ export const AddMapper = () => {
}); });
}; };
const syncModes = ["inherit", "import", "legacy", "force"];
const [syncModeOpen, setSyncModeOpen] = useState(false);
const targetOptions = ["local", "brokerId", "brokerUsername"]; const targetOptions = ["local", "brokerId", "brokerUsername"];
const [targetOptionsOpen, setTargetOptionsOpen] = useState(false); const [targetOptionsOpen, setTargetOptionsOpen] = useState(false);
const [mapperTypeOpen, setMapperTypeOpen] = useState(false);
const [selectedRole, setSelectedRole] = useState<RoleRepresentation[]>([]); const [selectedRole, setSelectedRole] = useState<RoleRepresentation[]>([]);
const formValues = form.getValues();
const isAdvancedAttrToRole =
formValues.identityProviderMapper === "saml-advanced-role-idp-mapper";
const isAttributeImporter =
formValues.identityProviderMapper === "saml-user-attribute-idp-mapper";
const isHardcodedAttribute =
form.getValues().identityProviderMapper ===
"hardcoded-attribute-idp-mapper";
const isHardcodedRole =
formValues.identityProviderMapper === "oidc-hardcoded-role-idp-mapper";
const isHardcodedUserSessionAttribute =
formValues.identityProviderMapper ===
"hardcoded-user-session-attribute-idp-mapper";
const isSAMLAttributeToRole =
formValues.identityProviderMapper === "saml-role-idp-mapper";
const isUsernameTemplateImporter =
formValues.identityProviderMapper === "saml-username-idp-mapper";
const toggleModal = () => { const toggleModal = () => {
setRolesModalOpen(!rolesModalOpen); setRolesModalOpen(!rolesModalOpen);
}; };
const formValues = form.getValues();
return ( return (
<PageSection variant="light"> <PageSection variant="light">
<ViewHeader <ViewHeader
@ -232,155 +252,18 @@ export const AddMapper = () => {
/> />
</FormGroup> </FormGroup>
)} )}
<FormGroup <AddMapperForm
label={t("common:name")} form={form}
labelIcon={ id={id}
<HelpItem providerId={providerId}
id="name-help-icon" mapperTypes={mapperTypes}
helpText="identity-providers-help:addIdpMapperName" updateMapperType={setMapperType}
forLabel={t("common:name")} formValues={formValues}
forID={t(`common:helpLabel`, { label: t("common:name") })} mapperType={mapperType}
/> />
}
fieldId="kc-name"
isRequired
validated={
errors.name ? ValidatedOptions.error : ValidatedOptions.default
}
helperTextInvalid={t("common:required")}
>
<TextInput
ref={register({ required: true })}
type="text"
datatest-id="name-input"
id="kc-name"
name="name"
isDisabled={!!id}
validated={
errors.name ? ValidatedOptions.error : ValidatedOptions.default
}
/>
</FormGroup>
<FormGroup
label={t("syncModeOverride")}
isRequired
labelIcon={
<HelpItem
helpText="identity-providers-help:syncModeOverride"
forLabel={t("syncModeOverride")}
forID={t(`common:helpLabel`, { label: t("syncModeOverride") })}
/>
}
fieldId="syncMode"
>
<Controller
name="config.syncMode"
defaultValue={syncModes[0]}
control={control}
render={({ onChange, value }) => (
<Select
toggleId="syncMode"
datatest-id="syncmode-select"
required
direction="down"
onToggle={() => setSyncModeOpen(!syncModeOpen)}
onSelect={(_, value) => {
onChange(value.toString().toUpperCase());
setSyncModeOpen(false);
}}
selections={t(`syncModes.${value.toLowerCase()}`)}
variant={SelectVariant.single}
aria-label={t("syncMode")}
isOpen={syncModeOpen}
>
{syncModes.map((option) => (
<SelectOption
selected={option === value}
key={option}
data-testid={option}
value={option.toUpperCase()}
>
{t(`syncModes.${option}`)}
</SelectOption>
))}
</Select>
)}
/>
</FormGroup>
<FormGroup
label={t("mapperType")}
labelIcon={
<HelpItem
helpText={
mapperType === "attributeImporter" &&
(providerId === "oidc" || providerId === "keycloak-oidc")
? `identity-providers-help:oidcAttributeImporter`
: `identity-providers-help:${mapperType}`
}
forLabel={t("mapperType")}
forID={t(`common:helpLabel`, { label: t("mapperType") })}
/>
}
fieldId="identityProviderMapper"
>
<Controller
name="identityProviderMapper"
defaultValue={
providerId === "saml"
? "saml-advanced-role-idp-mapper"
: "oidc-advanced-role-idp-mapper"
}
control={control}
render={({ onChange, value }) => (
<Select
toggleId="identityProviderMapper"
data-testid="idp-mapper-select"
isDisabled={!!id}
required
direction="down"
onToggle={() => setMapperTypeOpen(!mapperTypeOpen)}
onSelect={(e, value) => {
const theMapper =
mapperTypes &&
Object.values(mapperTypes).find(
(item) =>
item.name?.toLowerCase() ===
value.toString().toLowerCase()
);
setMapperType(_.camelCase(value.toString()));
onChange(theMapper?.id);
setMapperTypeOpen(false);
}}
selections={
mapperTypes &&
Object.values(mapperTypes).find(
(item) => item.id?.toLowerCase() === value
)?.name
}
variant={SelectVariant.single}
aria-label={t("syncMode")}
isOpen={mapperTypeOpen}
>
{mapperTypes &&
Object.values(mapperTypes).map((option) => (
<SelectOption
selected={option === value}
datatest-id={option.id}
key={option.name}
value={option.name?.toUpperCase()}
>
{t(`mapperTypes.${_.camelCase(option.name)}`)}
</SelectOption>
))}
</Select>
)}
/>
</FormGroup>
{isSAMLorOIDC ? ( {isSAMLorOIDC ? (
<> <>
{formValues.identityProviderMapper === {isAdvancedAttrToRole && (
"saml-advanced-role-idp-mapper" && (
<> <>
<FormGroup <FormGroup
label={t("common:attributes")} label={t("common:attributes")}
@ -430,8 +313,7 @@ export const AddMapper = () => {
</FormGroup> </FormGroup>
</> </>
)} )}
{formValues.identityProviderMapper === {isUsernameTemplateImporter && (
"saml-username-idp-mapper" && (
<> <>
<FormGroup <FormGroup
label={t("template")} label={t("template")}
@ -526,11 +408,9 @@ export const AddMapper = () => {
</FormGroup> </FormGroup>
</> </>
)} )}
{[ {(isAdvancedAttrToRole ||
"saml-advanced-role-idp-mapper", isHardcodedRole ||
"oidc-hardcoded-role-idp-mapper", isSAMLAttributeToRole) && (
"saml-role-idp-mapper",
].includes(formValues.identityProviderMapper!) && (
<FormGroup <FormGroup
label={t("common:role")} label={t("common:role")}
labelIcon={ labelIcon={
@ -572,15 +452,11 @@ export const AddMapper = () => {
</Button> </Button>
</FormGroup> </FormGroup>
)} )}
{[ {(isHardcodedAttribute || isHardcodedUserSessionAttribute) && (
"hardcoded-user-session-attribute-idp-mapper",
"hardcoded-attribute-idp-mapper",
].includes(formValues.identityProviderMapper!) && (
<> <>
<FormGroup <FormGroup
label={ label={
formValues.identityProviderMapper === isHardcodedUserSessionAttribute
"hardcoded-user-session-attribute-idp-mapper"
? t("userSessionAttribute") ? t("userSessionAttribute")
: t("userAttribute") : t("userAttribute")
} }
@ -607,7 +483,11 @@ export const AddMapper = () => {
type="text" type="text"
defaultValue={currentMapper?.config.attribute} defaultValue={currentMapper?.config.attribute}
id="kc-attribute" id="kc-attribute"
data-testid="user-session-attribute" data-testid={
isHardcodedUserSessionAttribute
? "user-session-attribute"
: "user-attribute"
}
name="config.attribute" name="config.attribute"
validated={ validated={
errors.name errors.name
@ -617,14 +497,24 @@ export const AddMapper = () => {
/> />
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={t("userSessionAttributeValue")} label={
isHardcodedUserSessionAttribute
? t("userSessionAttributeValue")
: t("userAttributeValue")
}
labelIcon={ labelIcon={
<HelpItem <HelpItem
id="user-session-attribute-value-help-icon" id="user-session-attribute-value-help-icon"
helpText="identity-providers-help:userAttributeValue" helpText="identity-providers-help:userAttributeValue"
forLabel={t("userSessionAttributeValue")} forLabel={
isHardcodedUserSessionAttribute
? t("userSessionAttributeValue")
: t("userAttributeValue")
}
forID={t(`common:helpLabel`, { forID={t(`common:helpLabel`, {
label: t("userSessionAttributeValue"), label: isHardcodedUserSessionAttribute
? t("userSessionAttributeValue")
: t("userAttributeValue"),
})} })}
/> />
} }
@ -640,7 +530,11 @@ export const AddMapper = () => {
ref={register()} ref={register()}
type="text" type="text"
defaultValue={currentMapper?.config["attribute-value"]} defaultValue={currentMapper?.config["attribute-value"]}
data-testid="user-session-attribute-value" data-testid={
isHardcodedUserSessionAttribute
? "user-session-attribute-value"
: "user-attribute-value"
}
id="kc-user-session-attribute-value" id="kc-user-session-attribute-value"
name="config.attribute-value" name="config.attribute-value"
validated={ validated={
@ -652,6 +546,114 @@ export const AddMapper = () => {
</FormGroup> </FormGroup>
</> </>
)} )}
{isAttributeImporter && (
<>
<FormGroup
label={t("mapperAttributeName")}
labelIcon={
<HelpItem
id="user-session-attribute-help-icon"
helpText="identity-providers-help:attributeName"
forLabel={t("mapperAttributeName")}
forID={t(`common:helpLabel`, {
label: t("mapperAttributeName"),
})}
/>
}
fieldId="kc-attribute-name"
validated={
errors.name
? ValidatedOptions.error
: ValidatedOptions.default
}
helperTextInvalid={t("common:required")}
>
<TextInput
ref={register()}
type="text"
defaultValue={currentMapper?.config["attribute-name"]}
id="kc-attribute-name"
data-testid="attribute-name"
name="config.attribute-name"
validated={
errors.name
? ValidatedOptions.error
: ValidatedOptions.default
}
/>
</FormGroup>
<FormGroup
label={t("mapperAttributeFriendlyName")}
labelIcon={
<HelpItem
id="mapper-attribute-friendly-name"
helpText="identity-providers-help:friendlyName"
forLabel={t("mapperAttributeFriendlyName")}
forID={t(`common:helpLabel`, {
label: t("mapperAttributeFriendlyName"),
})}
/>
}
fieldId="kc-friendly-name"
validated={
errors.name
? ValidatedOptions.error
: ValidatedOptions.default
}
helperTextInvalid={t("common:required")}
>
<TextInput
ref={register()}
type="text"
defaultValue={
currentMapper?.config["attribute-friendly-name"]
}
data-testid="attribute-friendly-name"
id="kc-attribute-friendly-name"
name="config.attribute-friendly-name"
validated={
errors.name
? ValidatedOptions.error
: ValidatedOptions.default
}
/>
</FormGroup>
<FormGroup
label={t("mapperUserAttributeName")}
labelIcon={
<HelpItem
id="user-attribute-name-help-icon"
helpText="identity-providers-help:userAttributeName"
forLabel={t("mapperUserAttributeName")}
forID={t(`common:helpLabel`, {
label: t("mapperUserAttributeName"),
})}
/>
}
fieldId="kc-user-attribute-name"
validated={
errors.name
? ValidatedOptions.error
: ValidatedOptions.default
}
helperTextInvalid={t("common:required")}
>
<TextInput
ref={register()}
type="text"
defaultValue={currentMapper?.config["attribute-value"]}
data-testid="user-attribute-name"
id="kc-user-attribute-name"
name="config.attribute-value"
validated={
errors.name
? ValidatedOptions.error
: ValidatedOptions.default
}
/>
</FormGroup>
</>
)}
</> </>
) : ( ) : (
<> <>

View file

@ -0,0 +1,198 @@
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { Controller, UseFormMethods } from "react-hook-form";
import {
FormGroup,
Select,
SelectOption,
SelectVariant,
TextInput,
ValidatedOptions,
} from "@patternfly/react-core";
import { HelpItem } from "../../components/help-enabler/HelpItem";
import _ from "lodash";
import type IdentityProviderMapperRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderMapperRepresentation";
import type { IdentityProviderAddMapperParams } from "../routes/AddMapper";
import { useParams } from "react-router-dom";
import type { IdPMapperRepresentationWithAttributes } from "./AddMapper";
type AddMapperFormProps = {
mapperTypes?: Record<string, IdentityProviderMapperRepresentation>;
mapperType: string;
providerId: string;
id: string;
updateMapperType: (mapperType: string) => void;
form: UseFormMethods<IdPMapperRepresentationWithAttributes>;
formValues: IdPMapperRepresentationWithAttributes;
};
export const AddMapperForm = ({
mapperTypes,
mapperType,
form,
id,
updateMapperType,
formValues,
}: AddMapperFormProps) => {
const { t } = useTranslation("identity-providers");
const { control, register, errors } = form;
const [mapperTypeOpen, setMapperTypeOpen] = useState(false);
const syncModes = ["inherit", "import", "legacy", "force"];
const [syncModeOpen, setSyncModeOpen] = useState(false);
const { providerId } = useParams<IdentityProviderAddMapperParams>();
return (
<>
<FormGroup
label={t("common:name")}
labelIcon={
<HelpItem
id="name-help-icon"
helpText="identity-providers-help:addIdpMapperName"
forLabel={t("common:name")}
forID={t(`common:helpLabel`, { label: t("common:name") })}
/>
}
fieldId="kc-name"
isRequired
validated={
errors.name ? ValidatedOptions.error : ValidatedOptions.default
}
helperTextInvalid={t("common:required")}
>
<TextInput
ref={register({ required: true })}
type="text"
datatest-id="name-input"
id="kc-name"
name="name"
isDisabled={!!id}
validated={
errors.name ? ValidatedOptions.error : ValidatedOptions.default
}
/>
</FormGroup>
<FormGroup
label={t("syncModeOverride")}
isRequired
labelIcon={
<HelpItem
helpText="identity-providers-help:syncModeOverride"
forLabel={t("syncModeOverride")}
forID={t(`common:helpLabel`, { label: t("syncModeOverride") })}
/>
}
fieldId="syncMode"
>
<Controller
name="config.syncMode"
defaultValue={syncModes[0]}
control={control}
render={({ onChange, value }) => (
<Select
toggleId="syncMode"
datatest-id="syncmode-select"
required
direction="down"
onToggle={() => setSyncModeOpen(!syncModeOpen)}
onSelect={(_, value) => {
onChange(value.toString().toUpperCase());
setSyncModeOpen(false);
}}
selections={t(`syncModes.${value.toLowerCase()}`)}
variant={SelectVariant.single}
aria-label={t("syncMode")}
isOpen={syncModeOpen}
>
{syncModes.map((option) => (
<SelectOption
selected={option === value}
key={option}
data-testid={option}
value={option.toUpperCase()}
>
{t(`syncModes.${option}`)}
</SelectOption>
))}
</Select>
)}
/>
</FormGroup>
<FormGroup
label={t("mapperType")}
labelIcon={
<HelpItem
helpText={
formValues.identityProviderMapper ===
"saml-user-attribute-idp-mapper" &&
(providerId === "oidc" || providerId === "keycloak-oidc")
? `identity-providers-help:oidcAttributeImporter`
: `identity-providers-help:${mapperType}`
}
forLabel={t("mapperType")}
forID={t(`common:helpLabel`, { label: t("mapperType") })}
/>
}
fieldId="identityProviderMapper"
>
<Controller
name="identityProviderMapper"
defaultValue={
providerId === "saml"
? "saml-advanced-role-idp-mapper"
: "oidc-advanced-role-idp-mapper"
}
control={control}
render={({ onChange, value }) => (
<Select
toggleId="identityProviderMapper"
data-testid="idp-mapper-select"
isDisabled={!!id}
required
direction="down"
onToggle={() => setMapperTypeOpen(!mapperTypeOpen)}
onSelect={(e, value) => {
const theMapper =
mapperTypes &&
Object.values(mapperTypes).find(
(item) =>
item.name?.toLowerCase() ===
value.toString().toLowerCase()
);
updateMapperType(_.camelCase(value.toString()));
onChange(theMapper?.id);
setMapperTypeOpen(false);
}}
selections={
mapperTypes &&
Object.values(mapperTypes).find(
(item) => item.id?.toLowerCase() === value
)?.name
}
variant={SelectVariant.single}
aria-label={t("syncMode")}
isOpen={mapperTypeOpen}
>
{mapperTypes &&
Object.values(mapperTypes).map((option) => (
<SelectOption
selected={option === value}
datatest-id={option.id}
key={option.name}
value={option.name?.toUpperCase()}
>
{t(`mapperTypes.${_.camelCase(option.name)}`)}
</SelectOption>
))}
</Select>
)}
/>
</FormGroup>
</>
);
};

View file

@ -71,6 +71,9 @@ export default {
subjectNameId: "Subject NameID", subjectNameId: "Subject NameID",
attributeName: "Attribute [Name]", attributeName: "Attribute [Name]",
attributeFriendlyName: "Attribute [Friendly Name]", attributeFriendlyName: "Attribute [Friendly Name]",
mapperAttributeName: "Attribute Name",
mapperUserAttributeName: "User Attribute Name",
mapperAttributeFriendlyName: "Friendly name",
httpPostBindingResponse: "HTTP-POST binding response", httpPostBindingResponse: "HTTP-POST binding response",
httpPostBindingAuthnRequest: "HTTP-POST binding for AuthnRequest", httpPostBindingAuthnRequest: "HTTP-POST binding for AuthnRequest",
httpPostBindingLogout: "HTTP-POST binding logout", httpPostBindingLogout: "HTTP-POST binding logout",
@ -167,6 +170,7 @@ export default {
mapperSaveSuccess: "Mapper saved successfully.", mapperSaveSuccess: "Mapper saved successfully.",
mapperSaveError: "Error saving mapper: {{error}}", mapperSaveError: "Error saving mapper: {{error}}",
userAttribute: "User Attribute", userAttribute: "User Attribute",
attributeValue: "Attribute Value",
userAttributeValue: "User Attribute Value", userAttributeValue: "User Attribute Value",
userSessionAttribute: "User Session Attribute", userSessionAttribute: "User Session Attribute",
userSessionAttributeValue: "User Session Attribute Value", userSessionAttributeValue: "User Session Attribute Value",