import React, { useState } from "react"; import { Link, useHistory } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { Alert, AlertVariant, Button, PageSection, ToolbarItem, } from "@patternfly/react-core"; import { ExpandableRowContent, TableComposable, Tbody, Td, Th, Thead, Tr, } from "@patternfly/react-table"; import type ResourceServerRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceServerRepresentation"; import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { PaginatingTableToolbar } from "../../components/table-toolbar/PaginatingTableToolbar"; import { useAdminClient, useFetch } from "../../context/auth/AdminClient"; import { useAlerts } from "../../components/alert/Alerts"; import { DetailCell } from "./DetailCell"; import { toCreateResource } from "../routes/NewResource"; import { useRealm } from "../../context/realm-context/RealmContext"; import { toResourceDetails } from "../routes/Resource"; import { MoreLabel } from "./MoreLabel"; import { toNewPermission } from "../routes/NewPermission"; type ResourcesProps = { clientId: string; }; type ExpandableResourceRepresentation = ResourceRepresentation & { isExpanded: boolean; }; export const AuthorizationResources = ({ clientId }: ResourcesProps) => { const { t } = useTranslation("clients"); const history = useHistory(); const adminClient = useAdminClient(); const { addAlert, addError } = useAlerts(); const { realm } = useRealm(); const [resources, setResources] = useState(); const [selectedResource, setSelectedResource] = useState(); const [permissions, setPermission] = useState(); const [key, setKey] = useState(0); const refresh = () => setKey(key + 1); const [max, setMax] = useState(10); const [first, setFirst] = useState(0); useFetch( () => { const params = { first, max, deep: false, }; return adminClient.clients.listResources({ ...params, id: clientId, }); }, (resources) => setResources( resources.map((resource) => ({ ...resource, isExpanded: false })) ), [key] ); const UriRenderer = ({ row }: { row: ResourceRepresentation }) => ( <> {row.uris?.[0]} ); const fetchPermissions = async (id: string) => { return adminClient.clients.listPermissionsByResource({ id: clientId, resourceId: id, }); }; const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ titleKey: "clients:deleteResource", children: ( <> {t("deleteResourceConfirm")} {permissions?.length && (

{permissions.map((permission) => ( {permission.name} ))}

)} ), continueButtonLabel: "clients:confirm", onConfirm: async () => { try { await adminClient.clients.delResource({ id: clientId, resourceId: selectedResource?._id!, }); addAlert(t("resourceDeletedSuccess"), AlertVariant.success); refresh(); } catch (error) { addError("clients:resourceDeletedError", error); } }, }); if (!resources) { return ; } return ( { setFirst(first); setMax(max); }} toolbarItem={ } > {t("common:name")} {t("common:type")} {t("owner")} {t("uris")} {resources.map((resource, rowIndex) => ( { const rows = resources.map((resource, index) => index === rowIndex ? { ...resource, isExpanded: !resource.isExpanded } : resource ); setResources(rows); }, }} /> {resource.name} {resource.type} {resource.owner?.name} { setSelectedResource(resource); setPermission(await fetchPermissions(resource._id!)); toggleDeleteDialog(); }, }, { title: t("createPermission"), className: "pf-m-link", isOutsideDropdown: true, onClick: () => history.push( toNewPermission({ realm, id: clientId, permissionType: "resource", }) ), }, ], }} /> {resource.isExpanded && ( )} ))} ); };