[Security Solution] Fix TopN filters in timeline (#183501)

## Summary

Fixes: https://github.com/elastic/kibana/issues/183497

Sets the `applyGlobalQueriesAndFilters` prop correctly to
_VisualizationEmbeddable_. This property was ignored when used from the
_TopN_ component, causing it to always apply the global filters and
query.

Extra: I cleaned all props that are not used in those component

### Screenshots

Pre-condition: Setting `user.name:"0q3c5et718"` query to the global
query in the background.

Before:


![before](0b9ee913-44dc-48a7-a170-1c537ae494cf)

After:


![after](89b6f752-d640-4e99-a826-0ff78d84992b)

---------

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Sergi Massaneda 2024-05-16 10:45:31 +02:00 committed by GitHub
parent ece10c6139
commit 5acea44cc9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 36 additions and 33 deletions

View file

@ -276,6 +276,12 @@ describe('StatefulTopN', () => {
expect(props.to).toEqual('2020-07-08T08:20:18.966Z');
});
test(`provides 'applyGlobalQueriesAndFilters' = true`, () => {
const props = wrapper.find('[data-test-subj="top-n"]').first().props() as Props;
expect(props.applyGlobalQueriesAndFilters).toEqual(true);
});
});
describe('rendering in a timeline context', () => {
@ -343,26 +349,38 @@ describe('StatefulTopN', () => {
expect(props.to).toEqual('2020-04-15T03:46:09.047Z');
});
test(`provides 'applyGlobalQueriesAndFilters' = false`, () => {
const props = wrapper.find('[data-test-subj="top-n"]').first().props() as Props;
expect(props.applyGlobalQueriesAndFilters).toEqual(false);
});
});
describe('rendering in alerts context', () => {
detectionAlertsTables.forEach((tableId) => {
test(`defaults to the 'Alert events' option when rendering in Alerts`, async () => {
const wrapper = mount(
describe.each(detectionAlertsTables)('tableId: %s', (tableId) => {
let wrapper: ReactWrapper;
beforeEach(() => {
wrapper = mount(
<TestProviders store={store}>
<StatefulTopN
{...{
...testProps,
scopeId: tableId,
}}
/>
<StatefulTopN {...{ ...testProps, scopeId: tableId }} />
</TestProviders>
);
});
afterEach(() => {
wrapper.unmount();
});
test(`defaults to the 'Alert events' option when rendering in Alerts`, async () => {
await waitFor(() => {
const props = wrapper.find('[data-test-subj="top-n"]').first().props() as Props;
expect(props.defaultView).toEqual('alert');
});
wrapper.unmount();
});
test(`provides 'applyGlobalQueriesAndFilters' = true`, () => {
const props = wrapper.find('[data-test-subj="top-n"]').first().props() as Props;
expect(props.applyGlobalQueriesAndFilters).toEqual(true);
});
});
});

View file

@ -111,6 +111,7 @@ const StatefulTopNComponent: React.FC<Props> = ({
const { from, deleteQuery, setQuery, to } = useGlobalTime();
const options = getOptions(isActiveTimeline(scopeId ?? '') ? activeTimelineEventType : undefined);
const applyGlobalQueriesAndFilters = !isActiveTimeline(scopeId ?? '');
const combinedQueries = useMemo(
() =>
@ -158,7 +159,6 @@ const StatefulTopNComponent: React.FC<Props> = ({
options={options}
paddingSize={paddingSize}
query={isActiveTimeline(scopeId ?? '') ? EMPTY_QUERY : globalQuery}
showLegend={showLegend}
setAbsoluteRangeDatePickerTarget={
isActiveTimeline(scopeId ?? '') ? InputsModelId.timeline : InputsModelId.global
}
@ -167,6 +167,7 @@ const StatefulTopNComponent: React.FC<Props> = ({
to={isActiveTimeline(scopeId ?? '') ? activeTimelineTo : to}
toggleTopN={toggleTopN}
onFilterAdded={onFilterAdded}
applyGlobalQueriesAndFilters={applyGlobalQueriesAndFilters}
/>
);
};

View file

@ -15,7 +15,6 @@ import { EventsByDataset } from '../../../overview/components/events_by_dataset'
import { SignalsByCategory } from '../../../overview/components/signals_by_category';
import type { InputsModelId } from '../../store/inputs/constants';
import type { TimelineEventsType } from '../../../../common/types/timeline';
import { useSourcererDataView } from '../../containers/sourcerer';
import type { TopNOption } from './helpers';
import { getSourcererScopeName, removeIgnoredAlertFilters } from './helpers';
import * as i18n from './translations';
@ -54,10 +53,10 @@ export interface Props extends Pick<GlobalTimeArgs, 'from' | 'to' | 'deleteQuery
paddingSize?: 's' | 'm' | 'l' | 'none';
query: Query;
setAbsoluteRangeDatePickerTarget: InputsModelId;
showLegend?: boolean;
scopeId?: string;
toggleTopN: () => void;
onFilterAdded?: () => void; // eslint-disable-line react/no-unused-prop-types
applyGlobalQueriesAndFilters?: boolean;
}
const TopNComponent: React.FC<Props> = ({
@ -71,12 +70,12 @@ const TopNComponent: React.FC<Props> = ({
options,
paddingSize,
query,
showLegend,
setAbsoluteRangeDatePickerTarget,
setQuery,
scopeId,
to,
toggleTopN,
applyGlobalQueriesAndFilters,
}) => {
const [view, setView] = useState<TimelineEventsType>(defaultView);
const onViewSelected = useCallback(
@ -84,7 +83,6 @@ const TopNComponent: React.FC<Props> = ({
[setView]
);
const sourcererScopeId = getSourcererScopeName({ scopeId, view });
const { selectedPatterns, runtimeMappings } = useSourcererDataView(sourcererScopeId);
useEffect(() => {
setView(defaultView);
@ -121,21 +119,17 @@ const TopNComponent: React.FC<Props> = ({
from={from}
headerChildren={headerChildren}
indexPattern={indexPattern}
indexNames={selectedPatterns}
runtimeMappings={runtimeMappings}
onlyField={field}
paddingSize={paddingSize}
query={query}
queryType="topN"
showLegend={showLegend}
setAbsoluteRangeDatePickerTarget={setAbsoluteRangeDatePickerTarget}
setQuery={setQuery}
showSpacer={false}
toggleTopN={toggleTopN}
scopeId={scopeId}
sourcererScopeId={sourcererScopeId}
to={to}
hideQueryToggle
applyGlobalQueriesAndFilters={applyGlobalQueriesAndFilters}
/>
) : (
<SignalsByCategory

View file

@ -7,7 +7,6 @@
import { Position } from '@elastic/charts';
import numeral from '@elastic/numeral';
import type { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import React, { useEffect, useMemo, useCallback } from 'react';
import type { DataViewBase, Filter, Query } from '@kbn/es-query';
@ -29,7 +28,6 @@ import {
eventsHistogramConfig,
} from '../../../common/components/events_tab/histogram_configurations';
import { HostsTableType } from '../../../explore/hosts/store/model';
import type { InputsModelId } from '../../../common/store/inputs/constants';
import type { GlobalTimeArgs } from '../../../common/containers/use_global_time';
import * as i18n from '../../pages/translations';
@ -48,20 +46,16 @@ interface Props extends Pick<GlobalTimeArgs, 'from' | 'to' | 'deleteQuery' | 'se
filters: Filter[];
headerChildren?: React.ReactNode;
indexPattern: DataViewBase;
indexNames: string[];
runtimeMappings?: MappingRuntimeFields;
onlyField?: string;
paddingSize?: 's' | 'm' | 'l' | 'none';
query: Query;
// Make a unique query type everywhere this query is used
queryType: 'topN' | 'overview';
setAbsoluteRangeDatePickerTarget?: InputsModelId;
showLegend?: boolean;
showSpacer?: boolean;
scopeId?: string;
toggleTopN?: () => void;
hideQueryToggle?: boolean;
sourcererScopeId?: SourcererScopeName;
applyGlobalQueriesAndFilters?: boolean;
}
const getHistogramOption = (fieldName: string): MatrixHistogramOption => ({
@ -83,21 +77,17 @@ const EventsByDatasetComponent: React.FC<Props> = ({
from,
headerChildren,
indexPattern,
indexNames,
runtimeMappings,
onlyField,
paddingSize,
query,
queryType,
setAbsoluteRangeDatePickerTarget,
setQuery,
showLegend,
showSpacer = true,
scopeId,
sourcererScopeId,
to,
toggleTopN,
hideQueryToggle = false,
applyGlobalQueriesAndFilters,
}) => {
const uniqueQueryId = useMemo(() => `${ID}-${queryType}`, [queryType]);
@ -204,6 +194,7 @@ const EventsByDatasetComponent: React.FC<Props> = ({
title={onlyField != null ? i18n.TOP(onlyField) : eventsByDatasetHistogramConfigs.title}
chartHeight={CHART_HEIGHT}
hideQueryToggle={hideQueryToggle}
applyGlobalQueriesAndFilters={applyGlobalQueriesAndFilters}
/>
);
};

View file

@ -115,7 +115,6 @@ const OverviewComponent = () => {
filters={filters}
from={from}
indexPattern={indexPattern}
indexNames={selectedPatterns}
query={query}
queryType="overview"
setQuery={setQuery}