Allow view client roles tab without view-realm access (#21142)
* Allow view client->roles tab with view-clients access. Fixes #21047 * Fix role deleted success message.
This commit is contained in:
parent
7fe7dfc529
commit
080b6a7981
4 changed files with 43 additions and 34 deletions
|
@ -23,7 +23,7 @@ export const ClientRoleRoute: AppRouteObject = {
|
|||
element: <RealmRoleTabs />,
|
||||
breadcrumb: (t) => t("roles:roleDetails"),
|
||||
handle: {
|
||||
access: "view-realm",
|
||||
access: "view-clients",
|
||||
},
|
||||
} satisfies AppRouteObject;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import { FilterIcon } from "@patternfly/react-icons";
|
|||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { useAccess } from "../../context/access/Access";
|
||||
import useLocaleSort from "../../utils/useLocaleSort";
|
||||
import { ListEmptyState } from "../list-empty-state/ListEmptyState";
|
||||
import { KeycloakDataTable } from "../table-toolbar/KeycloakDataTable";
|
||||
|
@ -40,10 +41,14 @@ export const AddRoleMappingModal = ({
|
|||
onClose,
|
||||
}: AddRoleMappingModalProps) => {
|
||||
const { t } = useTranslation(type);
|
||||
const { hasAccess } = useAccess();
|
||||
const canViewRealmRoles = hasAccess("view-realm");
|
||||
|
||||
const [searchToggle, setSearchToggle] = useState(false);
|
||||
|
||||
const [filterType, setFilterType] = useState<FilterType>("roles");
|
||||
const [filterType, setFilterType] = useState<FilterType>(
|
||||
canViewRealmRoles ? "roles" : "clients"
|
||||
);
|
||||
const [selectedRows, setSelectedRows] = useState<Row[]>([]);
|
||||
const [key, setKey] = useState(0);
|
||||
const refresh = () => setKey(key + 1);
|
||||
|
@ -137,34 +142,36 @@ export const AddRoleMappingModal = ({
|
|||
searchPlaceholderKey="clients:searchByRoleName"
|
||||
isPaginated={!(filterType === "roles" && type !== "roles")}
|
||||
searchTypeComponent={
|
||||
<ToolbarItem>
|
||||
<Dropdown
|
||||
onSelect={() => {
|
||||
setFilterType(filterType === "roles" ? "clients" : "roles");
|
||||
setSearchToggle(false);
|
||||
refresh();
|
||||
}}
|
||||
data-testid="filter-type-dropdown"
|
||||
toggle={
|
||||
<DropdownToggle
|
||||
onToggle={setSearchToggle}
|
||||
icon={<FilterIcon />}
|
||||
>
|
||||
{filterType === "roles"
|
||||
? t("common:filterByRoles")
|
||||
: t("common:filterByClients")}
|
||||
</DropdownToggle>
|
||||
}
|
||||
isOpen={searchToggle}
|
||||
dropdownItems={[
|
||||
<DropdownItem key="filter-type" data-testid={filterType}>
|
||||
{filterType === "roles"
|
||||
? t("common:filterByClients")
|
||||
: t("common:filterByRoles")}
|
||||
</DropdownItem>,
|
||||
]}
|
||||
/>
|
||||
</ToolbarItem>
|
||||
canViewRealmRoles && (
|
||||
<ToolbarItem>
|
||||
<Dropdown
|
||||
onSelect={() => {
|
||||
setFilterType(filterType === "roles" ? "clients" : "roles");
|
||||
setSearchToggle(false);
|
||||
refresh();
|
||||
}}
|
||||
data-testid="filter-type-dropdown"
|
||||
toggle={
|
||||
<DropdownToggle
|
||||
onToggle={setSearchToggle}
|
||||
icon={<FilterIcon />}
|
||||
>
|
||||
{filterType === "roles"
|
||||
? t("common:filterByRoles")
|
||||
: t("common:filterByClients")}
|
||||
</DropdownToggle>
|
||||
}
|
||||
isOpen={searchToggle}
|
||||
dropdownItems={[
|
||||
<DropdownItem key="filter-type" data-testid={filterType}>
|
||||
{filterType === "roles"
|
||||
? t("common:filterByClients")
|
||||
: t("common:filterByRoles")}
|
||||
</DropdownItem>,
|
||||
]}
|
||||
/>
|
||||
</ToolbarItem>
|
||||
)
|
||||
}
|
||||
canSelectAll
|
||||
isRadio={isRadio}
|
||||
|
|
|
@ -33,7 +33,6 @@ const RoleDetailLink = ({
|
|||
}: RoleDetailLinkProps) => {
|
||||
const { t } = useTranslation(messageBundle);
|
||||
const { realm } = useRealm();
|
||||
|
||||
return role.name !== defaultRoleName ? (
|
||||
<Link to={toDetail(role.id!)}>{role.name}</Link>
|
||||
) : (
|
||||
|
@ -107,7 +106,7 @@ export const RolesList = ({
|
|||
]);
|
||||
}
|
||||
setSelectedRole(undefined);
|
||||
addAlert(t("roleDeletedSuccess"), AlertVariant.success);
|
||||
addAlert(t("roles:roleDeletedSuccess"), AlertVariant.success);
|
||||
} catch (error) {
|
||||
addError("roles:roleDeleteError", error);
|
||||
}
|
||||
|
@ -145,7 +144,10 @@ export const RolesList = ({
|
|||
title: t("common:delete"),
|
||||
onRowClick: (role) => {
|
||||
setSelectedRole(role);
|
||||
if (role.name === realm!.defaultRole!.name) {
|
||||
if (
|
||||
realm!.defaultRole &&
|
||||
role.name === realm!.defaultRole!.name
|
||||
) {
|
||||
addAlert(
|
||||
t("defaultRoleDeleteError"),
|
||||
AlertVariant.danger
|
||||
|
|
|
@ -300,7 +300,7 @@ export default function RealmRoleTabs() {
|
|||
};
|
||||
|
||||
const isDefaultRole = (name: string | undefined) =>
|
||||
realm?.defaultRole!.name === name;
|
||||
realm?.defaultRole && realm.defaultRole!.name === name;
|
||||
|
||||
if (!realm) {
|
||||
return <KeycloakSpinner />;
|
||||
|
|
Loading…
Reference in a new issue