diff --git a/opencti-platform/opencti-front/src/private/components/common/containers/ContainerAddStixCoreObjects.jsx b/opencti-platform/opencti-front/src/private/components/common/containers/ContainerAddStixCoreObjects.jsx index 3e1d5b2755ad..2983cffbd2d7 100644 --- a/opencti-platform/opencti-front/src/private/components/common/containers/ContainerAddStixCoreObjects.jsx +++ b/opencti-platform/opencti-front/src/private/components/common/containers/ContainerAddStixCoreObjects.jsx @@ -13,11 +13,12 @@ import { useFormatter } from '../../../../components/i18n'; import ContainerAddStixCoreObjectsLines, { containerAddStixCoreObjectsLinesQuery } from './ContainerAddStixCoreObjectsLines'; import StixDomainObjectCreation from '../stix_domain_objects/StixDomainObjectCreation'; import StixCyberObservableCreation from '../../observations/stix_cyber_observables/StixCyberObservableCreation'; -import { UserContext } from '../../../../utils/hooks/useAuth'; +import useAuth from '../../../../utils/hooks/useAuth'; import ListLines from '../../../../components/list_lines/ListLines'; -import { constructHandleAddFilter, constructHandleRemoveFilter, emptyFilterGroup, filtersAfterSwitchLocalMode } from '../../../../utils/filters/filtersUtils'; +import { emptyFilterGroup } from '../../../../utils/filters/filtersUtils'; import Drawer from '../drawer/Drawer'; import useAttributes from '../../../../utils/hooks/useAttributes'; +import { usePaginationLocalStorage } from '../../../../utils/hooks/useLocalStorage'; const useStyles = makeStyles((theme) => ({ createButton: { @@ -76,10 +77,11 @@ const ContainerAddStixCoreObjects = (props) => { const [openSpeedDial, setOpenSpeedDial] = useState(false); const [openCreateEntity, setOpenCreateEntity] = useState(false); const [openCreateObservable, setOpenCreateObservable] = useState(false); - const [sortBy, setSortBy] = useState('_score'); - const [orderAsc, setOrderAsc] = useState(false); const { stixDomainObjectTypes, stixCyberObservableTypes } = useAttributes(); + const { + platformModuleHelpers: { isRuntimeFieldEnable }, + } = useAuth(); const targetEntityTypesFilterGroup = { mode: 'and', @@ -94,18 +96,71 @@ const ContainerAddStixCoreObjects = (props) => { ], }; - const [filters, setFilters] = useState( - targetStixCoreObjectTypes - && !(targetStixCoreObjectTypes.includes('Stix-Domain-Object') || targetStixCoreObjectTypes.includes('Stix-Cyber-Observable')) - ? targetEntityTypesFilterGroup - : emptyFilterGroup, + const isTypeDomainObject = (types) => { + return !types + || types.some((r) => stixDomainObjectTypes.indexOf(r) >= 0) + || (types.length === 1 && types[0] === 'Stix-Domain-Object'); + }; + const isTypeObservable = (types) => { + return !types + || types.some((r) => stixCyberObservableTypes.indexOf(r) >= 0) + || (types.length === 1 && types[0] === 'Stix-Cyber-Observable'); + }; + + const resolveAvailableTypes = () => { + if ( + targetStixCoreObjectTypes + && isTypeDomainObject(targetStixCoreObjectTypes) + && !isTypeObservable(targetStixCoreObjectTypes) + ) { + return 'Stix-Domain-Object'; + } + if ( + targetStixCoreObjectTypes + && isTypeObservable(targetStixCoreObjectTypes) + && !isTypeDomainObject(targetStixCoreObjectTypes) + ) { + return 'Stix-Cyber-Observable'; + } + if ( + !targetStixCoreObjectTypes + || (isTypeObservable(targetStixCoreObjectTypes) + && isTypeDomainObject(targetStixCoreObjectTypes)) + ) { + return 'Stix-Core-Object'; + } + return null; + }; + + const LOCAL_STORAGE_KEY = `container-${containerId}-add-objects`; + const { viewStorage, helpers, paginationOptions: addObjectsPaginationOptions } = usePaginationLocalStorage( + LOCAL_STORAGE_KEY, + { + searchTerm: '', + sortBy: '_score', + orderAsc: false, + filters: targetStixCoreObjectTypes + && !(targetStixCoreObjectTypes.includes('Stix-Domain-Object') || targetStixCoreObjectTypes.includes('Stix-Cyber-Observable')) + ? targetEntityTypesFilterGroup + : emptyFilterGroup, + types: [resolveAvailableTypes()], + numberOfElements: { + number: 0, + symbol: '', + }, + }, ); - const [numberOfElements, setNumberOfElements] = useState({ - number: 0, - symbol: '', - }); - const [searchTerm, setSearchTerm] = useState(''); + + const { + sortBy, + orderAsc, + searchTerm, + filters, + numberOfElements, + } = viewStorage; + const containerRef = useRef(null); + const keyword = mapping && searchTerm.length === 0 ? selectedText : searchTerm; const handleOpenCreateEntity = () => { setOpenCreateEntity(true); setOpenSpeedDial(false); @@ -122,56 +177,21 @@ const ContainerAddStixCoreObjects = (props) => { setOpenCreateObservable(false); setOpenSpeedDial(false); }; - const handleSort = (field, sortOrderAsc) => { - setSortBy(field); - setOrderAsc(sortOrderAsc); - }; - const handleAddFilter = (key, id, op = 'eq', event = null) => { - if (event) { - event.stopPropagation(); - event.preventDefault(); - } - setFilters(constructHandleAddFilter(filters, key, id, op)); - }; - const handleRemoveFilter = (key, op = 'eq') => { - setFilters(constructHandleRemoveFilter(filters, key, op)); - }; - - const handleSwitchLocalMode = (localFilter) => { - setFilters(filtersAfterSwitchLocalMode(filters, localFilter)); - }; - - const handleSwitchGlobalMode = () => { - if (filters) { - setFilters({ - ...filters, - mode: filters.mode === 'and' ? 'or' : 'and', - }); - } - }; - const isTypeDomainObject = (types) => { - return !types || types.some((r) => stixDomainObjectTypes.indexOf(r) >= 0); - }; - const isTypeObservable = (types) => { - return ( - !types || types.some((r) => stixCyberObservableTypes.indexOf(r) >= 0) - ); - }; const renderDomainObjectCreation = (searchPaginationOptions) => { return ( 0 - ? targetStixCoreObjectTypes - : [] - } + targetStixCoreObjectTypes && targetStixCoreObjectTypes.length > 0 + ? targetStixCoreObjectTypes + : [] + } /> ); }; @@ -180,7 +200,7 @@ const ContainerAddStixCoreObjects = (props) => { { 0 - ? targetStixCoreObjectTypes - : [] - } + targetStixCoreObjectTypes && targetStixCoreObjectTypes.length > 0 + ? targetStixCoreObjectTypes + : [] + } speeddial={true} open={openCreateEntity} handleClose={() => handleCloseCreateEntity()} @@ -241,7 +261,7 @@ const ContainerAddStixCoreObjects = (props) => { { ); }; - const resolveAvailableTypes = () => { - if ( - targetStixCoreObjectTypes - && isTypeDomainObject(targetStixCoreObjectTypes) - && !isTypeObservable(targetStixCoreObjectTypes) - ) { - return 'Stix-Domain-Object'; - } - if ( - targetStixCoreObjectTypes - && isTypeObservable(targetStixCoreObjectTypes) - && !isTypeDomainObject(targetStixCoreObjectTypes) - ) { - return 'Stix-Cyber-Observable'; - } - if ( - !targetStixCoreObjectTypes - || (isTypeObservable(targetStixCoreObjectTypes) - && isTypeDomainObject(targetStixCoreObjectTypes)) - ) { - return 'Stix-Core-Object'; - } - return null; - }; const renderEntityCreation = (searchPaginationOptions) => { if ( targetStixCoreObjectTypes @@ -301,8 +297,7 @@ const ContainerAddStixCoreObjects = (props) => { } return null; }; - const buildColumns = (platformModuleHelpers) => { - const isRuntimeSort = platformModuleHelpers.isRuntimeFieldEnable(); + const buildColumns = () => { return { entity_type: { label: 'Type', @@ -317,7 +312,7 @@ const ContainerAddStixCoreObjects = (props) => { createdBy: { label: 'Author', width: '15%', - isSortable: isRuntimeSort, + isSortable: isRuntimeFieldEnable(), }, objectLabel: { label: 'Labels', @@ -327,65 +322,60 @@ const ContainerAddStixCoreObjects = (props) => { objectMarking: { label: 'Marking', width: '15%', - isSortable: isRuntimeSort, + isSortable: isRuntimeFieldEnable(), }, }; }; const renderSearchResults = (searchPaginationOptions) => { return ( - - {({ platformModuleHelpers }) => ( - - ( - - )} + + ( + - - )} - + )} + /> + ); }; const searchPaginationOptions = { - types: [resolveAvailableTypes()], - search: mapping && searchTerm.length === 0 ? selectedText : searchTerm, - filters, - orderBy: sortBy, - orderMode: orderAsc ? 'asc' : 'desc', + ...addObjectsPaginationOptions, + search: keyword, }; const renderButton = () => { if (knowledgeGraph) { @@ -426,22 +416,12 @@ const ContainerAddStixCoreObjects = (props) => { ); }; - const resetState = () => { - setSearchTerm(''); - setFilters( - targetStixCoreObjectTypes - && !(targetStixCoreObjectTypes.includes('Stix-Domain-Object') || targetStixCoreObjectTypes.includes('Stix-Cyber-Observable')) - ? targetEntityTypesFilterGroup - : emptyFilterGroup, - ); - }; return ( <> {!mapping && renderButton()} { - resetState(); if (mapping) { handleClose(); } else { diff --git a/opencti-platform/opencti-front/src/private/components/workspaces/investigations/InvestigationAddStixCoreObjects.jsx b/opencti-platform/opencti-front/src/private/components/workspaces/investigations/InvestigationAddStixCoreObjects.jsx index 22e407cdc0cb..da95e29d8808 100644 --- a/opencti-platform/opencti-front/src/private/components/workspaces/investigations/InvestigationAddStixCoreObjects.jsx +++ b/opencti-platform/opencti-front/src/private/components/workspaces/investigations/InvestigationAddStixCoreObjects.jsx @@ -6,10 +6,11 @@ import InvestigationAddStixCoreObjectsLines, { investigationAddStixCoreObjectsLi import { QueryRenderer } from '../../../../relay/environment'; import { useFormatter } from '../../../../components/i18n'; import useAttributes from '../../../../utils/hooks/useAttributes'; -import { UserContext } from '../../../../utils/hooks/useAuth'; +import useAuth from '../../../../utils/hooks/useAuth'; import ListLines from '../../../../components/list_lines/ListLines'; -import { constructHandleAddFilter, constructHandleRemoveFilter, emptyFilterGroup, filtersAfterSwitchLocalMode } from '../../../../utils/filters/filtersUtils'; +import { emptyFilterGroup } from '../../../../utils/filters/filtersUtils'; import Drawer from '../../common/drawer/Drawer'; +import { usePaginationLocalStorage } from '../../../../utils/hooks/useLocalStorage'; const InvestigationAddStixCoreObjects = (props) => { const { @@ -26,63 +27,16 @@ const InvestigationAddStixCoreObjects = (props) => { const { t_i18n } = useFormatter(); const { stixDomainObjectTypes, stixCyberObservableTypes } = useAttributes(); const [open, setOpen] = useState(false); - const [sortBy, setSortBy] = useState('_score'); - const [orderAsc, setOrderAsc] = useState(false); - const [filters, setFilters] = useState( - targetStixCoreObjectTypes - && !( - targetStixCoreObjectTypes.includes('Stix-Domain-Object') - || targetStixCoreObjectTypes.includes('Stix-Cyber-Observable') - ) - ? { - mode: 'and', - filters: [{ - key: 'entity_type', - values: targetStixCoreObjectTypes, - }], - filterGroups: [], - } - : emptyFilterGroup, - ); - const [numberOfElements, setNumberOfElements] = useState({ - number: 0, - symbol: '', - }); - const [searchTerm, setSearchTerm] = useState(''); - const containerRef = useRef(null); - const handleSort = (field, sortOrderAsc) => { - setSortBy(field); - setOrderAsc(sortOrderAsc); - }; - const handleAddFilter = (key, id, op = 'eq', event = null) => { - if (event) { - event.stopPropagation(); - event.preventDefault(); - } - setFilters(constructHandleAddFilter(filters, key, id, op)); - }; - const handleRemoveFilter = (key, op = 'eq') => { - setFilters(constructHandleRemoveFilter(filters, key, op)); - }; - const handleSwitchLocalMode = (localFilter) => { - setFilters(filtersAfterSwitchLocalMode(filters, localFilter)); - }; - const handleSwitchGlobalMode = () => { - if (filters) { - setFilters({ - ...filters, - mode: filters.mode === 'and' ? 'or' : 'and', - }); - } - }; const isTypeDomainObject = (types) => { - return !types || types.some((r) => stixDomainObjectTypes.indexOf(r) >= 0); + return !types + || types.some((r) => stixDomainObjectTypes.indexOf(r) >= 0) + || (types.length === 1 && types[0] === 'Stix-Domain-Object'); }; const isTypeObservable = (types) => { - return ( - !types || types.some((r) => stixCyberObservableTypes.indexOf(r) >= 0) - ); + return !types + || types.some((r) => stixCyberObservableTypes.indexOf(r) >= 0) + || (types.length === 1 && types[0] === 'Stix-Cyber-Observable'); }; const resolveAvailableTypes = () => { if ( @@ -108,8 +62,50 @@ const InvestigationAddStixCoreObjects = (props) => { } return null; }; - const buildColumns = (platformModuleHelpers) => { - const isRuntimeSort = platformModuleHelpers.isRuntimeFieldEnable(); + + const LOCAL_STORAGE_KEY = `investigation-${workspaceId}-add-objects`; + const { viewStorage, helpers, paginationOptions: addObjectsPaginationOptions } = usePaginationLocalStorage( + LOCAL_STORAGE_KEY, + { + searchTerm: '', + sortBy: '_score', + orderAsc: false, + filters: targetStixCoreObjectTypes + && !( + targetStixCoreObjectTypes.includes('Stix-Domain-Object') + || targetStixCoreObjectTypes.includes('Stix-Cyber-Observable') + ) + ? { + mode: 'and', + filters: [{ + key: 'entity_type', + values: targetStixCoreObjectTypes, + }], + filterGroups: [], + } + : emptyFilterGroup, + types: [resolveAvailableTypes()], + numberOfElements: { + number: 0, + symbol: '', + }, + }, + ); + + const { + sortBy, + orderAsc, + searchTerm, + filters, + numberOfElements, + } = viewStorage; + + const containerRef = useRef(null); + + const { + platformModuleHelpers: { isRuntimeFieldEnable }, + } = useAuth(); + const buildColumns = () => { return { entity_type: { label: 'Type', @@ -124,7 +120,7 @@ const InvestigationAddStixCoreObjects = (props) => { createdBy: { label: 'Author', width: '15%', - isSortable: isRuntimeSort, + isSortable: isRuntimeFieldEnable(), }, objectLabel: { label: 'Labels', @@ -134,37 +130,15 @@ const InvestigationAddStixCoreObjects = (props) => { objectMarking: { label: 'Marking', width: '15%', - isSortable: isRuntimeSort, + isSortable: isRuntimeFieldEnable(), }, }; }; + const keyword = mapping && searchTerm.length === 0 ? selectedText : searchTerm; const searchPaginationOptions = { - types: [resolveAvailableTypes()], - search: mapping && searchTerm.length === 0 ? selectedText : searchTerm, - filters, - orderBy: sortBy, - orderMode: orderAsc ? 'asc' : 'desc', - }; - - const resetState = () => { - setSearchTerm(''); - setFilters( - targetStixCoreObjectTypes - && !( - targetStixCoreObjectTypes.includes('Stix-Domain-Object') - || targetStixCoreObjectTypes.includes('Stix-Cyber-Observable') - ) - ? { - mode: 'and', - filters: [{ - key: 'entity_type', - values: targetStixCoreObjectTypes, - }], - filterGroups: [], - } - : emptyFilterGroup, - ); + ...addObjectsPaginationOptions, + search: keyword, }; return ( @@ -184,7 +158,6 @@ const InvestigationAddStixCoreObjects = (props) => { { - resetState(); if (mapping) { handleClose(); } else { @@ -194,52 +167,48 @@ const InvestigationAddStixCoreObjects = (props) => { title={t_i18n('Add entities')} containerRef={containerRef} > - - {({ platformModuleHelpers }) => ( - - ( - - )} + + ( + - - )} - + )} + /> + ); diff --git a/opencti-platform/opencti-graphql/src/modules/malwareAnalysis/malwareAnalysis.ts b/opencti-platform/opencti-graphql/src/modules/malwareAnalysis/malwareAnalysis.ts index d47a48b996ec..b3473bb2c739 100644 --- a/opencti-platform/opencti-graphql/src/modules/malwareAnalysis/malwareAnalysis.ts +++ b/opencti-platform/opencti-graphql/src/modules/malwareAnalysis/malwareAnalysis.ts @@ -123,7 +123,7 @@ export const MALWARE_ANALYSIS_DEFINITION: ModuleDefinition