diff --git a/cypress/integration/clients_test.spec.ts b/cypress/integration/clients_test.spec.ts index 2b2898e51e..a6a66e8286 100644 --- a/cypress/integration/clients_test.spec.ts +++ b/cypress/integration/clients_test.spec.ts @@ -837,7 +837,7 @@ describe("Clients test", () => { .checkTabExists(ClientsDetailsTab.Settings, true) .checkTabExists(ClientsDetailsTab.Roles, true) .checkTabExists(ClientsDetailsTab.Advanced, true) - .checkNumberOfTabsIsEqual(3); + .checkNumberOfTabsIsEqual(4); }); it("Hides the delete action", () => { diff --git a/src/clients/ClientDetails.tsx b/src/clients/ClientDetails.tsx index 8218df30d3..6dada13a30 100644 --- a/src/clients/ClientDetails.tsx +++ b/src/clients/ClientDetails.tsx @@ -69,6 +69,8 @@ import { import { toClientScopesTab } from "./routes/ClientScopeTab"; import { AuthorizationExport } from "./authorization/AuthorizationExport"; import { arrayToAttributes } from "../components/attribute-form/attribute-convert"; +import { useServerInfo } from "../context/server-info/ServerInfoProvider"; +import { PermissionsTab } from "./permissions/PermissionTab"; type ClientDetailHeaderProps = { onChange: (value: boolean) => void; @@ -178,6 +180,7 @@ export default function ClientDetails() { const adminClient = useAdminClient(); const { addAlert, addError } = useAlerts(); const { realm } = useRealm(); + const { profileInfo } = useServerInfo(); const history = useHistory(); @@ -555,6 +558,19 @@ export default function ClientDetails() { )} + {!profileInfo?.disabledFeatures?.includes( + "ADMIN_FINE_GRAINED_AUTHZ" + ) && + client.access?.manage && ( + {t("permissions")}} + {...route("permissions")} + > + + + )} { + const { t } = useTranslation("clients"); + const history = useHistory(); + const adminClient = useAdminClient(); + const { realm } = useRealm(); + const [realmId, setRealmId] = useState(""); + const [permission, setPermission] = useState(); + + useEffect(() => { + Promise.all([ + adminClient.clients.find({ + search: true, + clientId: realm, + }), + adminClient.clients.listFineGrainPermissions({ id: clientId }), + ]).then(([clients, permission]) => { + setRealmId(clients[0]?.id!); + setPermission(permission); + }); + }, []); + + const PermissionDetailLink = (permission: Record) => ( + + {permission.name} + + ); + + if (!permission) { + return ; + } + + return ( + + +
+ + } + > + { + const p = await adminClient.clients.updateFineGrainPermission( + { id: clientId }, + { enabled } + ); + setPermission(p); + }} + /> + +
+
+ ({ + id, + name, + }) + )} + ariaLabelKey="clients:permissions" + searchPlaceholderKey="clients:searchForPermission" + actionResolver={(rowData: IRowData) => { + const permission: Record = rowData.data; + return [ + { + title: t("common:edit"), + onClick() { + history.push( + toPermissionDetails({ + realm, + id: realmId, + permissionType: "scope", + permissionId: permission.id, + }) + ); + }, + }, + ]; + }} + columns={[ + { + name: "scopeName", + displayKey: "common:name", + cellRenderer: PermissionDetailLink, + }, + { + name: "description", + displayKey: "common:description", + cellRenderer: (permission: Record) => + t(`scopePermissions.${permission.name}-description`), + }, + ]} + /> +
+ ); +}; diff --git a/src/clients/permissions/permissions-tab.css b/src/clients/permissions/permissions-tab.css new file mode 100644 index 0000000000..b9fbacc39c --- /dev/null +++ b/src/clients/permissions/permissions-tab.css @@ -0,0 +1,4 @@ + +.permission-label > .pf-c-form__group-label { + width: 120%; +} \ No newline at end of file diff --git a/src/clients/routes/Client.ts b/src/clients/routes/Client.ts index 5c72e38fac..b877fe7c69 100644 --- a/src/clients/routes/Client.ts +++ b/src/clients/routes/Client.ts @@ -12,7 +12,8 @@ export type ClientTab = | "advanced" | "mappers" | "authorization" - | "serviceAccount"; + | "serviceAccount" + | "permissions"; export type ClientParams = { realm: string;