mirror of
https://github.com/ansible/awx.git
synced 2026-02-14 17:50:02 -03:30
Adds filtering for system level roles
This commit is contained in:
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { TeamsAPI, UsersAPI } from '../../api';
|
||||
import { RolesAPI, TeamsAPI, UsersAPI } from '../../api';
|
||||
import AddResourceRole from '../AddRole/AddResourceRole';
|
||||
import AlertModal from '../AlertModal';
|
||||
import DataListToolbar from '../DataListToolbar';
|
||||
@@ -26,7 +26,13 @@ function ResourceAccessList({ i18n, apiModel, resource }) {
|
||||
const location = useLocation();
|
||||
|
||||
const {
|
||||
result: { accessRecords, itemCount, relatedSearchableKeys, searchableKeys },
|
||||
result: {
|
||||
accessRecords,
|
||||
itemCount,
|
||||
relatedSearchableKeys,
|
||||
searchableKeys,
|
||||
organizationRoles,
|
||||
},
|
||||
error: contentError,
|
||||
isLoading,
|
||||
request: fetchAccessRecords,
|
||||
@@ -37,6 +43,41 @@ function ResourceAccessList({ i18n, apiModel, resource }) {
|
||||
apiModel.readAccessList(resource.id, params),
|
||||
apiModel.readAccessOptions(resource.id),
|
||||
]);
|
||||
|
||||
// Eventually this could be expanded to other access lists.
|
||||
// We will need to combine the role ids of all the different level
|
||||
// of resource level roles.
|
||||
|
||||
let orgRoles;
|
||||
if (location.pathname.includes('/organizations')) {
|
||||
const {
|
||||
data: { results: roles },
|
||||
} = await RolesAPI.read({ content_type__isnull: true });
|
||||
const sysAdmin = roles.filter(
|
||||
role => role.name === 'System Administrator'
|
||||
);
|
||||
const sysAud = roles.filter(role => {
|
||||
let auditor;
|
||||
if (role.name === 'System Auditor') {
|
||||
auditor = role.id;
|
||||
}
|
||||
return auditor;
|
||||
});
|
||||
|
||||
orgRoles = Object.values(resource.summary_fields.object_roles).map(
|
||||
opt => {
|
||||
let item;
|
||||
if (opt.name === 'Admin') {
|
||||
item = [`${opt.id}, ${sysAdmin[0].id}`, opt.name];
|
||||
} else if (sysAud[0].id && opt.name === 'Auditor') {
|
||||
item = [`${sysAud[0].id}, ${opt.id}`, opt.name];
|
||||
} else {
|
||||
item = [`${opt.id}`, opt.name];
|
||||
}
|
||||
return item;
|
||||
}
|
||||
);
|
||||
}
|
||||
return {
|
||||
accessRecords: response.data.results,
|
||||
itemCount: response.data.count,
|
||||
@@ -46,8 +87,9 @@ function ResourceAccessList({ i18n, apiModel, resource }) {
|
||||
searchableKeys: Object.keys(
|
||||
actionsResponse.data.actions?.GET || {}
|
||||
).filter(key => actionsResponse.data.actions?.GET[key].filterable),
|
||||
organizationRoles: orgRoles,
|
||||
};
|
||||
}, [apiModel, location, resource.id]),
|
||||
}, [apiModel, location, resource]),
|
||||
{
|
||||
accessRecords: [],
|
||||
itemCount: 0,
|
||||
@@ -94,17 +136,14 @@ function ResourceAccessList({ i18n, apiModel, resource }) {
|
||||
},
|
||||
];
|
||||
|
||||
if (location.pathname.includes('/organizations')) {
|
||||
const roles = Object.values(
|
||||
resource.summary_fields.object_roles
|
||||
).map(opt => [opt.id.toString(), opt.name]);
|
||||
|
||||
if (organizationRoles?.length > 0) {
|
||||
toolbarSearchColumns.push({
|
||||
name: i18n._(t`Roles`),
|
||||
key: `or__roles__in`,
|
||||
options: roles,
|
||||
options: organizationRoles,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PaginatedDataList
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
waitForElement,
|
||||
} from '../../../testUtils/enzymeHelpers';
|
||||
|
||||
import { OrganizationsAPI, TeamsAPI, UsersAPI } from '../../api';
|
||||
import { OrganizationsAPI, TeamsAPI, UsersAPI, RolesAPI } from '../../api';
|
||||
|
||||
import ResourceAccessList from './ResourceAccessList';
|
||||
|
||||
@@ -105,6 +105,14 @@ describe('<ResourceAccessList />', () => {
|
||||
});
|
||||
TeamsAPI.disassociateRole.mockResolvedValue({});
|
||||
UsersAPI.disassociateRole.mockResolvedValue({});
|
||||
RolesAPI.read.mockResolvedValue({
|
||||
data: {
|
||||
results: [
|
||||
{ id: 1, name: 'System Administrator' },
|
||||
{ id: 14, name: 'System Auditor' },
|
||||
],
|
||||
},
|
||||
});
|
||||
const history = createMemoryHistory({
|
||||
initialEntries: ['/organizations/1/access'],
|
||||
});
|
||||
@@ -203,7 +211,7 @@ describe('<ResourceAccessList />', () => {
|
||||
key: 'or__roles__in',
|
||||
name: 'Roles',
|
||||
options: [
|
||||
['2', 'Admin'],
|
||||
['2, 1', 'Admin'],
|
||||
['3', 'Execute'],
|
||||
['4', 'Project Admin'],
|
||||
],
|
||||
|
||||
@@ -56,6 +56,8 @@ function ResourceAccessListItem({ accessRecord, onRoleDelete, i18n }) {
|
||||
onRoleDelete(role, accessRecord);
|
||||
}}
|
||||
isReadOnly={!role.user_capabilities.unattach}
|
||||
ouiaId={`${role.name}-${role.id}`}
|
||||
closeBtnAriaLabel={i18n._(t`Remove ${role.name} chip`)}
|
||||
>
|
||||
{role.name}
|
||||
</Chip>
|
||||
|
||||
@@ -98,11 +98,12 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
>
|
||||
<Chip
|
||||
className=""
|
||||
closeBtnAriaLabel="close"
|
||||
closeBtnAriaLabel="Remove Member chip"
|
||||
component="div"
|
||||
isOverflowChip={false}
|
||||
isReadOnly={false}
|
||||
onClick={[Function]}
|
||||
ouiaId="Member-3"
|
||||
tooltipPosition="top"
|
||||
>
|
||||
Member
|
||||
@@ -164,11 +165,12 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
>
|
||||
<Chip
|
||||
className=""
|
||||
closeBtnAriaLabel="close"
|
||||
closeBtnAriaLabel="Remove Member chip"
|
||||
component="div"
|
||||
isOverflowChip={false}
|
||||
isReadOnly={false}
|
||||
onClick={[Function]}
|
||||
ouiaId="Member-3"
|
||||
tooltipPosition="top"
|
||||
>
|
||||
Member
|
||||
@@ -253,11 +255,12 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
>
|
||||
<Chip
|
||||
className=""
|
||||
closeBtnAriaLabel="close"
|
||||
closeBtnAriaLabel="Remove Member chip"
|
||||
component="div"
|
||||
isOverflowChip={false}
|
||||
isReadOnly={false}
|
||||
onClick={[Function]}
|
||||
ouiaId="Member-3"
|
||||
tooltipPosition="top"
|
||||
>
|
||||
Member
|
||||
@@ -688,11 +691,12 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
>
|
||||
<Chip
|
||||
className=""
|
||||
closeBtnAriaLabel="close"
|
||||
closeBtnAriaLabel="Remove Member chip"
|
||||
component="div"
|
||||
isOverflowChip={false}
|
||||
isReadOnly={false}
|
||||
onClick={[Function]}
|
||||
ouiaId="Member-3"
|
||||
tooltipPosition="top"
|
||||
>
|
||||
Member
|
||||
@@ -865,12 +869,13 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
>
|
||||
<Chip
|
||||
className=""
|
||||
closeBtnAriaLabel="close"
|
||||
closeBtnAriaLabel="Remove Member chip"
|
||||
component="div"
|
||||
isOverflowChip={false}
|
||||
isReadOnly={false}
|
||||
key=".$3"
|
||||
onClick={[Function]}
|
||||
ouiaId="Member-3"
|
||||
tooltipPosition="top"
|
||||
>
|
||||
<GenerateId
|
||||
@@ -878,7 +883,7 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
>
|
||||
<div
|
||||
className="pf-c-chip"
|
||||
data-ouia-component-id="OUIA-Generated-Chip-1"
|
||||
data-ouia-component-id="Member-3"
|
||||
data-ouia-component-type="PF4/Chip"
|
||||
data-ouia-safe={true}
|
||||
>
|
||||
@@ -889,19 +894,19 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
Member
|
||||
</span>
|
||||
<Button
|
||||
aria-label="close"
|
||||
aria-label="Remove Member chip"
|
||||
aria-labelledby="remove_pf-random-id-1 pf-random-id-1"
|
||||
id="remove_pf-random-id-1"
|
||||
onClick={[Function]}
|
||||
ouiaId="close"
|
||||
ouiaId="Member-3"
|
||||
variant="plain"
|
||||
>
|
||||
<button
|
||||
aria-disabled={false}
|
||||
aria-label="close"
|
||||
aria-label="Remove Member chip"
|
||||
aria-labelledby="remove_pf-random-id-1 pf-random-id-1"
|
||||
className="pf-c-button pf-m-plain"
|
||||
data-ouia-component-id="close"
|
||||
data-ouia-component-id="Member-3"
|
||||
data-ouia-component-type="PF4/Button"
|
||||
data-ouia-safe={true}
|
||||
disabled={false}
|
||||
|
||||
Reference in New Issue
Block a user