Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

18 changes: 10 additions & 8 deletions openbas-api/src/main/java/io/openbas/rest/group/GroupApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,16 @@ public Group updateGroupRoles(
.findById(groupId)
.orElseThrow(() -> new ElementNotFoundException("Group not found with id: " + groupId));

input.getRoleIds().stream()
.map(
id ->
roleService
.findById(id)
.orElseThrow(
() -> new ElementNotFoundException("Role not found with id: " + id)))
.forEach(group.getRoles()::add);
group.setRoles(
input.getRoleIds().stream()
.map(
id ->
roleService
.findById(id)
.orElseThrow(
() -> new ElementNotFoundException("Role not found with id: " + id)))
.collect(toList()));

return groupRepository.save(group);
}

Expand Down
2 changes: 2 additions & 0 deletions openbas-front/src/actions/Group.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ export const updateGroupInformation = (groupId, data) => dispatch => putReferent
export const updateGroupUsers = (groupId, data) => dispatch => putReferential(schema.group, `/api/groups/${groupId}/users`, data)(dispatch);

export const deleteGroup = groupId => dispatch => delReferential(`/api/groups/${groupId}`, 'groups', groupId)(dispatch);

export const updateGroupRoles = (groupId, data) => dispatch => putReferential(schema.group, `/api/groups/${groupId}/roles`, data)(dispatch);
7 changes: 7 additions & 0 deletions openbas-front/src/actions/Schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ export const arrayOfGrants = new schema.Array(grant);
export const user = new schema.Entity('users', {}, { idAttribute: 'user_id' });
export const arrayOfUsers = new schema.Array(user);

export const role = new schema.Entity(
'roles',
{},
{ idAttribute: 'role_id' },
);
export const arrayOfRoles = new schema.Array(role);

