diff --git a/cypress/integration/realm_settings_client_policies_test.spec.ts b/cypress/integration/realm_settings_client_policies_test.spec.ts
index d35eff993c..297b7da1fe 100644
--- a/cypress/integration/realm_settings_client_policies_test.spec.ts
+++ b/cypress/integration/realm_settings_client_policies_test.spec.ts
@@ -158,7 +158,6 @@ describe("Realm settings client policies tab tests", () => {
// TODO: UNCOMMENT WHEN THE ISSUE 2050 IS FIXED
//realmSettingsPage.checkAlertMessage("Could not create client policy: 'proposed client policy name duplicated.'");
- sidebarPage.waitForPageLoad();
sidebarPage.goToRealmSettings();
realmSettingsPage
diff --git a/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts b/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts
index 1f8ea06e2b..549fb53e6f 100644
--- a/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts
+++ b/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts
@@ -218,8 +218,8 @@ export default class RealmSettingsPage {
private eventListenersDrwDwnSelect =
".pf-c-button.pf-c-select__toggle-button.pf-m-plain";
private eventListenerRemove = '[data-ouia-component-id="Remove"]';
- private roleSelect = ".pf-c-select.kc-role-select";
- private selectScopeButton = "select-scope-button";
+ private roleSelect = "#config\\.roles0";
+ private selectScopeButton = "addValue";
private deleteClientRolesConditionBtn = "delete-client-roles-condition";
private deleteClientScopesConditionBtn = "delete-client-scopes-condition";
@@ -947,13 +947,7 @@ export default class RealmSettingsPage {
cy.findByTestId(this.addConditionDrpDwnOption)
.contains("client-roles")
.click();
- cy.get(this.roleSelect).click().contains("impersonation").click();
-
- cy.get(this.roleSelect).contains("manage-realm").click();
-
- cy.get(this.roleSelect).contains("view-users").click();
-
- cy.get(this.roleSelect).click();
+ cy.get(this.roleSelect).clear().type("manage-realm");
cy.findByTestId(this.addConditionSaveBtn).click();
cy.get(this.alertMessage).should(
@@ -964,18 +958,14 @@ export default class RealmSettingsPage {
}
addClientScopes() {
+ cy.get("#config\\.scopes0").clear().type("one");
cy.findByTestId(this.selectScopeButton).click();
- cy.get(".pf-c-table__check input[name=checkrow0]").click();
- cy.get(".pf-c-table__check input[name=checkrow1]").click();
- cy.get(".pf-c-table__check input[name=checkrow2]").click();
-
- cy.findByTestId(this.modalConfirm).contains("Add").click();
+ cy.get("#config\\.scopes1").clear().type("two");
+ cy.findByTestId(this.selectScopeButton).click();
+ cy.get("#config\\.scopes2").clear().type("three");
}
shouldAddClientScopesCondition() {
- cy.intercept(`/auth/admin/realms/${this.realmName}/client-scopes`).as(
- "clientScopes"
- );
cy.get(this.clientPolicy).click();
cy.findByTestId(this.addCondition).click();
cy.get(this.addConditionDrpDwn).click();
@@ -983,7 +973,6 @@ export default class RealmSettingsPage {
.contains("client-scopes")
.click();
- cy.wait("@clientScopes");
this.addClientScopes();
cy.findByTestId(this.addConditionSaveBtn).click();
@@ -999,10 +988,8 @@ export default class RealmSettingsPage {
cy.findByTestId(this.clientRolesConditionLink).click();
- cy.get(this.roleSelect).click();
- cy.get(this.roleSelect).contains("create-client").click();
-
- cy.get(this.roleSelect).click();
+ cy.get(this.roleSelect).should("have.value", "manage-realm");
+ cy.get(this.roleSelect).clear().type("admin");
cy.findByTestId(this.addConditionSaveBtn).click();
cy.get(this.alertMessage).should(
@@ -1012,15 +999,11 @@ export default class RealmSettingsPage {
}
shouldEditClientScopesCondition() {
- cy.intercept(`/auth/admin/realms/${this.realmName}/client-scopes`).as(
- "clientScopes"
- );
cy.get(this.clientPolicy).click();
cy.findByTestId(this.clientScopesConditionLink).click();
- cy.wait("@clientScopes");
- this.addClientScopes();
+ cy.get("#config\\.scopes0").clear().type("edit");
cy.findByTestId(this.addConditionSaveBtn).click();
cy.get(this.alertMessage).should(
diff --git a/src/components/dynamic/DynamicComponents.tsx b/src/components/dynamic/DynamicComponents.tsx
index 504e7a90ea..5ab91ce9d7 100644
--- a/src/components/dynamic/DynamicComponents.tsx
+++ b/src/components/dynamic/DynamicComponents.tsx
@@ -16,7 +16,7 @@ export const DynamicComponents = ({
<>
{properties.map((property) => {
const componentType = property.type!;
- if (isValidComponentType(componentType) && property.name !== "scopes") {
+ if (isValidComponentType(componentType)) {
const Component = COMPONENTS[componentType];
return ;
} else {
diff --git a/src/components/dynamic/MultivaluedChipsComponent.tsx b/src/components/dynamic/MultivaluedChipsComponent.tsx
deleted file mode 100644
index e79d3e6c38..0000000000
--- a/src/components/dynamic/MultivaluedChipsComponent.tsx
+++ /dev/null
@@ -1,144 +0,0 @@
-import React, { useState } from "react";
-import { useTranslation } from "react-i18next";
-import { Controller, useFormContext } from "react-hook-form";
-import {
- Button,
- Chip,
- ChipGroup,
- FormGroup,
- TextInput,
-} from "@patternfly/react-core";
-
-import { HelpItem } from "../help-enabler/HelpItem";
-import type { ComponentProps } from "./components";
-import { AddScopeDialog } from "../../clients/scopes/AddScopeDialog";
-import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
-import type ClientScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientScopeRepresentation";
-import { useParams } from "react-router";
-import type { EditClientPolicyConditionParams } from "../../realm-settings/routes/EditCondition";
-import { GroupPickerDialog } from "../group/GroupPickerDialog";
-
-export const MultivaluedChipsComponent = ({
- defaultValue,
- name,
- label,
- helpText,
- isDisabled = false,
-}: ComponentProps) => {
- const { t } = useTranslation("dynamic");
- const { control } = useFormContext();
- const { conditionName } = useParams();
- const adminClient = useAdminClient();
- const [open, setOpen] = useState(false);
- const [clientScopes, setClientScopes] = useState(
- []
- );
-
- useFetch(
- () => adminClient.clientScopes.find(),
- (clientScopes) => {
- setClientScopes(clientScopes);
- },
- []
- );
-
- const toggleModal = () => {
- setOpen(!open);
- };
-
- return (
-
- }
- fieldId={name!}
- >
- (
- <>
- {open && name === "scopes" && (
- !value.includes(scope.name!)
- )}
- isClientScopesConditionType
- open={open}
- toggleDialog={() => setOpen(!open)}
- onAdd={(scopes) => {
- onChange([
- ...value,
- ...scopes
- .map((scope) => scope.scope)
- .map((item) => item.name!),
- ]);
- }}
- />
- )}
- {open && name === "groups" && (
- {
- onChange([...value, ...groups.map((group) => group.name)]);
- setOpen(false);
- }}
- onClose={() => {
- setOpen(false);
- }}
- filterGroups={value}
- />
- )}
- {value.length === 0 && !conditionName && (
-
- )}
- {
- onChange([]);
- }}
- >
- {value.map((currentChip: string) => (
- {
- onChange(
- value.filter((item: string) => item !== currentChip)
- );
- }}
- >
- {currentChip}
-
- ))}
-
-
- >
- )}
- />
-
- );
-};
diff --git a/src/components/dynamic/MultivaluedRoleComponent.tsx b/src/components/dynamic/MultivaluedRoleComponent.tsx
deleted file mode 100644
index 9c610ef09a..0000000000
--- a/src/components/dynamic/MultivaluedRoleComponent.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-import React, { useState } from "react";
-import { Controller, useFormContext } from "react-hook-form";
-import { useTranslation } from "react-i18next";
-import { sortedUniq } from "lodash-es";
-import {
- FormGroup,
- Select,
- SelectOption,
- SelectVariant,
-} from "@patternfly/react-core";
-
-import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
-import type { ComponentProps } from "./components";
-import type { MultiLine } from "../multi-line-input/multi-line-convert";
-import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
-import { HelpItem } from "../help-enabler/HelpItem";
-import { useWhoAmI } from "../../context/whoami/WhoAmI";
-
-export const MultivaluedRoleComponent = ({
- name,
- label,
- helpText,
- isDisabled = false,
-}: ComponentProps) => {
- const { t } = useTranslation("dynamic");
- const { whoAmI } = useWhoAmI();
- const fieldName = `config.${name}`;
-
- const adminClient = useAdminClient();
- const { control } = useFormContext();
-
- const [clientRoles, setClientRoles] = useState([]);
- const [open, setOpen] = useState(false);
-
- useFetch(
- async () => {
- const clients = await adminClient.clients.find();
- const clientRoles = await Promise.all(
- clients.map(async (client) => {
- const roles = await adminClient.clients.listRoles({ id: client.id! });
-
- return roles.map((role) => ({
- ...role,
- }));
- })
- );
-
- return clientRoles.flat();
- },
- (clientRoles) => {
- setClientRoles(clientRoles);
- },
- []
- );
-
- const alphabetizedClientRoles = sortedUniq(
- clientRoles.map((item) => item.name)
- ).sort((a, b) =>
- a!.localeCompare(b!, whoAmI.getLocale(), { ignorePunctuation: true })
- );
-
- return (
-
- }
- fieldId={name!}
- >
- (
-
- )}
- />
-
- );
-};
diff --git a/src/components/dynamic/MultivaluedStringComponent.tsx b/src/components/dynamic/MultivaluedStringComponent.tsx
index 5beb650d73..8d51014046 100644
--- a/src/components/dynamic/MultivaluedStringComponent.tsx
+++ b/src/components/dynamic/MultivaluedStringComponent.tsx
@@ -1,18 +1,41 @@
-import React from "react";
+import React, { Fragment, useEffect } from "react";
import { useTranslation } from "react-i18next";
-import { FormGroup } from "@patternfly/react-core";
+import { useFormContext } from "react-hook-form";
+import {
+ Button,
+ ButtonVariant,
+ FormGroup,
+ InputGroup,
+ TextInput,
+} from "@patternfly/react-core";
import { HelpItem } from "../../components/help-enabler/HelpItem";
import type { ComponentProps } from "./components";
-import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
+import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";
export const MultiValuedStringComponent = ({
name,
label,
+ defaultValue,
helpText,
isDisabled = false,
}: ComponentProps) => {
const { t } = useTranslation("dynamic");
+ const fieldName = `config.${name}`;
+ const { register, setValue, watch } = useFormContext();
+
+ const fields = watch(fieldName, [defaultValue]);
+
+ const remove = (id: number) => {
+ fields.splice(id, 1);
+ setValue(fieldName, [...fields]);
+ };
+
+ const append = () => {
+ setValue(fieldName, [...fields, ""]);
+ };
+
+ useEffect(() => register(`config.${name}`), [register]);
return (
-
+ {fields.map((value: string, index: number) => (
+
+
+ {
+ fields[index] = value;
+ setValue(fieldName, [...fields]);
+ }}
+ name={`${fieldName}[${index}]`}
+ value={value}
+ isDisabled={isDisabled}
+ />
+
+
+ {index === fields.length - 1 && (
+
+ )}
+
+ ))}
);
};
diff --git a/src/realm-settings/NewClientPolicyCondition.tsx b/src/realm-settings/NewClientPolicyCondition.tsx
index e9226e2b4f..571eb845a1 100644
--- a/src/realm-settings/NewClientPolicyCondition.tsx
+++ b/src/realm-settings/NewClientPolicyCondition.tsx
@@ -30,16 +30,8 @@ import {
toEditClientPolicy,
} from "./routes/EditClientPolicy";
import type { EditClientPolicyConditionParams } from "./routes/EditCondition";
-import {
- convertToMultiline,
- toValue,
-} from "../components/multi-line-input/multi-line-convert";
-import {
- COMPONENTS,
- isValidComponentType,
-} from "../components/dynamic/components";
-import { MultivaluedChipsComponent } from "../components/dynamic/MultivaluedChipsComponent";
-import { MultivaluedRoleComponent } from "../components/dynamic/MultivaluedRoleComponent";
+import { DynamicComponents } from "../components/dynamic/DynamicComponents";
+
export type ItemType = { value: string };
type ConfigProperty = ConfigPropertyRepresentation & {
@@ -69,7 +61,7 @@ export default function NewClientPolicyCondition() {
const { conditionName } = useParams();
const serverInfo = useServerInfo();
- const form = useForm({
+ const form = useForm({
shouldUnregister: false,
});
@@ -80,28 +72,8 @@ export default function NewClientPolicyCondition() {
const adminClient = useAdminClient();
- const setupForm = (
- condition: ClientPolicyConditionRepresentation,
- properties: ConfigPropertyRepresentation[]
- ) => {
- form.reset();
-
- Object.entries(condition.configuration!).map(([key, value]) => {
- const formKey = `config.${key}`;
-
- const property = properties.find((p) => p.name === key);
- if (
- property?.type === "MultivaluedString" &&
- property.name !== "scopes" &&
- property.name !== "groups"
- ) {
- form.setValue(formKey, convertToMultiline(value));
- } else if (property?.name === "client-scopes") {
- form.setValue("config.scopes", value);
- } else {
- form.setValue(formKey, value);
- }
- });
+ const setupForm = (condition: ClientPolicyConditionRepresentation) => {
+ form.reset({ config: condition.configuration || {} });
};
useFetch(
@@ -125,7 +97,7 @@ export default function NewClientPolicyCondition() {
setConditionData(typeAndConfigData!);
setConditionProperties(currentCondition?.properties!);
- setupForm(typeAndConfigData!, currentCondition?.properties!);
+ setupForm(typeAndConfigData!);
}
},
[]
@@ -136,11 +108,7 @@ export default function NewClientPolicyCondition() {
const writeConfig = () => {
return conditionProperties.reduce((r: any, p) => {
- p.type === "MultivaluedString" &&
- p.name !== "scopes" &&
- p.name !== "groups"
- ? (r[p.name!] = toValue(configValues[p.name!]))
- : (r[p.name!] = configValues[p.name!]);
+ r[p.name!] = configValues[p.name!];
return r;
}, {});
};
@@ -284,32 +252,7 @@ export default function NewClientPolicyCondition() {
- {conditionProperties.map((property) => {
- const componentType = property.type!;
- if (property.name === "roles") {
- return ;
- }
-
- if (property.name === "scopes" || property.name === "groups") {
- return (
-
- );
- }
-
- if (isValidComponentType(componentType)) {
- const Component = COMPONENTS[componentType];
- return ;
- } else {
- console.warn(
- `There is no editor registered for ${componentType}`
- );
- }
- })}
+