@keycloakify/keycloak-admin-ui
Version:
Repackaged Keycloak Admin UI
153 lines • 11.7 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, ButtonVariant, DescriptionList, Divider, Dropdown, DropdownItem, DropdownList, MenuToggle, 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 useToggle from "../../utils/useToggle";
import { toNewPermission } from "../../clients/routes/NewPermission";
import { toPermissionDetails } from "../../clients/routes/PermissionDetails";
import { toPolicyDetails } from "../../clients/routes/PolicyDetails";
import { DetailDescriptionLink } from "../../clients/authorization/DetailDescription";
import { EmptyPermissionsState } from "../../clients/authorization/EmptyPermissionsState";
import { MoreLabel } from "../../clients/authorization/MoreLabel";
import { SearchDropdown } from "../../clients/authorization/SearchDropdown";
import "./permissions.css";
const AssociatedPoliciesRenderer = ({ row, }) => {
var _a, _b;
return (_jsxs(_Fragment, { children: [((_b = (_a = row.associatedPolicies) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.name) || "—", " ", _jsx(MoreLabel, { array: row.associatedPolicies })] }));
};
export const AuthorizationPermissions = ({ clientId, isDisabled = false, }) => {
const { adminClient } = useAdminClient();
const { t } = useTranslation();
const navigate = useNavigate();
const { addAlert, addError } = useAlerts();
const { realm } = useRealm();
const [permissions, setPermissions] = useState();
const [selectedPermission, setSelectedPermission] = useState();
const [policyProviders, setPolicyProviders] = useState();
const [disabledCreate, setDisabledCreate] = useState();
const [createOpen, toggleCreate] = useToggle();
const [search, setSearch] = useState({});
const [key, setKey] = useState(0);
const refresh = () => setKey(key + 1);
const [max, setMax] = useState(10);
const [first, setFirst] = useState(0);
useFetch(async () => {
const permissions = await adminClient.clients.findPermissions({
first,
max: max + 1,
id: clientId,
...search,
});
return await Promise.all(permissions.map(async (permission) => {
const associatedPolicies = await adminClient.clients.getAssociatedPolicies({
id: clientId,
permissionId: permission.id,
});
return {
...permission,
associatedPolicies,
isExpanded: false,
};
}));
}, setPermissions, [key, search, first, max]);
useFetch(async () => {
const params = {
first: 0,
max: 1,
};
const [policies, resources, scopes] = await Promise.all([
adminClient.clients.listPolicyProviders({
id: clientId,
}),
adminClient.clients.listResources({ ...params, id: clientId }),
adminClient.clients.listAllScopes({ ...params, id: clientId }),
]);
return {
policies: policies.filter((p) => p.type === "resource" || p.type === "scope"),
resources: resources.length !== 1,
scopes: scopes.length !== 1,
};
}, ({ policies, resources, scopes }) => {
setPolicyProviders(policies);
setDisabledCreate({ resources, scopes });
}, []);
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
titleKey: "deletePermission",
messageKey: t("deletePermissionConfirm", {
permission: selectedPermission === null || selectedPermission === void 0 ? void 0 : selectedPermission.name,
}),
continueButtonVariant: ButtonVariant.danger,
continueButtonLabel: "confirm",
onConfirm: async () => {
try {
await adminClient.clients.delPermission({
id: clientId,
type: selectedPermission === null || selectedPermission === void 0 ? void 0 : selectedPermission.type,
permissionId: selectedPermission === null || selectedPermission === void 0 ? void 0 : selectedPermission.id,
});
addAlert(t("permissionDeletedSuccess"), AlertVariant.success);
refresh();
}
catch (error) {
addError("permissionDeletedError", error);
}
},
});
if (!permissions) {
return _jsx(KeycloakSpinner, {});
}
const noData = permissions.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) && (_jsx(PaginatingTableToolbar, { count: permissions.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: "permission" }) }), _jsx(ToolbarItem, { children: _jsx(Dropdown, { onOpenChange: toggleCreate, toggle: (ref) => (_jsx(MenuToggle, { ref: ref, onClick: toggleCreate, isDisabled: isDisabled, variant: "primary", "data-testid": "permissionCreateDropdown", children: t("createPermission") })), isOpen: createOpen, children: _jsxs(DropdownList, { children: [_jsx(DropdownItem, { "data-testid": "create-resource", isDisabled: isDisabled || (disabledCreate === null || disabledCreate === void 0 ? void 0 : disabledCreate.resources), component: "button", onClick: () => navigate(toNewPermission({
realm,
id: clientId,
permissionType: "resource",
})), children: t("createResourceBasedPermission") }), _jsx(Divider, {}), _jsxs(DropdownItem, { "data-testid": "create-scope", isDisabled: isDisabled || (disabledCreate === null || disabledCreate === void 0 ? void 0 : disabledCreate.scopes), component: "button", onClick: () => navigate(toNewPermission({
realm,
id: clientId,
permissionType: "scope",
})), children: [t("createScopeBasedPermission"), (disabledCreate === null || disabledCreate === void 0 ? void 0 : disabledCreate.scopes) && (_jsx(Alert, { className: "pf-v5-u-mt-sm", variant: "warning", isInline: true, isPlain: true, title: t("noScopeCreateHint") }))] })] }) }) })] }), 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("associatedPolicy") }), _jsx(Th, { children: t("description") }), _jsx(Th, { "aria-hidden": "true" })] }) }), permissions.map((permission, rowIndex) => {
var _a;
return (_jsxs(Tbody, { isExpanded: permission.isExpanded, children: [_jsxs(Tr, { children: [_jsx(Td, { expand: {
rowIndex,
isExpanded: permission.isExpanded,
onToggle: (_, rowIndex) => {
const rows = permissions.map((p, index) => index === rowIndex
? { ...p, isExpanded: !p.isExpanded }
: p);
setPermissions(rows);
},
} }), _jsx(Td, { "data-testid": `name-column-${permission.name}`, children: _jsx(Link, { to: toPermissionDetails({
realm,
id: clientId,
permissionType: permission.type,
permissionId: permission.id,
}), children: permission.name }) }), _jsx(Td, { children: (_a = policyProviders === null || policyProviders === void 0 ? void 0 : policyProviders.find((p) => p.type === permission.type)) === null || _a === void 0 ? void 0 : _a.name }), _jsx(Td, { children: _jsx(AssociatedPoliciesRenderer, { row: permission }) }), _jsx(Td, { children: permission.description || "—" }), _jsx(Td, { actions: {
items: [
{
title: t("delete"),
onClick: async () => {
setSelectedPermission(permission);
toggleDeleteDialog();
},
},
],
} })] }), _jsxs(Tr, { isExpanded: permission.isExpanded, children: [_jsx(Td, {}), _jsx(Td, { colSpan: 5, children: _jsx(ExpandableRowContent, { children: permission.isExpanded && (_jsx(DescriptionList, { isHorizontal: true, className: "keycloak_resource_details", children: _jsx(DetailDescriptionLink, { name: "associatedPolicy", array: permission.associatedPolicies, convert: (p) => p.name, link: (p) => toPolicyDetails({
id: clientId,
realm,
policyId: p.id,
policyType: p.type,
}) }) })) }) })] }, `child-${permission.id}`)] }, permission.id));
})] })) })), noData && !searching && (_jsx(EmptyPermissionsState, { clientId: clientId, isResourceEnabled: !isDisabled && (disabledCreate === null || disabledCreate === void 0 ? void 0 : disabledCreate.resources), isScopeEnabled: !isDisabled && (disabledCreate === null || disabledCreate === void 0 ? void 0 : disabledCreate.scopes) })), noData && searching && (_jsx(ListEmptyState, { isSearchVariant: true, message: t("noSearchResults"), instructions: t("noSearchResultsInstructions") }))] }));
};
//# sourceMappingURL=Permissions.js.map