Merge pull request #671 from mfrances17/role-mappers
Adds User Fed Group and Role mappers
This commit is contained in:
commit
2f012eecce
10 changed files with 383 additions and 135 deletions
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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={[
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
</>
|
||||
|
|
|
@ -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>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
</>
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue