import React, { useState } from "react"; import { AlertVariant, Button, ButtonVariant, Divider, Flex, FlexItem, PageSection, Radio, Spinner, Title, ToolbarItem, } from "@patternfly/react-core"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; import { useTranslation } from "react-i18next"; import { useAdminClient, useFetch } from "../context/auth/AdminClient"; import { prettyPrintJSON, upperCaseFormatter } from "../util"; import { CodeEditor, Language } from "@patternfly/react-code-editor"; import { Link, useHistory } from "react-router-dom"; import type ClientPolicyRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientPolicyRepresentation"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useAlerts } from "../components/alert/Alerts"; import "./RealmSettingsSection.css"; import { useRealm } from "../context/realm-context/RealmContext"; import { toNewClientPolicy } from "./routes/NewClientPolicy"; import { toEditClientPolicy } from "./routes/EditClientPolicy"; export const PoliciesTab = () => { const { t } = useTranslation("realm-settings"); const adminClient = useAdminClient(); const { addAlert, addError } = useAlerts(); const { realm } = useRealm(); const history = useHistory(); const [show, setShow] = useState(false); const [policies, setPolicies] = useState(); const [selectedPolicy, setSelectedPolicy] = useState(); const [key, setKey] = useState(0); const [code, setCode] = useState(); const [tablePolicies, setTablePolicies] = useState(); const refresh = () => setKey(key + 1); useFetch( () => adminClient.clientPolicies.listPolicies(), (policies) => { setPolicies(policies.policies), setTablePolicies(policies.policies || []), setCode(prettyPrintJSON(policies.policies)); }, [key] ); const loader = async () => policies ?? []; const ClientPolicyDetailLink = ({ name }: ClientPolicyRepresentation) => ( {name} ); const save = async () => { if (!code) { return; } try { const obj: ClientPolicyRepresentation[] = JSON.parse(code); try { await adminClient.clientPolicies.updatePolicy({ policies: obj, }); addAlert( t("realm-settings:updateClientPoliciesSuccess"), AlertVariant.success ); refresh(); } catch (error) { addError("realm-settings:updateClientPoliciesError", error); } } catch (error) { console.warn("Invalid json, ignoring value using {}"); addError("realm-settings:updateClientPoliciesError", error); } }; const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ titleKey: t("deleteClientPolicyConfirmTitle"), messageKey: t("deleteClientPolicyConfirm", { policyName: selectedPolicy?.name, }), continueButtonLabel: t("delete"), continueButtonVariant: ButtonVariant.danger, onConfirm: async () => { const updatedPolicies = policies?.filter( (policy) => policy.name !== selectedPolicy?.name ); try { await adminClient.clientPolicies.updatePolicy({ policies: updatedPolicies, }); addAlert(t("deleteClientPolicySuccess"), AlertVariant.success); refresh(); } catch (error) { addError(t("deleteClientPolicyError"), error); } }, }); if (!policies) { return (
); } return ( <> {t("policiesConfigType")} setShow(false)} label={t("policiesConfigTypes.formView")} id="formView-policiesView" data-testid="formView-policiesView" className="kc-form-radio-btn pf-u-mr-sm pf-u-ml-sm" /> setShow(true)} label={t("policiesConfigTypes.jsonEditor")} id="jsonEditor-policiesView" data-testid="jsonEditor-policiesView" className="kc-editor-radio-btn" /> {!show ? ( history.push(toNewClientPolicy({ realm }))} /> } ariaLabelKey="realm-settings:clientPolicies" searchPlaceholderKey="realm-settings:clientPolicySearch" loader={loader} toolbarItem={ } actions={[ { title: t("common:delete"), onRowClick: (item) => { toggleDeleteDialog(); setSelectedPolicy(item); }, }, ]} columns={[ { name: "name", cellRenderer: ClientPolicyDetailLink, }, { name: "enabled", cellFormatters: [upperCaseFormatter()], }, { name: "description", }, ]} /> ) : ( <>
{ setCode(value ?? ""); }} />
)} ); };