diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts index 9ee80636fab2e9..4567d043ad0be2 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts @@ -358,7 +358,8 @@ describe('Custom detection rules deletion and edition', () => { }); }); - it('Allows a rule to be edited', () => { + // TODO: Remove when https://github.com/elastic/kibana/pull/111251 is merged + it.skip('Allows a rule to be edited', () => { editFirstRule(); waitForKibana(); diff --git a/x-pack/plugins/security_solution/public/common/mock/global_state.ts b/x-pack/plugins/security_solution/public/common/mock/global_state.ts index fb772986bc6799..cb6536d585c1e0 100644 --- a/x-pack/plugins/security_solution/public/common/mock/global_state.ts +++ b/x-pack/plugins/security_solution/public/common/mock/global_state.ts @@ -242,6 +242,9 @@ export const mockGlobalState: State = { activeTab: TimelineTabs.query, prevActiveTab: TimelineTabs.notes, deletedEventIds: [], + documentType: '', + queryFields: [], + selectAll: false, id: 'test', savedObjectId: null, columns: defaultHeaders, diff --git a/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts b/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts index 1c16fda54b90ae..b601e531d49914 100644 --- a/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts +++ b/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts @@ -1979,6 +1979,7 @@ export const mockTimelineModel: TimelineModel = { }, deletedEventIds: [], description: 'This is a sample rule description', + documentType: '', eqlOptions: { eventCategoryField: 'event.category', tiebreakerField: 'event.sequence', @@ -2017,6 +2018,7 @@ export const mockTimelineModel: TimelineModel = { kqlQuery: { filterQuery: null, }, + queryFields: [], itemsPerPage: 25, itemsPerPageOptions: [10, 25, 50, 100], loadingEventIds: [], @@ -2024,6 +2026,7 @@ export const mockTimelineModel: TimelineModel = { pinnedEventIds: {}, pinnedEventsSaveObject: {}, savedObjectId: 'ef579e40-jibber-jabber', + selectAll: false, selectedEventIds: {}, show: false, showCheckboxes: false, @@ -2110,6 +2113,7 @@ export const defaultTimelineProps: CreateTimelineProps = { dateRange: { end: '2018-11-05T19:03:25.937Z', start: '2018-11-05T18:58:25.937Z' }, deletedEventIds: [], description: '', + documentType: '', eqlOptions: { eventCategoryField: 'event.category', query: '', @@ -2141,7 +2145,9 @@ export const defaultTimelineProps: CreateTimelineProps = { noteIds: [], pinnedEventIds: {}, pinnedEventsSaveObject: {}, + queryFields: [], savedObjectId: null, + selectAll: false, selectedEventIds: {}, show: false, showCheckboxes: false, diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx index 69160d90a011eb..e7a8ba91cff8f3 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx @@ -148,6 +148,7 @@ describe('alert actions', () => { }, deletedEventIds: [], description: 'This is a sample rule description', + documentType: '', eqlOptions: { eventCategoryField: 'event.category', query: '', @@ -204,7 +205,9 @@ describe('alert actions', () => { noteIds: [], pinnedEventIds: {}, pinnedEventsSaveObject: {}, + queryFields: [], savedObjectId: null, + selectAll: false, selectedEventIds: {}, show: true, showCheckboxes: false, diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.test.ts b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.test.ts index ae15768d26e70d..37bdfd38bf8bc0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.test.ts @@ -296,6 +296,7 @@ describe('helpers', () => { dataProviders: [], dateRange: { start: '2020-07-07T08:20:18.966Z', end: '2020-07-08T08:20:18.966Z' }, description: '', + documentType: '', deletedEventIds: [], eqlOptions: { eventCategoryField: 'event.category', @@ -328,7 +329,9 @@ describe('helpers', () => { noteIds: [], pinnedEventIds: {}, pinnedEventsSaveObject: {}, + queryFields: [], savedObjectId: 'savedObject-1', + selectAll: false, selectedEventIds: {}, show: false, showCheckboxes: false, @@ -366,6 +369,7 @@ describe('helpers', () => { dataProviders: [], dateRange: { start: '2020-07-07T08:20:18.966Z', end: '2020-07-08T08:20:18.966Z' }, description: '', + documentType: '', deletedEventIds: [], eqlOptions: { eventCategoryField: 'event.category', @@ -398,7 +402,9 @@ describe('helpers', () => { noteIds: [], pinnedEventIds: {}, pinnedEventsSaveObject: {}, + queryFields: [], savedObjectId: 'savedObject-1', + selectAll: false, selectedEventIds: {}, show: false, showCheckboxes: false, @@ -436,6 +442,7 @@ describe('helpers', () => { dataProviders: [], dateRange: { start: '2020-07-07T08:20:18.966Z', end: '2020-07-08T08:20:18.966Z' }, description: '', + documentType: '', deletedEventIds: [], eqlOptions: { eventCategoryField: 'event.category', @@ -468,7 +475,9 @@ describe('helpers', () => { noteIds: [], pinnedEventIds: {}, pinnedEventsSaveObject: {}, + queryFields: [], savedObjectId: 'savedObject-1', + selectAll: false, selectedEventIds: {}, show: false, showCheckboxes: false, @@ -504,6 +513,7 @@ describe('helpers', () => { dataProviders: [], dateRange: { start: '2020-07-07T08:20:18.966Z', end: '2020-07-08T08:20:18.966Z' }, description: '', + documentType: '', deletedEventIds: [], eqlOptions: { eventCategoryField: 'event.category', @@ -536,7 +546,9 @@ describe('helpers', () => { noteIds: [], pinnedEventIds: {}, pinnedEventsSaveObject: {}, + queryFields: [], savedObjectId: 'savedObject-1', + selectAll: false, selectedEventIds: {}, show: false, showCheckboxes: false, @@ -577,6 +589,7 @@ describe('helpers', () => { dataProviders: [], dateRange: { start: '2020-07-07T08:20:18.966Z', end: '2020-07-08T08:20:18.966Z' }, description: '', + documentType: '', deletedEventIds: [], eqlOptions: { eventCategoryField: 'event.category', @@ -612,6 +625,8 @@ describe('helpers', () => { noteIds: [], pinnedEventIds: {}, pinnedEventsSaveObject: {}, + queryFields: [], + selectAll: false, selectedEventIds: {}, show: false, showCheckboxes: false, @@ -680,6 +695,7 @@ describe('helpers', () => { dateRange: { start: '2020-07-07T08:20:18.966Z', end: '2020-07-08T08:20:18.966Z' }, dataProviders: [], description: '', + documentType: '', deletedEventIds: [], eqlOptions: { eventCategoryField: 'event.category', @@ -758,6 +774,8 @@ describe('helpers', () => { noteIds: [], pinnedEventIds: {}, pinnedEventsSaveObject: {}, + queryFields: [], + selectAll: false, selectedEventIds: {}, show: false, showCheckboxes: false, @@ -791,6 +809,7 @@ describe('helpers', () => { dataProviders: [], dateRange: { end: '2020-10-28T11:37:31.655Z', start: '2020-10-27T11:37:31.655Z' }, description: '', + documentType: '', deletedEventIds: [], eqlOptions: { eventCategoryField: 'event.category', @@ -823,7 +842,9 @@ describe('helpers', () => { noteIds: [], pinnedEventIds: {}, pinnedEventsSaveObject: {}, + queryFields: [], savedObjectId: 'savedObject-1', + selectAll: false, selectedEventIds: {}, show: false, showCheckboxes: false, @@ -861,6 +882,7 @@ describe('helpers', () => { dataProviders: [], dateRange: { end: '2020-07-08T08:20:18.966Z', start: '2020-07-07T08:20:18.966Z' }, description: '', + documentType: '', deletedEventIds: [], eqlOptions: { eventCategoryField: 'event.category', @@ -893,7 +915,9 @@ describe('helpers', () => { noteIds: [], pinnedEventIds: {}, pinnedEventsSaveObject: {}, + queryFields: [], savedObjectId: 'savedObject-1', + selectAll: false, selectedEventIds: {}, show: false, showCheckboxes: false, diff --git a/x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.test.ts b/x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.test.ts index f1b5f6a9446780..8fbb330d512316 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.test.ts +++ b/x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.test.ts @@ -28,6 +28,17 @@ const useKibanaMock = useKibana as jest.Mocked; const getExpectedColumns = (model: TimelineModel) => model.columns.map(migrateColumnWidthToInitialWidth).map(migrateColumnLabelToDisplayAsText); +const { + documentType, + filterManager, + isLoading, + loadingText, + queryFields, + selectAll, + unit, + ...timelineToStore +} = mockTimelineModel; + describe('SiemLocalStorage', () => { const { localStorage, storage } = createSecuritySolutionStorageMock(); @@ -41,7 +52,7 @@ describe('SiemLocalStorage', () => { const timelineStorage = useTimelinesStorage(); timelineStorage.addTimeline(TimelineId.hostsPageEvents, mockTimelineModel); expect(JSON.parse(localStorage.getItem(LOCAL_STORAGE_TIMELINE_KEY))).toEqual({ - [TimelineId.hostsPageEvents]: mockTimelineModel, + [TimelineId.hostsPageEvents]: timelineToStore, }); }); @@ -50,8 +61,8 @@ describe('SiemLocalStorage', () => { timelineStorage.addTimeline(TimelineId.hostsPageEvents, mockTimelineModel); timelineStorage.addTimeline(TimelineId.hostsPageExternalAlerts, mockTimelineModel); expect(JSON.parse(localStorage.getItem(LOCAL_STORAGE_TIMELINE_KEY))).toEqual({ - [TimelineId.hostsPageEvents]: mockTimelineModel, - [TimelineId.hostsPageExternalAlerts]: mockTimelineModel, + [TimelineId.hostsPageEvents]: timelineToStore, + [TimelineId.hostsPageExternalAlerts]: timelineToStore, }); }); }); @@ -63,8 +74,8 @@ describe('SiemLocalStorage', () => { timelineStorage.addTimeline(TimelineId.hostsPageExternalAlerts, mockTimelineModel); const timelines = timelineStorage.getAllTimelines(); expect(timelines).toEqual({ - [TimelineId.hostsPageEvents]: mockTimelineModel, - [TimelineId.hostsPageExternalAlerts]: mockTimelineModel, + [TimelineId.hostsPageEvents]: timelineToStore, + [TimelineId.hostsPageExternalAlerts]: timelineToStore, }); }); @@ -80,7 +91,7 @@ describe('SiemLocalStorage', () => { const timelineStorage = useTimelinesStorage(); timelineStorage.addTimeline(TimelineId.hostsPageEvents, mockTimelineModel); const timeline = timelineStorage.getTimelineById(TimelineId.hostsPageEvents); - expect(timeline).toEqual(mockTimelineModel); + expect(timeline).toEqual(timelineToStore); }); }); @@ -94,8 +105,8 @@ describe('SiemLocalStorage', () => { TimelineId.hostsPageExternalAlerts, ]); expect(timelines).toEqual({ - [TimelineId.hostsPageEvents]: mockTimelineModel, - [TimelineId.hostsPageExternalAlerts]: mockTimelineModel, + [TimelineId.hostsPageEvents]: timelineToStore, + [TimelineId.hostsPageExternalAlerts]: timelineToStore, }); }); @@ -126,7 +137,7 @@ describe('SiemLocalStorage', () => { TimelineId.hostsPageExternalAlerts, ]); expect(timelines).toEqual({ - [TimelineId.hostsPageEvents]: mockTimelineModel, + [TimelineId.hostsPageEvents]: timelineToStore, }); }); @@ -152,8 +163,8 @@ describe('SiemLocalStorage', () => { // all legacy `width` values are migrated to `initialWidth`: expect(timelines).toStrictEqual({ [TimelineId.hostsPageEvents]: { - ...mockTimelineModel, - columns: mockTimelineModel.columns.map((c) => ({ + ...timelineToStore, + columns: timelineToStore.columns.map((c) => ({ ...c, displayAsText: undefined, initialWidth: 98765, @@ -161,7 +172,7 @@ describe('SiemLocalStorage', () => { })), }, [TimelineId.hostsPageExternalAlerts]: { - ...mockTimelineModel, + ...timelineToStore, columns: getExpectedColumns(mockTimelineModel), }, }); @@ -187,8 +198,8 @@ describe('SiemLocalStorage', () => { expect(timelines).toStrictEqual({ [TimelineId.hostsPageEvents]: { - ...mockTimelineModel, - columns: mockTimelineModel.columns.map((c) => ({ + ...timelineToStore, + columns: timelineToStore.columns.map((c) => ({ ...c, displayAsText: undefined, initialWidth: c.initialWidth, // initialWidth is unchanged @@ -196,7 +207,7 @@ describe('SiemLocalStorage', () => { })), }, [TimelineId.hostsPageExternalAlerts]: { - ...mockTimelineModel, + ...timelineToStore, columns: getExpectedColumns(mockTimelineModel), }, }); @@ -223,15 +234,15 @@ describe('SiemLocalStorage', () => { // all legacy `label` values are migrated to `displayAsText`: expect(timelines).toStrictEqual({ [TimelineId.hostsPageEvents]: { - ...mockTimelineModel, - columns: mockTimelineModel.columns.map((c, i) => ({ + ...timelineToStore, + columns: timelineToStore.columns.map((c, i) => ({ ...c, displayAsText: `A legacy label ${i}`, label: `A legacy label ${i}`, })), }, [TimelineId.hostsPageExternalAlerts]: { - ...mockTimelineModel, + ...timelineToStore, columns: getExpectedColumns(mockTimelineModel), }, }); @@ -259,8 +270,8 @@ describe('SiemLocalStorage', () => { expect(timelines).toStrictEqual({ [TimelineId.hostsPageEvents]: { - ...mockTimelineModel, - columns: mockTimelineModel.columns.map((c, i) => ({ + ...timelineToStore, + columns: timelineToStore.columns.map((c, i) => ({ ...c, displayAsText: 'Label will NOT be migrated to displayAsText, because displayAsText already has a value', @@ -268,7 +279,7 @@ describe('SiemLocalStorage', () => { })), }, [TimelineId.hostsPageExternalAlerts]: { - ...mockTimelineModel, + ...timelineToStore, columns: getExpectedColumns(mockTimelineModel), }, }); @@ -293,11 +304,11 @@ describe('SiemLocalStorage', () => { expect(timelines).toStrictEqual({ [TimelineId.hostsPageEvents]: { - ...mockTimelineModel, + ...timelineToStore, columns: 'this is NOT an array', }, [TimelineId.hostsPageExternalAlerts]: { - ...mockTimelineModel, + ...timelineToStore, columns: getExpectedColumns(mockTimelineModel), }, }); @@ -311,8 +322,8 @@ describe('SiemLocalStorage', () => { timelineStorage.addTimeline(TimelineId.hostsPageExternalAlerts, mockTimelineModel); const timelines = getAllTimelinesInStorage(storage); expect(timelines).toEqual({ - [TimelineId.hostsPageEvents]: mockTimelineModel, - [TimelineId.hostsPageExternalAlerts]: mockTimelineModel, + [TimelineId.hostsPageEvents]: timelineToStore, + [TimelineId.hostsPageExternalAlerts]: timelineToStore, }); }); @@ -326,7 +337,7 @@ describe('SiemLocalStorage', () => { it('adds a timeline when storage is empty', () => { addTimelineInStorage(storage, TimelineId.hostsPageEvents, mockTimelineModel); expect(JSON.parse(localStorage.getItem(LOCAL_STORAGE_TIMELINE_KEY))).toEqual({ - [TimelineId.hostsPageEvents]: mockTimelineModel, + [TimelineId.hostsPageEvents]: timelineToStore, }); }); @@ -334,8 +345,8 @@ describe('SiemLocalStorage', () => { addTimelineInStorage(storage, TimelineId.hostsPageEvents, mockTimelineModel); addTimelineInStorage(storage, TimelineId.hostsPageExternalAlerts, mockTimelineModel); expect(JSON.parse(localStorage.getItem(LOCAL_STORAGE_TIMELINE_KEY))).toEqual({ - [TimelineId.hostsPageEvents]: mockTimelineModel, - [TimelineId.hostsPageExternalAlerts]: mockTimelineModel, + [TimelineId.hostsPageEvents]: timelineToStore, + [TimelineId.hostsPageExternalAlerts]: timelineToStore, }); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.tsx index 99f45c7d9a4b45..dd60656933ba83 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.tsx @@ -85,13 +85,29 @@ export const addTimelineInStorage = ( id: TimelineIdLiteral, timeline: TimelineModel ) => { + const timelineToStore = cleanStorageTimeline(timeline); const timelines = getAllTimelinesInStorage(storage); storage.set(LOCAL_STORAGE_TIMELINE_KEY, { ...timelines, - [id]: timeline, + [id]: timelineToStore, }); }; +const cleanStorageTimeline = (timeline: TimelineModel) => { + // discard unneeded fields to make sure the object serialization works + const { + documentType, + filterManager, + isLoading, + loadingText, + queryFields, + selectAll, + unit, + ...timelineToStore + } = timeline; + return timelineToStore; +}; + export const useTimelinesStorage = (): TimelinesStorage => { const { storage } = useKibana().services; diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/defaults.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/defaults.ts index f411c6ffac9b7e..0ba3f91173d0ad 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/defaults.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/defaults.ts @@ -19,6 +19,7 @@ export const timelineDefaults: SubsetTimelineModel & activeTab: TimelineTabs.query, prevActiveTab: TimelineTabs.query, columns: defaultHeaders, + documentType: '', defaultColumns: defaultHeaders, dataProviders: [], dateRange: { start, end }, @@ -51,6 +52,7 @@ export const timelineDefaults: SubsetTimelineModel & filterQuery: null, }, loadingEventIds: [], + queryFields: [], title: '', timelineType: TimelineType.default, templateTimelineId: null, @@ -59,6 +61,7 @@ export const timelineDefaults: SubsetTimelineModel & pinnedEventIds: {}, pinnedEventsSaveObject: {}, savedObjectId: null, + selectAll: false, selectedEventIds: {}, show: false, showCheckboxes: false, diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.test.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.test.ts index 8b40febbfe993a..686c8220f677bc 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.test.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.test.ts @@ -92,6 +92,7 @@ describe('Epic Timeline', () => { ], deletedEventIds: [], description: '', + documentType: '', eqlOptions: { eventCategoryField: 'event.category', tiebreakerField: '', @@ -146,6 +147,8 @@ describe('Epic Timeline', () => { }, }, loadingEventIds: [], + queryFields: [], + selectAll: false, title: 'saved', timelineType: TimelineType.default, templateTimelineId: null, diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/model.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/model.ts index a2d7e2300d1716..b53da997c08cb3 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/model.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/model.ts @@ -85,10 +85,12 @@ export type SubsetTimelineModel = Readonly< | 'dataProviders' | 'deletedEventIds' | 'description' + | 'documentType' | 'eventType' | 'eventIdToNoteIds' | 'excludedRowRendererIds' | 'expandedDetail' + | 'footerText' | 'graphEventId' | 'highlightedDropAndProviderId' | 'historyIds' @@ -100,15 +102,18 @@ export type SubsetTimelineModel = Readonly< | 'itemsPerPageOptions' | 'kqlMode' | 'kqlQuery' + | 'queryFields' | 'title' | 'timelineType' | 'templateTimelineId' | 'templateTimelineVersion' | 'loadingEventIds' + | 'loadingText' | 'noteIds' | 'pinnedEventIds' | 'pinnedEventsSaveObject' | 'dateRange' + | 'selectAll' | 'selectedEventIds' | 'show' | 'showCheckboxes' @@ -116,6 +121,7 @@ export type SubsetTimelineModel = Readonly< | 'isSaving' | 'isLoading' | 'savedObjectId' + | 'unit' | 'version' | 'status' > diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts index 96ae11cb8afdc2..c0dcba6920b608 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts @@ -88,6 +88,7 @@ const basicTimeline: TimelineModel = { }, deletedEventIds: [], description: '', + documentType: '', eqlOptions: { eventCategoryField: 'event.category', tiebreakerField: '', @@ -113,7 +114,9 @@ const basicTimeline: TimelineModel = { noteIds: [], pinnedEventIds: {}, pinnedEventsSaveObject: {}, + queryFields: [], savedObjectId: null, + selectAll: false, selectedEventIds: {}, show: true, showCheckboxes: false, diff --git a/x-pack/plugins/timelines/public/store/t_grid/model.ts b/x-pack/plugins/timelines/public/store/t_grid/model.ts index 0972189b38b304..dc6945d3fe3ad7 100644 --- a/x-pack/plugins/timelines/public/store/t_grid/model.ts +++ b/x-pack/plugins/timelines/public/store/t_grid/model.ts @@ -92,11 +92,15 @@ export type TGridModelForTimeline = Pick< | 'dataProviders' | 'dateRange' | 'deletedEventIds' + | 'documentType' | 'excludedRowRendererIds' | 'expandedDetail' | 'filters' + | 'filterManager' + | 'footerText' | 'graphEventId' | 'kqlQuery' + | 'queryFields' | 'id' | 'indexNames' | 'isLoading' @@ -104,11 +108,14 @@ export type TGridModelForTimeline = Pick< | 'itemsPerPage' | 'itemsPerPageOptions' | 'loadingEventIds' + | 'loadingText' + | 'selectAll' | 'showCheckboxes' | 'sort' | 'selectedEventIds' | 'savedObjectId' | 'title' + | 'unit' | 'version' >;