mirror of
https://github.com/keycloak/keycloak.git
synced 2025-12-30 19:39:55 -06:00
make group select required when specific group is selected (#38768)
* make group select required when specific group is selected fixes: #38767 Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * small refactor to make labels not dependant on route Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * fixed tests Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> --------- Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
This commit is contained in:
@@ -66,6 +66,7 @@ export const Role = () => {
|
||||
<AddRoleMappingModal
|
||||
id="role"
|
||||
type="roles"
|
||||
title={t("assignRole")}
|
||||
onAssign={(rows) => {
|
||||
field.onChange([
|
||||
...(field.value || []),
|
||||
@@ -77,7 +78,6 @@ export const Role = () => {
|
||||
onClose={() => {
|
||||
setOpen(false);
|
||||
}}
|
||||
isLDAPmapper
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
|
||||
@@ -24,8 +24,6 @@ import useLocaleSort from "../../utils/useLocaleSort";
|
||||
import { ResourcesKey, Row, ServiceRole } from "./RoleMapping";
|
||||
import { getAvailableRoles } from "./queries";
|
||||
import { getAvailableClientRoles } from "./resource";
|
||||
import { PermissionsConfigurationTabsParams } from "../../permissions-configuration/routes/PermissionsConfigurationTabs";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
type AddRoleMappingModalProps = {
|
||||
id: string;
|
||||
@@ -34,7 +32,8 @@ type AddRoleMappingModalProps = {
|
||||
isRadio?: boolean;
|
||||
onAssign: (rows: Row[]) => void;
|
||||
onClose: () => void;
|
||||
isLDAPmapper?: boolean;
|
||||
title?: string;
|
||||
actionLabel?: string;
|
||||
};
|
||||
|
||||
type FilterType = "roles" | "clients";
|
||||
@@ -52,9 +51,11 @@ export const AddRoleMappingModal = ({
|
||||
id,
|
||||
name,
|
||||
type,
|
||||
isLDAPmapper,
|
||||
isRadio,
|
||||
onAssign,
|
||||
onClose,
|
||||
title,
|
||||
actionLabel,
|
||||
}: AddRoleMappingModalProps) => {
|
||||
const { adminClient } = useAdminClient();
|
||||
|
||||
@@ -71,7 +72,6 @@ export const AddRoleMappingModal = ({
|
||||
|
||||
const localeSort = useLocaleSort();
|
||||
const compareRow = ({ role: { name } }: Row) => name?.toUpperCase();
|
||||
const { tab } = useParams<PermissionsConfigurationTabsParams>();
|
||||
|
||||
const loader = async (
|
||||
first?: number,
|
||||
@@ -123,13 +123,7 @@ export const AddRoleMappingModal = ({
|
||||
return (
|
||||
<Modal
|
||||
variant={ModalVariant.large}
|
||||
title={
|
||||
tab !== "evaluation"
|
||||
? isLDAPmapper
|
||||
? t("assignRole")
|
||||
: t("assignRolesTo", { client: name })
|
||||
: t("selectRole")
|
||||
}
|
||||
title={title || t("assignRolesTo", { client: name })}
|
||||
isOpen
|
||||
onClose={onClose}
|
||||
actions={[
|
||||
@@ -143,7 +137,7 @@ export const AddRoleMappingModal = ({
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
{tab !== "evaluation" ? t("assign") : t("select")}
|
||||
{actionLabel || t("assign")}
|
||||
</Button>,
|
||||
<Button
|
||||
data-testid="cancel"
|
||||
@@ -157,13 +151,7 @@ export const AddRoleMappingModal = ({
|
||||
>
|
||||
<KeycloakDataTable
|
||||
key={key}
|
||||
onSelect={(rows) => {
|
||||
if (tab === "evaluation") {
|
||||
setSelectedRows(rows.length > 0 ? [rows[0]] : []);
|
||||
} else {
|
||||
setSelectedRows([...rows]);
|
||||
}
|
||||
}}
|
||||
onSelect={(rows) => setSelectedRows([...rows])}
|
||||
searchPlaceholderKey="searchByRoleName"
|
||||
isPaginated={!(filterType === "roles" && type !== "roles")}
|
||||
searchTypeComponent={
|
||||
@@ -202,7 +190,7 @@ export const AddRoleMappingModal = ({
|
||||
)
|
||||
}
|
||||
canSelectAll
|
||||
isRadio={tab === "evaluation"}
|
||||
isRadio={isRadio}
|
||||
loader={filterType === "roles" ? loader : clientRolesLoader}
|
||||
ariaLabelKey="associatedRolesText"
|
||||
columns={[
|
||||
|
||||
@@ -196,6 +196,7 @@ const PermissionEvaluateContent = ({ client }: Props) => {
|
||||
defaultValue={[]}
|
||||
variant="typeahead"
|
||||
isRequired
|
||||
isRadio
|
||||
/>
|
||||
)}
|
||||
<SelectControl
|
||||
|
||||
@@ -69,14 +69,11 @@ export const GroupSelect = ({
|
||||
name={name!}
|
||||
control={control}
|
||||
defaultValue={defaultValue}
|
||||
rules={
|
||||
isRequired
|
||||
? {
|
||||
validate: (value?: GroupRepresentation[]) =>
|
||||
value && value.length > 0,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
rules={{
|
||||
validate: (value?: string[]) => {
|
||||
return isRequired && value && value.length > 0;
|
||||
},
|
||||
}}
|
||||
render={({ field }) => (
|
||||
<>
|
||||
{open && (
|
||||
@@ -147,7 +144,7 @@ export const GroupSelect = ({
|
||||
</Tbody>
|
||||
</Table>
|
||||
)}
|
||||
{errors.groups && <FormErrorText message={t("requiredGroups")} />}
|
||||
{errors[name!] && <FormErrorText message={t("requiredGroups")} />}
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -96,6 +96,7 @@ export const ResourceType = ({
|
||||
})}
|
||||
defaultValue={[]}
|
||||
variant="typeaheadMulti"
|
||||
isRequired={withEnforceAccessTo}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -12,14 +12,13 @@ import {
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { AddRoleMappingModal } from "../../components/role-mapping/AddRoleMappingModal";
|
||||
import { Row, ServiceRole } from "../../components/role-mapping/RoleMapping";
|
||||
import { PermissionsConfigurationTabsParams } from "../routes/PermissionsConfigurationTabs";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
type RoleSelectorProps = {
|
||||
name: string;
|
||||
isRadio?: boolean;
|
||||
};
|
||||
|
||||
export const RoleSelect = ({ name }: RoleSelectorProps) => {
|
||||
export const RoleSelect = ({ name, isRadio = false }: RoleSelectorProps) => {
|
||||
const { adminClient } = useAdminClient();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
@@ -30,7 +29,6 @@ export const RoleSelect = ({ name }: RoleSelectorProps) => {
|
||||
const values = getValues(name) || [];
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [selectedRoles, setSelectedRoles] = useState<Row[]>([]);
|
||||
const { tab } = useParams<PermissionsConfigurationTabsParams>();
|
||||
|
||||
useFetch(
|
||||
async () => {
|
||||
@@ -55,12 +53,10 @@ export const RoleSelect = ({ name }: RoleSelectorProps) => {
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
label={tab !== "evaluation" ? t("roles") : t("role")}
|
||||
label={isRadio ? t("role") : t("roles")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={
|
||||
tab !== "evaluation" ? t("policyRolesHelp") : t("selectRole")
|
||||
}
|
||||
helpText={isRadio ? t("selectRole") : t("policyRolesHelp")}
|
||||
fieldLabelId="roles"
|
||||
/>
|
||||
}
|
||||
@@ -71,19 +67,21 @@ export const RoleSelect = ({ name }: RoleSelectorProps) => {
|
||||
<AddRoleMappingModal
|
||||
id="role"
|
||||
type="roles"
|
||||
title={t("selectRole")}
|
||||
actionLabel={t("select")}
|
||||
isRadio={isRadio}
|
||||
onAssign={(rows) => {
|
||||
setValue(name, [
|
||||
...values,
|
||||
...(!isRadio ? values : []),
|
||||
...rows
|
||||
.filter((row) => row.role.id !== undefined)
|
||||
.map((row) => row.role.id!),
|
||||
]);
|
||||
|
||||
setSelectedRoles([...selectedRoles, ...rows]);
|
||||
setSelectedRoles(isRadio ? rows : [...selectedRoles, ...rows]);
|
||||
setIsModalOpen(false);
|
||||
}}
|
||||
onClose={() => setIsModalOpen(false)}
|
||||
isLDAPmapper
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
@@ -91,7 +89,7 @@ export const RoleSelect = ({ name }: RoleSelectorProps) => {
|
||||
variant="secondary"
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
>
|
||||
{tab !== "evaluation" ? t("addRoles") : t("selectRole")}
|
||||
{isRadio ? t("selectRole") : t("addRoles")}
|
||||
</Button>
|
||||
{selectedRoles.length > 0 && (
|
||||
<Table variant="compact">
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
clickCreatePermission,
|
||||
clickCreatePolicySaveButton,
|
||||
clickSearchButton,
|
||||
deletePermission,
|
||||
fillPermissionForm,
|
||||
goToEvaluation,
|
||||
goToPermissions,
|
||||
@@ -76,6 +77,7 @@ test.describe("Permissions section tests", () => {
|
||||
|
||||
await goToPermissions(page);
|
||||
await assertRowExists(page, "test-permission");
|
||||
await deletePermission(page, "test-permission");
|
||||
await goToPolicies(page);
|
||||
await assertRowExists(page, "test-policy");
|
||||
});
|
||||
@@ -95,7 +97,7 @@ test.describe("Permissions section tests", () => {
|
||||
await fillPolicyForm(
|
||||
page,
|
||||
{
|
||||
name: "test-policy",
|
||||
name: "test-policy2",
|
||||
description: "test-description",
|
||||
type: "User",
|
||||
user: "test-user",
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import PolicyRepresentation from "@keycloak/keycloak-admin-client/lib/defs/policyRepresentation";
|
||||
import { Page } from "@playwright/test";
|
||||
import { selectItem } from "../utils/form";
|
||||
import { confirmModal } from "../utils/modal";
|
||||
import { clickRowKebabItem } from "../utils/table";
|
||||
|
||||
type PermissionForm = PolicyRepresentation & {
|
||||
enforcementMode?: "allResources" | "specificResources";
|
||||
@@ -68,3 +70,8 @@ export async function openSearchPanel(page: Page) {
|
||||
export async function clickSearchButton(page: Page) {
|
||||
await page.getByTestId("search-btn").click();
|
||||
}
|
||||
|
||||
export async function deletePermission(page: Page, name: string) {
|
||||
await clickRowKebabItem(page, name, "Delete");
|
||||
await confirmModal(page);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user