export const exercise = new schema.Entity(
'exercises',
{},
Expand Down
33 changes: 33 additions & 0 deletions openbas-front/src/actions/roles/roles-actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { Dispatch } from 'redux';

import type { RoleCreateInput } from '../../admin/components/settings/roles/RoleForm';
import { delReferential, getReferential, postReferential, putReferential, simplePostCall } from '../../utils/Action';
import { type RoleOutput, type SearchPaginationInput } from '../../utils/api-types';
import * as schema from '../Schema';

const ROLES_URI = '/api/roles';
export const searchRoles = (paginationInput: SearchPaginationInput) => {
const data = paginationInput;
const uri = `${ROLES_URI}/search`;
return simplePostCall(uri, data);
};

export const fetchRoles = () => (dispatch: Dispatch): Promise<RoleOutput[]> => {
const uri = `${ROLES_URI}`;
return getReferential(schema.arrayOfRoles, uri)(dispatch);
};

export const deleteRole = (roleId: RoleOutput['role_id']) => (dispatch: Dispatch) => {
const uri = `${ROLES_URI}/${roleId}`;
return delReferential(uri, 'roles', roleId)(dispatch);
};

export const createRole = (data: RoleCreateInput) => (dispatch: Dispatch) => {
const uri = `${ROLES_URI}`;
return postReferential(schema.role, uri, data)(dispatch);
};

export const updateRole = (roleId: RoleOutput['role_id'], data: RoleCreateInput) => (dispatch: Dispatch) => {
const uri = `${ROLES_URI}/${roleId}`;
return putReferential(schema.role, uri, data)(dispatch);
};
1 change: 1 addition & 0 deletions openbas-front/src/actions/roles/roles-helper.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import { type Role } from '../../utils/api-types';export interface RoleResult { entities: { roles: Record<string, Role> }; result: string;}export interface RoleInput { role_name: string; role_description?: string; role_capabilities: string[];}
Expand Down
4 changes: 3 additions & 1 deletion openbas-front/src/admin/components/settings/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Groups from './groups/Groups';
import KillChainPhases from './kill_chain_phases/KillChainPhases';
import Parameters from './Parameters';
import Policies from './policies/Policies';
import Roles from './roles/Roles';
import TagRules from './tag_rules/TagRules';
import Tags from './tags/Tags';
import Users from './users/Users';
Expand All @@ -17,9 +18,10 @@ const Index = () => (
<Routes>
<Route path="" element={<Navigate to="parameters" replace={true} />} />
<Route path="parameters" element={errorWrapper(Parameters)()} />
<Route path="security" element={<Navigate to="groups" replace={true} />} />
<Route path="security" element={<Navigate to="roles" replace={true} />} />
<Route path="security/groups" element={errorWrapper(Groups)()} />
<Route path="security/users" element={errorWrapper(Users)()} />
<Route path="security/roles" element={errorWrapper(Roles)()} />
<Route path="security/policies" element={errorWrapper(Policies)()} />
<Route path="taxonomies" element={<Navigate to="tags" replace={true} />} />
<Route path="taxonomies/tags" element={errorWrapper(Tags)()} />
Expand Down
7 changes: 6 additions & 1 deletion openbas-front/src/admin/components/settings/SecurityMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { GroupsOutlined, LocalPoliceOutlined, PermIdentityOutlined } from '@mui/icons-material';
import { GroupsOutlined, LocalPoliceOutlined, PermIdentityOutlined, SecurityOutlined } from '@mui/icons-material';
import { type FunctionComponent, memo } from 'react';

import RightMenu, { type RightMenuEntry } from '../../../components/common/menu/RightMenu';

const SecurityMenuComponent: FunctionComponent = () => {
const entries: RightMenuEntry[] = [
{
path: '/admin/settings/security/roles',
icon: () => (<SecurityOutlined />),
label: 'Roles',
},
{
path: '/admin/settings/security/groups',
icon: () => (<GroupsOutlined />),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { SecurityOutlined } from '@mui/icons-material';
import { Box, Button, Checkbox, Divider } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import { type FC, useEffect, useState } from 'react';

import { fetchRoles } from '../../../../actions/roles/roles-actions';
import Drawer from '../../../../components/common/Drawer';
import { useFormatter } from '../../../../components/i18n';
import { type RoleOutput } from '../../../../utils/api-types';
import { useAppDispatch } from '../../../../utils/hooks';

interface GroupManageRolesProps {
initialState: string[];
open: boolean;
onClose: () => void;
onSubmit: (roleIds: string[]) => void;
}

const GroupManageRoles: FC<GroupManageRolesProps> = (
{
initialState,
open,
onClose,
onSubmit,
},
) => {
const { t } = useFormatter();
const theme = useTheme();
const dispatch = useAppDispatch();

const [roles, setRoles] = useState<RoleOutput[]>([]);
const [selectedRoleIds, setSelectedRoleIds] = useState<string[]>(initialState);

const handleToggleRole = (roleId: string) => {
setSelectedRoleIds(prev =>
prev.includes(roleId)
? prev.filter(id => id !== roleId)
: [...prev, roleId],
);
};

const fetchRolesToLoad = () => {
return dispatch(fetchRoles())
.then((result: { entities: { roles: Record<string, RoleOutput> } }) => {
const rolesArray = Object.values(result.entities.roles);
setRoles(rolesArray);
});
};

useEffect(() => {
if (open) {
fetchRolesToLoad();
}
}, [open]);

const handleClose = () => {
setRoles([]);
onClose();
};

const handleSubmit = () => {
onSubmit(selectedRoleIds);
handleClose();
};

return (
<Drawer
open={open}
handleClose={onClose}
title={t('Manage the roles of this group')}
>
<Box>
{roles.map(role => (
<div key={role.role_id}>
<Box display="flex" alignItems="center" gap={theme.spacing(2)} justifyContent="space-between">
<div style={{
display: 'flex',
alignItems: 'center',
gap: theme.spacing(1),
}}
>
<SecurityOutlined />
<p>{role.role_name}</p>
</div>
<Checkbox
checked={selectedRoleIds.includes(role.role_id)}
onChange={() => handleToggleRole(role.role_id)}
/>
</Box>
<Divider />
</div>
))}

<div style={{
float: 'right',
marginTop: theme.spacing(2),
}}
>
<Button variant="contained" style={{ marginRight: theme.spacing(1) }} onClick={onClose}>
{t('Cancel')}
</Button>
<Button variant="contained" color="secondary" onClick={handleSubmit}>
{t('Update')}
</Button>
</div>
</Box>
</Drawer>
);
};

export default GroupManageRoles;
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import { Component } from 'react';
import { connect } from 'react-redux';

import { addGrant, addGroupOrganization, deleteGrant, deleteGroupOrganization } from '../../../../actions/Grant';
import { deleteGroup, fetchGroup, updateGroupInformation, updateGroupUsers } from '../../../../actions/Group';
import { deleteGroup, fetchGroup, updateGroupInformation, updateGroupRoles, updateGroupUsers } from '../../../../actions/Group';
import { storeHelper } from '../../../../actions/Schema';
import Drawer from '../../../../components/common/Drawer';
import Transition from '../../../../components/common/Transition';
import inject18n from '../../../../components/i18n';
import GroupForm from './GroupForm';
import GroupManageRoles from './GroupManageRoles.js';
import GroupManageUsers from './GroupManageUsers';

const TabPanel = (props) => {
Expand Down Expand Up @@ -52,6 +53,7 @@ class GroupPopover extends Component {
keyword: '',
tags: [],
usersIds: props.groupUsersIds,
rolesIds: props.groupRolesIds,
};
}

Expand Down Expand Up @@ -119,6 +121,23 @@ class GroupPopover extends Component {
this.setState({ openGrants: false });
}

handleOpenRoles() {
this.setState({
openRoles: true,
rolesIds: this.props.groupRolesIds,
});
this.handlePopoverClose();
}

submitUpdateRoles(roleIds) {
this.props.updateGroupRoles(this.props.group.group_id, { group_roles: roleIds }).then(this.fetchAndUpdateGroup.bind(this));
this.handleCloseRoles();
}

handleCloseRoles() {
this.setState({ openRoles: false });
}

handleTabChange(_event, tabKey) {
this.setState({ tabSelect: tabKey });
}
Expand Down Expand Up @@ -239,6 +258,9 @@ class GroupPopover extends Component {
<MenuItem onClick={this.handleOpenGrants.bind(this)}>
{t('Manage grants')}
</MenuItem>
<MenuItem onClick={this.handleOpenRoles.bind(this)}>
{t('Manage roles')}
</MenuItem>
<MenuItem onClick={this.handleOpenDelete.bind(this)}>
{t('Delete')}
</MenuItem>
Expand Down Expand Up @@ -281,6 +303,12 @@ class GroupPopover extends Component {
onClose={this.handleCloseUsers.bind(this)}
onSubmit={this.submitUpdateUsers.bind(this)}
/>
<GroupManageRoles
initialState={this.state.rolesIds}
open={this.state.openRoles}
onClose={this.handleCloseRoles.bind(this)}
onSubmit={this.submitUpdateRoles.bind(this)}
/>
<Drawer
open={this.state.openGrants}
handleClose={this.handleCloseGrants.bind(this)}
Expand Down Expand Up @@ -565,6 +593,7 @@ class GroupPopover extends Component {
</div>
</>
</Drawer>

</>
);
}
Expand All @@ -575,13 +604,15 @@ GroupPopover.propTypes = {
group: PropTypes.object,
fetchGroup: PropTypes.func,
updateGroupUsers: PropTypes.func,
updateGroupRoles: PropTypes.func,
updateGroupInformation: PropTypes.func,
deleteGroup: PropTypes.func,
addGrant: PropTypes.func,
addGroupOrganization: PropTypes.func,
deleteGroupOrganization: PropTypes.func,
deleteGrant: PropTypes.func,
groupUsersIds: PropTypes.array,
groupRolesIds: PropTypes.array,
};

const select = (state) => {
Expand All @@ -599,6 +630,7 @@ export default R.compose(
fetchGroup,
updateGroupInformation,
updateGroupUsers,
updateGroupRoles,
deleteGroup,
addGrant,
deleteGrant,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ const Groups = () => {
<GroupPopover
group={group}
groupUsersIds={group.group_users}
groupRolesIds={group.group_roles}
onUpdate={result => setGroups(groups.map(g => (g.group_id !== result.group_id ? g : result)))}
onDelete={result => setGroups(groups.filter(g => (g.group_id !== result)))}
/>
Expand Down
Loading