From d4d3457a0d941e334a316e3e690129a7b188d74f Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Date: Tue, 22 Oct 2019 14:52:53 -0400 Subject: [PATCH] [SIEM] Move public to new platform (#48840) * shim public new platform * fix import * fix ml api with kbn version * review I * fix bad coding with the hooks --- x-pack/legacy/plugins/siem/index.ts | 4 +- x-pack/legacy/plugins/siem/public/app.ts | 2 +- .../public/apps/{kibana_app.ts => index.ts} | 10 +- .../plugins/siem/public/apps/plugin.tsx | 54 +++ .../plugins/siem/public/apps/start_app.tsx | 31 +- .../plugins/siem/public/apps/template.html | 1 + .../embeddables/embedded_map.test.tsx | 29 +- .../components/embeddables/embedded_map.tsx | 26 +- .../embeddables/embedded_map_helpers.test.tsx | 31 +- .../embeddables/embedded_map_helpers.tsx | 30 +- .../public/components/embeddables/types.ts | 6 + .../events_viewer/events_viewer.test.tsx | 12 +- .../events_viewer/events_viewer.tsx | 6 +- .../components/events_viewer/index.test.tsx | 11 +- .../ml/anomaly/use_anomalies_table_data.ts | 4 +- .../components/ml/api/anomalies_table_data.ts | 7 +- .../components/ml/api/get_ml_capabilities.ts | 7 +- .../permissions/ml_capabilities_provider.tsx | 5 +- .../siem/public/components/ml_popover/api.tsx | 33 +- .../ml_popover/hooks/use_siem_jobs.tsx | 13 +- .../components/ml_popover/ml_popover.tsx | 8 +- .../public/components/ml_popover/types.ts | 6 +- .../__snapshots__/index.test.tsx.snap | 314 +++++++++--------- .../page/hosts/hosts_table/index.test.tsx | 23 +- .../components/timeline/helpers.test.tsx | 25 +- .../public/components/timeline/helpers.tsx | 12 +- .../components/timeline/timeline.test.tsx | 8 + .../public/components/timeline/timeline.tsx | 4 + .../containers/kuery_autocompletion/index.tsx | 10 +- .../plugins/siem/public/hooks/api/api.tsx | 6 +- .../siem/public/hooks/use_index_patterns.tsx | 9 +- .../lib/compose/__mocks__/kibana_core.ts | 13 + .../lib/compose/__mocks__/kibana_plugins.ts | 13 + .../public/lib/compose/kibana_compose.tsx | 14 - .../siem/public/lib/compose/kibana_core.tsx | 25 ++ .../public/lib/compose/kibana_plugins.tsx | 27 ++ .../plugins/siem/public/lib/keury/index.ts | 25 +- .../lib/settings/use_kibana_ui_setting.ts | 7 +- .../settings/use_kibana_ui_settings.test.tsx | 21 +- .../plugins/siem/public/pages/home/index.tsx | 7 + .../public/pages/hosts/details/body.test.tsx | 12 +- .../siem/public/pages/hosts/details/body.tsx | 4 + .../siem/public/pages/hosts/details/index.tsx | 4 + .../siem/public/pages/hosts/hosts.test.tsx | 14 +- .../plugins/siem/public/pages/hosts/hosts.tsx | 5 +- .../siem/public/pages/hosts/hosts_body.tsx | 4 + .../pages/network/ip_details/index.test.tsx | 12 +- .../public/pages/network/ip_details/index.tsx | 4 + .../public/pages/network/network.test.tsx | 13 +- .../siem/public/pages/network/network.tsx | 198 +++++------ 50 files changed, 679 insertions(+), 490 deletions(-) rename x-pack/legacy/plugins/siem/public/apps/{kibana_app.ts => index.ts} (55%) create mode 100644 x-pack/legacy/plugins/siem/public/apps/plugin.tsx create mode 100644 x-pack/legacy/plugins/siem/public/apps/template.html create mode 100644 x-pack/legacy/plugins/siem/public/lib/compose/__mocks__/kibana_core.ts create mode 100644 x-pack/legacy/plugins/siem/public/lib/compose/__mocks__/kibana_plugins.ts create mode 100644 x-pack/legacy/plugins/siem/public/lib/compose/kibana_core.tsx create mode 100644 x-pack/legacy/plugins/siem/public/lib/compose/kibana_plugins.tsx diff --git a/x-pack/legacy/plugins/siem/index.ts b/x-pack/legacy/plugins/siem/index.ts index f78f55ddc445b8..30df3b5b63e2ae 100644 --- a/x-pack/legacy/plugins/siem/index.ts +++ b/x-pack/legacy/plugins/siem/index.ts @@ -29,7 +29,7 @@ import { defaultIndexPattern } from './default_index_pattern'; import { isAlertExecutor } from './server/lib/detection_engine/alerts/types'; // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function siem(kibana: any) { +export const siem = (kibana: any) => { return new kibana.Plugin({ id: APP_ID, configPrefix: 'xpack.siem', @@ -138,4 +138,4 @@ export function siem(kibana: any) { initServerWithKibana(server); }, }); -} +}; diff --git a/x-pack/legacy/plugins/siem/public/app.ts b/x-pack/legacy/plugins/siem/public/app.ts index 255c51c9e48cea..b068f8a9becda5 100644 --- a/x-pack/legacy/plugins/siem/public/app.ts +++ b/x-pack/legacy/plugins/siem/public/app.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -import './apps/kibana_app'; +import './apps/index'; diff --git a/x-pack/legacy/plugins/siem/public/apps/kibana_app.ts b/x-pack/legacy/plugins/siem/public/apps/index.ts similarity index 55% rename from x-pack/legacy/plugins/siem/public/apps/kibana_app.ts rename to x-pack/legacy/plugins/siem/public/apps/index.ts index 7ce67f3df9ff93..468e72c8a2e5ca 100644 --- a/x-pack/legacy/plugins/siem/public/apps/kibana_app.ts +++ b/x-pack/legacy/plugins/siem/public/apps/index.ts @@ -3,10 +3,10 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import chrome from 'ui/chrome'; -import { SiemRootController } from './start_app'; -import 'uiExports/embeddableFactories'; +import chrome from 'ui/chrome'; +import { npStart } from 'ui/new_platform'; +import { Plugin } from './plugin'; -// load the application -chrome.setRootController('siem', SiemRootController); +// eslint-disable-next-line @typescript-eslint/no-explicit-any +new Plugin({ opaqueId: Symbol('siem'), env: {} as any }, chrome).start(npStart); diff --git a/x-pack/legacy/plugins/siem/public/apps/plugin.tsx b/x-pack/legacy/plugins/siem/public/apps/plugin.tsx new file mode 100644 index 00000000000000..f3cbd44f34cdc2 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/apps/plugin.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { render } from 'react-dom'; +import { LegacyCoreStart, PluginInitializerContext } from 'src/core/public'; +import { PluginsStart } from 'ui/new_platform/new_platform'; +import { Chrome } from 'ui/chrome'; + +import { SiemApp } from './start_app'; +import template from './template.html'; + +export const ROOT_ELEMENT_ID = 'react-siem-root'; + +export interface StartObject { + core: LegacyCoreStart; + plugins: PluginsStart; +} + +export class Plugin { + constructor( + // @ts-ignore this is added to satisfy the New Platform typing constraint, + // but we're not leveraging any of its functionality yet. + private readonly initializerContext: PluginInitializerContext, + private readonly chrome: Chrome + ) { + this.chrome = chrome; + } + + public start(start: StartObject): void { + const { core, plugins } = start; + // @ts-ignore improper type description + this.chrome.setRootTemplate(template); + const checkForRoot = () => { + return new Promise(resolve => { + const ready = !!document.getElementById(ROOT_ELEMENT_ID); + if (ready) { + resolve(); + } else { + setTimeout(() => resolve(checkForRoot()), 10); + } + }); + }; + checkForRoot().then(() => { + const node = document.getElementById(ROOT_ELEMENT_ID); + if (node) { + render(, node); + } + }); + } +} diff --git a/x-pack/legacy/plugins/siem/public/apps/start_app.tsx b/x-pack/legacy/plugins/siem/public/apps/start_app.tsx index d923826cdd0197..47c8b6eee6452c 100644 --- a/x-pack/legacy/plugins/siem/public/apps/start_app.tsx +++ b/x-pack/legacy/plugins/siem/public/apps/start_app.tsx @@ -7,7 +7,6 @@ import { createHashHistory } from 'history'; import React, { memo, FC } from 'react'; import { ApolloProvider } from 'react-apollo'; -import { render, unmountComponentAtNode } from 'react-dom'; import { Provider as ReduxStoreProvider } from 'react-redux'; import { ThemeProvider } from 'styled-components'; @@ -22,13 +21,18 @@ import { DEFAULT_DARK_MODE } from '../../common/constants'; import { ErrorToastDispatcher } from '../components/error_toast_dispatcher'; import { compose } from '../lib/compose/kibana_compose'; import { AppFrontendLibs } from '../lib/lib'; +import { KibanaCoreContextProvider } from '../lib/compose/kibana_core'; +import { KibanaPluginsContextProvider } from '../lib/compose/kibana_plugins'; +import { useKibanaUiSetting } from '../lib/settings/use_kibana_ui_setting'; import { PageRouter } from '../routes'; import { createStore } from '../store'; import { GlobalToaster, ManageGlobalToaster } from '../components/toasters'; import { MlCapabilitiesProvider } from '../components/ml/permissions/ml_capabilities_provider'; -import { useKibanaUiSetting } from '../lib/settings/use_kibana_ui_setting'; + import { ApolloClientContext } from '../utils/apollo_context'; +import { StartObject } from './plugin'; + const StartApp: FC = memo(libs => { const history = createHashHistory(); @@ -68,21 +72,12 @@ const StartApp: FC = memo(libs => { return ; }); -const ROOT_ELEMENT_ID = 'react-siem-root'; +export const ROOT_ELEMENT_ID = 'react-siem-root'; -const App = memo(() => ( -
- -
+export const SiemApp = memo(({ core, plugins }) => ( + + + + + )); - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const SiemRootController = ($scope: any, $element: any) => { - const domNode: Element = $element[0]; - - render(, domNode); - - $scope.$on('$destroy', () => { - unmountComponentAtNode(domNode); - }); -}; diff --git a/x-pack/legacy/plugins/siem/public/apps/template.html b/x-pack/legacy/plugins/siem/public/apps/template.html new file mode 100644 index 00000000000000..9f757b25ccecb6 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/apps/template.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.test.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.test.tsx index 26755ecd4b5f64..de3e27d7646b90 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.test.tsx @@ -9,6 +9,7 @@ import toJson from 'enzyme-to-json'; import * as React from 'react'; import { EmbeddedMap } from './embedded_map'; import { SetQuery } from './types'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; jest.mock('../search_bar', () => ({ siemFilterManager: { @@ -16,29 +17,19 @@ jest.mock('../search_bar', () => ({ }, })); -jest.mock('ui/new_platform', () => ({ - npStart: { - core: { - injectedMetadata: { - getKibanaVersion: () => '8.0.0', - }, - }, - plugins: { - uiActions: require('../../../../../../../src/plugins/ui_actions/public/mocks').uiActionsPluginMock.createSetupContract(), - }, +const mockUseKibanaCore = useKibanaCore as jest.Mock; +jest.mock('../../lib/compose/kibana_core'); +mockUseKibanaCore.mockImplementation(() => ({ + uiSettings: { + get$: () => 'world', }, - npSetup: { - core: { - uiSettings: { - get$: () => 'world', - }, - }, - plugins: { - uiActions: require('../../../../../../../src/plugins/ui_actions/public/mocks').uiActionsPluginMock.createStartContract(), - }, + injectedMetadata: { + getKibanaVersion: () => '8.0.0', }, })); +jest.mock('../../lib/compose/kibana_plugins'); + describe('EmbeddedMap', () => { let setQuery: SetQuery; diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx index b66d3f7055a4e3..e07909d20e437b 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx @@ -7,7 +7,6 @@ import { EuiFlexGroup, EuiSpacer } from '@elastic/eui'; import { Filter } from '@kbn/es-query'; import React, { useEffect, useState } from 'react'; -import { npStart } from 'ui/new_platform'; import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder'; import { createPortalNode, InPortal } from 'react-reverse-portal'; import { Query } from 'src/plugins/data/common'; @@ -16,17 +15,20 @@ import styled from 'styled-components'; import { start } from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public/legacy'; import { EmbeddablePanel } from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public'; -import { Loader } from '../loader'; +import { getIndexPatternTitleIdMapping } from '../../hooks/api/helpers'; import { useIndexPatterns } from '../../hooks/use_index_patterns'; import { useKibanaUiSetting } from '../../lib/settings/use_kibana_ui_setting'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; +import { useKibanaPlugins } from '../../lib/compose/kibana_plugins'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; +import { useStateToaster } from '../toasters'; +import { Loader } from '../loader'; import { IndexPatternsMissingPrompt } from './index_patterns_missing_prompt'; import { MapEmbeddable, SetQuery } from './types'; import * as i18n from './translations'; -import { useStateToaster } from '../toasters'; + import { createEmbeddable, displayErrorToast, setupEmbeddablesAPI } from './embedded_map_helpers'; import { MapToolTip } from './map_tool_tip/map_tool_tip'; -import { getIndexPatternTitleIdMapping } from '../../hooks/api/helpers'; const EmbeddableWrapper = styled(EuiFlexGroup)` position: relative; @@ -63,13 +65,16 @@ export const EmbeddedMap = React.memo( // Search InPortal/OutPortal for implementation touch points const portalNode = React.useMemo(() => createPortalNode(), []); + const plugins = useKibanaPlugins(); + const core = useKibanaCore(); + // Initial Load useEffect useEffect(() => { let isSubscribed = true; async function setupEmbeddable() { // Configure Embeddables API try { - setupEmbeddablesAPI(); + setupEmbeddablesAPI(plugins); } catch (e) { displayErrorToast(i18n.ERROR_CONFIGURING_EMBEDDABLES_API, e.message, dispatchToaster); setIsLoading(false); @@ -96,7 +101,8 @@ export const EmbeddedMap = React.memo( startDate, endDate, setQuery, - portalNode + portalNode, + plugins.embeddable ); if (isSubscribed) { setEmbeddable(embeddableObject); @@ -154,12 +160,12 @@ export const EmbeddedMap = React.memo( ) : !isLoading && isIndexError ? ( diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.test.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.test.tsx index 83c51138411145..68bab4e5d61a1a 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.test.tsx @@ -5,31 +5,26 @@ */ import { createEmbeddable, displayErrorToast, setupEmbeddablesAPI } from './embedded_map_helpers'; -import { npStart } from 'ui/new_platform'; +import { createUiNewPlatformMock } from 'ui/new_platform/__mocks__/helpers'; import { createPortalNode } from 'react-reverse-portal'; +import { PluginsStart } from 'ui/new_platform/new_platform'; jest.mock('ui/new_platform'); jest.mock('../../lib/settings/use_kibana_ui_setting'); -jest.mock( - '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public/legacy', - () => ({ - start: { - getEmbeddableFactory: () => ({ - createFromState: () => ({ - reload: jest.fn(), - }), - }), - }, - }) -); - jest.mock('uuid', () => { return { v4: jest.fn(() => '9e1f72a9-7c73-4b7f-a562-09940f7daf4a'), }; }); +const { npStart } = createUiNewPlatformMock(); +npStart.plugins.embeddable.getEmbeddableFactory = jest.fn().mockImplementation(() => ({ + createFromState: () => ({ + reload: jest.fn(), + }), +})); + describe('embedded_map_helpers', () => { describe('displayErrorToast', () => { test('dispatches toast with correct title and message', () => { @@ -51,7 +46,7 @@ describe('embedded_map_helpers', () => { describe('setupEmbeddablesAPI', () => { test('attaches SIEM_FILTER_ACTION, and detaches extra UI actions', () => { - setupEmbeddablesAPI(); + setupEmbeddablesAPI((npStart.plugins as unknown) as PluginsStart); expect(npStart.plugins.uiActions.registerAction).toHaveBeenCalledTimes(1); expect(npStart.plugins.uiActions.detachAction).toHaveBeenCalledTimes(3); }); @@ -67,7 +62,8 @@ describe('embedded_map_helpers', () => { 0, 0, setQueryMock, - createPortalNode() + createPortalNode(), + npStart.plugins.embeddable ); expect(setQueryMock).toHaveBeenCalledTimes(1); }); @@ -81,7 +77,8 @@ describe('embedded_map_helpers', () => { 0, 0, setQueryMock, - createPortalNode() + createPortalNode(), + npStart.plugins.embeddable ); expect(setQueryMock.mock.calls[0][0].refetch).not.toBe(embeddable.reload); setQueryMock.mock.results[0].value(); diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx index bd14e65f0980b7..3494a13656f8ac 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx @@ -7,12 +7,11 @@ import { Filter } from '@kbn/es-query'; import uuid from 'uuid'; import React from 'react'; -import { npStart } from 'ui/new_platform'; import { OutPortal, PortalNode } from 'react-reverse-portal'; import { Query } from 'src/plugins/data/common'; +import { PluginsStart } from 'ui/new_platform/new_platform'; import { ActionToaster, AppToast } from '../toasters'; -import { start } from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public/legacy'; import { APPLY_FILTER_TRIGGER, CONTEXT_MENU_TRIGGER, @@ -24,7 +23,13 @@ import { APPLY_SIEM_FILTER_ACTION_ID, ApplySiemFilterAction, } from './actions/apply_siem_filter_action'; -import { IndexPatternMapping, MapEmbeddable, RenderTooltipContentParams, SetQuery } from './types'; +import { + IndexPatternMapping, + MapEmbeddable, + RenderTooltipContentParams, + SetQuery, + EmbeddableApi, +} from './types'; import { getLayerList } from './map_config'; // @ts-ignore Missing type defs as maps moves to Typescript import { MAP_SAVED_OBJECT_TYPE } from '../../../../maps/common/constants'; @@ -63,18 +68,18 @@ export const displayErrorToast = ( * * @throws Error if action is already registered */ -export const setupEmbeddablesAPI = () => { +export const setupEmbeddablesAPI = (plugins: PluginsStart) => { try { - const actions = npStart.plugins.uiActions.getTriggerActions(APPLY_FILTER_TRIGGER); + const actions = plugins.uiActions.getTriggerActions(APPLY_FILTER_TRIGGER); const actionLoaded = actions.some(a => a.id === APPLY_SIEM_FILTER_ACTION_ID); if (!actionLoaded) { const siemFilterAction = new ApplySiemFilterAction(); - npStart.plugins.uiActions.registerAction(siemFilterAction); - npStart.plugins.uiActions.attachAction(APPLY_FILTER_TRIGGER, siemFilterAction.id); + plugins.uiActions.registerAction(siemFilterAction); + plugins.uiActions.attachAction(APPLY_FILTER_TRIGGER, siemFilterAction.id); - npStart.plugins.uiActions.detachAction(CONTEXT_MENU_TRIGGER, 'CUSTOM_TIME_RANGE'); - npStart.plugins.uiActions.detachAction(PANEL_BADGE_TRIGGER, 'CUSTOM_TIME_RANGE_BADGE'); - npStart.plugins.uiActions.detachAction(APPLY_FILTER_TRIGGER, APPLY_FILTER_ACTION); + plugins.uiActions.detachAction(CONTEXT_MENU_TRIGGER, 'CUSTOM_TIME_RANGE'); + plugins.uiActions.detachAction(PANEL_BADGE_TRIGGER, 'CUSTOM_TIME_RANGE_BADGE'); + plugins.uiActions.detachAction(APPLY_FILTER_TRIGGER, APPLY_FILTER_ACTION); } } catch (e) { throw e; @@ -100,9 +105,10 @@ export const createEmbeddable = async ( startDate: number, endDate: number, setQuery: SetQuery, - portalNode: PortalNode + portalNode: PortalNode, + embeddableApi: EmbeddableApi ): Promise => { - const factory = start.getEmbeddableFactory(MAP_SAVED_OBJECT_TYPE); + const factory = embeddableApi.getEmbeddableFactory(MAP_SAVED_OBJECT_TYPE); const state = { layerList: getLayerList(indexPatterns), diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts b/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts index 7ab991aa7a8aef..3a13753ba25e46 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts @@ -11,6 +11,7 @@ import { EmbeddableInput, EmbeddableOutput, IEmbeddable, + EmbeddableFactory, } from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public'; import { inputsModel } from '../../store/inputs'; @@ -70,3 +71,8 @@ export interface RenderTooltipContentParams { } export type MapToolTipProps = Partial; + +export interface EmbeddableApi { + getEmbeddableFactory: (embeddableFactoryId: string) => EmbeddableFactory; + registerEmbeddableFactory: (id: string, factory: EmbeddableFactory) => void; +} diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.test.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.test.tsx index 96de698a6393e0..a97ef2cf5ca0c4 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.test.tsx @@ -7,21 +7,23 @@ import { mount } from 'enzyme'; import React from 'react'; import { MockedProvider } from 'react-apollo/test-utils'; -import { npSetup } from 'ui/new_platform'; import { TestProviders } from '../../mock'; -import { MockNpSetUp, mockUiSettings } from '../../mock/ui_settings'; +import { mockUiSettings } from '../../mock/ui_settings'; import { wait } from '../../lib/helpers'; import { mockEventViewerResponse } from './mock'; import { StatefulEventsViewer } from '.'; import { defaultHeaders } from './default_headers'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; jest.mock('../../lib/settings/use_kibana_ui_setting'); -const mockNpSetup: MockNpSetUp = (npSetup as unknown) as MockNpSetUp; -jest.mock('ui/new_platform'); -mockNpSetup.core.uiSettings = mockUiSettings; +const mockUseKibanaCore = useKibanaCore as jest.Mock; +jest.mock('../../lib/compose/kibana_core'); +mockUseKibanaCore.mockImplementation(() => ({ + uiSettings: mockUiSettings, +})); const from = 1566943856794; const to = 1566857456791; diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx index d8c8996b9af420..13f0666b31212c 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx @@ -5,7 +5,7 @@ */ import { EuiPanel } from '@elastic/eui'; -import { Filter } from '@kbn/es-query'; +import { Filter, getEsQueryConfig } from '@kbn/es-query'; import { getOr, isEmpty, isEqual } from 'lodash/fp'; import React from 'react'; import styled from 'styled-components'; @@ -15,6 +15,7 @@ import { Query } from 'src/plugins/data/common'; import { BrowserFields } from '../../containers/source'; import { TimelineQuery } from '../../containers/timeline'; import { Direction } from '../../graphql/types'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; import { KqlMode } from '../../store/timeline/model'; import { AutoSizer } from '../auto_sizer'; import { HeaderPanel } from '../header_panel'; @@ -81,8 +82,9 @@ export const EventsViewer = React.memo( toggleColumn, }) => { const columnsHeader = isEmpty(columns) ? defaultHeaders : columns; - + const core = useKibanaCore(); const combinedQueries = combineQueries({ + config: getEsQueryConfig(core.uiSettings), dataProviders, indexPattern, browserFields, diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.test.tsx index d6b65874a02e8e..671711c60bd165 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.test.tsx @@ -8,15 +8,22 @@ import { mount } from 'enzyme'; import React from 'react'; import { MockedProvider } from 'react-apollo/test-utils'; -import { TestProviders } from '../../mock'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; import { wait } from '../../lib/helpers'; -import '../../mock/ui_settings'; +import { TestProviders } from '../../mock'; +import { mockUiSettings } from '../../mock/ui_settings'; import { mockEventViewerResponse } from './mock'; import { StatefulEventsViewer } from '.'; jest.mock('../../lib/settings/use_kibana_ui_setting'); +const mockUseKibanaCore = useKibanaCore as jest.Mock; +jest.mock('../../lib/compose/kibana_core'); +mockUseKibanaCore.mockImplementation(() => ({ + uiSettings: mockUiSettings, +})); + const from = 1566943856794; const to = 1566857456791; diff --git a/x-pack/legacy/plugins/siem/public/components/ml/anomaly/use_anomalies_table_data.ts b/x-pack/legacy/plugins/siem/public/components/ml/anomaly/use_anomalies_table_data.ts index 6c3b6444578d6e..130c326339b1b2 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/anomaly/use_anomalies_table_data.ts +++ b/x-pack/legacy/plugins/siem/public/components/ml/anomaly/use_anomalies_table_data.ts @@ -99,9 +99,7 @@ export const useAnomaliesTableData = ({ maxRecords: 500, maxExamples: 10, }, - { - 'kbn-version': kbnVersion, - }, + kbnVersion, abortCtrl.signal ); if (isSubscribed) { diff --git a/x-pack/legacy/plugins/siem/public/components/ml/api/anomalies_table_data.ts b/x-pack/legacy/plugins/siem/public/components/ml/api/anomalies_table_data.ts index 12c68467fe117f..e66d984a152941 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/api/anomalies_table_data.ts +++ b/x-pack/legacy/plugins/siem/public/components/ml/api/anomalies_table_data.ts @@ -6,8 +6,6 @@ import chrome from 'ui/chrome'; -import { useKibanaUiSetting } from '../../../lib/settings/use_kibana_ui_setting'; -import { DEFAULT_KBN_VERSION } from '../../../../common/constants'; import { Anomalies, InfluencerInput, CriteriaFields } from '../types'; import { throwIfNotOk } from '../../../hooks/api/api'; export interface Body { @@ -25,10 +23,9 @@ export interface Body { export const anomaliesTableData = async ( body: Body, - headers: Record, + kbnVersion: string, signal: AbortSignal ): Promise => { - const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); const response = await fetch(`${chrome.getBasePath()}/api/ml/results/anomalies_table_data`, { method: 'POST', credentials: 'same-origin', @@ -37,7 +34,7 @@ export const anomaliesTableData = async ( 'kbn-system-api': 'true', 'content-Type': 'application/json', 'kbn-xsrf': kbnVersion, - ...headers, + 'kbn-version': kbnVersion, }, signal, }); diff --git a/x-pack/legacy/plugins/siem/public/components/ml/api/get_ml_capabilities.ts b/x-pack/legacy/plugins/siem/public/components/ml/api/get_ml_capabilities.ts index deec12aacfc42d..c1654a1648f2b5 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/api/get_ml_capabilities.ts +++ b/x-pack/legacy/plugins/siem/public/components/ml/api/get_ml_capabilities.ts @@ -6,8 +6,6 @@ import chrome from 'ui/chrome'; -import { DEFAULT_KBN_VERSION } from '../../../../common/constants'; -import { useKibanaUiSetting } from '../../../lib/settings/use_kibana_ui_setting'; import { InfluencerInput, MlCapabilities } from '../types'; import { throwIfNotOk } from '../../../hooks/api/api'; @@ -25,10 +23,9 @@ export interface Body { } export const getMlCapabilities = async ( - headers: Record, + kbnVersion: string, signal: AbortSignal ): Promise => { - const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); const response = await fetch(`${chrome.getBasePath()}/api/ml/ml_capabilities`, { method: 'GET', credentials: 'same-origin', @@ -36,7 +33,7 @@ export const getMlCapabilities = async ( 'kbn-system-api': 'true', 'content-Type': 'application/json', 'kbn-xsrf': kbnVersion, - ...headers, + 'kbn-version': kbnVersion, }, signal, }); diff --git a/x-pack/legacy/plugins/siem/public/components/ml/permissions/ml_capabilities_provider.tsx b/x-pack/legacy/plugins/siem/public/components/ml/permissions/ml_capabilities_provider.tsx index f9522231f44706..352f39a75ded16 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/permissions/ml_capabilities_provider.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml/permissions/ml_capabilities_provider.tsx @@ -44,10 +44,7 @@ export const MlCapabilitiesProvider = React.memo<{ children: JSX.Element }>(({ c async function fetchMlCapabilities() { try { - const mlCapabilities = await getMlCapabilities( - { 'kbn-version': kbnVersion }, - abortCtrl.signal - ); + const mlCapabilities = await getMlCapabilities(kbnVersion, abortCtrl.signal); if (isSubscribed) { setCapabilities({ ...mlCapabilities, capabilitiesFetched: true }); } diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/api.tsx b/x-pack/legacy/plugins/siem/public/components/ml_popover/api.tsx index 6f74df4aed3846..8e7bedd8f872a0 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml_popover/api.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/api.tsx @@ -19,8 +19,6 @@ import { StopDatafeedResponse, } from './types'; import { throwIfErrorAttached, throwIfErrorAttachedToSetup } from '../ml/api/throw_if_not_ok'; -import { useKibanaUiSetting } from '../../lib/settings/use_kibana_ui_setting'; -import { DEFAULT_KBN_VERSION } from '../../../common/constants'; import { throwIfNotOk } from '../../hooks/api/api'; /** @@ -32,10 +30,9 @@ import { throwIfNotOk } from '../../hooks/api/api'; */ export const checkRecognizer = async ({ indexPatternName, - headers = {}, + kbnVersion, signal, }: CheckRecognizerProps): Promise => { - const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); const response = await fetch( `${chrome.getBasePath()}/api/ml/modules/recognize/${indexPatternName}`, { @@ -46,7 +43,6 @@ export const checkRecognizer = async ({ 'content-type': 'application/json', 'kbn-version': kbnVersion, 'kbn-xsrf': kbnVersion, - ...headers, }, signal, } @@ -64,10 +60,9 @@ export const checkRecognizer = async ({ */ export const getModules = async ({ moduleId = '', - headers = {}, + kbnVersion, signal, }: GetModulesProps): Promise => { - const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); const response = await fetch(`${chrome.getBasePath()}/api/ml/modules/get_module/${moduleId}`, { method: 'GET', credentials: 'same-origin', @@ -76,7 +71,6 @@ export const getModules = async ({ 'content-type': 'application/json', 'kbn-version': kbnVersion, 'kbn-xsrf': kbnVersion, - ...headers, }, signal, }); @@ -99,10 +93,9 @@ export const setupMlJob = async ({ indexPatternName = 'auditbeat-*', jobIdErrorFilter = [], groups = ['siem'], + kbnVersion, prefix = '', - headers = {}, }: MlSetupArgs): Promise => { - const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); const response = await fetch(`${chrome.getBasePath()}/api/ml/modules/setup/${configTemplate}`, { method: 'POST', credentials: 'same-origin', @@ -118,7 +111,6 @@ export const setupMlJob = async ({ 'content-type': 'application/json', 'kbn-version': kbnVersion, 'kbn-xsrf': kbnVersion, - ...headers, }, }); await throwIfNotOk(response); @@ -136,14 +128,13 @@ export const setupMlJob = async ({ */ export const startDatafeeds = async ({ datafeedIds, - headers, + kbnVersion, start = 0, }: { datafeedIds: string[]; start: number; - headers?: Record; + kbnVersion: string; }): Promise => { - const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); const response = await fetch(`${chrome.getBasePath()}/api/ml/jobs/force_start_datafeeds`, { method: 'POST', credentials: 'same-origin', @@ -156,7 +147,6 @@ export const startDatafeeds = async ({ 'content-type': 'application/json', 'kbn-version': kbnVersion, 'kbn-xsrf': kbnVersion, - ...headers, }, }); await throwIfNotOk(response); @@ -173,12 +163,11 @@ export const startDatafeeds = async ({ */ export const stopDatafeeds = async ({ datafeedIds, - headers, + kbnVersion, }: { datafeedIds: string[]; - headers?: Record; + kbnVersion: string; }): Promise<[StopDatafeedResponse | ErrorResponse, CloseJobsResponse]> => { - const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); const stopDatafeedsResponse = await fetch(`${chrome.getBasePath()}/api/ml/jobs/stop_datafeeds`, { method: 'POST', credentials: 'same-origin', @@ -189,7 +178,6 @@ export const stopDatafeeds = async ({ 'kbn-system-api': 'true', 'content-type': 'application/json', 'kbn-xsrf': kbnVersion, - ...headers, }, }); @@ -211,7 +199,6 @@ export const stopDatafeeds = async ({ 'content-type': 'application/json', 'kbn-system-api': 'true', 'kbn-xsrf': kbnVersion, - ...headers, }, }); @@ -227,8 +214,10 @@ export const stopDatafeeds = async ({ * * @param signal to cancel request */ -export const getJobsSummary = async (signal: AbortSignal): Promise => { - const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); +export const getJobsSummary = async ( + signal: AbortSignal, + kbnVersion: string +): Promise => { const response = await fetch(`${chrome.getBasePath()}/api/ml/jobs/jobs_summary`, { method: 'POST', credentials: 'same-origin', diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/hooks/use_siem_jobs.tsx b/x-pack/legacy/plugins/siem/public/components/ml_popover/hooks/use_siem_jobs.tsx index 89f995773e8332..0bef34a7edc44e 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml_popover/hooks/use_siem_jobs.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/hooks/use_siem_jobs.tsx @@ -13,7 +13,7 @@ import { MlCapabilitiesContext } from '../../ml/permissions/ml_capabilities_prov import { useStateToaster } from '../../toasters'; import { errorToToaster } from '../../ml/api/error_to_toaster'; import { useKibanaUiSetting } from '../../../lib/settings/use_kibana_ui_setting'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; +import { DEFAULT_INDEX_KEY, DEFAULT_KBN_VERSION } from '../../../../common/constants'; import * as i18n from './translations'; import { createSiemJobs } from './use_siem_jobs_helpers'; @@ -34,6 +34,7 @@ export const useSiemJobs = (refetchData: boolean): Return => { const capabilities = useContext(MlCapabilitiesContext); const userPermissions = hasMlUserPermissions(capabilities); const [siemDefaultIndex] = useKibanaUiSetting(DEFAULT_INDEX_KEY); + const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); const [, dispatchToaster] = useStateToaster(); useEffect(() => { @@ -46,9 +47,13 @@ export const useSiemJobs = (refetchData: boolean): Return => { try { // Batch fetch all installed jobs, ML modules, and check which modules are compatible with siemDefaultIndex const [jobSummaryData, modulesData, compatibleModules] = await Promise.all([ - getJobsSummary(abortCtrl.signal), - getModules({ signal: abortCtrl.signal }), - checkRecognizer({ indexPatternName: siemDefaultIndex, signal: abortCtrl.signal }), + getJobsSummary(abortCtrl.signal, kbnVersion), + getModules({ signal: abortCtrl.signal, kbnVersion }), + checkRecognizer({ + indexPatternName: siemDefaultIndex, + kbnVersion, + signal: abortCtrl.signal, + }), ]); const compositeSiemJobs = createSiemJobs(jobSummaryData, modulesData, compatibleModules); diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx b/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx index 2c3bc469a51df0..15e9c15744e9ca 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/ml_popover.tsx @@ -23,6 +23,8 @@ import { errorToToaster } from '../ml/api/error_to_toaster'; import { METRIC_TYPE, TELEMETRY_EVENT, trackUiAction as track } from '../../lib/track_usage'; import { useSiemJobs } from './hooks/use_siem_jobs'; import { filterJobs } from './helpers'; +import { useKibanaUiSetting } from '../../lib/settings/use_kibana_ui_setting'; +import { DEFAULT_KBN_VERSION } from '../../../common/constants'; const PopoverContentsDiv = styled.div` max-width: 684px; @@ -93,6 +95,7 @@ export const MlPopover = React.memo(() => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [filterProperties, setFilterProperties] = useState(defaultFilterProps); + const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); const [isLoadingSiemJobs, siemJobs] = useSiemJobs(refreshToggle); const [, dispatchToaster] = useStateToaster(); const capabilities = useContext(MlCapabilitiesContext); @@ -108,6 +111,7 @@ export const MlPopover = React.memo(() => { indexPatternName: job.defaultIndexPattern, jobIdErrorFilter: [job.id], groups: job.groups, + kbnVersion, }); } catch (error) { errorToToaster({ title: i18n.CREATE_JOB_FAILURE, error, dispatchToaster }); @@ -125,14 +129,14 @@ export const MlPopover = React.memo(() => { if (enable) { const startTime = Math.max(latestTimestampMs, maxStartTime); try { - await startDatafeeds({ datafeedIds: [`datafeed-${job.id}`], start: startTime }); + await startDatafeeds({ datafeedIds: [`datafeed-${job.id}`], kbnVersion, start: startTime }); } catch (error) { track(METRIC_TYPE.COUNT, TELEMETRY_EVENT.JOB_ENABLE_FAILURE); errorToToaster({ title: i18n.START_JOB_FAILURE, error, dispatchToaster }); } } else { try { - await stopDatafeeds({ datafeedIds: [`datafeed-${job.id}`] }); + await stopDatafeeds({ datafeedIds: [`datafeed-${job.id}`], kbnVersion }); } catch (error) { track(METRIC_TYPE.COUNT, TELEMETRY_EVENT.JOB_DISABLE_FAILURE); errorToToaster({ title: i18n.STOP_JOB_FAILURE, error, dispatchToaster }); diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/types.ts b/x-pack/legacy/plugins/siem/public/components/ml_popover/types.ts index 203f4f646b62b7..88481e140cb03e 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml_popover/types.ts +++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/types.ts @@ -14,7 +14,7 @@ export interface Group { export interface CheckRecognizerProps { indexPatternName: string; - headers?: Record; + kbnVersion: string; signal: AbortSignal; } @@ -30,7 +30,7 @@ export interface RecognizerModule { export interface GetModulesProps { moduleId?: string; - headers?: Record; + kbnVersion: string; signal: AbortSignal; } @@ -97,7 +97,7 @@ export interface MlSetupArgs { jobIdErrorFilter: string[]; groups: string[]; prefix?: string; - headers?: Record; + kbnVersion: string; } /** diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/__snapshots__/index.test.tsx.snap index c320ab1be2d84f..4c84aa15fd4c28 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/__snapshots__/index.test.tsx.snap @@ -1,169 +1,181 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Hosts Table rendering it renders the default Hosts table 1`] = ` - + + fakeTotalCount={50} + id="hostsQuery" + indexPattern={ + Object { + "fields": Array [ + Object { + "aggregatable": true, + "name": "@timestamp", + "searchable": true, + "type": "date", + }, + Object { + "aggregatable": true, + "name": "@version", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "agent.ephemeral_id", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "agent.hostname", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "agent.id", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "agent.test1", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "agent.test2", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "agent.test3", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "agent.test4", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "agent.test5", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "agent.test6", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "agent.test7", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "agent.test8", + "searchable": true, + "type": "string", + }, + Object { + "aggregatable": true, + "name": "host.name", + "searchable": true, + "type": "string", + }, + ], + "title": "filebeat-*,auditbeat-*,packetbeat-*", + } + } + isInspect={false} + loadPage={[MockFunction]} + loading={false} + showMorePagesIndicator={true} + totalCount={4} + type="page" + /> + `; diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.test.tsx index 90d7a9c613dc25..44898e7a307ff2 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.test.tsx @@ -9,8 +9,6 @@ import toJson from 'enzyme-to-json'; import { getOr } from 'lodash/fp'; import * as React from 'react'; import { MockedProvider } from 'react-apollo/test-utils'; -import { Provider as ReduxStoreProvider } from 'react-redux'; -import { npSetup } from 'ui/new_platform'; import { apolloClientObservable, @@ -18,15 +16,24 @@ import { mockGlobalState, TestProviders, } from '../../../../mock'; -import { MockNpSetUp, mockUiSettings } from '../../../../mock/ui_settings'; +import { mockUiSettings } from '../../../../mock/ui_settings'; +import { useKibanaCore } from '../../../../lib/compose/kibana_core'; import { createStore, hostsModel, State } from '../../../../store'; import { HostsTableType } from '../../../../store/hosts/model'; import { HostsTable } from './index'; import { mockData } from './mock'; -const mockNpSetup: MockNpSetUp = (npSetup as unknown) as MockNpSetUp; -jest.mock('ui/new_platform'); -mockNpSetup.core.uiSettings = mockUiSettings; +const mockUseKibanaCore = useKibanaCore as jest.Mock; +jest.mock('../../../../lib/compose/kibana_core'); +mockUseKibanaCore.mockImplementation(() => ({ + uiSettings: mockUiSettings, +})); + +// Test will fail because we will to need to mock some core services to make the test work +// For now let's forget about SiemSearchBar +jest.mock('../../../search_bar', () => ({ + SiemSearchBar: () => null, +})); describe('Hosts Table', () => { const loadPage = jest.fn(); @@ -41,7 +48,7 @@ describe('Hosts Table', () => { describe('rendering', () => { test('it renders the default Hosts table', () => { const wrapper = shallow( - + { totalCount={mockData.Hosts.totalCount} type={hostsModel.HostsType.page} /> - + ); expect(toJson(wrapper)).toMatchSnapshot(); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/helpers.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/helpers.test.tsx index 8ab694df32c6d1..855c951fbceccd 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/helpers.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/helpers.test.tsx @@ -5,23 +5,18 @@ */ import { cloneDeep } from 'lodash/fp'; -import { npSetup } from 'ui/new_platform'; import { mockIndexPattern } from '../../mock'; -import { mockUiSettings, MockNpSetUp } from '../../mock/ui_settings'; import { mockDataProviders } from './data_providers/mock/mock_data_providers'; import { buildGlobalQuery, combineQueries } from './helpers'; import { mockBrowserFields } from '../../containers/source/mock'; +import { EsQueryConfig } from '../../lib/keury'; const cleanUpKqlQuery = (str: string) => str.replace(/\n/g, '').replace(/\s\s+/g, ' '); const startDate = new Date('2018-03-23T18:49:23.132Z').valueOf(); const endDate = new Date('2018-03-24T03:33:52.253Z').valueOf(); -const mockNpSetup: MockNpSetUp = (npSetup as unknown) as MockNpSetUp; -jest.mock('ui/new_platform'); -mockNpSetup.core.uiSettings = mockUiSettings; - describe('Build KQL Query', () => { test('Build KQL query with one data provider', () => { const dataProviders = mockDataProviders.slice(0, 1); @@ -122,9 +117,16 @@ describe('Build KQL Query', () => { }); describe('Combined Queries', () => { + const config: EsQueryConfig = { + allowLeadingWildcards: true, + queryStringOptions: {}, + ignoreFilterIfFieldNotInIndex: true, + dateFormatTZ: 'America/New_York', + }; test('No Data Provider & No kqlQuery & and isEventViewer is false', () => { expect( combineQueries({ + config, dataProviders: [], indexPattern: mockIndexPattern, browserFields: mockBrowserFields, @@ -141,6 +143,7 @@ describe('Combined Queries', () => { const isEventViewer = true; expect( combineQueries({ + config, dataProviders: [], indexPattern: mockIndexPattern, browserFields: mockBrowserFields, @@ -160,6 +163,7 @@ describe('Combined Queries', () => { test('Only Data Provider', () => { const dataProviders = mockDataProviders.slice(0, 1); const { filterQuery } = combineQueries({ + config, dataProviders, indexPattern: mockIndexPattern, browserFields: mockBrowserFields, @@ -179,6 +183,7 @@ describe('Combined Queries', () => { dataProviders[0].queryMatch.field = '@timestamp'; dataProviders[0].queryMatch.value = '2018-03-23T23:36:23.232Z'; const { filterQuery } = combineQueries({ + config, dataProviders, indexPattern: mockIndexPattern, browserFields: mockBrowserFields, @@ -198,6 +203,7 @@ describe('Combined Queries', () => { dataProviders[0].queryMatch.field = '@timestamp'; dataProviders[0].queryMatch.value = 1521848183232; const { filterQuery } = combineQueries({ + config, dataProviders, indexPattern: mockIndexPattern, browserFields: mockBrowserFields, @@ -217,6 +223,7 @@ describe('Combined Queries', () => { dataProviders[0].queryMatch.field = 'event.end'; dataProviders[0].queryMatch.value = '2018-03-23T23:36:23.232Z'; const { filterQuery } = combineQueries({ + config, dataProviders, indexPattern: mockIndexPattern, browserFields: mockBrowserFields, @@ -236,6 +243,7 @@ describe('Combined Queries', () => { dataProviders[0].queryMatch.field = 'event.end'; dataProviders[0].queryMatch.value = 1521848183232; const { filterQuery } = combineQueries({ + config, dataProviders, indexPattern: mockIndexPattern, browserFields: mockBrowserFields, @@ -252,6 +260,7 @@ describe('Combined Queries', () => { test('Only KQL search/filter query', () => { const { filterQuery } = combineQueries({ + config, dataProviders: [], indexPattern: mockIndexPattern, browserFields: mockBrowserFields, @@ -269,6 +278,7 @@ describe('Combined Queries', () => { test('Data Provider & KQL search query', () => { const dataProviders = mockDataProviders.slice(0, 1); const { filterQuery } = combineQueries({ + config, dataProviders, indexPattern: mockIndexPattern, browserFields: mockBrowserFields, @@ -286,6 +296,7 @@ describe('Combined Queries', () => { test('Data Provider & KQL filter query', () => { const dataProviders = mockDataProviders.slice(0, 1); const { filterQuery } = combineQueries({ + config, dataProviders, indexPattern: mockIndexPattern, browserFields: mockBrowserFields, @@ -305,6 +316,7 @@ describe('Combined Queries', () => { dataProviders[0].and = mockDataProviders.slice(2, 4); dataProviders[1].and = mockDataProviders.slice(4, 5); const { filterQuery } = combineQueries({ + config, dataProviders, indexPattern: mockIndexPattern, browserFields: mockBrowserFields, @@ -324,6 +336,7 @@ describe('Combined Queries', () => { dataProviders[0].and = mockDataProviders.slice(2, 4); dataProviders[1].and = mockDataProviders.slice(4, 5); const { filterQuery } = combineQueries({ + config, dataProviders, indexPattern: mockIndexPattern, browserFields: mockBrowserFields, diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx index b56145d3a058fe..a18e4d7962e955 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/helpers.tsx @@ -10,7 +10,7 @@ import memoizeOne from 'memoize-one'; import { StaticIndexPattern } from 'ui/index_patterns'; import { Query } from 'src/plugins/data/common'; -import { escapeQueryValue, convertToBuildEsQuery } from '../../lib/keury'; +import { escapeQueryValue, convertToBuildEsQuery, EsQueryConfig } from '../../lib/keury'; import { DataProvider, DataProvidersAnd, EXISTS_OPERATOR } from './data_providers/data_provider'; import { BrowserFields } from '../../containers/source'; @@ -91,6 +91,7 @@ export const buildGlobalQuery = (dataProviders: DataProvider[], browserFields: B .trim(); export const combineQueries = ({ + config, dataProviders, indexPattern, browserFields, @@ -101,6 +102,7 @@ export const combineQueries = ({ end, isEventViewer, }: { + config: EsQueryConfig; dataProviders: DataProvider[]; indexPattern: StaticIndexPattern; browserFields: BrowserFields; @@ -117,12 +119,12 @@ export const combineQueries = ({ } else if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && isEventViewer) { kuery.query = `@timestamp >= ${start} and @timestamp <= ${end}`; return { - filterQuery: convertToBuildEsQuery({ queries: [kuery], indexPattern, filters }), + filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), }; } else if (isEmpty(dataProviders) && !isEmpty(kqlQuery.query)) { kuery.query = `(${kqlQuery.query}) and @timestamp >= ${start} and @timestamp <= ${end}`; return { - filterQuery: convertToBuildEsQuery({ queries: [kuery], indexPattern, filters }), + filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), }; } else if (!isEmpty(dataProviders) && isEmpty(kqlQuery)) { kuery.query = `(${buildGlobalQuery( @@ -130,7 +132,7 @@ export const combineQueries = ({ browserFields )}) and @timestamp >= ${start} and @timestamp <= ${end}`; return { - filterQuery: convertToBuildEsQuery({ queries: [kuery], indexPattern, filters }), + filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), }; } const operatorKqlQuery = kqlMode === 'filter' ? 'and' : 'or'; @@ -139,7 +141,7 @@ export const combineQueries = ({ kqlQuery.query as string )}) and @timestamp >= ${start} and @timestamp <= ${end}`; return { - filterQuery: convertToBuildEsQuery({ queries: [kuery], indexPattern, filters }), + filterQuery: convertToBuildEsQuery({ config, queries: [kuery], indexPattern, filters }), }; }; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx index 85986d2ed471c1..700489f47d0cf3 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.test.tsx @@ -12,8 +12,10 @@ import { MockedProvider } from 'react-apollo/test-utils'; import { timelineQuery } from '../../containers/timeline/index.gql_query'; import { mockBrowserFields } from '../../containers/source/mock'; import { Direction } from '../../graphql/types'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; import { defaultHeaders, mockTimelineData, mockIndexPattern } from '../../mock'; import { TestProviders } from '../../mock/test_providers'; +import { mockUiSettings } from '../../mock/ui_settings'; import { flyoutHeaderHeight } from '../flyout'; import { @@ -27,6 +29,12 @@ import { mockDataProviders } from './data_providers/mock/mock_data_providers'; const testFlyoutHeight = 980; +const mockUseKibanaCore = useKibanaCore as jest.Mock; +jest.mock('../../lib/compose/kibana_core'); +mockUseKibanaCore.mockImplementation(() => ({ + uiSettings: mockUiSettings, +})); + describe('Timeline', () => { const sort: Sort = { columnId: '@timestamp', diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx index efab2ac52a0b6c..fb62b636398c23 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx @@ -5,6 +5,7 @@ */ import { EuiFlexGroup } from '@elastic/eui'; +import { getEsQueryConfig } from '@kbn/es-query'; import { getOr, isEmpty } from 'lodash/fp'; import * as React from 'react'; import styled from 'styled-components'; @@ -13,6 +14,7 @@ import { StaticIndexPattern } from 'ui/index_patterns'; import { BrowserFields } from '../../containers/source'; import { TimelineQuery } from '../../containers/timeline'; import { Direction } from '../../graphql/types'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; import { KqlMode } from '../../store/timeline/model'; import { AutoSizer } from '../auto_sizer'; import { ColumnHeader } from './body/column_headers/column_header'; @@ -111,7 +113,9 @@ export const Timeline = React.memo( sort, toggleColumn, }) => { + const core = useKibanaCore(); const combinedQueries = combineQueries({ + config: getEsQueryConfig(core.uiSettings), dataProviders, indexPattern, browserFields, diff --git a/x-pack/legacy/plugins/siem/public/containers/kuery_autocompletion/index.tsx b/x-pack/legacy/plugins/siem/public/containers/kuery_autocompletion/index.tsx index 9cf7331441da5e..dac531365c8702 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kuery_autocompletion/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/kuery_autocompletion/index.tsx @@ -5,9 +5,9 @@ */ import React, { useState } from 'react'; -import { npStart } from 'ui/new_platform'; import { StaticIndexPattern } from 'ui/index_patterns'; import { AutocompleteSuggestion } from '../../../../../../../src/plugins/data/public'; +import { useKibanaPlugins } from '../../lib/compose/kibana_plugins'; type RendererResult = React.ReactElement | null; type RendererFunction = (args: RenderArgs) => Result; @@ -26,23 +26,19 @@ interface KueryAutocompletionCurrentRequest { cursorPosition: number; } -const getAutocompleteProvider = (language: string) => - npStart.plugins.data.autocomplete.getProvider(language); - export const KueryAutocompletion = React.memo( ({ children, indexPattern }) => { const [currentRequest, setCurrentRequest] = useState( null ); - const [suggestions, setSuggestions] = useState([]); - + const plugins = useKibanaPlugins(); const loadSuggestions = async ( expression: string, cursorPosition: number, maxSuggestions?: number ) => { - const autocompletionProvider = getAutocompleteProvider('kuery'); + const autocompletionProvider = plugins.data.autocomplete.getProvider('kuery'); const config = { get: () => true, }; diff --git a/x-pack/legacy/plugins/siem/public/hooks/api/api.tsx b/x-pack/legacy/plugins/siem/public/hooks/api/api.tsx index b0493733a735b2..12282241247cbc 100644 --- a/x-pack/legacy/plugins/siem/public/hooks/api/api.tsx +++ b/x-pack/legacy/plugins/siem/public/hooks/api/api.tsx @@ -6,8 +6,6 @@ import chrome from 'ui/chrome'; -import { useKibanaUiSetting } from '../../lib/settings/use_kibana_ui_setting'; -import { DEFAULT_KBN_VERSION } from '../../../common/constants'; import * as i18n from '../translations'; import { parseJsonFromBody, ToasterErrors } from '../../components/ml/api/throw_if_not_ok'; import { IndexPatternResponse, IndexPatternSavedObject } from '../types'; @@ -24,9 +22,8 @@ const emptyIndexPattern: IndexPatternSavedObject[] = []; */ export const getIndexPatterns = async ( signal: AbortSignal, - headers?: Record + kbnVersion: string ): Promise => { - const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); const response = await fetch( `${chrome.getBasePath()}/api/saved_objects/_find?type=index-pattern&fields=title&fields=type&per_page=10000`, { @@ -37,7 +34,6 @@ export const getIndexPatterns = async ( 'kbn-xsrf': kbnVersion, 'kbn-version': kbnVersion, 'kbn-system-api': 'true', - ...headers, }, signal, } diff --git a/x-pack/legacy/plugins/siem/public/hooks/use_index_patterns.tsx b/x-pack/legacy/plugins/siem/public/hooks/use_index_patterns.tsx index b7e899cc50f753..091315df314d90 100644 --- a/x-pack/legacy/plugins/siem/public/hooks/use_index_patterns.tsx +++ b/x-pack/legacy/plugins/siem/public/hooks/use_index_patterns.tsx @@ -6,12 +6,14 @@ import { useEffect, useState } from 'react'; +import { DEFAULT_KBN_VERSION } from '../../common/constants'; import { useStateToaster } from '../components/toasters'; import { errorToToaster } from '../components/ml/api/error_to_toaster'; - -import * as i18n from './translations'; import { IndexPatternSavedObject } from '../components/ml_popover/types'; +import { useKibanaUiSetting } from '../lib/settings/use_kibana_ui_setting'; + import { getIndexPatterns } from './api/api'; +import * as i18n from './translations'; type Return = [boolean, IndexPatternSavedObject[]]; @@ -19,6 +21,7 @@ export const useIndexPatterns = (refreshToggle = false): Return => { const [indexPatterns, setIndexPatterns] = useState([]); const [isLoading, setIsLoading] = useState(true); const [, dispatchToaster] = useStateToaster(); + const [kbnVersion] = useKibanaUiSetting(DEFAULT_KBN_VERSION); useEffect(() => { let isSubscribed = true; @@ -27,7 +30,7 @@ export const useIndexPatterns = (refreshToggle = false): Return => { async function fetchIndexPatterns() { try { - const data = await getIndexPatterns(abortCtrl.signal); + const data = await getIndexPatterns(abortCtrl.signal, kbnVersion); if (isSubscribed) { setIndexPatterns(data); diff --git a/x-pack/legacy/plugins/siem/public/lib/compose/__mocks__/kibana_core.ts b/x-pack/legacy/plugins/siem/public/lib/compose/__mocks__/kibana_core.ts new file mode 100644 index 00000000000000..7511f65dfb3092 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/lib/compose/__mocks__/kibana_core.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { createUiNewPlatformMock } from 'ui/new_platform/__mocks__/helpers'; + +const npStart = createUiNewPlatformMock().npStart; + +export function useKibanaCore() { + return npStart.core; +} diff --git a/x-pack/legacy/plugins/siem/public/lib/compose/__mocks__/kibana_plugins.ts b/x-pack/legacy/plugins/siem/public/lib/compose/__mocks__/kibana_plugins.ts new file mode 100644 index 00000000000000..ab255f7c73a062 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/lib/compose/__mocks__/kibana_plugins.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { createUiNewPlatformMock } from 'ui/new_platform/__mocks__/helpers'; + +const npStart = createUiNewPlatformMock().npStart; + +export function useKibanaPlugins() { + return npStart.plugins; +} diff --git a/x-pack/legacy/plugins/siem/public/lib/compose/kibana_compose.tsx b/x-pack/legacy/plugins/siem/public/lib/compose/kibana_compose.tsx index 9a956ea885adde..00dfbcd8a4d8f0 100644 --- a/x-pack/legacy/plugins/siem/public/lib/compose/kibana_compose.tsx +++ b/x-pack/legacy/plugins/siem/public/lib/compose/kibana_compose.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ILocationProvider } from 'angular'; import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; import ApolloClient from 'apollo-client'; import { ApolloLink } from 'apollo-link'; @@ -32,19 +31,6 @@ export function compose(): AppFrontendLibs { const apolloClient = new ApolloClient(graphQLOptions); - const appModule = uiModules.get('app/siem'); - - // disable angular's location provider - appModule.config(($locationProvider: ILocationProvider) => { - $locationProvider.html5Mode({ - enabled: false, - requireBase: false, - rewriteLinks: false, - }); - }); - - // const framework = new AppKibanaFrameworkAdapter(appModule, uiRoutes, timezoneProvider); - const libs: AppFrontendLibs = { apolloClient, }; diff --git a/x-pack/legacy/plugins/siem/public/lib/compose/kibana_core.tsx b/x-pack/legacy/plugins/siem/public/lib/compose/kibana_core.tsx new file mode 100644 index 00000000000000..f2fa261bf3eb47 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/lib/compose/kibana_core.tsx @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { createContext, useContext } from 'react'; +import { LegacyCoreStart } from 'src/core/public'; + +interface CoreMountContext { + core: LegacyCoreStart; +} + +// TODO: Replace CoreStart/CoreSetup with AppMountContext +// see: https://github.com/elastic/kibana/pull/41007 + +export const KibanaCoreContext = createContext({} as CoreMountContext['core']); + +export const KibanaCoreContextProvider: React.FC<{ core: CoreMountContext['core'] }> = props => ( + +); + +export function useKibanaCore() { + return useContext(KibanaCoreContext); +} diff --git a/x-pack/legacy/plugins/siem/public/lib/compose/kibana_plugins.tsx b/x-pack/legacy/plugins/siem/public/lib/compose/kibana_plugins.tsx new file mode 100644 index 00000000000000..7d1f1bc01edd32 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/lib/compose/kibana_plugins.tsx @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { createContext, useContext } from 'react'; +import { PluginsStart } from 'ui/new_platform/new_platform'; + +interface PluginsMountContext { + plugins: PluginsStart; +} + +// TODO: Replace CoreStart/CoreSetup with AppMountContext +// see: https://github.com/elastic/kibana/pull/41007 + +export const KibanaPluginsContext = createContext({} as PluginsMountContext['plugins']); + +export const KibanaPluginsContextProvider: React.FC<{ + plugins: PluginsMountContext['plugins']; +}> = props => ( + +); + +export function useKibanaPlugins() { + return useContext(KibanaPluginsContext); +} diff --git a/x-pack/legacy/plugins/siem/public/lib/keury/index.ts b/x-pack/legacy/plugins/siem/public/lib/keury/index.ts index 2ded8923c4afa4..0c78fb9d6f45f6 100644 --- a/x-pack/legacy/plugins/siem/public/lib/keury/index.ts +++ b/x-pack/legacy/plugins/siem/public/lib/keury/index.ts @@ -4,16 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - buildEsQuery, - getEsQueryConfig, - Filter, - fromKueryExpression, - toElasticsearchQuery, -} from '@kbn/es-query'; +import { buildEsQuery, Filter, fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; import { isEmpty, isString, flow } from 'lodash/fp'; import { StaticIndexPattern } from 'ui/index_patterns'; -import { npSetup } from 'ui/new_platform'; import { Query } from 'src/plugins/data/common'; import { KueryFilterQuery } from '../../store'; @@ -74,23 +67,27 @@ export const escapeKuery = flow( escapeWhitespace ); +export interface EsQueryConfig { + allowLeadingWildcards: boolean; + queryStringOptions: unknown; + ignoreFilterIfFieldNotInIndex: boolean; + dateFormatTZ?: string | null; +} + export const convertToBuildEsQuery = ({ + config, indexPattern, queries, filters, }: { + config: EsQueryConfig; indexPattern: StaticIndexPattern; queries: Query[]; filters: Filter[]; }) => { try { return JSON.stringify( - buildEsQuery( - indexPattern, - queries, - filters.filter(f => f.meta.disabled === false), - getEsQueryConfig(npSetup.core.uiSettings) - ) + buildEsQuery(indexPattern, queries, filters.filter(f => f.meta.disabled === false), config) ); } catch (exp) { return ''; diff --git a/x-pack/legacy/plugins/siem/public/lib/settings/use_kibana_ui_setting.ts b/x-pack/legacy/plugins/siem/public/lib/settings/use_kibana_ui_setting.ts index 8f9eed15b19659..086e142f77fb2e 100644 --- a/x-pack/legacy/plugins/siem/public/lib/settings/use_kibana_ui_setting.ts +++ b/x-pack/legacy/plugins/siem/public/lib/settings/use_kibana_ui_setting.ts @@ -5,11 +5,11 @@ */ import { useCallback, useMemo } from 'react'; -import { npSetup, npStart } from 'ui/new_platform'; // @ts-ignore: path dynamic for kibana import { timezoneProvider } from 'ui/vis/lib/timezone'; import { DEFAULT_KBN_VERSION, DEFAULT_TIMEZONE_BROWSER } from '../../../common/constants'; +import { useKibanaCore } from '../compose/kibana_core'; import { useObservable } from './use_observable'; type GenericValue = string | boolean | number; @@ -31,8 +31,9 @@ type GenericValue = string | boolean | number; * because the underlying `UiSettingsClient` doesn't support that. */ export const useKibanaUiSetting = (key: string, defaultValue?: GenericValue) => { - const uiSettingsClient = npSetup.core.uiSettings; - const uiInjectedMetadata = npStart.core.injectedMetadata; + const core = useKibanaCore(); + const uiSettingsClient = core.uiSettings; + const uiInjectedMetadata = core.injectedMetadata; if (key === DEFAULT_KBN_VERSION) { return [uiInjectedMetadata.getKibanaVersion()]; diff --git a/x-pack/legacy/plugins/siem/public/lib/settings/use_kibana_ui_settings.test.tsx b/x-pack/legacy/plugins/siem/public/lib/settings/use_kibana_ui_settings.test.tsx index 825cd8ecafafcd..33f07411c8cb6e 100644 --- a/x-pack/legacy/plugins/siem/public/lib/settings/use_kibana_ui_settings.test.tsx +++ b/x-pack/legacy/plugins/siem/public/lib/settings/use_kibana_ui_settings.test.tsx @@ -7,23 +7,18 @@ import * as React from 'react'; import { DEFAULT_KBN_VERSION, DEFAULT_TIMEZONE_BROWSER } from '../../../common/constants'; import { HookWrapper } from '../../mock/hook_wrapper'; +import { useKibanaCore } from '../compose/kibana_core'; import { useKibanaUiSetting } from './use_kibana_ui_setting'; import { mount } from 'enzyme'; -jest.mock('ui/new_platform', () => ({ - npStart: { - core: { - injectedMetadata: { - getKibanaVersion: () => '8.0.0', - }, - }, +const mockUseKibanaCore = useKibanaCore as jest.Mock; +jest.mock('../compose/kibana_core'); +mockUseKibanaCore.mockImplementation(() => ({ + injectedMetadata: { + getKibanaVersion: () => '8.0.0', }, - npSetup: { - core: { - uiSettings: { - get$: () => 'world', - }, - }, + uiSettings: { + get$: () => 'world', }, })); diff --git a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx index 037c900568299d..da53ac8fceac4e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx @@ -34,6 +34,13 @@ import { SiemPageName } from './types'; import { UseUrlState } from '../../components/url_state'; import { SpyRoute } from '../../utils/route/spy_routes'; +/* + * This is import is important to keep because if we do not have it + * we will loose the map embeddable until they move to the New Platform + * we need to have it + */ +import 'uiExports/embeddableFactories'; + const WrappedByAutoSizer = styled.div` height: 100%; `; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.test.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.test.tsx index 5b4fadbbbc9a53..83af0a616a6604 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.test.tsx @@ -8,17 +8,19 @@ import { shallow, mount } from 'enzyme'; import toJson from 'enzyme-to-json'; import React from 'react'; import { StaticIndexPattern } from 'ui/index_patterns'; -import { npSetup } from 'ui/new_platform'; import { mockIndexPattern } from '../../../mock/index_pattern'; import { TestProviders } from '../../../mock/test_providers'; -import { mockUiSettings, MockNpSetUp } from '../../../mock/ui_settings'; +import { mockUiSettings } from '../../../mock/ui_settings'; import { CommonChildren } from '../navigation/types'; import { HostDetailsBody } from './body'; +import { useKibanaCore } from '../../../lib/compose/kibana_core'; -const mockNpSetup: MockNpSetUp = (npSetup as unknown) as MockNpSetUp; -jest.mock('ui/new_platform'); -mockNpSetup.core.uiSettings = mockUiSettings; +const mockUseKibanaCore = useKibanaCore as jest.Mock; +jest.mock('../../../lib/compose/kibana_core'); +mockUseKibanaCore.mockImplementation(() => ({ + uiSettings: mockUiSettings, +})); jest.mock('../../../containers/source', () => ({ indicesExistOrDataTemporarilyUnavailable: () => true, diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.tsx index d0f8d8037d028b..ae8ebcf41cd562 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.tsx @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { getEsQueryConfig } from '@kbn/es-query'; import React from 'react'; import { connect } from 'react-redux'; @@ -12,6 +13,7 @@ import { setAbsoluteRangeDatePicker as dispatchAbsoluteRangeDatePicker } from '. import { scoreIntervalToDateTime } from '../../../components/ml/score/score_interval_to_datetime'; import { Anomaly } from '../../../components/ml/types'; import { convertToBuildEsQuery } from '../../../lib/keury'; +import { useKibanaCore } from '../../../lib/compose/kibana_core'; import { HostDetailsBodyComponentProps } from './types'; import { type, makeMapStateToProps } from './utils'; @@ -29,10 +31,12 @@ const HostDetailsBodyComponent = React.memo( setQuery, to, }) => { + const core = useKibanaCore(); return ( {({ indicesExist, indexPattern }) => { const filterQuery = convertToBuildEsQuery({ + config: getEsQueryConfig(core.uiSettings), indexPattern, queries: [query], filters: [ diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx index 349ede91581131..d1d29c3d2ea821 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx @@ -5,6 +5,7 @@ */ import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; +import { getEsQueryConfig } from '@kbn/es-query'; import React, { useContext, useEffect } from 'react'; import { compose } from 'redux'; import { connect } from 'react-redux'; @@ -39,6 +40,7 @@ export { HostDetailsBody } from './body'; import { navTabsHostDetails } from './nav_tabs'; import { HostDetailsComponentProps } from './types'; import { makeMapStateToProps } from './utils'; +import { useKibanaCore } from '../../../lib/compose/kibana_core'; const HostOverviewManage = manageQuery(HostOverview); const KpiHostDetailsManage = manageQuery(KpiHostsComponent); @@ -59,11 +61,13 @@ const HostDetailsComponent = React.memo( setHostDetailsTablesActivePageToZero(null); }, [detailName]); const capabilities = useContext(MlCapabilitiesContext); + const core = useKibanaCore(); return ( <> {({ indicesExist, indexPattern }) => { const filterQuery = convertToBuildEsQuery({ + config: getEsQueryConfig(core.uiSettings), indexPattern, queries: [query], filters: [ diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx index a04638a50941fe..5b6444148045dd 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx @@ -10,7 +10,6 @@ import * as React from 'react'; import { Router } from 'react-router-dom'; import { MockedProvider } from 'react-apollo/test-utils'; import { ActionCreator } from 'typescript-fsa'; -import { npSetup } from 'ui/new_platform'; import '../../mock/match_media'; @@ -18,22 +17,25 @@ import { SiemNavigation } from '../../components/navigation'; import { mocksSource } from '../../containers/source/mock'; import { wait } from '../../lib/helpers'; import { TestProviders } from '../../mock'; -import { MockNpSetUp, mockUiSettings } from '../../mock/ui_settings'; +import { mockUiSettings } from '../../mock/ui_settings'; import { InputsModelId } from '../../store/inputs/constants'; import { Hosts, HostsComponentProps } from './hosts'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; jest.mock('../../lib/settings/use_kibana_ui_setting'); +const mockUseKibanaCore = useKibanaCore as jest.Mock; +jest.mock('../../lib/compose/kibana_core'); +mockUseKibanaCore.mockImplementation(() => ({ + uiSettings: mockUiSettings, +})); + jest.mock('ui/documentation_links', () => ({ documentationLinks: { kibana: 'http://www.example.com', }, })); -const mockNpSetup: MockNpSetUp = (npSetup as unknown) as MockNpSetUp; -jest.mock('ui/new_platform'); -mockNpSetup.core.uiSettings = mockUiSettings; - // Test will fail because we will to need to mock some core services to make the test work // For now let's forget about SiemSearchBar jest.mock('../../components/search_bar', () => ({ diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx index 96700b32826b2b..fc969974609ea4 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx @@ -5,7 +5,7 @@ */ import { EuiSpacer } from '@elastic/eui'; -import { Filter } from '@kbn/es-query'; +import { Filter, getEsQueryConfig } from '@kbn/es-query'; import * as React from 'react'; import { compose } from 'redux'; import { connect } from 'react-redux'; @@ -35,6 +35,7 @@ import { SpyRoute } from '../../utils/route/spy_routes'; import { HostsEmptyPage } from './hosts_empty_page'; import { navTabsHosts } from './nav_tabs'; import * as i18n from './translations'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; const KpiHostsComponentManage = manageQuery(KpiHostsComponent); @@ -60,11 +61,13 @@ export type HostsComponentProps = HostsComponentReduxProps & const HostsComponent = React.memo( ({ isInitializing, filters, from, query, setAbsoluteRangeDatePicker, setQuery, to }) => { const capabilities = React.useContext(MlCapabilitiesContext); + const core = useKibanaCore(); return ( <> {({ indicesExist, indexPattern }) => { const filterQuery = convertToBuildEsQuery({ + config: getEsQueryConfig(core.uiSettings), indexPattern, queries: [query], filters, diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx index 3aabedd0c72e09..242c66bb3a9ee0 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { getEsQueryConfig } from '@kbn/es-query'; import React, { memo } from 'react'; import { connect } from 'react-redux'; @@ -11,6 +12,7 @@ import { scoreIntervalToDateTime } from '../../components/ml/score/score_interva import { Anomaly } from '../../components/ml/types'; import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; import { convertToBuildEsQuery } from '../../lib/keury'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; import { hostsModel, inputsSelectors, State } from '../../store'; import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from '../../store/inputs/actions'; @@ -34,10 +36,12 @@ const HostsBodyComponent = memo( timezone, to, }) => { + const core = useKibanaCore(); return ( {({ indicesExist, indexPattern }) => { const filterQuery = convertToBuildEsQuery({ + config: getEsQueryConfig(core.uiSettings), indexPattern, queries: [query], filters, diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx index a438fcbaa5c464..ed93061ba25266 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx @@ -11,14 +11,14 @@ import * as React from 'react'; import { Router } from 'react-router-dom'; import { MockedProvider } from 'react-apollo/test-utils'; import { ActionCreator } from 'typescript-fsa'; -import { npSetup } from 'ui/new_platform'; import '../../../mock/match_media'; import { mocksSource } from '../../../containers/source/mock'; import { FlowTarget } from '../../../graphql/types'; +import { useKibanaCore } from '../../../lib/compose/kibana_core'; import { apolloClientObservable, mockGlobalState, TestProviders } from '../../../mock'; -import { MockNpSetUp, mockUiSettings } from '../../../mock/ui_settings'; +import { mockUiSettings } from '../../../mock/ui_settings'; import { createStore, State } from '../../../store'; import { InputsModelId } from '../../../store/inputs/constants'; @@ -31,9 +31,11 @@ const pop: Action = 'POP'; type GlobalWithFetch = NodeJS.Global & { fetch: jest.Mock }; -const mockNpSetup: MockNpSetUp = (npSetup as unknown) as MockNpSetUp; -jest.mock('ui/new_platform'); -mockNpSetup.core.uiSettings = mockUiSettings; +const mockUseKibanaCore = useKibanaCore as jest.Mock; +jest.mock('../../../lib/compose/kibana_core'); +mockUseKibanaCore.mockImplementation(() => ({ + uiSettings: mockUiSettings, +})); // Test will fail because we will to need to mock some core services to make the test work // For now let's forget about SiemSearchBar diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx index 9e7ef2975e2b51..824539cad8d523 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx @@ -5,6 +5,7 @@ */ import { EuiHorizontalRule, EuiSpacer, EuiFlexItem } from '@elastic/eui'; +import { getEsQueryConfig } from '@kbn/es-query'; import React, { useCallback, useEffect } from 'react'; import { connect } from 'react-redux'; import { StickyContainer } from 'react-sticky'; @@ -38,6 +39,7 @@ import { TlsQueryTable } from './tls_query_table'; import { UsersQueryTable } from './users_query_table'; import { NetworkTopNFlowQueryTable } from './network_top_n_flow_query_table'; import { NetworkTopCountriesQueryTable } from './network_top_countries_query_table'; +import { useKibanaCore } from '../../../lib/compose/kibana_core'; const IpOverviewManage = manageQuery(IpOverview); @@ -65,6 +67,7 @@ export const IPDetailsComponent = React.memo( }, [scoreIntervalToDateTime, setAbsoluteRangeDatePicker] ); + const core = useKibanaCore(); useEffect(() => { setIpDetailsTablesActivePageToZero(null); @@ -76,6 +79,7 @@ export const IPDetailsComponent = React.memo( {({ indicesExist, indexPattern }) => { const ip = decodeIpv6(detailName); const filterQuery = convertToBuildEsQuery({ + config: getEsQueryConfig(core.uiSettings), indexPattern, queries: [query], filters, diff --git a/x-pack/legacy/plugins/siem/public/pages/network/network.test.tsx b/x-pack/legacy/plugins/siem/public/pages/network/network.test.tsx index 9ab1bacf562595..a10118dc6ca6fe 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/network.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/network.test.tsx @@ -9,16 +9,15 @@ import { cloneDeep } from 'lodash/fp'; import * as React from 'react'; import { Router } from 'react-router-dom'; import { MockedProvider } from 'react-apollo/test-utils'; -import { npSetup } from 'ui/new_platform'; import '../../mock/match_media'; import { mocksSource } from '../../containers/source/mock'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; import { TestProviders } from '../../mock'; -import { mockUiSettings, MockNpSetUp } from '../../mock/ui_settings'; +import { mockUiSettings } from '../../mock/ui_settings'; import { Network } from './network'; -jest.mock('ui/new_platform'); jest.mock('../../lib/settings/use_kibana_ui_setting'); jest.mock('ui/documentation_links', () => ({ @@ -27,9 +26,11 @@ jest.mock('ui/documentation_links', () => ({ }, })); -const mockNpSetup: MockNpSetUp = (npSetup as unknown) as MockNpSetUp; -jest.mock('ui/new_platform'); -mockNpSetup.core.uiSettings = mockUiSettings; +const mockUseKibanaCore = useKibanaCore as jest.Mock; +jest.mock('../../lib/compose/kibana_core'); +mockUseKibanaCore.mockImplementation(() => ({ + uiSettings: mockUiSettings, +})); // Test will fail because we will to need to mock some core services to make the test work // For now let's forget about SiemSearchBar diff --git a/x-pack/legacy/plugins/siem/public/pages/network/network.tsx b/x-pack/legacy/plugins/siem/public/pages/network/network.tsx index f5e1892b6ec6e0..b10c09d65426be 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/network.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/network.tsx @@ -5,6 +5,7 @@ */ import { EuiSpacer } from '@elastic/eui'; +import { getEsQueryConfig } from '@kbn/es-query'; import React from 'react'; import { connect } from 'react-redux'; import { StickyContainer } from 'react-sticky'; @@ -18,18 +19,17 @@ import { KpiNetworkComponent } from '../../components/page/network'; import { SiemNavigation } from '../../components/navigation'; import { SiemSearchBar } from '../../components/search_bar'; import { KpiNetworkQuery } from '../../containers/kpi_network'; - import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; import { LastEventIndexKey } from '../../graphql/types'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; +import { convertToBuildEsQuery } from '../../lib/keury'; import { networkModel, State, inputsSelectors } from '../../store'; import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from '../../store/inputs/actions'; import { SpyRoute } from '../../utils/route/spy_routes'; -import { NetworkEmptyPage } from './network_empty_page'; -import * as i18n from './translations'; -import { convertToBuildEsQuery } from '../../lib/keury'; import { navTabsNetwork, NetworkRoutes, NetworkRoutesLoading } from './navigation'; - +import { NetworkEmptyPage } from './network_empty_page'; +import * as i18n from './translations'; import { NetworkComponentProps } from './types'; const KpiNetworkComponentManage = manageQuery(KpiNetworkComponent); @@ -47,99 +47,103 @@ const NetworkComponent = React.memo( isInitializing, hasMlUserPermissions, capabilitiesFetched, - }) => ( - <> - - {({ indicesExist, indexPattern }) => { - const filterQuery = convertToBuildEsQuery({ - indexPattern, - queries: [query], - filters, - }); - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - - - } - title={i18n.PAGE_TITLE} - /> - - - - - {({ kpiNetwork, loading, id, inspect, refetch }) => ( - { - setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); - }} - /> + }) => { + const core = useKibanaCore(); + return ( + <> + + {({ indicesExist, indexPattern }) => { + const filterQuery = convertToBuildEsQuery({ + config: getEsQueryConfig(core.uiSettings), + indexPattern, + queries: [query], + filters, + }); + return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( + + + + + + } + title={i18n.PAGE_TITLE} + /> + + + + + {({ kpiNetwork, loading, id, inspect, refetch }) => ( + { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }} + /> + )} + + + {capabilitiesFetched && !isInitializing ? ( + <> + + + + + + + + + ) : ( + )} - - - {capabilitiesFetched && !isInitializing ? ( - <> - - - - - - - - - ) : ( - - )} - - - - ) : ( - <> - - - - ); - }} - - - - ) + + + + ) : ( + <> + + + + ); + }} + + + + ); + } ); NetworkComponent.displayName = 'NetworkComponent';