@keycloakify/keycloak-admin-ui
Version:
Repackaged Keycloak Admin UI
124 lines • 10.2 kB
JavaScript
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { ListEmptyState, PaginatingTableToolbar, useAlerts, useFetch, } from "../../ui-shared";
import { Alert, AlertVariant, Button, DescriptionList, PageSection, ToolbarItem, } from "@patternfly/react-core";
import { ExpandableRowContent, Table, Tbody, Td, Th, Thead, Tr, } from "@patternfly/react-table";
import { useState } from "react";
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 { useRealm } from "../../context/realm-context/RealmContext";
import { toUpperCase } from "../../util";
import useToggle from "../../utils/useToggle";
import { toCreatePolicy } from "../../clients/routes/NewPolicy";
import { toPermissionDetails } from "../../clients/routes/PermissionDetails";
import { toPolicyDetails } from "../../clients/routes/PolicyDetails";
import { DetailDescriptionLink } from "../../clients/authorization/DetailDescription";
import { MoreLabel } from "../../clients/authorization/MoreLabel";
import { NewPolicyDialog } from "../../clients/authorization/NewPolicyDialog";
import { SearchDropdown } from "../../clients/authorization/SearchDropdown";
const DependentPoliciesRenderer = ({ row, }) => {
var _a, _b;
return (_jsxs(_Fragment, { children: [(_b = (_a = row.dependentPolicies) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.name, " ", _jsx(MoreLabel, { array: row.dependentPolicies })] }));
};
export const AuthorizationPolicies = ({ clientId, isDisabled = false, }) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation();
const { addAlert, addError } = useAlerts();
const { realm } = useRealm();
const navigate = useNavigate();
const [policies, setPolicies] = useState();
const [selectedPolicy, setSelectedPolicy] = useState();
const [policyProviders, setPolicyProviders] = useState();
const [key, setKey] = useState(0);
const refresh = () => setKey(key + 1);
const [max, setMax] = useState(10);
const [first, setFirst] = useState(0);
const [search, setSearch] = useState({});
const [newDialog, toggleDialog] = useToggle();
useFetch(async () => {
const policies = await adminClient.clients.listPolicies({
first,
max: max + 1,
id: clientId,
permission: "false",
...search,
});
return await Promise.all([
adminClient.clients.listPolicyProviders({ id: clientId }),
...(policies || []).map(async (policy) => {
const dependentPolicies = await adminClient.clients.listDependentPolicies({
id: clientId,
policyId: policy.id,
});
return {
...policy,
dependentPolicies,
isExpanded: false,
};
}),
]);
}, ([providers, ...policies]) => {
setPolicyProviders(providers.filter((p) => p.type !== "resource" && p.type !== "scope"));
setPolicies(policies);
}, [key, search, first, max]);
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
titleKey: "deletePolicy",
children: (_jsxs(_Fragment, { children: [t("deletePolicyConfirm"), (selectedPolicy === null || selectedPolicy === void 0 ? void 0 : selectedPolicy.dependentPolicies) &&
selectedPolicy.dependentPolicies.length > 0 && (_jsx(Alert, { variant: "warning", isInline: true, isPlain: true, component: "p", title: t("deletePolicyWarning"), className: "pf-v5-u-pt-lg", children: _jsx("p", { className: "pf-v5-u-pt-xs", children: selectedPolicy.dependentPolicies.map((policy) => (_jsx("strong", { className: "pf-v5-u-pr-md", children: policy.name }, policy.id))) }) }))] })),
continueButtonLabel: "confirm",
onConfirm: async () => {
try {
await adminClient.clients.delPolicy({
id: clientId,
policyId: selectedPolicy === null || selectedPolicy === void 0 ? void 0 : selectedPolicy.id,
});
addAlert(t("policyDeletedSuccess"), AlertVariant.success);
refresh();
}
catch (error) {
addError("policyDeletedError", error);
}
},
});
if (!policies) {
return _jsx(KeycloakSpinner, {});
}
const noData = policies.length === 0;
const searching = Object.keys(search).length !== 0;
return (_jsxs(PageSection, { variant: "light", className: "pf-v5-u-p-0", children: [_jsx(DeleteConfirm, {}), (!noData || searching) && (_jsxs(_Fragment, { children: [newDialog && (_jsx(NewPolicyDialog, { policyProviders: policyProviders, onSelect: (p) => navigate(toCreatePolicy({ id: clientId, realm, policyType: p.type })), toggleDialog: toggleDialog })), _jsx(PaginatingTableToolbar, { count: policies.length, first: first, max: max, onNextClick: setFirst, onPreviousClick: setFirst, onPerPageSelect: (first, max) => {
setFirst(first);
setMax(max);
}, toolbarItem: _jsxs(_Fragment, { children: [_jsx(ToolbarItem, { children: _jsx(SearchDropdown, { types: policyProviders, search: search, onSearch: setSearch, type: "policy" }) }), _jsx(ToolbarItem, { children: _jsx(Button, { "data-testid": "createPolicy", onClick: toggleDialog, isDisabled: isDisabled, children: t("createPolicy") }) })] }), children: !noData && (_jsxs(Table, { "aria-label": t("resources"), variant: "compact", children: [_jsx(Thead, { children: _jsxs(Tr, { children: [_jsx(Th, { "aria-hidden": "true" }), _jsx(Th, { children: t("name") }), _jsx(Th, { children: t("type") }), _jsx(Th, { children: t("dependentPermission") }), _jsx(Th, { children: t("description") }), _jsx(Th, { "aria-hidden": "true" })] }) }), policies.map((policy, rowIndex) => (_jsxs(Tbody, { isExpanded: policy.isExpanded, children: [_jsxs(Tr, { children: [_jsx(Td, { expand: {
rowIndex,
isExpanded: policy.isExpanded,
onToggle: (_, rowIndex) => {
const rows = policies.map((policy, index) => index === rowIndex
? { ...policy, isExpanded: !policy.isExpanded }
: policy);
setPolicies(rows);
},
} }), _jsx(Td, { "data-testid": `name-column-${policy.name}`, children: _jsx(Link, { to: toPolicyDetails({
realm,
id: clientId,
policyType: policy.type,
policyId: policy.id,
}), children: policy.name }) }), _jsx(Td, { children: toUpperCase(policy.type) }), _jsx(Td, { children: _jsx(DependentPoliciesRenderer, { row: policy }) }), _jsx(Td, { children: policy.description }), !isDisabled && (_jsx(Td, { actions: {
items: [
{
title: t("delete"),
onClick: () => {
setSelectedPolicy(policy);
toggleDeleteDialog();
},
},
],
} }))] }), _jsxs(Tr, { isExpanded: policy.isExpanded, children: [_jsx(Td, {}), _jsx(Td, { colSpan: 3 + (isDisabled ? 0 : 1), children: _jsx(ExpandableRowContent, { children: policy.isExpanded && (_jsx(DescriptionList, { isHorizontal: true, className: "keycloak_resource_details", children: _jsx(DetailDescriptionLink, { name: "dependentPermission", array: policy.dependentPolicies, convert: (p) => p.name, link: (permission) => toPermissionDetails({
realm,
id: clientId,
permissionId: permission.id,
permissionType: permission.type,
}) }) })) }) })] }, `child-${policy.id}`)] }, policy.id)))] })) })] })), noData && searching && (_jsx(ListEmptyState, { isSearchVariant: true, isDisabled: isDisabled, message: t("noSearchResults"), instructions: t("noSearchResultsInstructions") })), noData && !searching && (_jsxs(_Fragment, { children: [newDialog && (_jsx(NewPolicyDialog, { policyProviders: policyProviders === null || policyProviders === void 0 ? void 0 : policyProviders.filter((p) => p.type !== "aggregate"), onSelect: (p) => navigate(toCreatePolicy({ id: clientId, realm, policyType: p.type })), toggleDialog: toggleDialog })), _jsx(ListEmptyState, { message: t("emptyPolicies"), instructions: t("emptyPoliciesInstructions"), isDisabled: isDisabled, primaryActionText: t("createPolicy"), onPrimaryAction: toggleDialog })] }))] }));
};
//# sourceMappingURL=Policies.js.map