Change the way clients are stored in the form (#2184)

This commit is contained in:
Erik Jan de Wit 2022-03-07 15:28:42 +01:00 committed by GitHub
parent 2cb4fcc29d
commit 7d2abf0a9b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 83 deletions

View file

@ -59,8 +59,6 @@ import { AuthorizationScopes } from "./authorization/Scopes";
import { AuthorizationPolicies } from "./authorization/Policies"; import { AuthorizationPolicies } from "./authorization/Policies";
import { AuthorizationPermissions } from "./authorization/Permissions"; import { AuthorizationPermissions } from "./authorization/Permissions";
import { AuthorizationEvaluate } from "./authorization/AuthorizationEvaluate"; import { AuthorizationEvaluate } from "./authorization/AuthorizationEvaluate";
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
import { import {
routableTab, routableTab,
RoutableTabs, RoutableTabs,
@ -205,24 +203,6 @@ export default function ClientDetails() {
}); });
const [client, setClient] = useState<ClientRepresentation>(); const [client, setClient] = useState<ClientRepresentation>();
const [clients, setClients] = useState<ClientRepresentation[]>([]);
const [clientRoles, setClientRoles] = useState<RoleRepresentation[]>([]);
const [users, setUsers] = useState<UserRepresentation[]>([]);
useFetch(
() =>
Promise.all([
adminClient.clients.find(),
adminClient.roles.find(),
adminClient.users.find(),
]),
([clients, roles, users]) => {
setClients(clients);
setClientRoles(roles);
setUsers(users);
},
[]
);
const loader = async () => { const loader = async () => {
const roles = await adminClient.clients.listRoles({ id: clientId }); const roles = await adminClient.clients.listRoles({ id: clientId });
@ -543,13 +523,7 @@ export default function ClientDetails() {
title={<TabTitleText>{t("evaluate")}</TabTitleText>} title={<TabTitleText>{t("evaluate")}</TabTitleText>}
{...authenticationRoute("evaluate")} {...authenticationRoute("evaluate")}
> >
<AuthorizationEvaluate <AuthorizationEvaluate client={client} save={save} />
clients={clients}
clientName={client.clientId}
clientRoles={clientRoles}
users={users}
save={save}
/>
</Tab> </Tab>
<Tab <Tab
id="export" id="export"

View file

@ -32,7 +32,6 @@ import { AttributeInput } from "../../components/attribute-input/AttributeInput"
import { defaultContextAttributes } from "../utils"; import { defaultContextAttributes } from "../utils";
import type EvaluationResultRepresentation from "@keycloak/keycloak-admin-client/lib/defs/evaluationResultRepresentation"; import type EvaluationResultRepresentation from "@keycloak/keycloak-admin-client/lib/defs/evaluationResultRepresentation";
import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation"; import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation";
import { useParams } from "react-router-dom";
import type ScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/scopeRepresentation"; import type ScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/scopeRepresentation";
import type { KeyValueType } from "../../components/attribute-form/attribute-convert"; import type { KeyValueType } from "../../components/attribute-form/attribute-convert";
import { TableComposable, Th, Thead, Tr } from "@patternfly/react-table"; import { TableComposable, Th, Thead, Tr } from "@patternfly/react-table";
@ -43,13 +42,14 @@ import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState
interface EvaluateFormInputs interface EvaluateFormInputs
extends Omit<ResourceEvaluation, "context" | "resources"> { extends Omit<ResourceEvaluation, "context" | "resources"> {
applyToResource: boolean;
alias: string; alias: string;
authScopes: string[]; authScopes: string[];
context: { context: {
attributes: Record<string, string>[]; attributes: Record<string, string>[];
}; };
resources: Record<string, string>[]; resources: Record<string, string>[];
client: ClientRepresentation;
user: UserRepresentation;
} }
export type AttributeType = { export type AttributeType = {
@ -62,11 +62,8 @@ export type AttributeType = {
}; };
type ClientSettingsProps = { type ClientSettingsProps = {
clients: ClientRepresentation[]; client: ClientRepresentation;
clientName?: string;
save: () => void; save: () => void;
users: UserRepresentation[];
clientRoles: RoleRepresentation[];
}; };
export type AttributeForm = Omit< export type AttributeForm = Omit<
@ -81,18 +78,12 @@ export type AttributeForm = Omit<
type Props = ClientSettingsProps & EvaluationResultRepresentation; type Props = ClientSettingsProps & EvaluationResultRepresentation;
export const AuthorizationEvaluate = ({ export const AuthorizationEvaluate = ({ client }: Props) => {
clients,
clientRoles,
clientName,
users,
}: Props) => {
const form = useFormContext<EvaluateFormInputs>(); const form = useFormContext<EvaluateFormInputs>();
const { control, reset, trigger } = form; const { control, reset, trigger } = form;
const { t } = useTranslation("clients"); const { t } = useTranslation("clients");
const adminClient = useAdminClient(); const adminClient = useAdminClient();
const realm = useRealm(); const realm = useRealm();
const { clientId } = useParams<{ clientId: string }>();
const [clientsDropdownOpen, setClientsDropdownOpen] = useState(false); const [clientsDropdownOpen, setClientsDropdownOpen] = useState(false);
const [scopesDropdownOpen, setScopesDropdownOpen] = useState(false); const [scopesDropdownOpen, setScopesDropdownOpen] = useState(false);
@ -103,8 +94,6 @@ export const AuthorizationEvaluate = ({
const [applyToResourceType, setApplyToResourceType] = useState(false); const [applyToResourceType, setApplyToResourceType] = useState(false);
const [resources, setResources] = useState<ResourceRepresentation[]>([]); const [resources, setResources] = useState<ResourceRepresentation[]>([]);
const [scopes, setScopes] = useState<ScopeRepresentation[]>([]); const [scopes, setScopes] = useState<ScopeRepresentation[]>([]);
const [selectedClient, setSelectedClient] = useState<ClientRepresentation>();
const [selectedUser, setSelectedUser] = useState<UserRepresentation>();
const [evaluateResults, setEvaluateResults] = useState< const [evaluateResults, setEvaluateResults] = useState<
EvaluationResultRepresentation[] EvaluationResultRepresentation[]
>([]); >([]);
@ -117,7 +106,7 @@ export const AuthorizationEvaluate = ({
const [key, setKey] = useState(0); const [key, setKey] = useState(0);
const refresh = () => { const refresh = () => {
setKey(new Date().getTime()); setKey(key + 1);
}; };
const FilterType = { const FilterType = {
@ -128,14 +117,33 @@ export const AuthorizationEvaluate = ({
const [filterType, setFilterType] = useState(FilterType.allResults); const [filterType, setFilterType] = useState(FilterType.allResults);
const [clients, setClients] = useState<ClientRepresentation[]>([]);
const [clientRoles, setClientRoles] = useState<RoleRepresentation[]>([]);
const [users, setUsers] = useState<UserRepresentation[]>([]);
useFetch(
() =>
Promise.all([
adminClient.clients.find(),
adminClient.roles.find(),
adminClient.users.find(),
]),
([clients, roles, users]) => {
setClients(clients);
setClientRoles(roles);
setUsers(users);
},
[]
);
useFetch( useFetch(
async () => async () =>
Promise.all([ Promise.all([
adminClient.clients.listResources({ adminClient.clients.listResources({
id: clientId, id: client.id!,
}), }),
adminClient.clients.listAllScopes({ adminClient.clients.listAllScopes({
id: clientId, id: client.id!,
}), }),
]), ]),
([resources, scopes]) => { ([resources, scopes]) => {
@ -153,8 +161,8 @@ export const AuthorizationEvaluate = ({
const keys = formValues.resources.map(({ key }) => key); const keys = formValues.resources.map(({ key }) => key);
const resEval: ResourceEvaluation = { const resEval: ResourceEvaluation = {
roleIds: formValues.roleIds ?? [], roleIds: formValues.roleIds ?? [],
clientId: selectedClient ? selectedClient.id! : clientId, clientId: formValues.client.id!,
userId: selectedUser?.id!, userId: formValues.user.id!,
resources: resources.filter((resource) => keys.includes(resource.name!)), resources: resources.filter((resource) => keys.includes(resource.name!)),
entitlements: false, entitlements: false,
context: { context: {
@ -167,7 +175,7 @@ export const AuthorizationEvaluate = ({
}; };
const evaluation = await adminClient.clients.evaluateResource( const evaluation = await adminClient.clients.evaluateResource(
{ id: clientId!, realm: realm.realm }, { id: client.id!, realm: realm.realm },
resEval resEval
); );
@ -357,29 +365,25 @@ export const AuthorizationEvaluate = ({
fieldId="client" fieldId="client"
> >
<Controller <Controller
name="clientId" name="client"
rules={{ defaultValue={client}
validate: (value) => value.length > 0,
}}
defaultValue={clientName}
control={control} control={control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Select <Select
toggleId="client" toggleId="client"
onToggle={setClientsDropdownOpen} onToggle={setClientsDropdownOpen}
onSelect={(_, value) => { onSelect={(_, value) => {
setSelectedClient(value as ClientRepresentation); onChange(value);
onChange((value as ClientRepresentation).clientId);
setClientsDropdownOpen(false); setClientsDropdownOpen(false);
}} }}
selections={selectedClient === value ? value : clientName} selections={value.clientId}
variant={SelectVariant.typeahead} variant={SelectVariant.typeahead}
aria-label={t("client")} aria-label={t("client")}
isOpen={clientsDropdownOpen} isOpen={clientsDropdownOpen}
> >
{clients.map((client) => ( {clients.map((client) => (
<SelectOption <SelectOption
selected={client === value} selected={client.id === value.id}
key={client.clientId} key={client.clientId}
value={client} value={client}
> >
@ -399,12 +403,12 @@ export const AuthorizationEvaluate = ({
fieldLabelId="clients:userSelect" fieldLabelId="clients:userSelect"
/> />
} }
fieldId="loginTheme" fieldId="user"
> >
<Controller <Controller
name="userId" name="user"
rules={{ rules={{
validate: (value) => value.length > 0, required: true,
}} }}
defaultValue="" defaultValue=""
control={control} control={control}
@ -414,18 +418,17 @@ export const AuthorizationEvaluate = ({
placeholderText={t("selectAUser")} placeholderText={t("selectAUser")}
onToggle={setUserDropdownOpen} onToggle={setUserDropdownOpen}
onSelect={(_, value) => { onSelect={(_, value) => {
setSelectedUser(value as UserRepresentation); onChange(value);
onChange((value as UserRepresentation).username);
setUserDropdownOpen(false); setUserDropdownOpen(false);
}} }}
selections={value} selections={value.username}
variant={SelectVariant.typeahead} variant={SelectVariant.typeahead}
aria-label={t("user")} aria-label={t("user")}
isOpen={userDropdownOpen} isOpen={userDropdownOpen}
> >
{users.map((user) => ( {users.map((user) => (
<SelectOption <SelectOption
selected={user.username === value} selected={user.username === value.username}
key={user.username} key={user.username}
value={user} value={user}
> >
@ -498,26 +501,16 @@ export const AuthorizationEvaluate = ({
/> />
} }
> >
<Controller
name="applyToResource"
defaultValue=""
control={control}
render={({ onChange, value }) => (
<Switch <Switch
id="applyToResource-switch" id="applyToResource-switch"
label={t("common:on")} label={t("common:on")}
labelOff={t("common:off")} labelOff={t("common:off")}
isChecked={value === "true"} isChecked={applyToResourceType}
onChange={(value) => { onChange={setApplyToResourceType}
onChange(value.toString());
setApplyToResourceType(value);
}}
/>
)}
/> />
</FormGroup> </FormGroup>
{!applyToResourceType && ( {!applyToResourceType ? (
<FormGroup <FormGroup
label={t("resourcesAndAuthScopes")} label={t("resourcesAndAuthScopes")}
id="resourcesAndAuthScopes" id="resourcesAndAuthScopes"
@ -541,8 +534,7 @@ export const AuthorizationEvaluate = ({
name="resources" name="resources"
/> />
</FormGroup> </FormGroup>
)} ) : (
{applyToResourceType && (
<> <>
<FormGroup <FormGroup
label={t("resourceType")} label={t("resourceType")}