Added missing groups claim field (#2170)
This commit is contained in:
parent
01ab5b12e0
commit
e3c0bb82a1
3 changed files with 126 additions and 106 deletions
|
@ -2,7 +2,7 @@ import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useFormContext, Controller } from "react-hook-form";
|
import { useFormContext, Controller } from "react-hook-form";
|
||||||
import { MinusCircleIcon } from "@patternfly/react-icons";
|
import { MinusCircleIcon } from "@patternfly/react-icons";
|
||||||
import { FormGroup, Button, Checkbox } from "@patternfly/react-core";
|
import { FormGroup, Button, Checkbox, TextInput } from "@patternfly/react-core";
|
||||||
import {
|
import {
|
||||||
TableComposable,
|
TableComposable,
|
||||||
Thead,
|
Thead,
|
||||||
|
@ -24,7 +24,7 @@ export type GroupValue = {
|
||||||
|
|
||||||
export const Group = () => {
|
export const Group = () => {
|
||||||
const { t } = useTranslation("clients");
|
const { t } = useTranslation("clients");
|
||||||
const { control, getValues, setValue, errors } =
|
const { control, register, getValues, setValue, errors } =
|
||||||
useFormContext<{ groups?: GroupValue[] }>();
|
useFormContext<{ groups?: GroupValue[] }>();
|
||||||
const values = getValues("groups");
|
const values = getValues("groups");
|
||||||
|
|
||||||
|
@ -51,112 +51,129 @@ export const Group = () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormGroup
|
<>
|
||||||
label={t("groups")}
|
<FormGroup
|
||||||
labelIcon={
|
label={t("groupsClaim")}
|
||||||
<HelpItem
|
labelIcon={
|
||||||
helpText="clients-help:policyGroups"
|
<HelpItem
|
||||||
fieldLabelId="clients:groups"
|
helpText="clients-help:groupsClaim"
|
||||||
|
fieldLabelId="clients:groupsClaim"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="groups"
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
type="text"
|
||||||
|
id="groupsClaim"
|
||||||
|
name="groupsClaim"
|
||||||
|
data-testid="groupsClaim"
|
||||||
|
ref={register}
|
||||||
/>
|
/>
|
||||||
}
|
</FormGroup>
|
||||||
fieldId="groups"
|
<FormGroup
|
||||||
helperTextInvalid={t("requiredGroups")}
|
label={t("groups")}
|
||||||
validated={errors.groups ? "error" : "default"}
|
labelIcon={
|
||||||
isRequired
|
<HelpItem
|
||||||
>
|
helpText="clients-help:policyGroups"
|
||||||
<Controller
|
fieldLabelId="clients:groups"
|
||||||
name="groups"
|
/>
|
||||||
control={control}
|
}
|
||||||
defaultValue={[]}
|
fieldId="groups"
|
||||||
rules={{
|
helperTextInvalid={t("requiredGroups")}
|
||||||
validate: (value: GroupValue[]) =>
|
validated={errors.groups ? "error" : "default"}
|
||||||
value.filter((c) => c.id).length > 0,
|
isRequired
|
||||||
}}
|
>
|
||||||
render={({ onChange, value }) => (
|
<Controller
|
||||||
<>
|
name="groups"
|
||||||
{open && (
|
control={control}
|
||||||
<GroupPickerDialog
|
defaultValue={[]}
|
||||||
type="selectMany"
|
rules={{
|
||||||
text={{
|
validate: (value: GroupValue[]) =>
|
||||||
title: "clients:addGroupsToGroupPolicy",
|
value.filter(({ id }) => id).length > 0,
|
||||||
ok: "common:add",
|
}}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<>
|
||||||
|
{open && (
|
||||||
|
<GroupPickerDialog
|
||||||
|
type="selectMany"
|
||||||
|
text={{
|
||||||
|
title: "clients:addGroupsToGroupPolicy",
|
||||||
|
ok: "common:add",
|
||||||
|
}}
|
||||||
|
onConfirm={(groups) => {
|
||||||
|
onChange([...value, ...groups.map(({ id }) => ({ id }))]);
|
||||||
|
setSelectedGroups([...selectedGroups, ...groups]);
|
||||||
|
setOpen(false);
|
||||||
|
}}
|
||||||
|
onClose={() => {
|
||||||
|
setOpen(false);
|
||||||
|
}}
|
||||||
|
filterGroups={selectedGroups.map(({ name }) => name!)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
data-testid="select-group-button"
|
||||||
|
variant="secondary"
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(true);
|
||||||
}}
|
}}
|
||||||
onConfirm={(groups) => {
|
>
|
||||||
onChange([
|
{t("addGroups")}
|
||||||
...value,
|
</Button>
|
||||||
...groups.map((group) => ({ id: group.id })),
|
</>
|
||||||
]);
|
)}
|
||||||
setSelectedGroups([...selectedGroups, ...groups]);
|
/>
|
||||||
setOpen(false);
|
{selectedGroups.length > 0 && (
|
||||||
}}
|
<TableComposable>
|
||||||
onClose={() => {
|
<Thead>
|
||||||
setOpen(false);
|
<Tr>
|
||||||
}}
|
<Th>{t("groups")}</Th>
|
||||||
filterGroups={selectedGroups.map((g) => g.name!)}
|
<Th>{t("extendToChildren")}</Th>
|
||||||
/>
|
<Th />
|
||||||
)}
|
|
||||||
<Button
|
|
||||||
data-testid="select-group-button"
|
|
||||||
variant="secondary"
|
|
||||||
onClick={() => {
|
|
||||||
setOpen(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("addGroups")}
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{selectedGroups.length > 0 && (
|
|
||||||
<TableComposable>
|
|
||||||
<Thead>
|
|
||||||
<Tr>
|
|
||||||
<Th>{t("groups")}</Th>
|
|
||||||
<Th>{t("extendToChildren")}</Th>
|
|
||||||
<Th />
|
|
||||||
</Tr>
|
|
||||||
</Thead>
|
|
||||||
<Tbody>
|
|
||||||
{selectedGroups.map((group, index) => (
|
|
||||||
<Tr key={group.id}>
|
|
||||||
<Td>{group.path}</Td>
|
|
||||||
<Td>
|
|
||||||
<Controller
|
|
||||||
name={`groups[${index}].extendChildren`}
|
|
||||||
defaultValue={false}
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Checkbox
|
|
||||||
id="extendChildren"
|
|
||||||
data-testid="standard"
|
|
||||||
name="extendChildren"
|
|
||||||
isChecked={value}
|
|
||||||
onChange={onChange}
|
|
||||||
isDisabled={group.subGroups?.length === 0}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Td>
|
|
||||||
<Td>
|
|
||||||
<Button
|
|
||||||
variant="link"
|
|
||||||
className="keycloak__client-authorization__policy-row-remove"
|
|
||||||
icon={<MinusCircleIcon />}
|
|
||||||
onClick={() => {
|
|
||||||
setValue("groups", [
|
|
||||||
...(values || []).filter((s) => s.id !== group.id),
|
|
||||||
]);
|
|
||||||
setSelectedGroups([
|
|
||||||
...selectedGroups.filter((s) => s.id !== group.id),
|
|
||||||
]);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
</Tr>
|
||||||
))}
|
</Thead>
|
||||||
</Tbody>
|
<Tbody>
|
||||||
</TableComposable>
|
{selectedGroups.map((group, index) => (
|
||||||
)}
|
<Tr key={group.id}>
|
||||||
</FormGroup>
|
<Td>{group.path}</Td>
|
||||||
|
<Td>
|
||||||
|
<Controller
|
||||||
|
name={`groups[${index}].extendChildren`}
|
||||||
|
defaultValue={false}
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Checkbox
|
||||||
|
id="extendChildren"
|
||||||
|
data-testid="standard"
|
||||||
|
name="extendChildren"
|
||||||
|
isChecked={value}
|
||||||
|
onChange={onChange}
|
||||||
|
isDisabled={group.subGroups?.length === 0}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Td>
|
||||||
|
<Td>
|
||||||
|
<Button
|
||||||
|
variant="link"
|
||||||
|
className="keycloak__client-authorization__policy-row-remove"
|
||||||
|
icon={<MinusCircleIcon />}
|
||||||
|
onClick={() => {
|
||||||
|
setValue("groups", [
|
||||||
|
...(values || []).filter(({ id }) => id !== group.id),
|
||||||
|
]);
|
||||||
|
setSelectedGroups([
|
||||||
|
...selectedGroups.filter(({ id }) => id !== group.id),
|
||||||
|
]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Td>
|
||||||
|
</Tr>
|
||||||
|
))}
|
||||||
|
</Tbody>
|
||||||
|
</TableComposable>
|
||||||
|
)}
|
||||||
|
</FormGroup>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -255,6 +255,8 @@ export default {
|
||||||
applyPolicy:
|
applyPolicy:
|
||||||
"Specifies all the policies that must be applied to the scopes defined by this policy or permission.",
|
"Specifies all the policies that must be applied to the scopes defined by this policy or permission.",
|
||||||
policyClient: "Specifies which client(s) are allowed by this policy.",
|
policyClient: "Specifies which client(s) are allowed by this policy.",
|
||||||
|
groupsClaim:
|
||||||
|
"If defined, the policy will fetch user's groups from the given claim within an access token or ID token representing the identity asking permissions. If not defined, user's groups are obtained from your realm configuration.",
|
||||||
policyGroups: "Specifies which user(s) are allowed by this policy.",
|
policyGroups: "Specifies which user(s) are allowed by this policy.",
|
||||||
targetClaim: "Specifies the target claim which the policy will fetch.",
|
targetClaim: "Specifies the target claim which the policy will fetch.",
|
||||||
regexPattern: "Specifies the regex pattern.",
|
regexPattern: "Specifies the regex pattern.",
|
||||||
|
|
|
@ -230,6 +230,7 @@ export default {
|
||||||
applyPolicy: "Apply policy",
|
applyPolicy: "Apply policy",
|
||||||
addClientScopes: "Add client scopes",
|
addClientScopes: "Add client scopes",
|
||||||
clientScope: "Client scope",
|
clientScope: "Client scope",
|
||||||
|
groupsClaim: "Groups claim",
|
||||||
addGroups: "Add groups",
|
addGroups: "Add groups",
|
||||||
groups: "Groups",
|
groups: "Groups",
|
||||||
users: "Users",
|
users: "Users",
|
||||||
|
|
Loading…
Reference in a new issue