From cda8fe97a37754cac5b61700bac50383a8feabb3 Mon Sep 17 00:00:00 2001 From: Bonsai8863 <131906254+Bonsai8863@users.noreply.github.com> Date: Thu, 20 Jun 2024 12:43:07 -0400 Subject: [PATCH] [frontend] Add page titles to Settings pages Revert WIP conversion of Sectors test commit Fix paginationOptions issue for Groups, KillChainPhases, Roles Fix MarkingDefinitions, update KillChainPhases to reflect master Remove changes established in PR #7753 Add Malwares.tsx to removed changes Post-rebase cleanup Remove changes from PR 7753 Remove outdated changes to KillChainPhases Fix translations Align GroupLine design with master Fix typing on GroupLines; --- .../opencti-front/lang/front/de.json | 4 + .../opencti-front/lang/front/en.json | 4 + .../opencti-front/lang/front/es.json | 4 + .../opencti-front/lang/front/fr.json | 4 + .../opencti-front/lang/front/ja.json | 6 +- .../opencti-front/lang/front/ko.json | 4 + .../opencti-front/lang/front/zh.json | 4 + .../settings/{Groups.jsx => Groups.tsx} | 135 +++---- .../settings/MarkingDefinitions.jsx | 142 -------- .../settings/MarkingDefinitions.tsx | 134 +++++++ .../src/private/components/settings/Roles.jsx | 134 ------- .../src/private/components/settings/Roles.tsx | 131 +++++++ .../private/components/settings/Sessions.jsx | 111 +++--- .../components/settings/SessionsList.jsx | 328 ++++++++---------- .../settings/groups/GroupsLines.tsx | 5 +- 15 files changed, 554 insertions(+), 596 deletions(-) rename opencti-platform/opencti-front/src/private/components/settings/{Groups.jsx => Groups.tsx} (50%) delete mode 100644 opencti-platform/opencti-front/src/private/components/settings/MarkingDefinitions.jsx create mode 100644 opencti-platform/opencti-front/src/private/components/settings/MarkingDefinitions.tsx delete mode 100644 opencti-platform/opencti-front/src/private/components/settings/Roles.jsx create mode 100644 opencti-platform/opencti-front/src/private/components/settings/Roles.tsx 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 }