"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.useTimelineEventsHandler = exports.useTimelineEvents = exports.initSortDefault = void 0; var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal")); var _fp = require("lodash/fp"); var _react = require("react"); var _reactRedux = require("react-redux"); var _rxjs = require("rxjs"); var _common = require("@kbn/data-plugin/common"); var _kibana = require("../../common/lib/kibana"); var _helpers = require("../../common/containers/helpers"); var _timeline = require("../store/timeline"); var _helpers2 = require("./helpers"); var _helpers3 = require("../../helpers"); var _search_strategy = require("../../../common/search_strategy"); var i18n = _interopRequireWildcard(require("./translations")); var _timeline2 = require("../../../common/types/timeline"); var _use_route_spy = require("../../common/utils/route/use_route_spy"); var _active_timeline_context = require("./active_timeline_context"); var _use_app_toasts = require("../../common/hooks/use_app_toasts"); var _use_track_http_request = require("../../common/lib/apm/use_track_http_request"); var _constants = require("../../../common/constants"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * 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 getTimelineEvents = timelineEdges => timelineEdges.map(e => e.node); const ID = 'timelineEventsQuery'; const initSortDefault = [{ field: '@timestamp', direction: _search_strategy.Direction.asc, type: 'date', esTypes: ['date'] }]; exports.initSortDefault = initSortDefault; const deStructureEqlOptions = eqlOptions => ({ ...(!(0, _fp.isEmpty)(eqlOptions === null || eqlOptions === void 0 ? void 0 : eqlOptions.eventCategoryField) ? { eventCategoryField: eqlOptions === null || eqlOptions === void 0 ? void 0 : eqlOptions.eventCategoryField } : {}), ...(!(0, _fp.isEmpty)(eqlOptions === null || eqlOptions === void 0 ? void 0 : eqlOptions.size) ? { size: eqlOptions === null || eqlOptions === void 0 ? void 0 : eqlOptions.size } : {}), ...(!(0, _fp.isEmpty)(eqlOptions === null || eqlOptions === void 0 ? void 0 : eqlOptions.tiebreakerField) ? { tiebreakerField: eqlOptions === null || eqlOptions === void 0 ? void 0 : eqlOptions.tiebreakerField } : {}), ...(!(0, _fp.isEmpty)(eqlOptions === null || eqlOptions === void 0 ? void 0 : eqlOptions.timestampField) ? { timestampField: eqlOptions === null || eqlOptions === void 0 ? void 0 : eqlOptions.timestampField } : {}) }); const useTimelineEventsHandler = ({ dataViewId, endDate, eqlOptions = undefined, id = ID, indexNames, fields, filterQuery, runtimeMappings, startDate, language = 'kuery', limit, sort = initSortDefault, skip = false, timerangeKind }) => { const [{ pageName }] = (0, _use_route_spy.useRouteSpy)(); const dispatch = (0, _reactRedux.useDispatch)(); const { data } = (0, _kibana.useKibana)().services; const refetch = (0, _react.useRef)(_fp.noop); const abortCtrl = (0, _react.useRef)(new AbortController()); const searchSubscription$ = (0, _react.useRef)(new _rxjs.Subscription()); const [loading, setLoading] = (0, _react.useState)(false); const [activePage, setActivePage] = (0, _react.useState)(id === _timeline2.TimelineId.active ? _active_timeline_context.activeTimeline.getActivePage() : 0); const [timelineRequest, setTimelineRequest] = (0, _react.useState)(null); const prevTimelineRequest = (0, _react.useRef)(null); const { startTracking } = (0, _use_track_http_request.useTrackHttpRequest)(); const clearSignalsState = (0, _react.useCallback)(() => { if (id != null && _helpers2.detectionsTimelineIds.some(timelineId => timelineId === id)) { dispatch(_timeline.timelineActions.clearEventsLoading({ id })); dispatch(_timeline.timelineActions.clearEventsDeleted({ id })); } }, [dispatch, id]); const wrappedLoadPage = (0, _react.useCallback)(newActivePage => { clearSignalsState(); if (id === _timeline2.TimelineId.active) { _active_timeline_context.activeTimeline.setExpandedDetail({}); _active_timeline_context.activeTimeline.setActivePage(newActivePage); } setActivePage(newActivePage); }, [clearSignalsState, id]); const refetchGrid = (0, _react.useCallback)(() => { if (refetch.current != null) { refetch.current(); } wrappedLoadPage(0); }, [wrappedLoadPage]); const setUpdated = (0, _react.useCallback)(updatedAt => { dispatch(_timeline.timelineActions.setTimelineUpdatedAt({ id, updated: updatedAt })); }, [dispatch, id]); const [timelineResponse, setTimelineResponse] = (0, _react.useState)({ id, inspect: { dsl: [], response: [] }, refetch: refetchGrid, totalCount: -1, pageInfo: { activePage: 0, querySize: 0 }, events: [], loadPage: wrappedLoadPage, updatedAt: 0 }); const { addWarning } = (0, _use_app_toasts.useAppToasts)(); const timelineSearch = (0, _react.useCallback)(async (request, onNextHandler) => { if (request == null || pageName === '' || skip) { return; } const asyncSearch = async () => { prevTimelineRequest.current = request; abortCtrl.current = new AbortController(); setLoading(true); const { endTracking } = startTracking({ name: `${_constants.APP_UI_ID} timeline events search` }); searchSubscription$.current = data.search.search(request, { strategy: request.language === 'eql' ? 'timelineEqlSearchStrategy' : 'timelineSearchStrategy', abortSignal: abortCtrl.current.signal, // we only need the id to throw better errors indexPattern: { id: dataViewId } }).subscribe({ next: response => { if ((0, _common.isCompleteResponse)(response)) { endTracking('success'); setLoading(false); setTimelineResponse(prevResponse => { const newTimelineResponse = { ...prevResponse, events: getTimelineEvents(response.edges), inspect: (0, _helpers3.getInspectResponse)(response, prevResponse.inspect), pageInfo: response.pageInfo, totalCount: response.totalCount, updatedAt: Date.now() }; setUpdated(newTimelineResponse.updatedAt); if (id === _timeline2.TimelineId.active) { _active_timeline_context.activeTimeline.setExpandedDetail({}); _active_timeline_context.activeTimeline.setPageName(pageName); if (request.language === 'eql') { _active_timeline_context.activeTimeline.setEqlRequest(request); _active_timeline_context.activeTimeline.setEqlResponse(newTimelineResponse); } else { // @ts-expect-error EqlSearchRequest.query is not compatible with QueryDslQueryContainer _active_timeline_context.activeTimeline.setRequest(request); _active_timeline_context.activeTimeline.setResponse(newTimelineResponse); } } if (onNextHandler) onNextHandler(newTimelineResponse); return newTimelineResponse; }); searchSubscription$.current.unsubscribe(); } else if ((0, _common.isErrorResponse)(response)) { endTracking('invalid'); setLoading(false); addWarning(i18n.ERROR_TIMELINE_EVENTS); searchSubscription$.current.unsubscribe(); } }, error: msg => { endTracking(abortCtrl.current.signal.aborted ? 'aborted' : 'error'); setLoading(false); data.search.showError(msg); searchSubscription$.current.unsubscribe(); } }); }; if (id === _timeline2.TimelineId.active && _active_timeline_context.activeTimeline.getPageName() !== '' && pageName !== _active_timeline_context.activeTimeline.getPageName()) { _active_timeline_context.activeTimeline.setPageName(pageName); abortCtrl.current.abort(); setLoading(false); if (request.language === 'eql') { prevTimelineRequest.current = _active_timeline_context.activeTimeline.getEqlRequest(); refetch.current = asyncSearch.bind(null, _active_timeline_context.activeTimeline.getEqlRequest()); } else { prevTimelineRequest.current = _active_timeline_context.activeTimeline.getRequest(); refetch.current = asyncSearch.bind(null, _active_timeline_context.activeTimeline.getRequest()); } setTimelineResponse(prevResp => { const resp = request.language === 'eql' ? _active_timeline_context.activeTimeline.getEqlResponse() : _active_timeline_context.activeTimeline.getResponse(); if (resp != null) { return { ...resp, refetch: refetchGrid, loadPage: wrappedLoadPage }; } return prevResp; }); if (request.language !== 'eql' && _active_timeline_context.activeTimeline.getResponse() != null) { return; } else if (request.language === 'eql' && _active_timeline_context.activeTimeline.getEqlResponse() != null) { return; } } searchSubscription$.current.unsubscribe(); abortCtrl.current.abort(); await asyncSearch(); refetch.current = asyncSearch; }, [pageName, skip, id, startTracking, data.search, dataViewId, setUpdated, addWarning, refetchGrid, wrappedLoadPage]); (0, _react.useEffect)(() => { if (indexNames.length === 0) { return; } setTimelineRequest(prevRequest => { var _prevRequest$defaultI, _prevRequest$filterQu, _prevRequest$paginati, _prevRequest$sort, _prevRequest$timerang, _prevRequest$runtimeM; const prevEqlRequest = prevRequest; const prevSearchParameters = { defaultIndex: (_prevRequest$defaultI = prevRequest === null || prevRequest === void 0 ? void 0 : prevRequest.defaultIndex) !== null && _prevRequest$defaultI !== void 0 ? _prevRequest$defaultI : [], filterQuery: (_prevRequest$filterQu = prevRequest === null || prevRequest === void 0 ? void 0 : prevRequest.filterQuery) !== null && _prevRequest$filterQu !== void 0 ? _prevRequest$filterQu : '', querySize: (_prevRequest$paginati = prevRequest === null || prevRequest === void 0 ? void 0 : prevRequest.pagination.querySize) !== null && _prevRequest$paginati !== void 0 ? _prevRequest$paginati : 0, sort: (_prevRequest$sort = prevRequest === null || prevRequest === void 0 ? void 0 : prevRequest.sort) !== null && _prevRequest$sort !== void 0 ? _prevRequest$sort : initSortDefault, timerange: (_prevRequest$timerang = prevRequest === null || prevRequest === void 0 ? void 0 : prevRequest.timerange) !== null && _prevRequest$timerang !== void 0 ? _prevRequest$timerang : {}, runtimeMappings: (_prevRequest$runtimeM = prevRequest === null || prevRequest === void 0 ? void 0 : prevRequest.runtimeMappings) !== null && _prevRequest$runtimeM !== void 0 ? _prevRequest$runtimeM : {}, ...deStructureEqlOptions(prevEqlRequest) }; const timerange = startDate && endDate ? { timerange: { interval: '12h', from: startDate, to: endDate } } : {}; const currentSearchParameters = { defaultIndex: indexNames, filterQuery: (0, _helpers.createFilter)(filterQuery), querySize: limit, sort, runtimeMappings, ...timerange, ...deStructureEqlOptions(eqlOptions) }; const newActivePage = (0, _fastDeepEqual.default)(prevSearchParameters, currentSearchParameters) ? activePage : 0; const currentRequest = { defaultIndex: indexNames, factoryQueryType: _search_strategy.TimelineEventsQueries.all, fieldRequested: fields, fields, filterQuery: (0, _helpers.createFilter)(filterQuery), pagination: { activePage: newActivePage, querySize: limit }, language, runtimeMappings, sort, ...timerange, ...(eqlOptions ? eqlOptions : {}) }; if (activePage !== newActivePage) { setActivePage(newActivePage); if (id === _timeline2.TimelineId.active) { _active_timeline_context.activeTimeline.setActivePage(newActivePage); } } if (!(0, _fastDeepEqual.default)(prevRequest, currentRequest)) { return currentRequest; } return prevRequest; }); }, [dispatch, indexNames, activePage, endDate, eqlOptions, filterQuery, id, language, limit, startDate, sort, fields, runtimeMappings]); const timelineSearchHandler = (0, _react.useCallback)(async onNextHandler => { if (id !== _timeline2.TimelineId.active || timerangeKind === 'absolute' || !(0, _fastDeepEqual.default)(prevTimelineRequest.current, timelineRequest)) { await timelineSearch(timelineRequest, onNextHandler); } }, [id, timelineRequest, timelineSearch, timerangeKind]); /* cleanup timeline events response when the filters were removed completely to avoid displaying previous query results */ (0, _react.useEffect)(() => { if ((0, _fp.isEmpty)(filterQuery)) { setTimelineResponse({ id, inspect: { dsl: [], response: [] }, refetch: refetchGrid, totalCount: -1, pageInfo: { activePage: 0, querySize: 0 }, events: [], loadPage: wrappedLoadPage, updatedAt: 0 }); } }, [filterQuery, id, refetchGrid, wrappedLoadPage]); return [loading, timelineResponse, timelineSearchHandler]; }; exports.useTimelineEventsHandler = useTimelineEventsHandler; const useTimelineEvents = ({ dataViewId, endDate, eqlOptions = undefined, id = ID, indexNames, fields, filterQuery, runtimeMappings, startDate, language = 'kuery', limit, sort = initSortDefault, skip = false, timerangeKind }) => { const [loading, timelineResponse, timelineSearchHandler] = useTimelineEventsHandler({ dataViewId, endDate, eqlOptions, id, indexNames, fields, filterQuery, runtimeMappings, startDate, language, limit, sort, skip, timerangeKind }); (0, _react.useEffect)(() => { if (!timelineSearchHandler) return; timelineSearchHandler(); }, [timelineSearchHandler]); return [loading, timelineResponse]; }; exports.useTimelineEvents = useTimelineEvents;