mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Bug][Security Solution] - Reliably persist dataview selections for timeline (#211343)
resolves https://github.com/elastic/kibana/issues/198944 ## Summary Currently, the redux store can become out of sync with the state in the UI, leading to the selected dataview not being preserved in the store, and thereby not being saved when the timeline is saved. This PR sets the selected dataview and patterns at the point of saving to ensure that they are set and not overriden. For additional background, see referenced issues.
This commit is contained in:
parent
ccae358d37
commit
4abf1a151e
3 changed files with 28 additions and 7 deletions
|
@ -12,7 +12,7 @@ import { TimelineId, TimelineTabs } from '../../../../common/types/timeline';
|
|||
import { TimelineTypeEnum, TimelineStatusEnum } from '../../../../common/api/timeline';
|
||||
import { convertTimelineAsInput } from './timeline_save';
|
||||
import type { TimelineModel } from '../model';
|
||||
import { createMockStore, kibanaMock } from '../../../common/mock';
|
||||
import { createMockStore, kibanaMock, mockGlobalState } from '../../../common/mock';
|
||||
import { selectTimelineById } from '../selectors';
|
||||
import { copyTimeline, persistTimeline } from '../../containers/api';
|
||||
import { refreshTimelines } from './helpers';
|
||||
|
@ -71,7 +71,14 @@ describe('Timeline save middleware', () => {
|
|||
await store.dispatch(saveTimeline({ id: TimelineId.test, saveAsNew: false }));
|
||||
|
||||
expect(startTimelineSavingMock).toHaveBeenCalled();
|
||||
expect(persistTimeline as unknown as jest.Mock).toHaveBeenCalled();
|
||||
expect(persistTimeline as unknown as jest.Mock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
timeline: expect.objectContaining({
|
||||
dataViewId: mockGlobalState.sourcerer.sourcererScopes.timeline.selectedDataViewId,
|
||||
indexNames: mockGlobalState.sourcerer.sourcererScopes.timeline.selectedPatterns,
|
||||
}),
|
||||
})
|
||||
);
|
||||
expect(refreshTimelines as unknown as jest.Mock).toHaveBeenCalled();
|
||||
expect(endTimelineSavingMock).toHaveBeenCalled();
|
||||
expect(selectTimelineById(store.getState(), TimelineId.test)).toEqual(
|
||||
|
|
|
@ -20,6 +20,7 @@ import {
|
|||
isPhrasesFilter,
|
||||
} from '@kbn/es-query';
|
||||
|
||||
import { sourcererSelectors } from '../../../sourcerer/store';
|
||||
import {
|
||||
updateTimeline,
|
||||
startTimelineSaving,
|
||||
|
@ -43,6 +44,7 @@ import type {
|
|||
import type { TimelineModel } from '../model';
|
||||
import type { ColumnHeaderOptions } from '../../../../common/types/timeline';
|
||||
import { refreshTimelines } from './helpers';
|
||||
import { SourcererScopeName } from '../../../sourcerer/store/model';
|
||||
|
||||
function isSaveTimelineAction(action: Action): action is ReturnType<typeof saveTimeline> {
|
||||
return action.type === saveTimeline.type;
|
||||
|
@ -55,10 +57,19 @@ export const saveTimelineMiddleware: (kibana: CoreStart) => Middleware<{}, State
|
|||
|
||||
if (isSaveTimelineAction(action)) {
|
||||
const { id: localTimelineId } = action.payload;
|
||||
const timeline = selectTimelineById(store.getState(), localTimelineId);
|
||||
const storeState = store.getState();
|
||||
const timeline = selectTimelineById(storeState, localTimelineId);
|
||||
const { timelineId, timelineVersion, templateTimelineId, templateTimelineVersion } =
|
||||
extractTimelineIdsAndVersions(timeline);
|
||||
const timelineTimeRange = inputsSelectors.timelineTimeRangeSelector(store.getState());
|
||||
const timelineTimeRange = inputsSelectors.timelineTimeRangeSelector(storeState);
|
||||
const selectedDataViewIdSourcerer = sourcererSelectors.sourcererScopeSelectedDataViewId(
|
||||
storeState,
|
||||
SourcererScopeName.timeline
|
||||
);
|
||||
const selectedPatterns = sourcererSelectors.sourcererScopeSelectedPatterns(
|
||||
storeState,
|
||||
SourcererScopeName.timeline
|
||||
);
|
||||
|
||||
store.dispatch(startTimelineSaving({ id: localTimelineId }));
|
||||
|
||||
|
@ -68,6 +79,8 @@ export const saveTimelineMiddleware: (kibana: CoreStart) => Middleware<{}, State
|
|||
timelineId,
|
||||
timeline: {
|
||||
...convertTimelineAsInput(timeline, timelineTimeRange),
|
||||
dataViewId: selectedDataViewIdSourcerer,
|
||||
indexNames: selectedPatterns,
|
||||
templateTimelineId,
|
||||
templateTimelineVersion,
|
||||
},
|
||||
|
@ -78,6 +91,8 @@ export const saveTimelineMiddleware: (kibana: CoreStart) => Middleware<{}, State
|
|||
version: timelineVersion,
|
||||
timeline: {
|
||||
...convertTimelineAsInput(timeline, timelineTimeRange),
|
||||
dataViewId: selectedDataViewIdSourcerer,
|
||||
indexNames: selectedPatterns,
|
||||
templateTimelineId,
|
||||
templateTimelineVersion,
|
||||
},
|
||||
|
|
|
@ -40,8 +40,7 @@ import { closeTimeline, openTimelineById } from '../../../tasks/timeline';
|
|||
const siemDataViewTitle = 'Security Default Data View';
|
||||
const dataViews = ['logs-*', 'metrics-*', '.kibana-event-log-*'];
|
||||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/198944
|
||||
describe.skip('Timeline scope', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
describe('Timeline scope', { tags: ['@ess', '@serverless'] }, () => {
|
||||
before(() => {
|
||||
waitForRulesBootstrap();
|
||||
});
|
||||
|
@ -132,7 +131,7 @@ describe.skip('Timeline scope', { tags: ['@ess', '@serverless', '@skipInServerle
|
|||
});
|
||||
|
||||
const defaultPatterns = [`auditbeat-*`, `${DEFAULT_ALERTS_INDEX}-default`];
|
||||
it('alerts checkbox behaves as expected', () => {
|
||||
it('alerts checkbox behaves as expected', { tags: ['@skipInServerless'] }, () => {
|
||||
isDataViewSelection(siemDataViewTitle);
|
||||
defaultPatterns.forEach((pattern) => isSourcererSelection(pattern));
|
||||
openDataViewSelection();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue