diff --git a/opencti-platform/opencti-front/lang/front/de.json b/opencti-platform/opencti-front/lang/front/de.json index 9c341c4f06359..0c5224ee1b994 100644 --- a/opencti-platform/opencti-front/lang/front/de.json +++ b/opencti-platform/opencti-front/lang/front/de.json @@ -2319,6 +2319,10 @@ "Sectors": "Sektoren", "Sectors and organizations": "Sektoren und Organisationen", "Security": "Sicherheit", + "Security: Groups | Settings": "Sicherheit: Gruppen | Einstellungen", + "Security: Marking Definitions | Settings": "Sicherheit: Markierungsdefinitionen | Einstellungen", + "Security: Roles | Settings": "Sicherheit: Rollen | Einstellungen", + "Security: Sessions | Settings": "Sicherheit: Sitzungen | Einstellungen", "See all entities created by user": "Alle vom Benutzer erstellten Entitäten anzeigen", "See all relationships created by user": "Alle vom Benutzer erstellten Beziehungen anzeigen", "Select": "Wählen Sie", diff --git a/opencti-platform/opencti-front/lang/front/en.json b/opencti-platform/opencti-front/lang/front/en.json index 8fb175646216a..d3beda45df696 100644 --- a/opencti-platform/opencti-front/lang/front/en.json +++ b/opencti-platform/opencti-front/lang/front/en.json @@ -2319,6 +2319,10 @@ "Sectors": "Sectors", "Sectors and organizations": "Sectors and organizations", "Security": "Security", + "Security: Groups | Settings": "Security: Groups | Settings", + "Security: Marking Definitions | Settings": "Security: Marking Definitions | Settings", + "Security: Roles | Settings": "Security: Roles | Settings", + "Security: Sessions | Settings": "Security: Sessions | Settings", "See all entities created by user": "See all entities created by user", "See all relationships created by user": "See all relationships created by user", "Select": "Select", diff --git a/opencti-platform/opencti-front/lang/front/es.json b/opencti-platform/opencti-front/lang/front/es.json index 6eb7fbc5c88e0..87f3758c3a159 100644 --- a/opencti-platform/opencti-front/lang/front/es.json +++ b/opencti-platform/opencti-front/lang/front/es.json @@ -2319,6 +2319,10 @@ "Sectors": "Sectores", "Sectors and organizations": "Sectores y organizaciones", "Security": "Seguridad", + "Security: Groups | Settings": "Seguridad: Grupos | Configuración", + "Security: Marking Definitions | Settings": "Seguridad: Definiciones de marcado | Configuración", + "Security: Roles | Settings": "Seguridad: Roles | Configuración", + "Security: Sessions | Settings": "Seguridad: Sesiones | Configuración", "See all entities created by user": "Ver todas las entidades creadas por el usuario", "See all relationships created by user": "Ver todas las relaciones creadas por el usuario", "Select": "Seleccione", diff --git a/opencti-platform/opencti-front/lang/front/fr.json b/opencti-platform/opencti-front/lang/front/fr.json index 16d1f3ad2e643..18a1f7e4f4081 100644 --- a/opencti-platform/opencti-front/lang/front/fr.json +++ b/opencti-platform/opencti-front/lang/front/fr.json @@ -2318,6 +2318,10 @@ "Sectors": "Secteurs", "Sectors and organizations": "Secteurs et organisations", "Security": "Sécurité", + "Security: Groups | Settings": "Sécurité : Groupes | Paramètres", + "Security: Marking Definitions | Settings": "Sécurité : définitions de marquage | Paramètres", + "Security: Roles | Settings": "Sécurité : Rôles | Paramètres", + "Security: Sessions | Settings": "Sécurité : Sessions | Paramètres", "See all entities created by user": "Voir toutes les entités crées par l'utilisateur", "See all relationships created by user": "Voir toutes les relations crées par l'utilisateur", "Select": "Sélectionnez", diff --git a/opencti-platform/opencti-front/lang/front/ja.json b/opencti-platform/opencti-front/lang/front/ja.json index 223c2c250c024..f01895c5ff802 100644 --- a/opencti-platform/opencti-front/lang/front/ja.json +++ b/opencti-platform/opencti-front/lang/front/ja.json @@ -2319,6 +2319,10 @@ "Sectors": "セクター", "Sectors and organizations": "セクターと組織", "Security": "安全", + "Security: Groups | Settings": "セキュリティ:グループ|設定", + "Security: Marking Definitions | Settings": "セキュリティ:マーキング定義|設定", + "Security: Roles | Settings": "セキュリティ:ロール|設定", + "Security: Sessions | Settings": "セキュリティ:セッション|設定", "See all entities created by user": "ユーザーが作成したすべてのエンティティを見る", "See all relationships created by user": "ユーザーが作成したすべての関係を見る", "Select": "選択する", @@ -3003,4 +3007,4 @@ "Zoom": "ズーム", "Zoom in": "ズームイン", "Zoom out": "ズームアウト" -} +} \ No newline at end of file diff --git a/opencti-platform/opencti-front/lang/front/ko.json b/opencti-platform/opencti-front/lang/front/ko.json index f18882de70067..cf224c24506c0 100644 --- a/opencti-platform/opencti-front/lang/front/ko.json +++ b/opencti-platform/opencti-front/lang/front/ko.json @@ -2319,6 +2319,10 @@ "Sectors": "부문", "Sectors and organizations": "부문 및 조직", "Security": "보안", + "Security: Groups | Settings": "보안: 그룹 | 설정", + "Security: Marking Definitions | Settings": "보안: 정의 표시 | 설정", + "Security: Roles | Settings": "보안: 역할 | 설정", + "Security: Sessions | Settings": "보안: 세션 | 설정", "See all entities created by user": "사용자가 만든 모든 엔터티 보기", "See all relationships created by user": "사용자가 만든 모든 관계 보기", "Select": "선택", diff --git a/opencti-platform/opencti-front/lang/front/zh.json b/opencti-platform/opencti-front/lang/front/zh.json index 329500359d47d..4337807250deb 100644 --- a/opencti-platform/opencti-front/lang/front/zh.json +++ b/opencti-platform/opencti-front/lang/front/zh.json @@ -2319,6 +2319,10 @@ "Sectors": "部门", "Sectors and organizations": "部门和组织", "Security": "安全", + "Security: Groups | Settings": "安全:组|设置", + "Security: Marking Definitions | Settings": "安全性:标记定义|设置", + "Security: Roles | Settings": "安全:角色|设置", + "Security: Sessions | Settings": "安全:会话|设置", "See all entities created by user": "查看用户创建的所有实体", "See all relationships created by user": "查看用户创建的所有关系", "Select": "选择", diff --git a/opencti-platform/opencti-front/src/private/components/settings/Groups.jsx b/opencti-platform/opencti-front/src/private/components/settings/Groups.tsx similarity index 50% rename from opencti-platform/opencti-front/src/private/components/settings/Groups.jsx rename to opencti-platform/opencti-front/src/private/components/settings/Groups.tsx index c661ec77a84e8..2d444f7000a6e 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/Groups.jsx +++ b/opencti-platform/opencti-front/src/private/components/settings/Groups.tsx @@ -1,17 +1,26 @@ -import React, { Component } from 'react'; -import * as PropTypes from 'prop-types'; -import { compose, propOr } from 'ramda'; -import withStyles from '@mui/styles/withStyles'; +import React, { useState, useEffect } from 'react'; +import makeStyles from '@mui/styles/makeStyles'; import { graphql } from 'react-relay'; -import { QueryRenderer } from '../../../relay/environment'; +import { useLocation, useNavigate } from 'react-router-dom'; import { buildViewParamsFromUrlAndStorage, saveViewParameters } from '../../../utils/ListParameters'; -import inject18n from '../../../components/i18n'; +import type { Theme } from '../../../components/Theme'; +import { useFormatter } from '../../../components/i18n'; import ListLines from '../../../components/list_lines/ListLines'; import GroupsLines, { groupsLinesQuery } from './groups/GroupsLines'; import GroupCreation from './groups/GroupCreation'; -import AccessesMenu from './AccessesMenu'; +import { OrderMode, PaginationOptions } from '../../../components/list_lines'; import Breadcrumbs from '../../../components/Breadcrumbs'; -import withRouter from '../../../utils/compat_router/withRouter'; +import useConnectedDocumentModifier from '../../../utils/hooks/useConnectedDocumentModifier'; +import { GroupsLinesPaginationQuery$data } from './groups/__generated__/GroupsLinesPaginationQuery.graphql'; +import AccessesMenu from './AccessesMenu'; +import { QueryRenderer } from '../../../relay/environment'; + +const useStyles = makeStyles(() => ({ + container: { + margin: 0, + padding: '0 200px 50px 0', + }, +})); export const groupsSearchQuery = graphql` query GroupsSearchQuery($search: String) { @@ -40,49 +49,51 @@ export const groupsSearchQuery = graphql` } `; -const styles = () => ({ - container: { - margin: 0, - padding: '0 200px 50px 0', - }, -}); - const LOCAL_STORAGE_KEY = 'groups'; -class Groups extends Component { - constructor(props) { - super(props); - const params = buildViewParamsFromUrlAndStorage( - props.navigate, - props.location, - LOCAL_STORAGE_KEY, - ); - this.state = { - sortBy: propOr('name', 'sortBy', params), - orderAsc: propOr(true, 'orderAsc', params), - searchTerm: propOr('', 'searchTerm', params), - view: propOr('lines', 'view', params), - }; - } - saveView() { +const Groups = () => { + const classes = useStyles(); + const { t_i18n } = useFormatter(); + const navigate = useNavigate(); + const location = useLocation(); + const { setTitle } = useConnectedDocumentModifier(); + setTitle(t_i18n('Security: Groups | Settings')); + const params = buildViewParamsFromUrlAndStorage( + navigate, + location, + LOCAL_STORAGE_KEY, + ); + + const [groupState, setGroupState] = useState<{ orderAsc: boolean, searchTerm: string, view: string, sortBy: string }>({ + sortBy: params.sortBy ?? 'name', + orderAsc: params.orderAsc !== false, + searchTerm: params.searchTerm ?? '', + view: params.view ?? 'lines', + }); + + function saveView() { saveViewParameters( - this.props.navigate, - this.props.location, + navigate, + location, LOCAL_STORAGE_KEY, - this.state, + groupState, ); } - handleSearch(value) { - this.setState({ searchTerm: value }, () => this.saveView()); + function handleSearch(value: string) { + setGroupState({ ...groupState, searchTerm: value }); } - handleSort(field, orderAsc) { - this.setState({ sortBy: field, orderAsc }, () => this.saveView()); + function handleSort(field: string, orderAsc: boolean) { + setGroupState({ ...groupState, sortBy: field, orderAsc }); } - renderLines(paginationOptions) { - const { sortBy, orderAsc, searchTerm } = this.state; + useEffect(() => { + saveView(); + }, [groupState]); + + function renderLines(paginationOptions: PaginationOptions) { + const { sortBy, orderAsc, searchTerm } = groupState; const dataColumns = { name: { label: 'Name', @@ -125,8 +136,8 @@ class Groups extends Component { sortBy={sortBy} orderAsc={orderAsc} dataColumns={dataColumns} - handleSort={this.handleSort.bind(this)} - handleSearch={this.handleSearch.bind(this)} + handleSort={handleSort} + handleSearch={handleSearch} displayImport={false} secondaryAction={false} keyword={searchTerm} @@ -134,7 +145,7 @@ class Groups extends Component { ( + render={({ props }: { props: GroupsLinesPaginationQuery$data }) => ( - - - {view === 'lines' ? this.renderLines(paginationOptions) : ''} - - - ); - } -} + const paginationOptions: PaginationOptions = { + search: groupState.searchTerm, + orderBy: groupState.sortBy ? groupState.sortBy : null, + orderMode: groupState.orderAsc ? OrderMode.asc : OrderMode.desc, + }; -Groups.propTypes = { - t: PropTypes.func, - classes: PropTypes.object, - navigate: PropTypes.func, - location: PropTypes.object, + return ( +
+ + + {groupState.view === 'lines' ? renderLines(paginationOptions) : ''} + +
+ ); }; -export default compose(inject18n, withRouter, withStyles(styles))(Groups); +export default Groups; diff --git a/opencti-platform/opencti-front/src/private/components/settings/MarkingDefinitions.jsx b/opencti-platform/opencti-front/src/private/components/settings/MarkingDefinitions.jsx deleted file mode 100644 index 961497e8d887a..0000000000000 --- a/opencti-platform/opencti-front/src/private/components/settings/MarkingDefinitions.jsx +++ /dev/null @@ -1,142 +0,0 @@ -import React, { Component } from 'react'; -import * as PropTypes from 'prop-types'; -import { compose, propOr } from 'ramda'; -import withStyles from '@mui/styles/withStyles'; -import { QueryRenderer } from '../../../relay/environment'; -import { buildViewParamsFromUrlAndStorage, saveViewParameters } from '../../../utils/ListParameters'; -import inject18n from '../../../components/i18n'; -import ListLines from '../../../components/list_lines/ListLines'; -import MarkingDefinitionsLines, { markingDefinitionsLinesQuery } from './marking_definitions/MarkingDefinitionsLines'; -import MarkingDefinitionCreation from './marking_definitions/MarkingDefinitionCreation'; -import AccessesMenu from './AccessesMenu'; -import withRouter from '../../../utils/compat_router/withRouter'; -import Breadcrumbs from '../../../components/Breadcrumbs'; - -const styles = () => ({ - container: { - margin: 0, - padding: '0 200px 0 0', - }, -}); - -const LOCAL_STORAGE_KEY = 'MarkingDefinitions'; -class MarkingDefinitions extends Component { - constructor(props) { - super(props); - const params = buildViewParamsFromUrlAndStorage( - props.navigate, - props.location, - LOCAL_STORAGE_KEY, - ); - this.state = { - sortBy: propOr('definition', 'sortBy', params), - orderAsc: propOr(true, 'orderAsc', params), - searchTerm: propOr('', 'searchTerm', params), - view: propOr('lines', 'view', params), - }; - } - - saveView() { - saveViewParameters( - this.props.navigate, - this.props.location, - LOCAL_STORAGE_KEY, - this.state, - ); - } - - handleSearch(value) { - this.setState({ searchTerm: value }, () => this.saveView()); - } - - handleSort(field, orderAsc) { - this.setState({ sortBy: field, orderAsc }, () => this.saveView()); - } - - renderLines(paginationOptions) { - const { sortBy, orderAsc, searchTerm } = this.state; - const dataColumns = { - definition_type: { - label: 'Type', - width: '25%', - isSortable: true, - }, - definition: { - label: 'Definition', - width: '25%', - isSortable: true, - }, - x_opencti_color: { - label: 'Color', - width: '15%', - isSortable: true, - }, - x_opencti_order: { - label: 'Order', - width: '10%', - isSortable: true, - }, - created: { - label: 'Original creation date', - width: '15%', - isSortable: true, - }, - }; - return ( - - ( - - )} - /> - - ); - } - - render() { - const { t, classes } = this.props; - const { view, sortBy, orderAsc, searchTerm } = this.state; - const paginationOptions = { - search: searchTerm, - orderBy: sortBy, - orderMode: orderAsc ? 'asc' : 'desc', - }; - return ( -
- - - {view === 'lines' ? this.renderLines(paginationOptions) : ''} - -
- ); - } -} - -MarkingDefinitions.propTypes = { - t: PropTypes.func, - classes: PropTypes.object, - navigate: PropTypes.func, - location: PropTypes.object, -}; - -export default compose( - inject18n, - withRouter, - withStyles(styles), -)(MarkingDefinitions); diff --git a/opencti-platform/opencti-front/src/private/components/settings/MarkingDefinitions.tsx b/opencti-platform/opencti-front/src/private/components/settings/MarkingDefinitions.tsx new file mode 100644 index 0000000000000..74be8fc5b2232 --- /dev/null +++ b/opencti-platform/opencti-front/src/private/components/settings/MarkingDefinitions.tsx @@ -0,0 +1,134 @@ +import React, { useEffect, useState } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; +import { useFormatter } from '../../../components/i18n'; +import { buildViewParamsFromUrlAndStorage, saveViewParameters } from '../../../utils/ListParameters'; +import ListLines from '../../../components/list_lines/ListLines'; +import MarkingDefinitionsLines, { markingDefinitionsLinesQuery } from './marking_definitions/MarkingDefinitionsLines'; +import AccessesMenu from './AccessesMenu'; +import { OrderMode, PaginationOptions } from '../../../components/list_lines'; +import MarkingDefinitionCreation from './marking_definitions/MarkingDefinitionCreation'; +import Breadcrumbs from '../../../components/Breadcrumbs'; +import { MarkingDefinitionsLinesPaginationQuery$data } from './marking_definitions/__generated__/MarkingDefinitionsLinesPaginationQuery.graphql'; +import { QueryRenderer } from '../../../relay/environment'; +import useConnectedDocumentModifier from '../../../utils/hooks/useConnectedDocumentModifier'; + +const LOCAL_STORAGE_KEY = 'MarkingDefinitions'; + +const MarkingDefinitions = () => { + const { t_i18n } = useFormatter(); + const navigate = useNavigate(); + const location = useLocation(); + const { setTitle } = useConnectedDocumentModifier(); + setTitle(t_i18n('Security: Marking Definitions | Settings')); + const params = buildViewParamsFromUrlAndStorage( + navigate, + location, + LOCAL_STORAGE_KEY, + ); + + const [markingDefinitionsState, setMarkingDefinitionsState] = useState<{ orderAsc: boolean, searchTerm: string, view: string, sortBy: string }>({ + orderAsc: params.orderAsc !== false, + searchTerm: params.searchTerm ?? '', + view: params.view ?? 'lines', + sortBy: params.sortBy ?? 'name', + }); + + function saveView() { + saveViewParameters( + navigate, + location, + LOCAL_STORAGE_KEY, + markingDefinitionsState, + ); + } + + function handleSearch(value: string) { + setMarkingDefinitionsState({ ...markingDefinitionsState, searchTerm: value }); + } + + function handleSort(field: string, orderAsc: boolean) { + setMarkingDefinitionsState({ ...markingDefinitionsState, sortBy: field, orderAsc }); + } + + useEffect(() => { + saveView(); + }, [markingDefinitionsState]); + + function renderLines(paginationOptions: PaginationOptions) { + const { sortBy, orderAsc, searchTerm } = markingDefinitionsState; + const dataColumns = { + definition_type: { + label: 'Type', + width: '25%', + isSortable: true, + }, + definition: { + label: 'Definition', + width: '25%', + isSortable: true, + }, + x_opencti_color: { + label: 'Color', + width: '15%', + isSortable: true, + }, + x_opencti_order: { + label: 'Order', + width: '10%', + isSortable: true, + }, + created: { + label: 'Original creation date', + width: '15%', + isSortable: true, + }, + }; + return ( + + ( + + )} + /> + + ); + } + + const paginationOptions: PaginationOptions = { + search: markingDefinitionsState.searchTerm, + orderBy: markingDefinitionsState.sortBy ? markingDefinitionsState.sortBy : null, + orderMode: markingDefinitionsState.orderAsc ? OrderMode.asc : OrderMode.desc, + }; + + return ( +
+ + + {markingDefinitionsState.view === 'lines' ? renderLines(paginationOptions) : ''} + +
+ ); +}; + +export default MarkingDefinitions; diff --git a/opencti-platform/opencti-front/src/private/components/settings/Roles.jsx b/opencti-platform/opencti-front/src/private/components/settings/Roles.jsx deleted file mode 100644 index 6e086fae4ddbd..0000000000000 --- a/opencti-platform/opencti-front/src/private/components/settings/Roles.jsx +++ /dev/null @@ -1,134 +0,0 @@ -import React, { Component } from 'react'; -import * as PropTypes from 'prop-types'; -import { compose, propOr } from 'ramda'; -import withStyles from '@mui/styles/withStyles'; -import { QueryRenderer } from '../../../relay/environment'; -import { buildViewParamsFromUrlAndStorage, saveViewParameters } from '../../../utils/ListParameters'; -import inject18n from '../../../components/i18n'; -import ListLines from '../../../components/list_lines/ListLines'; -import RolesLines, { rolesLinesQuery } from './roles/RolesLines'; -import AccessesMenu from './AccessesMenu'; -import RoleCreation from './roles/RoleCreation'; -import withRouter from '../../../utils/compat_router/withRouter'; -import Breadcrumbs from '../../../components/Breadcrumbs'; - -const styles = () => ({ - container: { - margin: 0, - padding: '0 200px 50px 0', - }, -}); - -const LOCAL_STORAGE_KEY = 'roles'; - -class Roles extends Component { - constructor(props) { - super(props); - const params = buildViewParamsFromUrlAndStorage( - props.navigate, - props.location, - LOCAL_STORAGE_KEY, - ); - this.state = { - sortBy: propOr('name', 'sortBy', params), - orderAsc: propOr(true, 'orderAsc', params), - searchTerm: propOr('', 'searchTerm', params), - view: propOr('lines', 'view', params), - }; - } - - saveView() { - saveViewParameters( - this.props.navigate, - this.props.location, - LOCAL_STORAGE_KEY, - this.state, - ); - } - - handleSort(field, orderAsc) { - this.setState({ sortBy: field, orderAsc }, () => this.saveView()); - } - - handleSearch(value) { - this.setState({ searchTerm: value }, () => this.saveView()); - } - - renderLines(paginationOptions) { - const { sortBy, orderAsc, searchTerm } = this.state; - const dataColumns = { - name: { - label: 'Name', - width: '40%', - isSortable: true, - }, - groups: { - label: 'Groups with this role', - width: '20%', - isSortable: false, - }, - created_at: { - label: 'Platform creation date', - width: '20%', - isSortable: true, - }, - updated_at: { - label: 'Modification date', - width: '20%', - isSortable: true, - }, - }; - return ( - - ( - - )} - /> - - ); - } - - render() { - const { view, sortBy, orderAsc, searchTerm } = this.state; - const { classes, t } = this.props; - const paginationOptions = { - search: searchTerm, - orderBy: sortBy, - orderMode: orderAsc ? 'asc' : 'desc', - }; - return ( -
- - - {view === 'lines' ? this.renderLines(paginationOptions) : ''} - -
- ); - } -} - -Roles.propTypes = { - t: PropTypes.func, - classes: PropTypes.object, - navigate: PropTypes.func, - location: PropTypes.object, -}; - -export default compose(inject18n, withRouter, withStyles(styles))(Roles); diff --git a/opencti-platform/opencti-front/src/private/components/settings/Roles.tsx b/opencti-platform/opencti-front/src/private/components/settings/Roles.tsx new file mode 100644 index 0000000000000..7314402aa335a --- /dev/null +++ b/opencti-platform/opencti-front/src/private/components/settings/Roles.tsx @@ -0,0 +1,131 @@ +import React, { useEffect, useState } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; +import makeStyles from '@mui/styles/makeStyles'; +import { useFormatter } from '../../../components/i18n'; +import { buildViewParamsFromUrlAndStorage, saveViewParameters } from '../../../utils/ListParameters'; +import ListLines from '../../../components/list_lines/ListLines'; +import RolesLines, { rolesLinesQuery } from './roles/RolesLines'; +import AccessesMenu from './AccessesMenu'; +import { OrderMode, PaginationOptions } from '../../../components/list_lines'; +import RoleCreation from './roles/RoleCreation'; +import Breadcrumbs from '../../../components/Breadcrumbs'; +import { RolesLinesPaginationQuery$data } from './roles/__generated__/RolesLinesPaginationQuery.graphql'; +import { QueryRenderer } from '../../../relay/environment'; +import useConnectedDocumentModifier from '../../../utils/hooks/useConnectedDocumentModifier'; + +const LOCAL_STORAGE_KEY = 'roles'; + +const useStyles = makeStyles(() => ({ + container: { + margin: 0, + padding: '0 200px 50px 0', + }, +})); + +const Role = () => { + const { t_i18n } = useFormatter(); + const navigate = useNavigate(); + const location = useLocation(); + const { setTitle } = useConnectedDocumentModifier(); + setTitle(t_i18n('Security: Roles | Settings')); + const params = buildViewParamsFromUrlAndStorage( + navigate, + location, + LOCAL_STORAGE_KEY, + ); + const classes = useStyles(); + const [rolesState, setRolesState] = useState<{ orderAsc: boolean, searchTerm: string, view: string, sortBy: string }>({ + orderAsc: params.orderAsc !== false, + searchTerm: params.searchTerm ?? '', + view: params.view ?? 'lines', + sortBy: params.sortBy ?? 'name', + }); + + function saveView() { + saveViewParameters( + navigate, + location, + LOCAL_STORAGE_KEY, + rolesState, + ); + } + + function handleSearch(value: string) { + setRolesState({ ...rolesState, searchTerm: value }); + } + + function handleSort(field: string, orderAsc: boolean) { + setRolesState({ ...rolesState, sortBy: field, orderAsc }); + } + + useEffect(() => { + saveView(); + }, [rolesState]); + + function renderLines(paginationOptions: PaginationOptions) { + const { sortBy, orderAsc } = rolesState; + const dataColumns = { + name: { + label: 'Name', + width: '40%', + isSortable: true, + }, + groups: { + label: 'Groups with this role', + width: '20%', + isSortable: false, + }, + created_at: { + label: 'Platform creation date', + width: '20%', + isSortable: true, + }, + updated_at: { + label: 'Modification date', + width: '20%', + isSortable: true, + }, + }; + return ( + + ( + + )} + /> + + ); + } + + const paginationOptions: PaginationOptions = { + search: rolesState.searchTerm, + orderBy: rolesState.sortBy ? rolesState.sortBy : null, + orderMode: rolesState.orderAsc ? OrderMode.asc : OrderMode.desc, + }; + return ( +
+ + + {rolesState.view === 'lines' ? renderLines(paginationOptions) : ''} + +
+ ); +}; + +export default Role; diff --git a/opencti-platform/opencti-front/src/private/components/settings/Sessions.jsx b/opencti-platform/opencti-front/src/private/components/settings/Sessions.jsx index bdf6993160d4a..756588c55ad4f 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/Sessions.jsx +++ b/opencti-platform/opencti-front/src/private/components/settings/Sessions.jsx @@ -1,17 +1,15 @@ -import React, { Component } from 'react'; -import * as PropTypes from 'prop-types'; -import { compose, propOr } from 'ramda'; -import withStyles from '@mui/styles/withStyles'; +import React from 'react'; +import makeStyles from '@mui/styles/makeStyles'; import AccessesMenu from './AccessesMenu'; -import inject18n from '../../../components/i18n'; import { QueryRenderer } from '../../../relay/environment'; import SessionsList, { sessionsListQuery } from './SessionsList'; import SearchInput from '../../../components/SearchInput'; -import { buildViewParamsFromUrlAndStorage, saveViewParameters } from '../../../utils/ListParameters'; -import withRouter from '../../../utils/compat_router/withRouter'; import Breadcrumbs from '../../../components/Breadcrumbs'; +import { useFormatter } from '../../../components/i18n'; +import { usePaginationLocalStorage } from '../../../utils/hooks/useLocalStorage'; +import useConnectedDocumentModifier from '../../../utils/hooks/useConnectedDocumentModifier'; -const styles = () => ({ +const useStyles = makeStyles(() => ({ container: { margin: 0, padding: '0 200px 50px 0', @@ -20,73 +18,44 @@ const styles = () => ({ float: 'left', marginTop: -10, }, -}); +})); const LOCAL_STORAGE_KEY = 'sessions'; -class Sessions extends Component { - constructor(props) { - super(props); - const params = buildViewParamsFromUrlAndStorage( - props.navigate, - props.location, - LOCAL_STORAGE_KEY, - ); - this.state = { - searchTerm: propOr('', 'searchTerm', params), - openExports: false, - }; - } - - saveView() { - saveViewParameters( - this.props.navigate, - this.props.location, - LOCAL_STORAGE_KEY, - this.state, - ); - } - - handleSearch(value) { - this.setState({ searchTerm: value }, () => this.saveView()); - } - - render() { - const { searchTerm } = this.state; - const { t, classes } = this.props; - return ( -
- - -
-
- -
+const Sessions = () => { + const classes = useStyles(); + const { t_i18n } = useFormatter(); + const { setTitle } = useConnectedDocumentModifier(); + setTitle(t_i18n('Security: Sessions | Settings')); + const { viewStorage, helpers } = usePaginationLocalStorage( + LOCAL_STORAGE_KEY, + {}, + ); + return ( +
+ + +
+
+
-
- { - if (props) { - return ; - } - return
; - }} - />
- ); - } -} - -Sessions.propTypes = { - t: PropTypes.func, - classes: PropTypes.object, - navigate: PropTypes.func, - location: PropTypes.object, +
+ { + if (props) { + return ; + } + return
; + }} + /> +
+ ); }; -export default compose(inject18n, withRouter, withStyles(styles))(Sessions); +export default Sessions; diff --git a/opencti-platform/opencti-front/src/private/components/settings/SessionsList.jsx b/opencti-platform/opencti-front/src/private/components/settings/SessionsList.jsx index b6ab3dacf78d8..25107fe42e94e 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/SessionsList.jsx +++ b/opencti-platform/opencti-front/src/private/components/settings/SessionsList.jsx @@ -1,8 +1,6 @@ -import React, { Component } from 'react'; -import * as PropTypes from 'prop-types'; +import React, { useEffect, useState } from 'react'; import * as R from 'ramda'; import { Link } from 'react-router-dom'; -import withStyles from '@mui/styles/withStyles'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import ListItemIcon from '@mui/material/ListItemIcon'; @@ -17,17 +15,17 @@ import Button from '@mui/material/Button'; import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'; import IconButton from '@mui/material/IconButton'; import { graphql, createRefetchContainer } from 'react-relay'; -import inject18n from '../../../components/i18n'; +import makeStyles from '@mui/styles/makeStyles'; import { commitMutation } from '../../../relay/environment'; import { FIVE_SECONDS, timestamp } from '../../../utils/Time'; import { userSessionKillMutation } from './users/User'; import ItemIcon from '../../../components/ItemIcon'; import Transition from '../../../components/Transition'; -import withRouter from '../../../utils/compat_router/withRouter'; +import { useFormatter } from '../../../components/i18n'; const interval$ = interval(FIVE_SECONDS); -const styles = (theme) => ({ +const useStyles = makeStyles((theme) => ({ item: {}, itemNested: { paddingLeft: theme.spacing(4), @@ -76,187 +74,167 @@ const styles = (theme) => ({ position: 'absolute', right: -10, }, -}); +})); -class SessionsListComponent extends Component { - constructor(props) { - super(props); - this.state = { - displayUpdate: false, - displayKillSession: false, - killing: false, - sessionToKill: null, - }; - } +const SessionsListComponent = ({ relay, data, keyword }) => { + const classes = useStyles(); + const { t_i18n, nsdt } = useFormatter(); + const [displayKillSession, setDisplayKillSession] = useState(false); + const [killing, setKilling] = useState(false); + const [sessionToKill, setSessionToKill] = useState(null); - componentDidMount() { - this.subscription = interval$.subscribe(() => { - this.props.relay.refetch(); - }); - } - - componentWillUnmount() { - this.subscription.unsubscribe(); - } + useEffect(() => { + const subscription = interval$.subscribe(() => relay.refetch()); + return () => { + subscription.unsubscribe(); + }; + }, []); - handleOpenKillSession(session) { - this.setState({ displayKillSession: true, sessionToKill: session }); - } + const handleOpenKillSession = (session) => { + setDisplayKillSession(true); + setSessionToKill(session); + }; - handleCloseKillSession() { - this.setState({ displayKillSession: false, sessionToKill: null }); - } + const handleCloseKillSession = () => { + setDisplayKillSession(false); + setSessionToKill(null); + }; - submitKillSession() { - this.setState({ killing: true }); + const submitKillSession = () => { + setKilling(true); commitMutation({ mutation: userSessionKillMutation, variables: { - id: this.state.sessionToKill, + id: sessionToKill, }, onCompleted: () => { - this.setState({ killing: false }); - this.handleCloseKillSession(); + setKilling(false); + handleCloseKillSession(); }, onError: () => { - this.setState({ killing: false }); + setKilling(false); }, }); - } + }; - render() { - const { classes, nsdt, t, data, keyword } = this.props; - const sortByNameCaseInsensitive = R.sortBy( - R.compose(R.toLower, R.path(['user', 'name'])), - ); - const filterByKeyword = (n) => keyword === '' - || n.user.name.toLowerCase().indexOf(keyword.toLowerCase()) !== -1; - const sessions = R.pipe( - R.propOr([], 'sessions'), - R.filter(filterByKeyword), - sortByNameCaseInsensitive, - )(data); - return ( - <> - - {sessions.map((session) => { - const { user, sessions: userSessions } = session; - const orderedSessions = R.sort( - (a, b) => timestamp(a.created) - timestamp(b.created), - userSessions, - ); - return ( -
- - - - - -
{user.name}
-
{user.email}
-
- } - /> - -   - - - - {orderedSessions.map((userSession) => ( - - - - - -
- {nsdt(userSession.created)} -
-
- {Math.round(userSession.ttl / 60)}{' '} - {t('minutes left')} /{' '} - {Math.round(userSession.originalMaxAge / 60)} -
+ const sortByNameCaseInsensitive = R.sortBy( + R.compose(R.toLower, R.path(['user', 'name'])), + ); + const filterByKeyword = (n) => keyword === '' + || n.user.name.toLowerCase().indexOf(keyword.toLowerCase()) !== -1; + const sessions = R.pipe( + R.propOr([], 'sessions'), + R.filter(filterByKeyword), + sortByNameCaseInsensitive, + )(data); + return ( + <> + + {sessions.map((session) => { + const { user, sessions: userSessions } = session; + const orderedSessions = R.sort( + (a, b) => timestamp(a.created) - timestamp(b.created), + userSessions, + ); + return ( +
+ + + + + +
{user.name}
+
{user.email}
+
+ } + /> + +   + +
+ + {orderedSessions.map((userSession) => ( + + + + + +
+ {nsdt(userSession.created)}
- } - /> - - - - - -
- ))} -
-
- ); - })} - - - - - {t('Do you want to kill this session?')} - - - - - - - - - ); - } -} - -SessionsListComponent.propTypes = { - t: PropTypes.func, - classes: PropTypes.object, - navigate: PropTypes.func, - location: PropTypes.object, - nsdt: PropTypes.func, - data: PropTypes.object, +
+ {Math.round(userSession.ttl / 60)}{' '} + {t_i18n('minutes left')} /{' '} + {Math.round(userSession.originalMaxAge / 60)} +
+
+ } + /> + + handleOpenKillSession(userSession.id)} + size="large" + color="primary" + > + + + + + ))} + +
+ ); + })} + + + + + {t_i18n('Do you want to kill this session?')} + + + + + + + + + ); }; export const sessionsListQuery = graphql` @@ -265,7 +243,7 @@ export const sessionsListQuery = graphql` } `; -const SessionsList = createRefetchContainer( +export default createRefetchContainer( SessionsListComponent, { data: graphql` @@ -287,9 +265,3 @@ const SessionsList = createRefetchContainer( }, sessionsListQuery, ); - -export default R.compose( - inject18n, - withRouter, - withStyles(styles), -)(SessionsList); diff --git a/opencti-platform/opencti-front/src/private/components/settings/groups/GroupsLines.tsx b/opencti-platform/opencti-front/src/private/components/settings/groups/GroupsLines.tsx index 0ffdaeec2cc05..8d7ecbf71b805 100644 --- a/opencti-platform/opencti-front/src/private/components/settings/groups/GroupsLines.tsx +++ b/opencti-platform/opencti-front/src/private/components/settings/groups/GroupsLines.tsx @@ -1,11 +1,10 @@ import React from 'react'; import { graphql, createPaginationContainer, RelayPaginationProp } from 'react-relay'; import { pathOr } from 'ramda'; -import { GroupsLinesPaginationQuery$variables } from '@components/settings/groups/__generated__/GroupsLinesPaginationQuery.graphql'; import { GroupsLines_data$data } from '@components/settings/groups/__generated__/GroupsLines_data.graphql'; import ListLinesContent from '../../../../components/list_lines/ListLinesContent'; import { GroupLine, GroupLineDummy } from './GroupLine'; -import { DataColumns } from '../../../../components/list_lines'; +import { DataColumns, PaginationOptions } from '../../../../components/list_lines'; const nbOfRowsToLoad = 50; @@ -13,7 +12,7 @@ interface GroupsLinesProps { initialLoading: boolean dataColumns: DataColumns relay: RelayPaginationProp, - paginationOptions: GroupsLinesPaginationQuery$variables + paginationOptions: PaginationOptions, data: GroupsLines_data$data }