mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 10:00:01 -03:30
Add RBAC rules to the side-nav
Add RBAC rules to the side-nav System Admin System Auditor Org Admin Notification Admin Execution Environment Admin Normal User Those are the user profiles taken in consideration when displaying the side-nav. See: https://github.com/ansible/awx/issues/4426
This commit is contained in:
parent
04f6fe6cd2
commit
4d2c64ebb4
@ -12,7 +12,11 @@ import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { I18nProvider } from '@lingui/react';
|
||||
import { i18n } from '@lingui/core';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import { ConfigProvider, useAuthorizedPath } from './contexts/Config';
|
||||
import {
|
||||
ConfigProvider,
|
||||
useAuthorizedPath,
|
||||
useUserProfile,
|
||||
} from './contexts/Config';
|
||||
import { SessionProvider, useSession } from './contexts/Session';
|
||||
import AppContainer from './components/AppContainer';
|
||||
import Background from './components/Background';
|
||||
@ -38,6 +42,17 @@ function ErrorFallback({ error }) {
|
||||
);
|
||||
}
|
||||
|
||||
const RenderAppContainer = () => {
|
||||
const userProfile = useUserProfile();
|
||||
const navRouteConfig = getRouteConfig(userProfile);
|
||||
|
||||
return (
|
||||
<AppContainer navRouteConfig={navRouteConfig}>
|
||||
<AuthorizedRoutes routeConfig={navRouteConfig} />
|
||||
</AppContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const AuthorizedRoutes = ({ routeConfig }) => {
|
||||
const isAuthorized = useAuthorizedPath();
|
||||
const match = useRouteMatch();
|
||||
@ -150,9 +165,7 @@ function App() {
|
||||
</Route>
|
||||
<ProtectedRoute>
|
||||
<ConfigProvider>
|
||||
<AppContainer navRouteConfig={getRouteConfig()}>
|
||||
<AuthorizedRoutes routeConfig={getRouteConfig()} />
|
||||
</AppContainer>
|
||||
<RenderAppContainer />
|
||||
</ConfigProvider>
|
||||
</ProtectedRoute>
|
||||
</Switch>
|
||||
|
||||
@ -27,7 +27,7 @@ class NavExpandableGroup extends Component {
|
||||
render() {
|
||||
const { groupId, groupTitle, routes } = this.props;
|
||||
|
||||
if (routes.length === 1) {
|
||||
if (routes.length === 1 && groupId === 'settings') {
|
||||
const [{ path }] = routes;
|
||||
return (
|
||||
<NavItem itemId={groupId} isActive={this.isActivePath(path)} key={path}>
|
||||
|
||||
@ -3,7 +3,7 @@ import { useRouteMatch } from 'react-router-dom';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
import { ConfigAPI, MeAPI } from '../api';
|
||||
import { ConfigAPI, MeAPI, UsersAPI, OrganizationsAPI } from '../api';
|
||||
import useRequest, { useDismissableError } from '../util/useRequest';
|
||||
import AlertModal from '../components/AlertModal';
|
||||
import ErrorDetail from '../components/ErrorDetail';
|
||||
@ -35,9 +35,32 @@ export const ConfigProvider = ({ children }) => {
|
||||
},
|
||||
},
|
||||
] = await Promise.all([ConfigAPI.read(), MeAPI.read()]);
|
||||
return { ...data, me };
|
||||
|
||||
const [
|
||||
{
|
||||
data: { count: adminOrgCount },
|
||||
},
|
||||
{
|
||||
data: { count: notifAdminCount },
|
||||
},
|
||||
{
|
||||
data: { count: execEnvAdminCount },
|
||||
},
|
||||
] = await Promise.all([
|
||||
UsersAPI.readAdminOfOrganizations(me?.id),
|
||||
OrganizationsAPI.read({
|
||||
page_size: 1,
|
||||
role_level: 'notification_admin_role',
|
||||
}),
|
||||
OrganizationsAPI.read({
|
||||
page_size: 1,
|
||||
role_level: 'execution_environment_admin_role',
|
||||
}),
|
||||
]);
|
||||
|
||||
return { ...data, me, adminOrgCount, notifAdminCount, execEnvAdminCount };
|
||||
}, []),
|
||||
{}
|
||||
{ adminOrgCount: 0, notifAdminCount: 0, execEnvAdminCount: 0 }
|
||||
);
|
||||
|
||||
const { error, dismissError } = useDismissableError(configError);
|
||||
@ -77,6 +100,17 @@ export const ConfigProvider = ({ children }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const useUserProfile = () => {
|
||||
const config = useConfig();
|
||||
return {
|
||||
isSuperUser: !!config.me?.is_superuser,
|
||||
isSystemAuditor: !!config.me?.is_system_auditor,
|
||||
isOrgAdmin: config.adminOrgCount,
|
||||
isNotificationAdmin: config.notifAdminCount,
|
||||
isExecEnvAdmin: config.execEnvAdminCount,
|
||||
};
|
||||
};
|
||||
|
||||
export const useAuthorizedPath = () => {
|
||||
const config = useConfig();
|
||||
const subscriptionMgmtRoute = useRouteMatch({
|
||||
|
||||
@ -22,8 +22,8 @@ import Users from './screens/User';
|
||||
import WorkflowApprovals from './screens/WorkflowApproval';
|
||||
import { Jobs } from './screens/Job';
|
||||
|
||||
function getRouteConfig() {
|
||||
return [
|
||||
function getRouteConfig(userProfile = {}) {
|
||||
let routeConfig = [
|
||||
{
|
||||
groupTitle: <Trans>Views</Trans>,
|
||||
groupId: 'views_group',
|
||||
@ -155,6 +155,29 @@ function getRouteConfig() {
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const deleteRoute = name => {
|
||||
routeConfig.forEach(group => {
|
||||
group.routes = group.routes.filter(({ path }) => !path.includes(name));
|
||||
});
|
||||
routeConfig = routeConfig.filter(groups => groups.routes.length);
|
||||
};
|
||||
|
||||
const deleteRouteGroup = name => {
|
||||
routeConfig = routeConfig.filter(({ groupId }) => !groupId.includes(name));
|
||||
};
|
||||
|
||||
if (userProfile?.isSuperUser || userProfile?.isSystemAuditor)
|
||||
return routeConfig;
|
||||
deleteRouteGroup('settings');
|
||||
deleteRoute('management_jobs');
|
||||
deleteRoute('credential_types');
|
||||
if (userProfile?.isOrgAdmin) return routeConfig;
|
||||
deleteRoute('applications');
|
||||
deleteRoute('instance_groups');
|
||||
if (!userProfile?.isNotificationAdmin) deleteRoute('notification_templates');
|
||||
|
||||
return routeConfig;
|
||||
}
|
||||
|
||||
export default getRouteConfig;
|
||||
|
||||
248
awx/ui_next/src/routeConfig.test.jsx
Normal file
248
awx/ui_next/src/routeConfig.test.jsx
Normal file
@ -0,0 +1,248 @@
|
||||
import getRouteConfig from './routeConfig';
|
||||
|
||||
const userProfile = {
|
||||
isSuperUser: false,
|
||||
isSystemAuditor: false,
|
||||
isOrgAdmin: false,
|
||||
isNotificationAdmin: false,
|
||||
isExecEnvAdmin: false,
|
||||
};
|
||||
|
||||
const filterPaths = sidebar => {
|
||||
const visibleRoutes = [];
|
||||
sidebar.forEach(({ routes }) => {
|
||||
routes.forEach(route => {
|
||||
visibleRoutes.push(route.path);
|
||||
});
|
||||
});
|
||||
|
||||
return visibleRoutes;
|
||||
};
|
||||
describe('getRouteConfig', () => {
|
||||
test('routes for system admin', () => {
|
||||
const sidebar = getRouteConfig({ ...userProfile, isSuperUser: true });
|
||||
const filteredPaths = filterPaths(sidebar);
|
||||
expect(filteredPaths).toEqual([
|
||||
'/home',
|
||||
'/jobs',
|
||||
'/schedules',
|
||||
'/activity_stream',
|
||||
'/workflow_approvals',
|
||||
'/templates',
|
||||
'/credentials',
|
||||
'/projects',
|
||||
'/inventories',
|
||||
'/hosts',
|
||||
'/organizations',
|
||||
'/users',
|
||||
'/teams',
|
||||
'/credential_types',
|
||||
'/notification_templates',
|
||||
'/management_jobs',
|
||||
'/instance_groups',
|
||||
'/applications',
|
||||
'/execution_environments',
|
||||
'/settings',
|
||||
]);
|
||||
});
|
||||
|
||||
test('routes for system auditor', () => {
|
||||
const sidebar = getRouteConfig({ ...userProfile, isSystemAuditor: true });
|
||||
const filteredPaths = filterPaths(sidebar);
|
||||
expect(filteredPaths).toEqual([
|
||||
'/home',
|
||||
'/jobs',
|
||||
'/schedules',
|
||||
'/activity_stream',
|
||||
'/workflow_approvals',
|
||||
'/templates',
|
||||
'/credentials',
|
||||
'/projects',
|
||||
'/inventories',
|
||||
'/hosts',
|
||||
'/organizations',
|
||||
'/users',
|
||||
'/teams',
|
||||
'/credential_types',
|
||||
'/notification_templates',
|
||||
'/management_jobs',
|
||||
'/instance_groups',
|
||||
'/applications',
|
||||
'/execution_environments',
|
||||
'/settings',
|
||||
]);
|
||||
});
|
||||
|
||||
test('routes for org admin', () => {
|
||||
const sidebar = getRouteConfig({ ...userProfile, isOrgAdmin: true });
|
||||
const filteredPaths = filterPaths(sidebar);
|
||||
expect(filteredPaths).toEqual([
|
||||
'/home',
|
||||
'/jobs',
|
||||
'/schedules',
|
||||
'/activity_stream',
|
||||
'/workflow_approvals',
|
||||
'/templates',
|
||||
'/credentials',
|
||||
'/projects',
|
||||
'/inventories',
|
||||
'/hosts',
|
||||
'/organizations',
|
||||
'/users',
|
||||
'/teams',
|
||||
'/notification_templates',
|
||||
'/instance_groups',
|
||||
'/applications',
|
||||
'/execution_environments',
|
||||
]);
|
||||
});
|
||||
|
||||
test('routes for notifications admin', () => {
|
||||
const sidebar = getRouteConfig({
|
||||
...userProfile,
|
||||
isNotificationAdmin: true,
|
||||
});
|
||||
const filteredPaths = filterPaths(sidebar);
|
||||
expect(filteredPaths).toEqual([
|
||||
'/home',
|
||||
'/jobs',
|
||||
'/schedules',
|
||||
'/activity_stream',
|
||||
'/workflow_approvals',
|
||||
'/templates',
|
||||
'/credentials',
|
||||
'/projects',
|
||||
'/inventories',
|
||||
'/hosts',
|
||||
'/organizations',
|
||||
'/users',
|
||||
'/teams',
|
||||
'/notification_templates',
|
||||
'/execution_environments',
|
||||
]);
|
||||
});
|
||||
|
||||
test('routes for execution environments admin', () => {
|
||||
const sidebar = getRouteConfig({ ...userProfile, isExecEnvAdmin: true });
|
||||
const filteredPaths = filterPaths(sidebar);
|
||||
expect(filteredPaths).toEqual([
|
||||
'/home',
|
||||
'/jobs',
|
||||
'/schedules',
|
||||
'/activity_stream',
|
||||
'/workflow_approvals',
|
||||
'/templates',
|
||||
'/credentials',
|
||||
'/projects',
|
||||
'/inventories',
|
||||
'/hosts',
|
||||
'/organizations',
|
||||
'/users',
|
||||
'/teams',
|
||||
'/execution_environments',
|
||||
]);
|
||||
});
|
||||
|
||||
test('routes for regular users', () => {
|
||||
const sidebar = getRouteConfig(userProfile);
|
||||
const filteredPaths = filterPaths(sidebar);
|
||||
expect(filteredPaths).toEqual([
|
||||
'/home',
|
||||
'/jobs',
|
||||
'/schedules',
|
||||
'/activity_stream',
|
||||
'/workflow_approvals',
|
||||
'/templates',
|
||||
'/credentials',
|
||||
'/projects',
|
||||
'/inventories',
|
||||
'/hosts',
|
||||
'/organizations',
|
||||
'/users',
|
||||
'/teams',
|
||||
'/execution_environments',
|
||||
]);
|
||||
});
|
||||
|
||||
test('routes for execution environment admins and notification admin', () => {
|
||||
const sidebar = getRouteConfig({
|
||||
...userProfile,
|
||||
isExecEnvAdmin: true,
|
||||
isNotificationAdmin: true,
|
||||
});
|
||||
const filteredPaths = filterPaths(sidebar);
|
||||
expect(filteredPaths).toEqual([
|
||||
'/home',
|
||||
'/jobs',
|
||||
'/schedules',
|
||||
'/activity_stream',
|
||||
'/workflow_approvals',
|
||||
'/templates',
|
||||
'/credentials',
|
||||
'/projects',
|
||||
'/inventories',
|
||||
'/hosts',
|
||||
'/organizations',
|
||||
'/users',
|
||||
'/teams',
|
||||
'/notification_templates',
|
||||
'/execution_environments',
|
||||
]);
|
||||
});
|
||||
|
||||
test('routes for execution environment admins and organization admins', () => {
|
||||
const sidebar = getRouteConfig({
|
||||
...userProfile,
|
||||
isExecEnvAdmin: true,
|
||||
isOrgAdmin: true,
|
||||
});
|
||||
const filteredPaths = filterPaths(sidebar);
|
||||
expect(filteredPaths).toEqual([
|
||||
'/home',
|
||||
'/jobs',
|
||||
'/schedules',
|
||||
'/activity_stream',
|
||||
'/workflow_approvals',
|
||||
'/templates',
|
||||
'/credentials',
|
||||
'/projects',
|
||||
'/inventories',
|
||||
'/hosts',
|
||||
'/organizations',
|
||||
'/users',
|
||||
'/teams',
|
||||
'/notification_templates',
|
||||
'/instance_groups',
|
||||
'/applications',
|
||||
'/execution_environments',
|
||||
]);
|
||||
});
|
||||
|
||||
test('routes for notification admins and organization admins', () => {
|
||||
const sidebar = getRouteConfig({
|
||||
...userProfile,
|
||||
isNotificationAdmin: true,
|
||||
isOrgAdmin: true,
|
||||
});
|
||||
const filteredPaths = filterPaths(sidebar);
|
||||
expect(filteredPaths).toEqual([
|
||||
'/home',
|
||||
'/jobs',
|
||||
'/schedules',
|
||||
'/activity_stream',
|
||||
'/workflow_approvals',
|
||||
'/templates',
|
||||
'/credentials',
|
||||
'/projects',
|
||||
'/inventories',
|
||||
'/hosts',
|
||||
'/organizations',
|
||||
'/users',
|
||||
'/teams',
|
||||
'/notification_templates',
|
||||
'/instance_groups',
|
||||
'/applications',
|
||||
'/execution_environments',
|
||||
]);
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user