@keycloakify/keycloak-admin-ui
Version:
Repackaged Keycloak Admin UI
184 lines • 10.7 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { KeycloakDataTable, useAlerts, useFetch, } from "../ui-shared";
import { CodeEditor, Language } from "@patternfly/react-code-editor";
import { AlertVariant, Button, ButtonVariant, Divider, Flex, FlexItem, PageSection, Radio, Switch, Title, ToolbarItem, } from "@patternfly/react-core";
import { omit } from "lodash-es";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../admin-client";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { KeycloakSpinner } from "../ui-shared";
import { ListEmptyState } from "../ui-shared";
import { useRealm } from "../context/realm-context/RealmContext";
import { prettyPrintJSON } from "../util";
import { translationFormatter } from "../utils/translationFormatter";
import { toAddClientPolicy } from "../realm-settings/routes/AddClientPolicy";
import { toClientPolicies } from "../realm-settings/routes/ClientPolicies";
import { toEditClientPolicy } from "../realm-settings/routes/EditClientPolicy";
import "./realm-settings-section.css";
export const PoliciesTab = () => {
const { adminClient } = useAdminClient();
const { t } = useTranslation();
const { addAlert, addError } = useAlerts();
const { realm } = useRealm();
const navigate = useNavigate();
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);
const form = useForm({ mode: "onChange" });
useFetch(() => adminClient.clientPolicies.listPolicies({
includeGlobalPolicies: true,
}), (allPolicies) => {
var _a, _b;
const globalPolicies = (_a = allPolicies.globalPolicies) === null || _a === void 0 ? void 0 : _a.map((globalPolicies) => ({
...globalPolicies,
global: true,
}));
const policies = (_b = allPolicies.policies) === null || _b === void 0 ? void 0 : _b.map((policies) => ({
...policies,
global: false,
}));
const allClientPolicies = globalPolicies === null || globalPolicies === void 0 ? void 0 : globalPolicies.concat(policies !== null && policies !== void 0 ? policies : []);
setPolicies(allClientPolicies);
setTablePolicies(allClientPolicies || []);
setCode(prettyPrintJSON(allClientPolicies));
}, [key]);
const loader = async () => policies !== null && policies !== void 0 ? policies : [];
const saveStatus = async () => {
const switchValues = form.getValues();
const updatedPolicies = policies === null || policies === void 0 ? void 0 : policies.filter((policy) => {
return !policy.global;
}).map((policy) => {
const enabled = switchValues[policy.name];
const enabledPolicy = {
...policy,
enabled,
};
delete enabledPolicy.global;
return enabledPolicy;
});
try {
await adminClient.clientPolicies.updatePolicy({
policies: updatedPolicies,
});
navigate(toClientPolicies({ realm, tab: "policies" }));
addAlert(t("updateClientPolicySuccess"), AlertVariant.success);
}
catch (error) {
addError("updateClientPolicyError", error);
}
};
const normalizePolicy = (policy) => omit(policy, "global");
const save = async () => {
if (!code) {
return;
}
try {
const obj = JSON.parse(code);
const changedPolicies = obj
.filter((policy) => !policy.global)
.map((policy) => normalizePolicy(policy));
const changedGlobalPolicies = obj
.filter((policy) => policy.global)
.map((policy) => normalizePolicy(policy));
try {
await adminClient.clientPolicies.updatePolicy({
policies: changedPolicies,
globalPolicies: changedGlobalPolicies,
});
addAlert(t("updateClientPoliciesSuccess"), AlertVariant.success);
refresh();
}
catch (error) {
addError("updateClientPoliciesError", error);
}
}
catch (error) {
console.warn("Invalid json, ignoring value using {}");
addError("invalidJsonClientPoliciesError", error);
}
};
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
titleKey: t("deleteClientPolicyConfirmTitle"),
messageKey: t("deleteClientPolicyConfirm", {
policyName: selectedPolicy === null || selectedPolicy === void 0 ? void 0 : selectedPolicy.name,
}),
continueButtonLabel: t("delete"),
continueButtonVariant: ButtonVariant.danger,
onConfirm: async () => {
const updatedPolicies = policies === null || policies === void 0 ? void 0 : policies.filter((policy) => {
return !policy.global && policy.name !== (selectedPolicy === null || selectedPolicy === void 0 ? void 0 : selectedPolicy.name);
}).map((policy) => {
const newPolicy = { ...policy };
delete newPolicy.global;
return newPolicy;
});
try {
await adminClient.clientPolicies.updatePolicy({
policies: updatedPolicies,
});
addAlert(t("deleteClientPolicySuccess"), AlertVariant.success);
refresh();
}
catch (error) {
addError("deleteClientPolicyError", error);
}
},
});
if (!policies) {
return _jsx(KeycloakSpinner, {});
}
return (_jsxs(_Fragment, { children: [_jsx(DeleteConfirm, {}), _jsx(PageSection, { children: _jsxs(Flex, { className: "kc-policies-config-section", children: [_jsx(FlexItem, { children: _jsx(Title, { headingLevel: "h1", size: "md", children: t("policiesConfigType") }) }), _jsx(FlexItem, { children: _jsx(Radio, { isChecked: !show, name: "policiesView", onChange: () => setShow(false), label: t("policiesConfigTypes.formView"), id: "formView-policiesView", "data-testid": "formView-policiesView", className: "kc-form-radio-btn pf-v5-u-mr-sm pf-v5-u-ml-sm" }) }), _jsx(FlexItem, { children: _jsx(Radio, { isChecked: show, name: "policiesView", onChange: () => setShow(true), label: t("policiesConfigTypes.jsonEditor"), id: "jsonEditor-policiesView", "data-testid": "jsonEditor-policiesView", className: "kc-editor-radio-btn" }) })] }) }), _jsx(Divider, {}), !show ? (_jsx(KeycloakDataTable, { emptyState: _jsx(ListEmptyState, { message: t("noClientPolicies"), instructions: t("noClientPoliciesInstructions"), primaryActionText: t("createClientPolicy"), onPrimaryAction: () => navigate(toAddClientPolicy({ realm })) }), ariaLabelKey: "clientPolicies", searchPlaceholderKey: "clientPolicySearch", loader: loader, toolbarItem: _jsx(ToolbarItem, { children: _jsx(Button, { id: "createPolicy", component: (props) => (_jsx(Link, { ...props, to: toAddClientPolicy({ realm }) })), "data-testid": "createPolicy", children: t("createClientPolicy") }) }), isRowDisabled: (value) => !!value.global, actions: [
{
title: t("delete"),
onRowClick: (item) => {
toggleDeleteDialog();
setSelectedPolicy(item);
},
},
], columns: [
{
name: "name",
cellRenderer: ({ name }) => (_jsx(Link, { to: toEditClientPolicy({ realm, policyName: name }), children: name })),
},
{
name: "enabled",
displayKey: "status",
cellRenderer: (clientPolicy) => (_jsx(SwitchRenderer, { clientPolicy: clientPolicy, form: form, saveStatus: saveStatus, onConfirm: () => {
form.setValue(clientPolicy.name, false);
saveStatus();
} })),
},
{
name: "description",
cellFormatters: [translationFormatter(t)],
},
] }, policies.length)) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "pf-v5-u-mt-md pf-v5-u-ml-lg", children: _jsx(CodeEditor, { isLineNumbersVisible: true, isLanguageLabelVisible: true, isReadOnly: false, code: code, language: Language.json, height: "30rem", onChange: setCode }) }), _jsxs("div", { className: "pf-v5-u-mt-md", children: [_jsx(Button, { variant: ButtonVariant.primary, className: "pf-v5-u-mr-md pf-v5-u-ml-lg", "data-testid": "jsonEditor-policies-saveBtn", onClick: save, children: t("save") }), _jsx(Button, { variant: ButtonVariant.link, "data-testid": "jsonEditor-reloadBtn", onClick: () => {
setCode(prettyPrintJSON(tablePolicies));
}, children: t("reload") })] })] }))] }));
};
const SwitchRenderer = ({ clientPolicy, form, saveStatus, onConfirm, }) => {
const { t } = useTranslation();
const [toggleDisableDialog, DisableConfirm] = useConfirmDialog({
titleKey: "disablePolicyConfirmTitle",
messageKey: "disablePolicyConfirm",
continueButtonLabel: "disable",
onConfirm,
});
return (_jsxs(_Fragment, { children: [_jsx(DisableConfirm, {}), _jsx(Controller, { name: clientPolicy.name, "data-testid": `${clientPolicy.name}-switch`, defaultValue: clientPolicy.enabled, control: form.control, render: ({ field }) => (_jsx(Switch, { label: t("enabled"), labelOff: t("disabled"), isChecked: field.value, isDisabled: clientPolicy.global, onChange: (_event, value) => {
if (!value) {
toggleDisableDialog();
}
else {
field.onChange(value);
saveStatus();
}
}, "aria-label": clientPolicy.name })) })] }));
};
//# sourceMappingURL=PoliciesTab.js.map