"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.queryTimelineById = exports.omitTypenameInTimeline = exports.isUntitled = exports.getTimelineTitle = exports.getTimelineStatus = exports.getPinnedEventCount = exports.getNotesCount = exports.formatTimelineResultToModel = exports.dispatchUpdateTimeline = exports.defaultTimelineToTimelineModel = exports.OPEN_TIMELINE_CLASS_NAME = void 0; var _fp = require("@kbn/safer-lodash-set/fp"); var _fp2 = require("lodash/fp"); var _uuid = require("uuid"); var _deepmerge = _interopRequireDefault(require("deepmerge")); var _constants = require("../../../common/store/inputs/constants"); var _timeline = require("../../../../common/types/timeline"); var _timeline2 = require("../../../../common/api/timeline"); var _actions = require("../../../common/store/app/actions"); var _actions2 = require("../../../common/store/inputs/actions"); var _actions3 = require("../../store/timeline/actions"); var _defaults = require("../../store/timeline/defaults"); var _default_headers = require("../timeline/body/column_headers/default_headers"); var _constants2 = require("../timeline/body/constants"); var _helpers = require("../notes/helpers"); var _data_provider = require("../timeline/data_providers/data_provider"); var _normalize_time_range = require("../../../common/utils/normalize_time_range"); var _sourcerer = require("../../../common/store/sourcerer"); var _model = require("../../../common/store/sourcerer/model"); var _default_date_settings = require("../../../common/utils/default_date_settings"); var _api = require("../../containers/api"); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ const OPEN_TIMELINE_CLASS_NAME = 'open-timeline'; /** Returns a count of the pinned events in a timeline */ exports.OPEN_TIMELINE_CLASS_NAME = OPEN_TIMELINE_CLASS_NAME; const getPinnedEventCount = ({ pinnedEventIds }) => pinnedEventIds != null ? Object.keys(pinnedEventIds).length : 0; /** Returns the sum of all notes added to pinned events and notes applicable to the timeline */ exports.getPinnedEventCount = getPinnedEventCount; const getNotesCount = ({ eventIdToNoteIds, noteIds }) => { const eventNoteCount = eventIdToNoteIds != null ? Object.keys(eventIdToNoteIds).reduce((count, eventId) => count + eventIdToNoteIds[eventId].length, 0) : 0; const globalNoteCount = noteIds != null ? noteIds.length : 0; return eventNoteCount + globalNoteCount; }; /** Returns true if the timeline is untitlied */ exports.getNotesCount = getNotesCount; const isUntitled = ({ title }) => title == null || title.trim().length === 0; exports.isUntitled = isUntitled; const omitTypename = (key, value) => key === '__typename' ? undefined : value; const omitTypenameInTimeline = timeline => JSON.parse(JSON.stringify(timeline), omitTypename); exports.omitTypenameInTimeline = omitTypenameInTimeline; const parseString = params => { try { return JSON.parse(params); } catch { return params; } }; const setTimelineColumn = col => Object.entries(col).reduce((acc, [key, value]) => { if (key !== 'id' && value != null) { return { ...acc, [key]: value }; } return acc; }, { columnHeaderType: _default_headers.defaultColumnHeaderType, id: col.id != null ? col.id : 'unknown', initialWidth: col.id === '@timestamp' ? _constants2.DEFAULT_DATE_COLUMN_MIN_WIDTH : _constants2.DEFAULT_COLUMN_MIN_WIDTH }); const setTimelineFilters = filter => ({ $state: { store: 'appState' }, meta: { ...filter.meta, ...(filter.meta && filter.meta.field != null ? { params: parseString(filter.meta.field) } : {}), ...(filter.meta && filter.meta.params != null ? { params: parseString(filter.meta.params) } : {}), ...(filter.meta && filter.meta.value != null ? { value: parseString(filter.meta.value) } : {}) }, ...(filter.exists != null ? { exists: parseString(filter.exists) } : {}), ...(filter.match_all != null ? { exists: parseString(filter.match_all) } : {}), ...(filter.missing != null ? { exists: parseString(filter.missing) } : {}), ...(filter.query != null ? { query: parseString(filter.query) } : {}), ...(filter.range != null ? { range: parseString(filter.range) } : {}), ...(filter.script != null ? { exists: parseString(filter.script) } : {}) }); const setEventIdToNoteIds = (duplicate, eventIdToNoteIds) => duplicate ? {} : eventIdToNoteIds != null ? eventIdToNoteIds.reduce((acc, note) => { if (note.eventId != null) { const eventNotes = (0, _fp2.getOr)([], note.eventId, acc); return { ...acc, [note.eventId]: [...eventNotes, note.noteId] }; } return acc; }, {}) : {}; const setPinnedEventsSaveObject = (duplicate, pinnedEventsSaveObject) => duplicate ? {} : pinnedEventsSaveObject != null ? pinnedEventsSaveObject.reduce((acc, pinnedEvent) => ({ ...acc, ...(pinnedEvent.eventId != null ? { [pinnedEvent.eventId]: pinnedEvent } : {}) }), {}) : {}; const setPinnedEventIds = (duplicate, pinnedEventIds) => duplicate ? {} : pinnedEventIds != null ? pinnedEventIds.reduce((acc, pinnedEventId) => ({ ...acc, [pinnedEventId]: true }), {}) : {}; const getTemplateTimelineId = (timeline, duplicate, targetTimelineType) => { if (targetTimelineType === _timeline2.TimelineType.default && timeline.timelineType === _timeline2.TimelineType.template) { return timeline.templateTimelineId; } return duplicate && timeline.timelineType === _timeline2.TimelineType.template ? // TODO: MOVE TO THE BACKEND (0, _uuid.v4)() : timeline.templateTimelineId; }; const convertToDefaultField = ({ and, ...dataProvider }) => { if (dataProvider.type === _timeline2.DataProviderType.template) { return (0, _deepmerge.default)(dataProvider, { type: _timeline2.DataProviderType.default, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion enabled: dataProvider.queryMatch.operator !== _data_provider.IS_OPERATOR, queryMatch: { value: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion dataProvider.queryMatch.operator === _data_provider.IS_OPERATOR ? '' : dataProvider.queryMatch.value } }); } return dataProvider; }; const getDataProviders = (duplicate, dataProviders, timelineType) => { if (duplicate && dataProviders && timelineType === _timeline2.TimelineType.default) { return dataProviders.map(dataProvider => { var _dataProvider$and$map, _dataProvider$and; return { ...convertToDefaultField(dataProvider), and: (_dataProvider$and$map = (_dataProvider$and = dataProvider.and) === null || _dataProvider$and === void 0 ? void 0 : _dataProvider$and.map(convertToDefaultField)) !== null && _dataProvider$and$map !== void 0 ? _dataProvider$and$map : [] }; }); } return dataProviders; }; const getTimelineTitle = (timeline, duplicate, timelineType) => { const isCreateTimelineFromAction = timelineType && timeline.timelineType !== timelineType; if (isCreateTimelineFromAction) return ''; return duplicate ? `${timeline.title} - Duplicate` : timeline.title || ''; }; exports.getTimelineTitle = getTimelineTitle; const getTimelineStatus = (timeline, duplicate, timelineType) => { const isCreateTimelineFromAction = timelineType && timeline.timelineType !== timelineType; if (isCreateTimelineFromAction) return _timeline2.TimelineStatus.draft; return duplicate ? _timeline2.TimelineStatus.active : timeline.status; }; exports.getTimelineStatus = getTimelineStatus; const defaultTimelineToTimelineModel = (timeline, duplicate, timelineType) => { const isTemplate = timeline.timelineType === _timeline2.TimelineType.template; const timelineEntries = { ...timeline, columns: timeline.columns != null ? timeline.columns.map(setTimelineColumn) : _default_headers.defaultHeaders, defaultColumns: _default_headers.defaultHeaders, dateRange: timeline.status === _timeline2.TimelineStatus.immutable && timeline.timelineType === _timeline2.TimelineType.template ? { start: _default_date_settings.DEFAULT_FROM_MOMENT.toISOString(), end: _default_date_settings.DEFAULT_TO_MOMENT.toISOString() } : timeline.dateRange, dataProviders: getDataProviders(duplicate, timeline.dataProviders, timelineType), eventIdToNoteIds: setEventIdToNoteIds(duplicate, timeline.eventIdToNoteIds), filters: timeline.filters != null ? timeline.filters.map(setTimelineFilters) : [], isFavorite: duplicate ? false : timeline.favorite != null ? timeline.favorite.length > 0 : false, noteIds: duplicate ? [] : timeline.noteIds != null ? timeline.noteIds : [], pinnedEventIds: setPinnedEventIds(duplicate, timeline.pinnedEventIds), pinnedEventsSaveObject: setPinnedEventsSaveObject(duplicate, timeline.pinnedEventsSaveObject), id: duplicate ? '' : timeline.savedObjectId, status: getTimelineStatus(timeline, duplicate, timelineType), savedObjectId: duplicate ? null : timeline.savedObjectId, version: duplicate ? null : timeline.version, timelineType: timelineType !== null && timelineType !== void 0 ? timelineType : timeline.timelineType, title: getTimelineTitle(timeline, duplicate, timelineType), templateTimelineId: getTemplateTimelineId(timeline, duplicate, timelineType), templateTimelineVersion: duplicate && isTemplate ? 1 : timeline.templateTimelineVersion }; return Object.entries(timelineEntries).reduce((acc, [key, value]) => value != null ? (0, _fp.set)(key, value, acc) : acc, { ..._defaults.timelineDefaults, id: '' }); }; exports.defaultTimelineToTimelineModel = defaultTimelineToTimelineModel; const formatTimelineResultToModel = (timelineToOpen, duplicate = false, timelineType) => { const { notes, ...timelineModel } = timelineToOpen; return { notes, timeline: defaultTimelineToTimelineModel(timelineModel, duplicate, timelineType) }; }; exports.formatTimelineResultToModel = formatTimelineResultToModel; const queryTimelineById = ({ activeTimelineTab = _timeline.TimelineTabs.query, duplicate = false, graphEventId = '', timelineId, timelineType, onError, onOpenTimeline, openTimeline = true, updateIsLoading, updateTimeline }) => { updateIsLoading({ id: _timeline.TimelineId.active, isLoading: true }); if (timelineId == null) { updateTimeline({ id: _timeline.TimelineId.active, duplicate: false, notes: [], from: _default_date_settings.DEFAULT_FROM_MOMENT.toISOString(), to: _default_date_settings.DEFAULT_TO_MOMENT.toISOString(), timeline: { ..._defaults.timelineDefaults, id: _timeline.TimelineId.active, activeTab: activeTimelineTab, show: openTimeline, initialized: true } })(); updateIsLoading({ id: _timeline.TimelineId.active, isLoading: false }); } else { Promise.resolve((0, _api.resolveTimeline)(timelineId)).then(result => { const data = (0, _fp2.getOr)(null, 'data', result); if (!data) return; const timelineToOpen = omitTypenameInTimeline(data.timeline); const { timeline, notes } = formatTimelineResultToModel(timelineToOpen, duplicate, timelineType); if (onOpenTimeline != null) { onOpenTimeline(timeline); } else if (updateTimeline) { const { from, to } = (0, _normalize_time_range.normalizeTimeRange)({ from: (0, _fp2.getOr)(null, 'dateRange.start', timeline), to: (0, _fp2.getOr)(null, 'dateRange.end', timeline) }); updateTimeline({ duplicate, from, id: _timeline.TimelineId.active, notes, resolveTimelineConfig: { outcome: data.outcome, alias_target_id: data.alias_target_id, alias_purpose: data.alias_purpose }, timeline: { ...timeline, activeTab: activeTimelineTab, graphEventId, show: openTimeline, dateRange: { start: from, end: to } }, to })(); } }).catch(error => { if (onError != null) { onError(error, timelineId); } }).finally(() => { updateIsLoading({ id: _timeline.TimelineId.active, isLoading: false }); }); } }; exports.queryTimelineById = queryTimelineById; const dispatchUpdateTimeline = dispatch => ({ duplicate, id, forceNotes = false, from, notes, resolveTimelineConfig, timeline, to, ruleNote, ruleAuthor }) => () => { if (!(0, _fp2.isEmpty)(timeline.indexNames)) { dispatch(_sourcerer.sourcererActions.setSelectedDataView({ id: _model.SourcererScopeName.timeline, selectedDataViewId: timeline.dataViewId, selectedPatterns: timeline.indexNames })); } if (timeline.status === _timeline2.TimelineStatus.immutable && timeline.timelineType === _timeline2.TimelineType.template) { dispatch((0, _actions2.setRelativeRangeDatePicker)({ id: _constants.InputsModelId.timeline, fromStr: 'now-24h', toStr: 'now', from: _default_date_settings.DEFAULT_FROM_MOMENT.toISOString(), to: _default_date_settings.DEFAULT_TO_MOMENT.toISOString() })); } else { dispatch((0, _actions2.setTimelineRangeDatePicker)({ from, to })); } dispatch((0, _actions3.addTimeline)({ id, timeline, resolveTimelineConfig, savedTimeline: duplicate })); if (timeline.kqlQuery != null && timeline.kqlQuery.filterQuery != null && timeline.kqlQuery.filterQuery.kuery != null && timeline.kqlQuery.filterQuery.kuery.expression !== '') { var _timeline$kqlQuery$fi; dispatch((0, _actions3.applyKqlFilterQuery)({ id, filterQuery: { kuery: { kind: (_timeline$kqlQuery$fi = timeline.kqlQuery.filterQuery.kuery.kind) !== null && _timeline$kqlQuery$fi !== void 0 ? _timeline$kqlQuery$fi : 'kuery', expression: timeline.kqlQuery.filterQuery.kuery.expression || '' }, serializedQuery: timeline.kqlQuery.filterQuery.serializedQuery || '' } })); } if (duplicate && ruleNote != null && !(0, _fp2.isEmpty)(ruleNote)) { const newNote = (0, _helpers.createNote)({ newNote: ruleNote, user: ruleAuthor || 'elastic' }); dispatch((0, _actions.updateNote)({ note: newNote })); dispatch((0, _actions3.addNote)({ noteId: newNote.id, id })); } if (!duplicate || forceNotes) { dispatch((0, _actions.addNotes)({ notes: notes != null ? notes.map(note => { var _note$eventId, _note$timelineId; return { created: note.created != null ? new Date(note.created) : new Date(), id: note.noteId, lastEdit: note.updated != null ? new Date(note.updated) : new Date(), note: note.note || '', user: note.updatedBy || 'unknown', saveObjectId: note.noteId, version: note.version, eventId: (_note$eventId = note.eventId) !== null && _note$eventId !== void 0 ? _note$eventId : null, timelineId: (_note$timelineId = note.timelineId) !== null && _note$timelineId !== void 0 ? _note$timelineId : null }; }) : [] })); } }; exports.dispatchUpdateTimeline = dispatchUpdateTimeline;