Enhanced associated roles (#30968)

Signed-off-by: Agnieszka Gancarczyk <agancarc@redhat.com>
Co-authored-by: Agnieszka Gancarczyk <agancarc@redhat.com>
This commit is contained in:
agagancarczyk 2024-07-01 14:38:42 +01:00 committed by GitHub
parent 0d6ecab862
commit 4924847676
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 97 deletions

View file

@ -1,6 +1,4 @@
export default class AssociatedRolesPage { export default class AssociatedRolesPage {
#actionDropdown = "action-dropdown";
#addRolesDropdownItem = "add-roles";
#addRoleToolbarButton = "assignRole"; #addRoleToolbarButton = "assignRole";
#addAssociatedRolesModalButton = "assign"; #addAssociatedRolesModalButton = "assign";
#compositeRoleBadge = "composite-role-badge"; #compositeRoleBadge = "composite-role-badge";
@ -9,11 +7,13 @@ export default class AssociatedRolesPage {
#usersPage = "users-page"; #usersPage = "users-page";
#removeRolesButton = "unAssignRole"; #removeRolesButton = "unAssignRole";
#addRoleTable = '[aria-label="Roles"] td'; #addRoleTable = '[aria-label="Roles"] td';
#associatedRolesTab = "associatedRolesTab";
#assignRole = "no-roles-in-this-realm-empty-action";
addAssociatedRealmRole(roleName: string) { addAssociatedRealmRole(roleName: string) {
cy.findByTestId(this.#actionDropdown).last().click(); cy.findByTestId(this.#associatedRolesTab).should("exist").click();
cy.findByTestId(this.#addRolesDropdownItem).click(); cy.findByTestId(this.#assignRole).click();
cy.findByTestId(this.#filterTypeDropdown).click(); cy.findByTestId(this.#filterTypeDropdown).click();

View file

@ -845,7 +845,6 @@ helpFileUpload=Upload a JSON file
addProvider_one=Add {{provider}} provider addProvider_one=Add {{provider}} provider
clientPoliciesPolicies=Client Policies Policies clientPoliciesPolicies=Client Policies Policies
editUSernameHelp=If enabled, the username is editable, otherwise it is read-only. editUSernameHelp=If enabled, the username is editable, otherwise it is read-only.
removeAllAssociatedRoles=Remove all associated roles
flowCreatedSuccess=Flow created flowCreatedSuccess=Flow created
fineGrainOpenIdConnectConfiguration=Fine grain OpenID Connect configuration fineGrainOpenIdConnectConfiguration=Fine grain OpenID Connect configuration
flow.reset\ credentials=Reset credentials flow flow.reset\ credentials=Reset credentials flow
@ -2732,7 +2731,6 @@ firstName=First name
emptySecondaryAction=Configure a new mapper emptySecondaryAction=Configure a new mapper
defaultGroupAdded_one=New group added to the default groups defaultGroupAdded_one=New group added to the default groups
unexpectedError=An unexpected error occurred\: '{{error}}' unexpectedError=An unexpected error occurred\: '{{error}}'
removeAllAssociatedRolesConfirmDialog=This action will remove the associated roles of {{name}}. Users who have permission to {{name}} will no longer have access to these roles.
noRolesInstructions=You haven't assigned any roles to this user. Assign a role to get started. noRolesInstructions=You haven't assigned any roles to this user. Assign a role to get started.
authorizationEncryptedResponseEncHelp=JWA Algorithm used for content encryption in encrypting the authorization response when the response mode is jwt. This option is needed if you want encrypted authorization response. If left empty, the authorization response is just signed, but not encrypted. authorizationEncryptedResponseEncHelp=JWA Algorithm used for content encryption in encrypting the authorization response when the response mode is jwt. This option is needed if you want encrypted authorization response. If left empty, the authorization response is just signed, but not encrypted.
permissionName=The name of this permission. permissionName=The name of this permission.

View file

@ -15,7 +15,7 @@ import {
useWatch, useWatch,
} from "react-hook-form"; } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useLocation, useMatch, useNavigate } from "react-router-dom"; import { useMatch, useNavigate } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { toClient } from "../clients/routes/Client"; import { toClient } from "../clients/routes/Client";
import { import {
@ -66,10 +66,7 @@ export default function RealmRoleTabs() {
const navigate = useNavigate(); const navigate = useNavigate();
const { id, clientId } = useParams<ClientRoleParams>(); const { id, clientId } = useParams<ClientRoleParams>();
const { pathname } = useLocation();
const { realm: realmName, realmRepresentation: realm } = useRealm(); const { realm: realmName, realmRepresentation: realm } = useRealm();
const [key, setKey] = useState(0); const [key, setKey] = useState(0);
const [attributes, setAttributes] = useState<KeyValueType[] | undefined>(); const [attributes, setAttributes] = useState<KeyValueType[] | undefined>();
@ -217,76 +214,6 @@ export default function RealmRoleTabs() {
}, },
}); });
const dropdownItems = pathname.includes("associated-roles")
? [
<DropdownItem
key="delete-all-associated"
component="button"
onClick={() => toggleDeleteAllAssociatedRolesDialog()}
>
{t("removeAllAssociatedRoles")}
</DropdownItem>,
<DropdownItem
key="delete-role"
component="button"
onClick={() => {
toggleDeleteDialog();
}}
>
{t("deleteRole")}
</DropdownItem>,
]
: [
<DropdownItem
key="toggle-modal"
data-testid="add-roles"
component="button"
onClick={() => toggleModal()}
>
{t("addAssociatedRolesText")}
</DropdownItem>,
<DropdownItem
key="delete-role"
component="button"
onClick={() => toggleDeleteDialog()}
>
{t("deleteRole")}
</DropdownItem>,
];
const [
toggleDeleteAllAssociatedRolesDialog,
DeleteAllAssociatedRolesConfirm,
] = useConfirmDialog({
titleKey: t("removeAllAssociatedRoles") + "?",
messageKey: t("removeAllAssociatedRolesConfirmDialog", {
name: roleName || t("createRole"),
}),
continueButtonLabel: "delete",
continueButtonVariant: ButtonVariant.danger,
onConfirm: async () => {
try {
const additionalRoles = await adminClient.roles.getCompositeRoles({
id,
});
await adminClient.roles.delCompositeRoles({ id }, additionalRoles);
addAlert(
t("compositeRoleOff"),
AlertVariant.success,
t("compositesRemovedAlertDescription"),
);
navigate(toTab("details"));
refresh();
} catch (error) {
addError("roleDeleteError", error);
}
},
});
const toggleModal = () => {
setOpen(!open);
};
const addComposites = async (composites: RoleRepresentation[]) => { const addComposites = async (composites: RoleRepresentation[]) => {
try { try {
await adminClient.roles.createComposite( await adminClient.roles.createComposite(
@ -311,7 +238,6 @@ export default function RealmRoleTabs() {
return ( return (
<> <>
<DeleteConfirm /> <DeleteConfirm />
<DeleteAllAssociatedRolesConfirm />
{open && ( {open && (
<AddRoleMappingModal <AddRoleMappingModal
id={id} id={id}
@ -331,7 +257,17 @@ export default function RealmRoleTabs() {
}, },
]} ]}
actionsDropdownId="roles-actions-dropdown" actionsDropdownId="roles-actions-dropdown"
dropdownItems={dropdownItems} dropdownItems={[
<DropdownItem
key="delete-role"
component="button"
onClick={() => {
toggleDeleteDialog();
}}
>
{t("deleteRole")}
</DropdownItem>,
]}
divider={false} divider={false}
/> />
<PageSection variant="light" className="pf-v5-u-p-0"> <PageSection variant="light" className="pf-v5-u-p-0">
@ -353,21 +289,19 @@ export default function RealmRoleTabs() {
editMode editMode
/> />
</Tab> </Tab>
{composites && ( <Tab
<Tab data-testid="associatedRolesTab"
data-testid="associatedRolesTab" title={<TabTitleText>{t("associatedRolesText")}</TabTitleText>}
title={<TabTitleText>{t("associatedRolesText")}</TabTitleText>} {...associatedRolesTab}
{...associatedRolesTab} >
> <RoleMapping
<RoleMapping name={roleName!}
name={roleName!} id={id}
id={id} type="roles"
type="roles" isManager
isManager save={(rows) => addComposites(rows.map((r) => r.role))}
save={(rows) => addComposites(rows.map((r) => r.role))} />
/> </Tab>
</Tab>
)}
{!isDefaultRole(roleName) && ( {!isDefaultRole(roleName) && (
<Tab <Tab
data-testid="attributesTab" data-testid="attributesTab"