Merge pull request #671 from mfrances17/role-mappers

Adds User Fed Group and Role mappers
This commit is contained in:
mfrances17 2021-06-10 12:02:15 -04:00 committed by GitHub
commit 2f012eecce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 383 additions and 135 deletions

View file

@ -3,6 +3,7 @@ import SidebarPage from "../support/pages/admin_console/SidebarPage";
import ListingPage from "../support/pages/admin_console/ListingPage";
import GroupModal from "../support/pages/admin_console/manage/groups/GroupModal";
import ProviderPage from "../support/pages/admin_console/manage/providers/ProviderPage";
import CreateClientPage from "../support/pages/admin_console/manage/clients/CreateClientPage";
import Masthead from "../support/pages/admin_console/Masthead";
import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_before";
@ -12,6 +13,7 @@ const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const listingPage = new ListingPage();
const groupModal = new GroupModal();
const createClientPage = new CreateClientPage();
const providersPage = new ProviderPage();
const modalUtils = new ModalUtils();
@ -41,8 +43,15 @@ const providerDeleteSuccess = "The user federation provider has been deleted.";
const providerDeleteTitle = "Delete user federation provider?";
const mapperDeletedSuccess = "Mapping successfully deleted";
const mapperDeleteTitle = "Delete mapping?";
const groupName = "my-mappers-group";
const groupDeleteTitle = "Delete group?";
const groupCreatedSuccess = "Group created";
const groupDeletedSuccess = "Group deleted";
const clientCreatedSuccess = "Client created successfully";
const clientDeletedSuccess = "The client has been deleted";
const roleCreatedSuccess = "Role created";
const groupName = "aa-uf-mappers-group";
const clientName = "aa-uf-mappers-client";
const roleName = "aa-uf-mappers-role";
// mapperType variables
const msadUserAcctMapper = "msad-user-account-control-mapper";
@ -53,9 +62,10 @@ const certLdapMapper = "certificate-ldap-mapper";
const fullNameLdapMapper = "full-name-ldap-mapper";
const hcLdapGroupMapper = "hardcoded-ldap-group-mapper";
const hcLdapAttMapper = "hardcoded-ldap-attribute-mapper";
// const groupLdapMapper = "group-ldap-mapper";
// const roleMapper = "role-ldap-mapper";
// const hcLdapRoleMapper = "hardcoded-ldap-role-mapper";
const groupLdapMapper = "group-ldap-mapper";
const roleLdapMapper = "role-ldap-mapper";
const hcLdapRoleMapper = "hardcoded-ldap-role-mapper";
const creationDateMapper = "creation date";
const emailMapper = "email";
@ -96,9 +106,7 @@ describe("User Fed LDAP mapper tests", () => {
firstUuidLdapAtt,
firstUserObjClasses
);
providersPage.save(provider);
masthead.checkNotificationMessage(providerCreatedSuccess);
sidebarPage.goToUserFederation();
});
@ -111,7 +119,26 @@ describe("User Fed LDAP mapper tests", () => {
.fillGroupForm(groupName)
.clickCreate();
masthead.checkNotificationMessage("Group created");
masthead.checkNotificationMessage(groupCreatedSuccess);
});
// create a new client and then new role for that client
it("Create client and role", () => {
sidebarPage.goToClients();
listingPage.goToCreateItem();
createClientPage
.selectClientType("openid-connect")
.fillClientData(clientName)
.continue()
.continue();
masthead.checkNotificationMessage(clientCreatedSuccess);
providersPage.createRole(roleName);
masthead.checkNotificationMessage(roleCreatedSuccess);
sidebarPage.goToClients();
listingPage.searchItem(clientName).itemExist(clientName);
});
// delete default mappers
@ -156,6 +183,7 @@ describe("User Fed LDAP mapper tests", () => {
masthead.checkNotificationMessage(mapperDeletedSuccess);
});
// mapper CRUD tests
// create mapper
it("Create certificate ldap mapper", () => {
providersPage.clickExistingCard(ldapName);
@ -188,7 +216,7 @@ describe("User Fed LDAP mapper tests", () => {
masthead.checkNotificationMessage(mapperDeletedSuccess);
});
// create one of every kind of non-group/role mapper (8)
// create one of each mapper type
it("Create user account control mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
@ -261,17 +289,51 @@ describe("User Fed LDAP mapper tests", () => {
listingPage.itemExist(hcLdapAttMapper, true);
});
// *** test cleanup ***
it("Cleanup - delete group", () => {
sidebarPage.goToGroups();
listingPage.deleteItem(groupName);
modalUtils.confirmModal();
masthead.checkNotificationMessage("Group deleted");
it("Create group ldap mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(groupLdapMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(groupLdapMapper, true);
it("Create hardcoded ldap role mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(hcLdapRoleMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(hcLdapRoleMapper, true);
});
it("Create role ldap mapper", () => {
providersPage.clickExistingCard(ldapName);
providersPage.goToMappers();
providersPage.createNewMapper(roleLdapMapper);
providersPage.save("ldap-mapper");
masthead.checkNotificationMessage(mapperCreatedSuccess);
listingPage.itemExist(roleLdapMapper, true);
});
});
// *** test cleanup ***
it("Cleanup - delete LDAP provider", () => {
providersPage.deleteCardFromMenu(provider, ldapName);
modalUtils.checkModalTitle(providerDeleteTitle).confirmModal();
masthead.checkNotificationMessage(providerDeleteSuccess);
});
it("Cleanup - delete group", () => {
sidebarPage.goToGroups();
listingPage.deleteItem(groupName);
modalUtils.checkModalTitle(groupDeleteTitle).confirmModal();
masthead.checkNotificationMessage(groupDeletedSuccess);
});
it("Cleanup - delete client", () => {
sidebarPage.goToClients();
listingPage.deleteItem(clientName);
modalUtils.checkModalTitle(`Delete ${clientName} ?`).confirmModal();
masthead.checkNotificationMessage(clientDeletedSuccess);
});
});

View file

@ -44,6 +44,7 @@ export default class ProviderPage {
private ldapAttNameInput = "data-testid=mapper-ldapAttributeName-fld";
private ldapAttValueInput = "data-testid=mapper-ldapAttributeValue-fld";
private groupInput = "data-testid=mapper-group-fld";
private ldapDnInput = "data-testid=ldap-dn";
// mapper types
private msadUserAcctMapper = "msad-user-account-control-mapper";
@ -54,11 +55,28 @@ export default class ProviderPage {
private fullNameLdapMapper = "full-name-ldap-mapper";
private hcLdapAttMapper = "hardcoded-ldap-attribute-mapper";
private hcLdapGroupMapper = "hardcoded-ldap-group-mapper";
// this.groupLdapMapper = "group-ldap-mapper";
// this.roleMapper = "role-ldap-mapper";
// this.hcLdapRoleMapper = "hardcoded-ldap-role-mapper";
private groupLdapMapper = "group-ldap-mapper";
private roleLdapMapper = "role-ldap-mapper";
private hcLdapRoleMapper = "hardcoded-ldap-role-mapper";
private groupName = "my-mappers-group";
private tab = "#pf-tab-serviceAccount-serviceAccount";
private scopeTab = "scopeTab";
private assignRole = "assignRole";
private unAssign = "unAssignRole";
private assign = "assign";
private hide = "#hideInheritedRoles";
private assignedRolesTable = "assigned-roles";
private namesColumn = 'td[data-label="Name"]:visible';
private rolesTab = "#pf-tab-roles-roles";
private createRoleBtn = "data-testid=empty-primary-action";
private realmRolesSaveBtn = "data-testid=realm-roles-save-button";
private roleNameField = "#kc-name";
private clientIdSelect = "#kc-client-id";
private groupName = "aa-uf-mappers-group";
private clientName = "aa-uf-mappers-client";
private roleName = "aa-uf-mappers-role";
changeCacheTime(unit: string, time: string) {
switch (unit) {
@ -183,9 +201,21 @@ export default class ProviderPage {
cy.get(`[data-testid="ldap-mappers-tab"]`).click();
}
createRole(roleName: string) {
cy.get(this.rolesTab).click();
cy.wait(1000);
cy.get(`[${this.createRoleBtn}]`).click();
cy.wait(1000);
cy.get(this.roleNameField).type(roleName);
cy.wait(1000);
cy.get(`[${this.realmRolesSaveBtn}]`).click();
cy.wait(1000);
}
createNewMapper(mapperType: string) {
const userModelAttValue = "firstName";
const ldapAttValue = "cn";
const ldapDnValue = "ou=groups";
cy.get(`[data-testid="add-mapper-btn"]`).click();
cy.wait(1000);
@ -218,12 +248,29 @@ export default class ProviderPage {
case this.hcLdapGroupMapper:
cy.get(`[${this.groupInput}]`).type(this.groupName);
break;
// case this.groupLdapMapper:
// break;
// case this.roleMapper:
// break;
// case this.hcLdapRoleMapper:
// break;
case this.groupLdapMapper:
cy.get(`[${this.ldapDnInput}]`).type(ldapDnValue);
break;
case this.roleLdapMapper:
cy.get(`[${this.ldapDnInput}]`).type(ldapDnValue);
// cy select clientID dropdown and choose clientName (var)
cy.get(this.clientIdSelect).click();
cy.get("button").contains(this.clientName).click({ force: true });
break;
case this.hcLdapRoleMapper:
cy.get(`[data-testid="selectRole"]`).click();
cy.wait(2000);
cy.get(this.namesColumn)
.contains(this.clientName)
.parent()
.parent()
.within(() => {
cy.get('input[name="radioGroup"]').click();
});
cy.getId(this.assign).click();
break;
default:
console.log("Invalid mapper type.");
break;
@ -261,14 +308,6 @@ export default class ProviderPage {
cy.get(`[${this.ldapAttValueInput}]`).clear;
cy.get(`[${this.ldapAttValueInput}]`).type(ldapAttValue);
break;
// case this.hcLdapGroupMapper:
// break;
// case this.groupLdapMapper:
// break;
// case this.roleMapper:
// break;
// case this.hcLdapRoleMapper:
// break;
default:
console.log("Invalid mapper name.");
break;

View file

@ -23,12 +23,13 @@ import { FilterIcon } from "@patternfly/react-icons";
import { Row, ServiceRole } from "./RoleMapping";
import type RoleRepresentation from "keycloak-admin/lib/defs/roleRepresentation";
export type MappingType = "service-account" | "client-scope";
export type MappingType = "service-account" | "client-scope" | "user-fed";
type AddRoleMappingModalProps = {
id: string;
type: MappingType;
name: string;
name?: string;
isRadio?: boolean;
onAssign: (rows: Row[]) => void;
onClose: () => void;
};
@ -45,6 +46,7 @@ export const AddRoleMappingModal = ({
id,
name,
type,
isRadio = false,
onAssign,
onClose,
}: AddRoleMappingModalProps) => {
@ -67,18 +69,28 @@ export const AddRoleMappingModal = ({
await Promise.all(
clients.map(async (client) => {
let roles: RoleRepresentation[] = [];
if (type === "service-account") {
roles = await adminClient.users.listAvailableClientRoleMappings({
id: id,
clientUniqueId: client.id!,
});
} else if (type === "client-scope") {
roles = await adminClient.clientScopes.listAvailableClientScopeMappings(
{
id,
client: client.id!,
}
);
switch (type) {
case "service-account":
roles = await adminClient.users.listAvailableClientRoleMappings(
{
id: id,
clientUniqueId: client.id!,
}
);
break;
case "client-scope":
roles = await adminClient.clientScopes.listAvailableClientScopeMappings(
{
id,
client: client.id!,
}
);
break;
case "user-fed":
roles = await adminClient.roles.find();
break;
}
return {
roles,
@ -118,15 +130,25 @@ export const AddRoleMappingModal = ({
}
let availableRoles: RoleRepresentation[] = [];
if (type === "service-account") {
availableRoles = await adminClient.users.listAvailableRealmRoleMappings({
id,
});
} else if (type === "client-scope") {
availableRoles = await adminClient.clientScopes.listAvailableRealmScopeMappings(
{ id }
);
switch (type) {
case "service-account":
availableRoles = await adminClient.users.listAvailableRealmRoleMappings(
{
id,
}
);
break;
case "client-scope":
availableRoles = await adminClient.clientScopes.listAvailableRealmScopeMappings(
{ id }
);
break;
case "user-fed":
availableRoles = await adminClient.roles.find();
break;
}
const realmRoles = availableRoles.map((role) => {
return {
role,
@ -143,18 +165,28 @@ export const AddRoleMappingModal = ({
await Promise.all(
allClients.map(async (client) => {
let clientAvailableRoles: RoleRepresentation[] = [];
if (type === "service-account") {
clientAvailableRoles = await adminClient.users.listAvailableClientRoleMappings(
{
id,
clientUniqueId: client.id!,
}
);
} else if (type === "client-scope") {
clientAvailableRoles = await adminClient.clientScopes.listAvailableClientScopeMappings(
{ id, client: client.id! }
);
switch (type) {
case "service-account":
clientAvailableRoles = await adminClient.users.listAvailableClientRoleMappings(
{
id,
clientUniqueId: client.id!,
}
);
break;
case "client-scope":
clientAvailableRoles = await adminClient.clientScopes.listAvailableClientScopeMappings(
{ id, client: client.id! }
);
break;
case "user-fed":
clientAvailableRoles = await adminClient.clients.listRoles({
id: client.id!,
});
break;
}
return clientAvailableRoles.map((role) => {
return {
role,
@ -220,7 +252,7 @@ export const AddRoleMappingModal = ({
toggleId="role"
onToggle={() => setSearchToggle(!searchToggle)}
isOpen={searchToggle}
variant={SelectVariant.checkbox}
variant={isRadio ? SelectVariant.single : SelectVariant.checkbox}
hasInlineFilter
menuAppendTo="parent"
placeholderText={
@ -270,6 +302,7 @@ export const AddRoleMappingModal = ({
onSelect={(rows) => setSelectedRows([...rows])}
searchPlaceholderKey="clients:searchByRoleName"
canSelectAll={false}
isRadio={isRadio}
loader={loader}
ariaLabelKey="clients:roles"
columns={[

View file

@ -19,7 +19,6 @@ import "./role-mapping.css";
import { useConfirmDialog } from "../confirm-dialog/ConfirmDialog";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAlerts } from "../alert/Alerts";
import _ from "lodash";
export type CompositeRole = RoleRepresentation & {
parent: RoleRepresentation;
@ -85,46 +84,49 @@ export const RoleMapping = ({
continueButtonVariant: ButtonVariant.danger,
onConfirm: async () => {
try {
if (type === "service-account") {
await Promise.all(
selected.map((row) => {
const role = { id: row.role.id!, name: row.role.name! };
if (row.client) {
return adminClient.users.delClientRoleMappings({
id,
clientUniqueId: row.client!.id!,
roles: [role],
});
} else {
return adminClient.users.delRealmRoleMappings({
id,
roles: [role],
});
}
})
);
} else if (type === "client-scope") {
await Promise.all(
selected.map((row) => {
const role = { id: row.role.id!, name: row.role.name! };
if (row.client) {
return adminClient.clientScopes.delClientScopeMappings(
{
switch (type) {
case "service-account":
await Promise.all(
selected.map((row) => {
const role = { id: row.role.id!, name: row.role.name! };
if (row.client) {
return adminClient.users.delClientRoleMappings({
id,
client: row.client!.id!,
},
[role]
);
} else {
return adminClient.clientScopes.delRealmScopeMappings(
{
clientUniqueId: row.client!.id!,
roles: [role],
});
} else {
return adminClient.users.delRealmRoleMappings({
id,
},
[role]
);
}
})
);
roles: [role],
});
}
})
);
break;
case "client-scope":
await Promise.all(
selected.map((row) => {
const role = { id: row.role.id!, name: row.role.name! };
if (row.client) {
return adminClient.clientScopes.delClientScopeMappings(
{
id,
client: row.client!.id!,
},
[role]
);
} else {
return adminClient.clientScopes.delRealmScopeMappings(
{
id,
},
[role]
);
}
})
);
break;
}
addAlert(t("clientScopeRemoveSuccess"), AlertVariant.success);
refresh();

View file

@ -54,6 +54,7 @@ type DataTableProps<T> = {
onCollapse?: (isOpen: boolean, rowIndex: number) => void;
canSelectAll: boolean;
isNotCompact?: boolean;
isRadio?: boolean;
};
function DataTable<T>({
@ -66,6 +67,7 @@ function DataTable<T>({
onCollapse,
canSelectAll,
isNotCompact,
isRadio,
...props
}: DataTableProps<T>) {
const { t } = useTranslation();
@ -83,6 +85,7 @@ function DataTable<T>({
? (_, rowIndex, isOpen) => onCollapse(isOpen, rowIndex)
: undefined
}
selectVariant={isRadio ? "radio" : "checkbox"}
canSelectAll={canSelectAll}
cells={columns.map((column) => {
return { ...column, title: t(column.displayKey || column.name) };
@ -133,6 +136,7 @@ export type DataListProps<T> = {
emptyState?: ReactNode;
icon?: React.ComponentClass<SVGIconProps>;
isNotCompact?: boolean;
isRadio?: boolean;
};
/**
@ -165,6 +169,7 @@ export function KeycloakDataTable<T>({
onSelect,
canSelectAll = false,
isNotCompact,
isRadio,
detailColumns,
isRowDisabled,
loader,
@ -394,6 +399,7 @@ export function KeycloakDataTable<T>({
rows={filteredData || rows}
columns={columns}
isNotCompact={isNotCompact}
isRadio={isRadio}
ariaLabelKey={ariaLabelKey}
/>
)}

View file

@ -10,6 +10,7 @@ import {
SelectOption,
SelectVariant,
TextInput,
ValidatedOptions,
} from "@patternfly/react-core";
import { convertFormValuesToObject, convertToFormValues } from "../../../util";
import type ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
@ -158,7 +159,12 @@ export const LdapMapperDetails = () => {
id="kc-ldap-mapper-name"
data-testid="ldap-mapper-name"
name="name"
ref={form.register}
ref={form.register({ required: true })}
validated={
form.errors.name
? ValidatedOptions.error
: ValidatedOptions.default
}
/>
<TextInput
hidden

View file

@ -1,4 +1,4 @@
import { FormGroup, TextInput } from "@patternfly/react-core";
import { FormGroup, TextInput, ValidatedOptions } from "@patternfly/react-core";
import React from "react";
import { HelpItem } from "../../../components/help-enabler/HelpItem";
import type { UseFormMethods } from "react-hook-form";
@ -34,7 +34,12 @@ export const LdapMapperHardcodedLdapGroup = ({
id="kc-group"
data-testid="mapper-group-fld"
name="config.group[0]"
ref={form.register}
ref={form.register({ required: true })}
validated={
form.errors.config && form.errors.config.group
? ValidatedOptions.error
: ValidatedOptions.default
}
/>
</FormGroup>
</>

View file

@ -1,21 +1,62 @@
import { FormGroup, TextInput } from "@patternfly/react-core";
import React from "react";
import {
Button,
FormGroup,
TextInput,
ValidatedOptions,
} from "@patternfly/react-core";
import React, { useState } from "react";
import { HelpItem } from "../../../components/help-enabler/HelpItem";
import type { UseFormMethods } from "react-hook-form";
import { useTranslation } from "react-i18next";
import type ClientRepresentation from "keycloak-admin/lib/defs/clientRepresentation";
import type RoleRepresentation from "keycloak-admin/lib/defs/roleRepresentation";
import { AddRoleMappingModal } from "../../../components/role-mapping/AddRoleMappingModal";
import "../../user-federation.css";
export type LdapMapperHardcodedLdapRoleProps = {
form: UseFormMethods;
};
export type CompositeRole = RoleRepresentation & {
parent: RoleRepresentation;
};
export type Row = {
client?: ClientRepresentation;
role: CompositeRole | RoleRepresentation;
};
export const LdapMapperHardcodedLdapRole = ({
form,
}: LdapMapperHardcodedLdapRoleProps) => {
const { t } = useTranslation("user-federation");
const helpText = useTranslation("user-federation-help").t;
const [showAssign, setShowAssign] = useState(false);
const selectRoles = async (rows: Row[]) => {
if (rows[0].client) {
form.setValue(
"config.role[0]",
`${rows[0].client.clientId}.${rows[0].role.name}`
);
} else {
form.setValue("config.role[0]", `${rows[0].role.name}`);
}
};
return (
<>
{showAssign && (
<AddRoleMappingModal
id=""
type="user-fed"
onAssign={selectRoles}
isRadio={true}
onClose={() => setShowAssign(false)}
/>
)}
<FormGroup
label={t("common:role")}
labelIcon={
@ -28,14 +69,28 @@ export const LdapMapperHardcodedLdapRole = ({
fieldId="kc-role"
isRequired
>
<TextInput
isRequired
type="text"
id="kc-role"
data-testid="role"
name="config.role[0]"
ref={form.register}
/>
<div className="keycloak__user-federation__assign-role">
<TextInput
isRequired
type="text"
id="kc-role"
data-testid="role"
name="config.role[0]"
ref={form.register({ required: true })}
validated={
form.errors.config && form.errors.config.role
? ValidatedOptions.error
: ValidatedOptions.default
}
/>
<Button
className="keycloak__user-federation__assign-role-btn"
data-testid="selectRole"
onClick={() => setShowAssign(true)}
>
{t("selectRole")}
</Button>
</div>
</FormGroup>
</>
);

View file

@ -5,11 +5,14 @@ import {
SelectVariant,
Switch,
TextInput,
ValidatedOptions,
} from "@patternfly/react-core";
import React, { useState } from "react";
import { HelpItem } from "../../../components/help-enabler/HelpItem";
import { Controller, UseFormMethods } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { useAdminClient, useFetch } from "../../../context/auth/AdminClient";
import type ClientRepresentation from "keycloak-admin/lib/defs/clientRepresentation";
export type LdapMapperRoleGroupProps = {
form: UseFormMethods;
@ -22,7 +25,7 @@ export const LdapMapperRoleGroup = ({
}: LdapMapperRoleGroupProps) => {
const { t } = useTranslation("user-federation");
const helpText = useTranslation("user-federation-help").t;
const adminClient = useAdminClient();
const [isMbAttTypeDropdownOpen, setIsMbAttTypeDropdownOpen] = useState(false);
const [isModeDropdownOpen, setIsModeDropdownOpen] = useState(false);
const [
@ -30,6 +33,7 @@ export const LdapMapperRoleGroup = ({
setIsRetrieveStratDropdownOpen,
] = useState(false);
const [isClientIdDropdownOpen, setIsClientIdDropdownOpen] = useState(false);
const [clients, setClients] = useState<ClientRepresentation[]>([]);
let isRole = true;
const groupMapper = "group-ldap-mapper";
@ -38,6 +42,18 @@ export const LdapMapperRoleGroup = ({
isRole = false;
}
useFetch(
async () => {
const clients = await adminClient.clients.find();
if (clients) {
setClients(clients);
}
return clients;
},
(clients) => setClients(clients),
[]
);
return (
<>
<FormGroup
@ -62,7 +78,16 @@ export const LdapMapperRoleGroup = ({
id="kc-ldap-dn"
data-testid="ldap-dn"
name={isRole ? "config.roles-dn[0]" : "config.groups-dn[0]"}
ref={form.register}
ref={form.register({ required: true })}
validated={
isRole
? form.errors.config && form.errors.config["roles-dn"]
? ValidatedOptions.error
: ValidatedOptions.default
: form.errors.config && form.errors.config["groups-dn"]
? ValidatedOptions.error
: ValidatedOptions.default
}
/>
</FormGroup>
<FormGroup
@ -90,6 +115,7 @@ export const LdapMapperRoleGroup = ({
type="text"
id="kc-name-attribute"
data-testid="name-attribute"
defaultValue="cn"
name={
isRole
? "config.role-name-ldap-attribute[0]"
@ -119,6 +145,7 @@ export const LdapMapperRoleGroup = ({
type="text"
id="kc-object-classes"
data-testid="object-classes"
defaultValue="group"
name={
isRole
? "config.role-object-classes[0]"
@ -143,7 +170,7 @@ export const LdapMapperRoleGroup = ({
>
<Controller
name="config.preserve-group-inheritance"
defaultValue={["false"]}
defaultValue={["true"]}
control={form.control}
render={({ onChange, value }) => (
<Switch
@ -202,6 +229,7 @@ export const LdapMapperRoleGroup = ({
<TextInput
isRequired
type="text"
defaultValue="member"
id="kc-membership-ldap-attribute"
data-testid="membership-ldap-attribute"
name="config.membership-ldap-attribute[0]"
@ -264,6 +292,7 @@ export const LdapMapperRoleGroup = ({
type="text"
id="kc-membership-user-ldap-attribute"
data-testid="membership-user-ldap-attribute"
defaultValue="cn"
name="config.membership-user-ldap-attribute[0]"
ref={form.register}
/>
@ -278,10 +307,8 @@ export const LdapMapperRoleGroup = ({
/>
}
fieldId="kc-ldap-filter"
isRequired
>
<TextInput
isRequired
type="text"
id="kc-ldap-filter"
data-testid="ldap-filter"
@ -413,6 +440,7 @@ export const LdapMapperRoleGroup = ({
isRequired
type="text"
id="kc-member-of-attribute"
defaultValue="memberOf"
data-testid="member-of-attribute"
name="config.memberof-ldap-attribute[0]"
ref={form.register}
@ -434,7 +462,7 @@ export const LdapMapperRoleGroup = ({
>
<Controller
name="config.use-realm-roles-mapping"
defaultValue={["false"]}
defaultValue={["true"]}
control={form.control}
render={({ onChange, value }) => (
<Switch
@ -461,7 +489,6 @@ export const LdapMapperRoleGroup = ({
>
<Controller
name="config.client-id[0]"
defaultValue=""
control={form.control}
render={({ onChange, value }) => (
<Select
@ -477,12 +504,11 @@ export const LdapMapperRoleGroup = ({
selections={value}
variant={SelectVariant.single}
>
<SelectOption key={0} value="account">
Need to fetch clients here
</SelectOption>
<SelectOption key={1} value="admin-cli">
These are placeholders
</SelectOption>
{clients.map((client) => (
<SelectOption key={client.id} value={client.id}>
{client.clientId}
</SelectOption>
))}
</Select>
)}
></Controller>
@ -501,10 +527,8 @@ export const LdapMapperRoleGroup = ({
/>
}
fieldId="kc-mapped-attributes"
isRequired
>
<TextInput
isRequired
type="text"
id="kc-mapped-attributes"
data-testid="mapped-attributes"
@ -557,8 +581,14 @@ export const LdapMapperRoleGroup = ({
type="text"
id="kc-path"
data-testid="path"
defaultValue="/"
name="config.groups-path[0]"
ref={form.register}
ref={form.register({ required: true })}
validated={
form.errors.config && form.errors.config["groups-path"]
? ValidatedOptions.error
: ValidatedOptions.default
}
/>
</FormGroup>
</>

View file

@ -9,3 +9,13 @@
.error {
color: red;
}
.keycloak__user-federation__assign-role {
display: flex;
flex-direction: row;
align-items: right;
}
.keycloak__user-federation__assign-role-btn {
margin-left: 10px;
}