From fa0e162c0b431a64e6a770ee5062977b13e54131 Mon Sep 17 00:00:00 2001 From: Jenny <32821331+jenny-s51@users.noreply.github.com> Date: Thu, 17 Feb 2022 11:03:18 -0500 Subject: [PATCH] Clients(authorization -> evaluate): Adds expandable results table (#2004) --- .../authorization/AuthorizationEvaluate.tsx | 216 +++++++++++++++++- .../AuthorizationEvaluateResource.tsx | 93 ++++++++ .../AuthorizationEvaluateResourcePolicies.tsx | 114 +++++++++ src/clients/authorization/auth-evaluate.css | 23 ++ src/clients/messages.ts | 16 ++ 5 files changed, 455 insertions(+), 7 deletions(-) create mode 100644 src/clients/authorization/AuthorizationEvaluateResource.tsx create mode 100644 src/clients/authorization/AuthorizationEvaluateResourcePolicies.tsx create mode 100644 src/clients/authorization/auth-evaluate.css diff --git a/src/clients/authorization/AuthorizationEvaluate.tsx b/src/clients/authorization/AuthorizationEvaluate.tsx index fb6d8b9770..93734ca2fd 100644 --- a/src/clients/authorization/AuthorizationEvaluate.tsx +++ b/src/clients/authorization/AuthorizationEvaluate.tsx @@ -12,6 +12,11 @@ import { Switch, ExpandableSection, TextInput, + ButtonVariant, + InputGroup, + Toolbar, + ToolbarGroup, + ToolbarItem, } from "@patternfly/react-core"; import { Controller, useFormContext } from "react-hook-form"; @@ -25,10 +30,16 @@ import type ResourceEvaluation from "@keycloak/keycloak-admin-client/lib/defs/re import { useRealm } from "../../context/realm-context/RealmContext"; import { AttributeInput } from "../../components/attribute-input/AttributeInput"; import { defaultContextAttributes } from "../utils"; +import type EvaluationResultRepresentation from "@keycloak/keycloak-admin-client/lib/defs/evaluationResultRepresentation"; 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 { KeyValueType } from "../../components/attribute-form/attribute-convert"; +import { TableComposable, Th, Thead, Tr } from "@patternfly/react-table"; +import "./auth-evaluate.css"; +import { AuthorizationEvaluateResource } from "./AuthorizationEvaluateResource"; +import { SearchIcon } from "@patternfly/react-icons"; +import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState"; interface EvaluateFormInputs extends Omit { @@ -68,12 +79,14 @@ export type AttributeForm = Omit< resources?: KeyValueType[]; }; +type Props = ClientSettingsProps & EvaluationResultRepresentation; + export const AuthorizationEvaluate = ({ clients, clientRoles, clientName, users, -}: ClientSettingsProps) => { +}: Props) => { const form = useFormContext(); const { control, reset, trigger } = form; const { t } = useTranslation("clients"); @@ -92,6 +105,28 @@ export const AuthorizationEvaluate = ({ const [scopes, setScopes] = useState([]); const [selectedClient, setSelectedClient] = useState(); const [selectedUser, setSelectedUser] = useState(); + const [evaluateResults, setEvaluateResults] = useState< + EvaluationResultRepresentation[] + >([]); + const [showEvaluateResults, setShowEvaluateResults] = useState(false); + const [searchVal, setSearchVal] = useState(""); + const [filteredResources, setFilteredResources] = useState< + EvaluationResultRepresentation[] + >([]); + const [filterDropdownOpen, setFilterDropdownOpen] = useState(false); + const [key, setKey] = useState(0); + + const refresh = () => { + setKey(new Date().getTime()); + }; + + const FilterType = { + allResults: t("allResults"), + resultPermit: t("resultPermit"), + resultDeny: t("resultDeny"), + }; + + const [filterType, setFilterType] = useState(FilterType.allResults); useFetch( async () => @@ -107,7 +142,7 @@ export const AuthorizationEvaluate = ({ setResources(resources); setScopes(scopes); }, - [] + [key, filterType] ); const evaluate = async () => { @@ -131,13 +166,175 @@ export const AuthorizationEvaluate = ({ }, }; - return adminClient.clients.evaluateResource( + const evaluation = await adminClient.clients.evaluateResource( { id: clientId!, realm: realm.realm }, resEval ); + + setEvaluateResults(evaluation.results); + setShowEvaluateResults(true); + return evaluateResults; }; - return ( + const onSearch = () => { + if (searchVal !== "") { + setSearchVal(searchVal); + const filtered = evaluateResults.filter((resource) => + resource.resource?.name?.includes(searchVal) + ); + setFilteredResources(filtered); + } else { + setSearchVal(""); + setFilteredResources(evaluateResults); + } + }; + + const handleKeyDown = (e: any) => { + if (e.key === "Enter") { + onSearch(); + } + }; + + const handleInputChange = (value: string) => { + setSearchVal(value); + }; + + const noEvaluatedData = evaluateResults.length === 0; + const noFilteredData = filteredResources.length === 0; + + const options = [ + , + , + , + ]; + + return showEvaluateResults ? ( + + + + + + + + + + + + + + + {!noEvaluatedData && !noFilteredData && ( + + + + + {t("resource")} + {t("overallResults")} + {t("scopes")} + + + + {(filterType == FilterType.allResults + ? evaluateResults + : filteredResources + ).map((resource, rowIndex) => ( + + ))} + + )} + {noEvaluatedData || + (noFilteredData && ( + + ))} + + + + + + + ) : ( } helperTextInvalid={t("common:required")} - fieldId={name!} + fieldId="resourcesAndAuthScopes" > ((item) => ({ @@ -428,7 +625,7 @@ export const AuthorizationEvaluate = ({ /> } helperTextInvalid={t("common:required")} - fieldId={name!} + fieldId="contextualAttributes" > -