[CTI] ensures isThreatIntelModuleEnabled query for Overview page is made only once (#104523)

This commit is contained in:
Ece Özalp 2021-07-07 13:18:57 -04:00 committed by GitHub
parent de9ba92340
commit efa0476192
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 42 additions and 26 deletions

View file

@ -6,12 +6,14 @@
*/ */
import React from 'react'; import React from 'react';
import { ThreatIntelLinkPanelProps } from './index'; import { ThreatIntelLinkPanelProps } from '.';
import { useCtiEventCounts } from '../../containers/overview_cti_links/use_cti_event_counts'; import { useCtiEventCounts } from '../../containers/overview_cti_links/use_cti_event_counts';
import { CtiNoEvents } from './cti_no_events'; import { CtiNoEvents } from './cti_no_events';
import { CtiWithEvents } from './cti_with_events'; import { CtiWithEvents } from './cti_with_events';
export const CtiEnabledModuleComponent: React.FC<ThreatIntelLinkPanelProps> = (props) => { export type CtiEnabledModuleProps = Omit<ThreatIntelLinkPanelProps, 'isThreatIntelModuleEnabled'>;
export const CtiEnabledModuleComponent: React.FC<CtiEnabledModuleProps> = (props) => {
const { eventCountsByDataset, totalCount } = useCtiEventCounts(props); const { eventCountsByDataset, totalCount } = useCtiEventCounts(props);
const { to, from } = props; const { to, from } = props;

View file

@ -23,7 +23,7 @@ const warning = (
export const CtiNoEventsComponent = ({ to, from }: { to: string; from: string }) => { export const CtiNoEventsComponent = ({ to, from }: { to: string; from: string }) => {
const { buttonHref, listItems, isDashboardPluginDisabled } = useCtiDashboardLinks( const { buttonHref, listItems, isDashboardPluginDisabled } = useCtiDashboardLinks(
{ ...emptyEventCountsByDataset }, emptyEventCountsByDataset,
to, to,
from from
); );

View file

@ -6,6 +6,7 @@
*/ */
import React from 'react'; import React from 'react';
import { isEqual } from 'lodash';
import { useCtiDashboardLinks } from '../../containers/overview_cti_links'; import { useCtiDashboardLinks } from '../../containers/overview_cti_links';
import { ThreatIntelPanelView } from './threat_intel_panel_view'; import { ThreatIntelPanelView } from './threat_intel_panel_view';
@ -38,4 +39,11 @@ export const CtiWithEventsComponent = ({
CtiWithEventsComponent.displayName = 'CtiWithEvents'; CtiWithEventsComponent.displayName = 'CtiWithEvents';
export const CtiWithEvents = React.memo(CtiWithEventsComponent); export const CtiWithEvents = React.memo(
CtiWithEventsComponent,
(prevProps, nextProps) =>
prevProps.to === nextProps.to &&
prevProps.from === nextProps.from &&
prevProps.totalCount === nextProps.totalCount &&
isEqual(prevProps.eventCountsByDataset, nextProps.eventCountsByDataset)
);

View file

@ -20,14 +20,9 @@ import {
SUB_PLUGINS_REDUCER, SUB_PLUGINS_REDUCER,
} from '../../../common/mock'; } from '../../../common/mock';
import { mockTheme, mockProps } from './mock'; import { mockTheme, mockProps } from './mock';
import { useIsThreatIntelModuleEnabled } from '../../containers/overview_cti_links/use_is_threat_intel_module_enabled';
jest.mock('../../../common/lib/kibana'); jest.mock('../../../common/lib/kibana');
jest.mock('../../containers/overview_cti_links/use_is_threat_intel_module_enabled');
const useIsThreatIntelModuleEnabledMock = useIsThreatIntelModuleEnabled as jest.Mock;
useIsThreatIntelModuleEnabledMock.mockReturnValue(true);
describe('ThreatIntelLinkPanel', () => { describe('ThreatIntelLinkPanel', () => {
const state: State = mockGlobalState; const state: State = mockGlobalState;
@ -44,7 +39,7 @@ describe('ThreatIntelLinkPanel', () => {
<Provider store={store}> <Provider store={store}>
<I18nProvider> <I18nProvider>
<ThemeProvider theme={mockTheme}> <ThemeProvider theme={mockTheme}>
<ThreatIntelLinkPanel {...mockProps} /> <ThreatIntelLinkPanel {...mockProps} isThreatIntelModuleEnabled={true} />
</ThemeProvider> </ThemeProvider>
</I18nProvider> </I18nProvider>
</Provider> </Provider>
@ -54,12 +49,11 @@ describe('ThreatIntelLinkPanel', () => {
}); });
it('renders CtiDisabledModule when Threat Intel module is disabled', () => { it('renders CtiDisabledModule when Threat Intel module is disabled', () => {
useIsThreatIntelModuleEnabledMock.mockReturnValueOnce(false);
const wrapper = mount( const wrapper = mount(
<Provider store={store}> <Provider store={store}>
<I18nProvider> <I18nProvider>
<ThemeProvider theme={mockTheme}> <ThemeProvider theme={mockTheme}>
<ThreatIntelLinkPanel {...mockProps} /> <ThreatIntelLinkPanel {...mockProps} isThreatIntelModuleEnabled={false} />
</ThemeProvider> </ThemeProvider>
</I18nProvider> </I18nProvider>
</Provider> </Provider>
@ -69,12 +63,11 @@ describe('ThreatIntelLinkPanel', () => {
}); });
it('renders null while Threat Intel module state is loading', () => { it('renders null while Threat Intel module state is loading', () => {
useIsThreatIntelModuleEnabledMock.mockReturnValueOnce(undefined);
const wrapper = mount( const wrapper = mount(
<Provider store={store}> <Provider store={store}>
<I18nProvider> <I18nProvider>
<ThemeProvider theme={mockTheme}> <ThemeProvider theme={mockTheme}>
<ThreatIntelLinkPanel {...mockProps} /> <ThreatIntelLinkPanel {...mockProps} isThreatIntelModuleEnabled={undefined} />
</ThemeProvider> </ThemeProvider>
</I18nProvider> </I18nProvider>
</Provider> </Provider>

View file

@ -8,19 +8,18 @@
import React from 'react'; import React from 'react';
import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { GlobalTimeArgs } from '../../../common/containers/use_global_time';
import { useIsThreatIntelModuleEnabled } from '../../containers/overview_cti_links/use_is_threat_intel_module_enabled';
import { CtiEnabledModule } from './cti_enabled_module'; import { CtiEnabledModule } from './cti_enabled_module';
import { CtiDisabledModule } from './cti_disabled_module'; import { CtiDisabledModule } from './cti_disabled_module';
export type ThreatIntelLinkPanelProps = Pick< export type ThreatIntelLinkPanelProps = Pick<
GlobalTimeArgs, GlobalTimeArgs,
'from' | 'to' | 'deleteQuery' | 'setQuery' 'from' | 'to' | 'deleteQuery' | 'setQuery'
>; > & {
isThreatIntelModuleEnabled: boolean | undefined;
};
const ThreatIntelLinkPanelComponent: React.FC<ThreatIntelLinkPanelProps> = (props) => { const ThreatIntelLinkPanelComponent: React.FC<ThreatIntelLinkPanelProps> = (props) => {
const isThreatIntelModuleEnabled = useIsThreatIntelModuleEnabled(); switch (props.isThreatIntelModuleEnabled) {
switch (isThreatIntelModuleEnabled) {
case true: case true:
return <CtiEnabledModule {...props} data-test-subj="cti-enabled-module" />; return <CtiEnabledModule {...props} data-test-subj="cti-enabled-module" />;
case false: case false:

View file

@ -6,19 +6,14 @@
*/ */
import { useEffect, useState, useMemo } from 'react'; import { useEffect, useState, useMemo } from 'react';
import { ThreatIntelLinkPanelProps } from '../../components/overview_cti_links';
import { useRequestEventCounts } from './use_request_event_counts'; import { useRequestEventCounts } from './use_request_event_counts';
import { emptyEventCountsByDataset } from './helpers'; import { emptyEventCountsByDataset } from './helpers';
import { CtiEnabledModuleProps } from '../../components/overview_cti_links/cti_enabled_module';
export const ID = 'ctiEventCountQuery'; export const ID = 'ctiEventCountQuery';
const PREFIX = 'threatintel.'; const PREFIX = 'threatintel.';
export const useCtiEventCounts = ({ export const useCtiEventCounts = ({ deleteQuery, from, setQuery, to }: CtiEnabledModuleProps) => {
deleteQuery,
from,
setQuery,
to,
}: ThreatIntelLinkPanelProps) => {
const [isInitialLoading, setIsInitialLoading] = useState(true); const [isInitialLoading, setIsInitialLoading] = useState(true);
const [loading, { data, inspect, totalCount, refetch }] = useRequestEventCounts(to, from); const [loading, { data, inspect, totalCount, refetch }] = useRequestEventCounts(to, from);

View file

@ -87,6 +87,7 @@ describe('Overview', () => {
}, },
]); ]);
}); });
describe('rendering', () => { describe('rendering', () => {
test('it DOES NOT render the Getting started text when an index is available', () => { test('it DOES NOT render the Getting started text when an index is available', () => {
mockUseSourcererScope.mockReturnValue({ mockUseSourcererScope.mockReturnValue({
@ -277,4 +278,18 @@ describe('Overview', () => {
}); });
}); });
}); });
describe('Threat Intel Dashboard Links', () => {
it('invokes useIsThreatIntelModuleEnabled hook only once', () => {
useIsThreatIntelModuleEnabledMock.mockClear();
mount(
<TestProviders>
<MemoryRouter>
<Overview />
</MemoryRouter>
</TestProviders>
);
expect(useIsThreatIntelModuleEnabledMock).toHaveBeenCalledTimes(1);
});
});
}); });

View file

@ -33,6 +33,7 @@ import { Sourcerer } from '../../common/components/sourcerer';
import { SourcererScopeName } from '../../common/store/sourcerer/model'; import { SourcererScopeName } from '../../common/store/sourcerer/model';
import { useDeepEqualSelector } from '../../common/hooks/use_selector'; import { useDeepEqualSelector } from '../../common/hooks/use_selector';
import { ThreatIntelLinkPanel } from '../components/overview_cti_links'; import { ThreatIntelLinkPanel } from '../components/overview_cti_links';
import { useIsThreatIntelModuleEnabled } from '../containers/overview_cti_links/use_is_threat_intel_module_enabled';
const SidebarFlexItem = styled(EuiFlexItem)` const SidebarFlexItem = styled(EuiFlexItem)`
margin-right: 24px; margin-right: 24px;
@ -70,6 +71,8 @@ const OverviewComponent = () => {
addMessage('management', 'dismissEndpointNotice'); addMessage('management', 'dismissEndpointNotice');
}, [addMessage]); }, [addMessage]);
const { allEnabled: isIngestEnabled } = useIngestEnabledCheck(); const { allEnabled: isIngestEnabled } = useIngestEnabledCheck();
const isThreatIntelModuleEnabled = useIsThreatIntelModuleEnabled();
return ( return (
<> <>
{indicesExist ? ( {indicesExist ? (
@ -143,6 +146,7 @@ const OverviewComponent = () => {
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<ThreatIntelLinkPanel <ThreatIntelLinkPanel
isThreatIntelModuleEnabled={isThreatIntelModuleEnabled}
deleteQuery={deleteQuery} deleteQuery={deleteQuery}
from={from} from={from}
setQuery={setQuery} setQuery={setQuery}