import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation"; import type ResourceRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation"; import type ResourceServerRepresentation from "@keycloak/keycloak-admin-client/lib/defs/resourceServerRepresentation"; import { ActionGroup, Alert, AlertVariant, Button, ButtonVariant, DropdownItem, FormGroup, PageSection, } from "@patternfly/react-core"; import { useState } from "react"; import { FormProvider, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { Link, useNavigate } from "react-router-dom"; import { HelpItem, TextControl } from "ui-shared"; import { adminClient } from "../../admin-client"; import { useAlerts } from "../../components/alert/Alerts"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { FormAccess } from "../../components/form/FormAccess"; import type { KeyValueType } from "../../components/key-value-form/key-value-convert"; import { KeyValueInput } from "../../components/key-value-form/KeyValueInput"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput"; import { ViewHeader } from "../../components/view-header/ViewHeader"; import { convertFormValuesToObject, convertToFormValues } from "../../util"; import { useFetch } from "../../utils/useFetch"; import { useParams } from "../../utils/useParams"; import { toAuthorizationTab } from "../routes/AuthenticationTab"; import { ResourceDetailsParams, toResourceDetails } from "../routes/Resource"; import { ScopePicker } from "./ScopePicker"; import { DefaultSwitchControl } from "../../components/SwitchControl"; import { useAccess } from "../../context/access/Access"; import "./resource-details.css"; type SubmittedResource = Omit< ResourceRepresentation, "attributes" | "scopes" > & { attributes: KeyValueType[]; }; export default function ResourceDetails() { const { t } = useTranslation(); const [client, setClient] = useState(); const [resource, setResource] = useState(); const [permissions, setPermission] = useState(); const { addAlert, addError } = useAlerts(); const form = useForm({ mode: "onChange", }); const { setValue, handleSubmit } = form; const { id, resourceId, realm } = useParams(); const navigate = useNavigate(); const setupForm = (resource: ResourceRepresentation = {}) => { convertToFormValues(resource, setValue); }; const { hasAccess } = useAccess(); const isDisabled = !hasAccess("manage-authorization"); useFetch( () => Promise.all([ adminClient.clients.findOne({ id }), resourceId ? adminClient.clients.getResource({ id, resourceId }) : Promise.resolve(undefined), resourceId ? adminClient.clients.listPermissionsByResource({ id, resourceId }) : Promise.resolve(undefined), ]), ([client, resource, permissions]) => { if (!client) { throw new Error(t("notFound")); } setClient(client); setPermission(permissions); setResource(resource); setupForm(resource); }, [], ); const submit = async (submitted: SubmittedResource) => { const resource = convertFormValuesToObject< SubmittedResource, ResourceRepresentation >(submitted); try { if (resourceId) { await adminClient.clients.updateResource({ id, resourceId }, resource); } else { const result = await adminClient.clients.createResource( { id }, resource, ); setResource(resource); navigate(toResourceDetails({ realm, id, resourceId: result._id! })); } addAlert( t((resourceId ? "update" : "create") + "ResourceSuccess"), AlertVariant.success, ); } catch (error) { addError("resourceSaveError", error); } }; const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ titleKey: "deleteResource", children: ( <> {t("deleteResourceConfirm")} {permissions?.length !== 0 && (

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

)} ), continueButtonLabel: "confirm", onConfirm: async () => { try { await adminClient.clients.delResource({ id, resourceId: resourceId!, }); addAlert(t("resourceDeletedSuccess"), AlertVariant.success); navigate(toAuthorizationTab({ realm, clientId: id, tab: "resources" })); } catch (error) { addError("resourceDeletedError", error); } }, }); if (!client) { return ; } return ( <> toggleDeleteDialog()} > {t("delete")} , ] : undefined } /> } > } fieldId="resourceAttribute" >
); }