diff --git a/x-pack/legacy/plugins/maps/index.js b/x-pack/legacy/plugins/maps/index.js index 5aa8ff302bc1..d1354ef013a9 100644 --- a/x-pack/legacy/plugins/maps/index.js +++ b/x-pack/legacy/plugins/maps/index.js @@ -7,7 +7,6 @@ import { i18n } from '@kbn/i18n'; import { resolve } from 'path'; import { getAppTitle } from '../../../plugins/maps/common/i18n_getters'; -import { MapPlugin } from './server/plugin'; import { APP_ID, APP_ICON } from '../../../plugins/maps/common/constants'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server'; @@ -17,6 +16,13 @@ export function maps(kibana) { id: APP_ID, configPrefix: 'xpack.maps', publicDir: resolve(__dirname, 'public'), + config(Joi) { + return Joi.object({ + enabled: Joi.boolean().default(true), + }) + .unknown() + .default(); + }, uiExports: { app: { title: getAppTitle(), @@ -29,68 +35,7 @@ export function maps(kibana) { category: DEFAULT_APP_CATEGORIES.kibana, order: 4000, }, - injectDefaultVars(server) { - const serverConfig = server.config(); - - return { - showMapVisualizationTypes: serverConfig.get('xpack.maps.showMapVisualizationTypes'), - showMapsInspectorAdapter: serverConfig.get('xpack.maps.showMapsInspectorAdapter'), - enableVectorTiles: serverConfig.get('xpack.maps.enableVectorTiles'), - preserveDrawingBuffer: serverConfig.get('xpack.maps.preserveDrawingBuffer'), - kbnPkgVersion: serverConfig.get('pkg.version'), - }; - }, styleSheetPaths: `${__dirname}/public/index.scss`, }, - config(Joi) { - return Joi.object({ - enabled: Joi.boolean().default(true), - showMapVisualizationTypes: Joi.boolean().default(false), - showMapsInspectorAdapter: Joi.boolean().default(false), // flag used in functional testing - preserveDrawingBuffer: Joi.boolean().default(false), // flag used in functional testing - enableVectorTiles: Joi.boolean().default(false), // flag used to enable/disable vector-tiles - }).default(); - }, - - init(server) { - const mapsEnabled = server.config().get('xpack.maps.enabled'); - if (!mapsEnabled) { - server.log(['info', 'maps'], 'Maps app disabled by configuration'); - return; - } - - // Init saved objects client deps - const callCluster = server.plugins.elasticsearch.getCluster('admin').callWithInternalUser; - const { SavedObjectsClient, getSavedObjectsRepository } = server.savedObjects; - const internalRepository = getSavedObjectsRepository(callCluster); - - const coreSetup = server.newPlatform.setup.core; - const newPlatformPlugins = server.newPlatform.setup.plugins; - const pluginsSetup = { - featuresPlugin: newPlatformPlugins.features, - licensing: newPlatformPlugins.licensing, - home: newPlatformPlugins.home, - usageCollection: newPlatformPlugins.usageCollection, - mapsLegacy: newPlatformPlugins.mapsLegacy, - }; - - // legacy dependencies - const __LEGACY = { - config: server.config, - route: server.route.bind(server), - plugins: { - elasticsearch: server.plugins.elasticsearch, - }, - savedObjects: { - savedObjectsClient: new SavedObjectsClient(internalRepository), - getSavedObjectsRepository: server.savedObjects.getSavedObjectsRepository, - }, - injectUiAppVars: server.injectUiAppVars, - getInjectedUiAppVars: server.getInjectedUiAppVars, - }; - - const mapPlugin = new MapPlugin(); - mapPlugin.setup(coreSetup, pluginsSetup, __LEGACY); - }, }); } diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index bb1a6b74d43a..adae80e7fc50 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -97,7 +97,9 @@ const REACT_ANCHOR_DOM_ELEMENT_ID = 'react-maps-root'; const app = uiModules.get(MAP_APP_PATH, []); // Init required services. Necessary while in legacy -bindNpSetupCoreAndPlugins(npSetup.core, npSetup.plugins); +const config = _.get(npSetup, 'plugins.maps.config', {}); +const kibanaVersion = npSetup.core.injectedMetadata.getKibanaVersion(); +bindNpSetupCoreAndPlugins(npSetup.core, npSetup.plugins, config, kibanaVersion); bindNpStartCoreAndPlugins(npStart.core, npStart.plugins); loadKbnTopNavDirectives(getNavigation().ui); diff --git a/x-pack/legacy/plugins/maps/public/plugin.ts b/x-pack/legacy/plugins/maps/public/plugin.ts index 0123e32b6d3b..08bc184ef549 100644 --- a/x-pack/legacy/plugins/maps/public/plugin.ts +++ b/x-pack/legacy/plugins/maps/public/plugin.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import _ from 'lodash'; import { Plugin, CoreStart, CoreSetup } from 'src/core/public'; // @ts-ignore import { Start as InspectorStartContract } from 'src/plugins/inspector/public'; @@ -55,7 +56,12 @@ export class MapsPlugin implements Plugin { return reactDirective(wrapInI18nContext(MapListing)); }); - bindNpSetupCoreAndPlugins(core, np); + // @ts-ignore + const config = _.get(np, 'maps.config', {}); + // @ts-ignore + const kibanaVersion = core.injectedMetadata.getKibanaVersion(); + // @ts-ignore + bindNpSetupCoreAndPlugins(core, np, config, kibanaVersion); } public start(core: CoreStart, plugins: MapsPluginStartDependencies) { diff --git a/x-pack/legacy/plugins/maps/server/plugin.js b/x-pack/legacy/plugins/maps/server/plugin.js deleted file mode 100644 index 6a542dff2eb1..000000000000 --- a/x-pack/legacy/plugins/maps/server/plugin.js +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 { i18n } from '@kbn/i18n'; -import { - APP_ID, - APP_ICON, - createMapPath, - MAP_SAVED_OBJECT_TYPE, -} from '../../../../plugins/maps/common/constants'; -import { getEcommerceSavedObjects } from './sample_data/ecommerce_saved_objects'; -import { getFlightsSavedObjects } from './sample_data/flights_saved_objects.js'; -import { getWebLogsSavedObjects } from './sample_data/web_logs_saved_objects.js'; -import { registerMapsUsageCollector } from './maps_telemetry/collectors/register'; -import { initRoutes } from './routes'; -import { emsBoundariesSpecProvider } from './tutorials/ems'; - -export class MapPlugin { - setup(core, plugins, __LEGACY) { - const { home, licensing, usageCollection, mapsLegacy } = plugins; - let routesInitialized = false; - const mapConfig = mapsLegacy.config; - - licensing.license$.subscribe(license => { - const { state } = license.check('maps', 'basic'); - if (state === 'valid' && !routesInitialized) { - routesInitialized = true; - initRoutes(__LEGACY, license.uid, mapConfig); - } - }); - - // Init telemetry - const { savedObjectsClient } = __LEGACY.savedObjects; - registerMapsUsageCollector(usageCollection, savedObjectsClient, __LEGACY.config); - - const sampleDataLinkLabel = i18n.translate('xpack.maps.sampleDataLinkLabel', { - defaultMessage: 'Map', - }); - if (home) { - home.sampleData.addSavedObjectsToSampleDataset('ecommerce', getEcommerceSavedObjects()); - - home.sampleData.addAppLinksToSampleDataset('ecommerce', [ - { - path: createMapPath('2c9c1f60-1909-11e9-919b-ffe5949a18d2'), - label: sampleDataLinkLabel, - icon: APP_ICON, - }, - ]); - - home.sampleData.replacePanelInSampleDatasetDashboard({ - sampleDataId: 'ecommerce', - dashboardId: '722b74f0-b882-11e8-a6d9-e546fe2bba5f', - oldEmbeddableId: '9c6f83f0-bb4d-11e8-9c84-77068524bcab', - embeddableId: '2c9c1f60-1909-11e9-919b-ffe5949a18d2', - embeddableType: 'map', - embeddableConfig: { - isLayerTOCOpen: false, - }, - }); - - home.sampleData.addSavedObjectsToSampleDataset('flights', getFlightsSavedObjects()); - - home.sampleData.addAppLinksToSampleDataset('flights', [ - { - path: createMapPath('5dd88580-1906-11e9-919b-ffe5949a18d2'), - label: sampleDataLinkLabel, - icon: APP_ICON, - }, - ]); - - home.sampleData.replacePanelInSampleDatasetDashboard({ - sampleDataId: 'flights', - dashboardId: '7adfa750-4c81-11e8-b3d7-01146121b73d', - oldEmbeddableId: '334084f0-52fd-11e8-a160-89cc2ad9e8e2', - embeddableId: '5dd88580-1906-11e9-919b-ffe5949a18d2', - embeddableType: MAP_SAVED_OBJECT_TYPE, - embeddableConfig: { - isLayerTOCOpen: true, - }, - }); - - home.sampleData.addSavedObjectsToSampleDataset('logs', getWebLogsSavedObjects()); - home.sampleData.addAppLinksToSampleDataset('logs', [ - { - path: createMapPath('de71f4f0-1902-11e9-919b-ffe5949a18d2'), - label: sampleDataLinkLabel, - icon: APP_ICON, - }, - ]); - home.sampleData.replacePanelInSampleDatasetDashboard({ - sampleDataId: 'logs', - dashboardId: 'edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b', - oldEmbeddableId: '06cf9c40-9ee8-11e7-8711-e7a007dcef99', - embeddableId: 'de71f4f0-1902-11e9-919b-ffe5949a18d2', - embeddableType: MAP_SAVED_OBJECT_TYPE, - embeddableConfig: { - isLayerTOCOpen: false, - }, - }); - - home.tutorials.registerTutorial( - emsBoundariesSpecProvider({ - prependBasePath: core.http.basePath.prepend, - emsLandingPageUrl: mapConfig.emsLandingPageUrl, - }) - ); - } - - __LEGACY.injectUiAppVars(APP_ID, async () => { - return await __LEGACY.getInjectedUiAppVars('kibana'); - }); - } -} diff --git a/x-pack/plugins/maps/config.ts b/x-pack/plugins/maps/config.ts new file mode 100644 index 000000000000..8bb0b7551b0e --- /dev/null +++ b/x-pack/plugins/maps/config.ts @@ -0,0 +1,28 @@ +/* + * 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 { schema, TypeOf } from '@kbn/config-schema'; + +export interface MapsConfigType { + enabled: boolean; + showMapVisualizationTypes: boolean; + showMapsInspectorAdapter: boolean; + preserveDrawingBuffer: boolean; + enableVectorTiles: boolean; +} + +export const configSchema = schema.object({ + enabled: schema.boolean({ defaultValue: true }), + showMapVisualizationTypes: schema.boolean({ defaultValue: false }), + // flag used in functional testing + showMapsInspectorAdapter: schema.boolean({ defaultValue: false }), + // flag used in functional testing + preserveDrawingBuffer: schema.boolean({ defaultValue: false }), + // flag used to enable/disable vector-tiles + enableVectorTiles: schema.boolean({ defaultValue: false }), +}); + +export type MapsXPackConfig = TypeOf; diff --git a/x-pack/plugins/maps/kibana.json b/x-pack/plugins/maps/kibana.json index efbac56a817b..67520321de76 100644 --- a/x-pack/plugins/maps/kibana.json +++ b/x-pack/plugins/maps/kibana.json @@ -14,7 +14,8 @@ "navigation", "visualizations", "embeddable", - "mapsLegacy" + "mapsLegacy", + "usageCollection" ], "ui": true, "server": true diff --git a/x-pack/plugins/maps/public/angular/get_initial_layers.test.js b/x-pack/plugins/maps/public/angular/get_initial_layers.test.js index 867025cd7021..8ddcd7cb5bbb 100644 --- a/x-pack/plugins/maps/public/angular/get_initial_layers.test.js +++ b/x-pack/plugins/maps/public/angular/get_initial_layers.test.js @@ -15,7 +15,7 @@ const layerListNotProvided = undefined; describe('Saved object has layer list', () => { beforeEach(() => { - require('../kibana_services').getInjectedVarFunc = () => jest.fn(); + require('../kibana_services').getIsEmsEnabled = () => true; }); it('Should get initial layers from saved object', () => { @@ -66,18 +66,11 @@ describe('EMS is enabled', () => { return null; }; require('../kibana_services').getIsEmsEnabled = () => true; - require('../kibana_services').getInjectedVarFunc = () => key => { - switch (key) { - case 'emsTileLayerId': - return { - bright: 'road_map', - desaturated: 'road_map_desaturated', - dark: 'dark_map', - }; - default: - throw new Error(`Unexpected call to getInjectedVarFunc with key ${key}`); - } - }; + require('../kibana_services').getEmsTileLayerId = () => ({ + bright: 'road_map', + desaturated: 'road_map_desaturated', + dark: 'dark_map', + }); }); it('Should get initial layer with EMS tile source', () => { diff --git a/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts b/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts index e81bce43133e..8b6f0a0f3f22 100644 --- a/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts +++ b/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts @@ -25,7 +25,7 @@ import { tmsLayerWizardConfig } from '../sources/xyz_tms_source'; import { wmsLayerWizardConfig } from '../sources/wms_source'; import { mvtVectorSourceWizardConfig } from '../sources/mvt_single_layer_vector_source'; import { ObservabilityLayerWizardConfig } from './solution_layers/observability'; -import { getInjectedVarFunc } from '../../kibana_services'; +import { getEnableVectorTiles } from '../../kibana_services'; let registered = false; export function registerLayerWizards() { @@ -56,8 +56,7 @@ export function registerLayerWizards() { // @ts-ignore registerLayerWizard(wmsLayerWizardConfig); - const getInjectedVar = getInjectedVarFunc(); - if (getInjectedVar && getInjectedVar('enableVectorTiles', false)) { + if (getEnableVectorTiles()) { // eslint-disable-next-line no-console console.warn('Vector tiles are an experimental feature and should not be used in production.'); registerLayerWizard(mvtVectorSourceWizardConfig); diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/view.js b/x-pack/plugins/maps/public/connected_components/map/mb/view.js index 7afb326f42e0..800daec76989 100644 --- a/x-pack/plugins/maps/public/connected_components/map/mb/view.js +++ b/x-pack/plugins/maps/public/connected_components/map/mb/view.js @@ -25,8 +25,7 @@ import { DrawControl } from './draw_control'; import { TooltipControl } from './tooltip_control'; import { clampToLatBounds, clampToLonBounds } from '../../../elasticsearch_geo_utils'; import { getInitialView } from './get_initial_view'; - -import { getInjectedVarFunc } from '../../../kibana_services'; +import { getPreserveDrawingBuffer } from '../../../kibana_services'; mapboxgl.workerUrl = mbWorkerUrl; mapboxgl.setRTLTextPlugin(mbRtlPlugin); @@ -130,7 +129,7 @@ export class MBMapContainer extends React.Component { container: this.refs.mapContainer, style: mbStyle, scrollZoom: this.props.scrollZoom, - preserveDrawingBuffer: getInjectedVarFunc()('preserveDrawingBuffer', false), + preserveDrawingBuffer: getPreserveDrawingBuffer(), interactive: !this.props.disableInteractive, maxZoom: this.props.settings.maxZoom, minZoom: this.props.settings.minZoom, diff --git a/x-pack/plugins/maps/public/index.ts b/x-pack/plugins/maps/public/index.ts index 79953e35d51e..9428946bb62e 100644 --- a/x-pack/plugins/maps/public/index.ts +++ b/x-pack/plugins/maps/public/index.ts @@ -5,10 +5,15 @@ */ import { PluginInitializer } from 'kibana/public'; +import { PluginInitializerContext } from 'kibana/public'; import { MapsPlugin, MapsPluginSetup, MapsPluginStart } from './plugin'; +import { MapsXPackConfig } from '../config'; -export const plugin: PluginInitializer = () => { - return new MapsPlugin(); +export const plugin: PluginInitializer = ( + initContext: PluginInitializerContext +) => { + // @ts-ignore + return new MapsPlugin(initContext); }; export { MAP_SAVED_OBJECT_TYPE } from '../common/constants'; diff --git a/x-pack/plugins/maps/public/kibana_services.d.ts b/x-pack/plugins/maps/public/kibana_services.d.ts index 454ba6ededcb..45a4ace8e27a 100644 --- a/x-pack/plugins/maps/public/kibana_services.d.ts +++ b/x-pack/plugins/maps/public/kibana_services.d.ts @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import { IIndexPattern, DataPublicPluginStart } from 'src/plugins/data/public'; -import _ from 'lodash'; +import { MapsConfigType } from '../config'; +import { MapsLegacyConfigType } from '../../../../src/plugins/maps_legacy/public'; export function getLicenseId(): any; export function getInspector(): any; @@ -12,7 +13,6 @@ export function getFileUploadComponent(): any; export function getIndexPatternSelectComponent(): any; export function getHttp(): any; export function getTimeFilter(): any; -export function getInjectedVarFunc(): any; export function getToasts(): any; export function getIndexPatternService(): { get: (id: string) => IIndexPattern | undefined; @@ -31,7 +31,8 @@ export function getCore(): any; export function getNavigation(): any; export function getCoreI18n(): any; export function getSearchService(): DataPublicPluginStart['search']; -export function getMapConfig(): any; +export function getKibanaCommonConfig(): MapsLegacyConfigType; +export function getMapAppConfig(): MapsConfigType; export function getIsEmsEnabled(): any; export function getEmsFontLibraryUrl(): any; export function getEmsTileLayerId(): any; @@ -40,6 +41,13 @@ export function getEmsTileApiUrl(): any; export function getEmsLandingPageUrl(): any; export function getRegionmapLayers(): any; export function getTilemap(): any; +export function getKibanaVersion(): string; +export function getEnabled(): boolean; +export function getShowMapVisualizationTypes(): boolean; +export function getShowMapsInspectorAdapter(): boolean; +export function getPreserveDrawingBuffer(): boolean; +export function getEnableVectorTiles(): boolean; +export function getProxyElasticMapsServiceInMaps(): boolean; export function setLicenseId(args: unknown): void; export function setInspector(args: unknown): void; @@ -47,7 +55,6 @@ export function setFileUpload(args: unknown): void; export function setIndexPatternSelect(args: unknown): void; export function setHttp(args: unknown): void; export function setTimeFilter(args: unknown): void; -export function setInjectedVarFunc(args: unknown): void; export function setToasts(args: unknown): void; export function setIndexPatternService(args: unknown): void; export function setAutocompleteService(args: unknown): void; @@ -64,4 +71,6 @@ export function setCore(args: unknown): void; export function setNavigation(args: unknown): void; export function setCoreI18n(args: unknown): void; export function setSearchService(args: DataPublicPluginStart['search']): void; -export function setMapConfig(args: unknown): void; +export function setKibanaCommonConfig(config: MapsLegacyConfigType): void; +export function setMapAppConfig(config: MapsConfigType): void; +export function setKibanaVersion(version: string): void; diff --git a/x-pack/plugins/maps/public/kibana_services.js b/x-pack/plugins/maps/public/kibana_services.js index 2f07c1c5d086..4e874d45bf12 100644 --- a/x-pack/plugins/maps/public/kibana_services.js +++ b/x-pack/plugins/maps/public/kibana_services.js @@ -36,12 +36,6 @@ export const getFileUploadComponent = () => { return fileUploadPlugin.JsonUploadAndParse; }; -let getInjectedVar; -export const setInjectedVarFunc = getInjectedVarFunc => { - getInjectedVar = getInjectedVarFunc; -}; -export const getInjectedVarFunc = () => getInjectedVar; - let uiSettings; export const setUiSettings = coreUiSettings => (uiSettings = coreUiSettings); export const getUiSettings = () => uiSettings; @@ -141,15 +135,33 @@ let dataSearchService; export const setSearchService = searchService => (dataSearchService = searchService); export const getSearchService = () => dataSearchService; -let mapConfig; -export const setMapConfig = config => (mapConfig = config); -export const getMapConfig = () => mapConfig; - -export const getIsEmsEnabled = () => getMapConfig().includeElasticMapsService; -export const getEmsFontLibraryUrl = () => getMapConfig().emsFontLibraryUrl; -export const getEmsTileLayerId = () => getMapConfig().emsTileLayerId; -export const getEmsFileApiUrl = () => getMapConfig().emsFileApiUrl; -export const getEmsTileApiUrl = () => getMapConfig().emsTileApiUrl; -export const getEmsLandingPageUrl = () => getMapConfig().emsLandingPageUrl; -export const getRegionmapLayers = () => _.get(getMapConfig(), 'regionmap.layers', []); -export const getTilemap = () => _.get(getMapConfig(), 'tilemap', []); +let kibanaVersion; +export const setKibanaVersion = version => (kibanaVersion = version); +export const getKibanaVersion = () => kibanaVersion; + +// xpack.maps.* kibana.yml settings from this plugin +let mapAppConfig; +export const setMapAppConfig = config => (mapAppConfig = config); +export const getMapAppConfig = () => mapAppConfig; + +export const getEnabled = () => getMapAppConfig().enabled; +export const getShowMapVisualizationTypes = () => getMapAppConfig().showMapVisualizationTypes; +export const getShowMapsInspectorAdapter = () => getMapAppConfig().showMapsInspectorAdapter; +export const getPreserveDrawingBuffer = () => getMapAppConfig().preserveDrawingBuffer; +export const getEnableVectorTiles = () => getMapAppConfig().enableVectorTiles; + +// map.* kibana.yml settings from maps_legacy plugin that are shared between OSS map visualizations and maps app +let kibanaCommonConfig; +export const setKibanaCommonConfig = config => (kibanaCommonConfig = config); +export const getKibanaCommonConfig = () => kibanaCommonConfig; + +export const getIsEmsEnabled = () => getKibanaCommonConfig().includeElasticMapsService; +export const getEmsFontLibraryUrl = () => getKibanaCommonConfig().emsFontLibraryUrl; +export const getEmsTileLayerId = () => getKibanaCommonConfig().emsTileLayerId; +export const getEmsFileApiUrl = () => getKibanaCommonConfig().emsFileApiUrl; +export const getEmsTileApiUrl = () => getKibanaCommonConfig().emsTileApiUrl; +export const getEmsLandingPageUrl = () => getKibanaCommonConfig().emsLandingPageUrl; +export const getProxyElasticMapsServiceInMaps = () => + getKibanaCommonConfig().proxyElasticMapsServiceInMaps; +export const getRegionmapLayers = () => _.get(getKibanaCommonConfig(), 'regionmap.layers', []); +export const getTilemap = () => _.get(getKibanaCommonConfig(), 'tilemap', []); diff --git a/x-pack/plugins/maps/public/maps_vis_type_alias.js b/x-pack/plugins/maps/public/maps_vis_type_alias.js index 8481a03e1223..14f31d7660a5 100644 --- a/x-pack/plugins/maps/public/maps_vis_type_alias.js +++ b/x-pack/plugins/maps/public/maps_vis_type_alias.js @@ -6,10 +6,10 @@ import { i18n } from '@kbn/i18n'; import { APP_ID, APP_ICON, MAP_SAVED_OBJECT_TYPE } from '../common/constants'; -import { getInjectedVarFunc, getVisualizations } from './kibana_services'; +import { getShowMapVisualizationTypes, getVisualizations } from './kibana_services'; export function getMapsVisTypeAlias() { - const showMapVisualizationTypes = getInjectedVarFunc()('showMapVisualizationTypes', false); + const showMapVisualizationTypes = getShowMapVisualizationTypes(); if (!showMapVisualizationTypes) { getVisualizations().hideTypes(['region_map', 'tile_map']); } diff --git a/x-pack/plugins/maps/public/meta.js b/x-pack/plugins/maps/public/meta.js index 77183e334cb1..3ffd0578796c 100644 --- a/x-pack/plugins/maps/public/meta.js +++ b/x-pack/plugins/maps/public/meta.js @@ -14,7 +14,6 @@ import { import { i18n } from '@kbn/i18n'; import { EMSClient } from '@elastic/ems-client'; import { - getInjectedVarFunc, getLicenseId, getIsEmsEnabled, getRegionmapLayers, @@ -23,6 +22,8 @@ import { getEmsTileApiUrl, getEmsLandingPageUrl, getEmsFontLibraryUrl, + getProxyElasticMapsServiceInMaps, + getKibanaVersion, } from './kibana_services'; import fetch from 'node-fetch'; @@ -52,10 +53,7 @@ export function getEMSClient() { if (!emsClient) { const isEmsEnabled = getIsEmsEnabled(); if (isEmsEnabled) { - const proxyElasticMapsServiceInMaps = getInjectedVarFunc()( - 'proxyElasticMapsServiceInMaps', - false - ); + const proxyElasticMapsServiceInMaps = getProxyElasticMapsServiceInMaps(); const proxyPath = ''; const tileApiUrl = proxyElasticMapsServiceInMaps ? relativeToAbsolute(`${GIS_API_RELATIVE}/${EMS_TILES_CATALOGUE_PATH}`) @@ -66,7 +64,7 @@ export function getEMSClient() { emsClient = new EMSClient({ language: i18n.getLocale(), - appVersion: getInjectedVarFunc()('kbnPkgVersion'), + appVersion: getKibanaVersion(), appName: EMS_APP_NAME, tileApiUrl, fileApiUrl, @@ -99,7 +97,7 @@ export function getGlyphUrl() { if (!getIsEmsEnabled()) { return ''; } - return getInjectedVarFunc()('proxyElasticMapsServiceInMaps', false) + return getProxyElasticMapsServiceInMaps() ? relativeToAbsolute(`../${GIS_API_PATH}/${EMS_TILES_CATALOGUE_PATH}/${EMS_GLYPHS_PATH}`) + `/{fontstack}/{range}` : getEmsFontLibraryUrl(); diff --git a/x-pack/plugins/maps/public/meta.test.js b/x-pack/plugins/maps/public/meta.test.js index c6cc9b53b930..24dc65e9fc71 100644 --- a/x-pack/plugins/maps/public/meta.test.js +++ b/x-pack/plugins/maps/public/meta.test.js @@ -11,17 +11,7 @@ jest.mock('@elastic/ems-client'); describe('default use without proxy', () => { beforeEach(() => { - require('./kibana_services').getInjectedVarFunc = () => key => { - if (key === 'proxyElasticMapsServiceInMaps') { - return false; - } else if (key === 'isEmsEnabled') { - return true; - } else if (key === 'emsFileApiUrl') { - return 'https://file-api'; - } else if (key === 'emsTileApiUrl') { - return 'https://tile-api'; - } - }; + require('./kibana_services').getProxyElasticMapsServiceInMaps = () => false; require('./kibana_services').getLicenseId = () => { return 'foobarlicenseid'; }; diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 8fe16c0d99d7..3a20f6738a05 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Plugin, CoreSetup, CoreStart } from 'src/core/public'; +import { Plugin, CoreSetup, CoreStart, PluginInitializerContext } from 'src/core/public'; import { Setup as InspectorSetupContract } from 'src/plugins/inspector/public'; // @ts-ignore import { MapView } from './inspector/views/map_view'; @@ -20,7 +20,6 @@ import { setHttp, setIndexPatternSelect, setIndexPatternService, - setInjectedVarFunc, setInspector, setLicenseId, setMapsCapabilities, @@ -32,7 +31,9 @@ import { setUiSettings, setVisualizations, setSearchService, - setMapConfig, + setMapAppConfig, + setKibanaCommonConfig, + setKibanaVersion, } from './kibana_services'; import { featureCatalogueEntry } from './feature_catalogue_entry'; // @ts-ignore @@ -42,6 +43,7 @@ import { VisualizationsSetup } from '../../../../src/plugins/visualizations/publ import { MAP_SAVED_OBJECT_TYPE } from '../common/constants'; import { MapEmbeddableFactory } from './embeddable/map_embeddable_factory'; import { EmbeddableSetup } from '../../../../src/plugins/embeddable/public'; +import { MapsXPackConfig, MapsConfigType } from '../config'; export interface MapsPluginSetupDependencies { inspector: InspectorSetupContract; @@ -53,19 +55,24 @@ export interface MapsPluginSetupDependencies { // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface MapsPluginStartDependencies {} -export const bindSetupCoreAndPlugins = (core: CoreSetup, plugins: any) => { +export const bindSetupCoreAndPlugins = ( + core: CoreSetup, + plugins: any, + config: MapsConfigType, + kibanaVersion: string +) => { const { licensing, mapsLegacy } = plugins; - const { injectedMetadata, uiSettings, http, notifications } = core; + const { uiSettings, http, notifications } = core; if (licensing) { licensing.license$.subscribe(({ uid }: { uid: string }) => setLicenseId(uid)); } - setInjectedVarFunc(injectedMetadata.getInjectedVar); setHttp(http); setToasts(notifications.toasts); - setInjectedVarFunc(injectedMetadata.getInjectedVar); setVisualizations(plugins.visualizations); setUiSettings(uiSettings); - setMapConfig(mapsLegacy.config); + setKibanaCommonConfig(mapsLegacy.config); + setMapAppConfig(config); + setKibanaVersion(kibanaVersion); }; export const bindStartCoreAndPlugins = (core: CoreStart, plugins: any) => { @@ -106,14 +113,25 @@ export class MapsPlugin MapsPluginSetupDependencies, MapsPluginStartDependencies > { + readonly _initializerContext: PluginInitializerContext; + + constructor(initializerContext: PluginInitializerContext) { + this._initializerContext = initializerContext; + } + public setup(core: CoreSetup, plugins: MapsPluginSetupDependencies) { + const config = this._initializerContext.config.get(); + const kibanaVersion = this._initializerContext.env.packageInfo.version; const { inspector, home, visualizations, embeddable } = plugins; - bindSetupCoreAndPlugins(core, plugins); + bindSetupCoreAndPlugins(core, plugins, config, kibanaVersion); inspector.registerView(MapView); home.featureCatalogue.register(featureCatalogueEntry); visualizations.registerAlias(getMapsVisTypeAlias()); embeddable.registerEmbeddableFactory(MAP_SAVED_OBJECT_TYPE, new MapEmbeddableFactory()); + return { + config, + }; } public start(core: CoreStart, plugins: any) { diff --git a/x-pack/plugins/maps/public/reducers/non_serializable_instances.js b/x-pack/plugins/maps/public/reducers/non_serializable_instances.js index 8265c70ae180..bbefe09bb6e4 100644 --- a/x-pack/plugins/maps/public/reducers/non_serializable_instances.js +++ b/x-pack/plugins/maps/public/reducers/non_serializable_instances.js @@ -6,7 +6,7 @@ import { RequestAdapter } from '../../../../../src/plugins/inspector/common/adapters/request'; import { MapAdapter } from '../inspector/adapters/map_adapter'; -import { getInjectedVarFunc } from '../kibana_services'; +import { getShowMapsInspectorAdapter } from '../kibana_services'; const REGISTER_CANCEL_CALLBACK = 'REGISTER_CANCEL_CALLBACK'; const UNREGISTER_CANCEL_CALLBACK = 'UNREGISTER_CANCEL_CALLBACK'; @@ -16,8 +16,7 @@ function createInspectorAdapters() { const inspectorAdapters = { requests: new RequestAdapter(), }; - const getInjectedVar = getInjectedVarFunc(); - if (getInjectedVar && getInjectedVar('showMapsInspectorAdapter', false)) { + if (getShowMapsInspectorAdapter()) { inspectorAdapters.map = new MapAdapter(); } return inspectorAdapters; diff --git a/x-pack/plugins/maps/server/index.ts b/x-pack/plugins/maps/server/index.ts index 1b714a3555b3..a73ba91098e9 100644 --- a/x-pack/plugins/maps/server/index.ts +++ b/x-pack/plugins/maps/server/index.ts @@ -4,7 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ import { PluginInitializerContext } from 'src/core/server'; +import { PluginConfigDescriptor } from 'kibana/server'; import { MapsPlugin } from './plugin'; +import { configSchema, MapsXPackConfig } from '../config'; + +export const config: PluginConfigDescriptor = { + // exposeToBrowser specifies kibana.yml settings to expose to the browser + // the value `true` in this context signals configuration is exposed to browser + exposeToBrowser: { + enabled: true, + showMapVisualizationTypes: true, + showMapsInspectorAdapter: true, + enableVectorTiles: true, + preserveDrawingBuffer: true, + }, + schema: configSchema, +}; export const plugin = (initializerContext: PluginInitializerContext) => new MapsPlugin(initializerContext); diff --git a/x-pack/plugins/maps/server/kibana_server_services.ts b/x-pack/plugins/maps/server/kibana_server_services.ts new file mode 100644 index 000000000000..9cc28182662c --- /dev/null +++ b/x-pack/plugins/maps/server/kibana_server_services.ts @@ -0,0 +1,15 @@ +/* + * 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 { ISavedObjectsRepository } from 'kibana/server'; + +let internalRepository: ISavedObjectsRepository; +export const setInternalRepository = ( + createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository +) => { + internalRepository = createInternalRepository(); +}; +export const getInternalRepository = () => internalRepository; diff --git a/x-pack/legacy/plugins/maps/server/lib/get_index_pattern_settings.js b/x-pack/plugins/maps/server/lib/get_index_pattern_settings.js similarity index 90% rename from x-pack/legacy/plugins/maps/server/lib/get_index_pattern_settings.js rename to x-pack/plugins/maps/server/lib/get_index_pattern_settings.js index b7cd1687dc25..066996ef8a6b 100644 --- a/x-pack/legacy/plugins/maps/server/lib/get_index_pattern_settings.js +++ b/x-pack/plugins/maps/server/lib/get_index_pattern_settings.js @@ -5,10 +5,7 @@ */ import _ from 'lodash'; -import { - DEFAULT_MAX_RESULT_WINDOW, - DEFAULT_MAX_INNER_RESULT_WINDOW, -} from '../../../../../plugins/maps/common/constants'; +import { DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_INNER_RESULT_WINDOW } from '../../common/constants'; export function getIndexPatternSettings(indicesSettingsResp) { let maxResultWindow = Infinity; diff --git a/x-pack/legacy/plugins/maps/server/lib/get_index_pattern_settings.test.js b/x-pack/plugins/maps/server/lib/get_index_pattern_settings.test.js similarity index 96% rename from x-pack/legacy/plugins/maps/server/lib/get_index_pattern_settings.test.js rename to x-pack/plugins/maps/server/lib/get_index_pattern_settings.test.js index 46949a2e3e2c..856062d7195e 100644 --- a/x-pack/legacy/plugins/maps/server/lib/get_index_pattern_settings.test.js +++ b/x-pack/plugins/maps/server/lib/get_index_pattern_settings.test.js @@ -5,10 +5,7 @@ */ import { getIndexPatternSettings } from './get_index_pattern_settings'; -import { - DEFAULT_MAX_RESULT_WINDOW, - DEFAULT_MAX_INNER_RESULT_WINDOW, -} from '../../../../../plugins/maps/common/constants'; +import { DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_INNER_RESULT_WINDOW } from '../../common/constants'; describe('max_result_window and max_inner_result_window are not set', () => { test('Should provide default values when values not set', () => { diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/collectors/register.ts b/x-pack/plugins/maps/server/maps_telemetry/collectors/register.ts similarity index 70% rename from x-pack/legacy/plugins/maps/server/maps_telemetry/collectors/register.ts rename to x-pack/plugins/maps/server/maps_telemetry/collectors/register.ts index d34e306d1fff..383d7773663c 100644 --- a/x-pack/legacy/plugins/maps/server/maps_telemetry/collectors/register.ts +++ b/x-pack/plugins/maps/server/maps_telemetry/collectors/register.ts @@ -5,16 +5,14 @@ */ import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -// @ts-ignore -import { SavedObjectsClientContract } from 'src/core/server'; import { getMapsTelemetry } from '../maps_telemetry'; // @ts-ignore -import { TELEMETRY_TYPE } from '../../../../../../plugins/maps/common/constants'; +import { TELEMETRY_TYPE } from '../../../common/constants'; +import { MapsConfigType } from '../../../config'; export function registerMapsUsageCollector( usageCollection: UsageCollectionSetup, - savedObjectsClient: SavedObjectsClientContract, - config: Function + config: MapsConfigType ): void { if (!usageCollection) { return; @@ -23,7 +21,7 @@ export function registerMapsUsageCollector( const mapsUsageCollector = usageCollection.makeUsageCollector({ type: TELEMETRY_TYPE, isReady: () => true, - fetch: async () => await getMapsTelemetry(savedObjectsClient, config), + fetch: async () => await getMapsTelemetry(config), }); usageCollection.registerCollector(mapsUsageCollector); diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/collectors/register_collector.test.js b/x-pack/plugins/maps/server/maps_telemetry/collectors/register_collector.test.js similarity index 100% rename from x-pack/legacy/plugins/maps/server/maps_telemetry/collectors/register_collector.test.js rename to x-pack/plugins/maps/server/maps_telemetry/collectors/register_collector.test.js diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.test.js b/x-pack/plugins/maps/server/maps_telemetry/maps_telemetry.test.js similarity index 100% rename from x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.test.js rename to x-pack/plugins/maps/server/maps_telemetry/maps_telemetry.test.js diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts b/x-pack/plugins/maps/server/maps_telemetry/maps_telemetry.ts similarity index 91% rename from x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts rename to x-pack/plugins/maps/server/maps_telemetry/maps_telemetry.ts index fe22c114cd92..6c62ceb347c8 100644 --- a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts +++ b/x-pack/plugins/maps/server/maps_telemetry/maps_telemetry.ts @@ -9,16 +9,19 @@ import { SavedObjectsClientContract, SavedObjectAttributes, SavedObjectAttribute, -} from 'src/core/server'; +} from 'kibana/server'; import { IFieldType, IIndexPattern } from 'src/plugins/data/public'; import { SOURCE_TYPES, ES_GEO_FIELD_TYPE, MAP_SAVED_OBJECT_TYPE, TELEMETRY_TYPE, -} from '../../../../../plugins/maps/common/constants'; -import { LayerDescriptor } from '../../../../../plugins/maps/common/descriptor_types'; -import { MapSavedObject } from '../../../../../plugins/maps/common/map_saved_object_type'; +} from '../../common/constants'; +import { LayerDescriptor } from '../../common/descriptor_types'; +import { MapSavedObject } from '../../common/map_saved_object_type'; +// @ts-ignore +import { getInternalRepository } from '../kibana_server_services'; +import { MapsConfigType } from '../../config'; interface IStats { [key: string]: { @@ -172,16 +175,16 @@ async function getIndexPatternSavedObjects(savedObjectsClient: SavedObjectsClien return _.get(indexPatternSavedObjects, 'saved_objects', []); } -export async function getMapsTelemetry( - savedObjectsClient: SavedObjectsClientContract, - config: Function -) { +export async function getMapsTelemetry(config: MapsConfigType) { + const savedObjectsClient = getInternalRepository(); + // @ts-ignore const mapSavedObjects: MapSavedObject[] = await getMapSavedObjects(savedObjectsClient); const indexPatternSavedObjects: IIndexPattern[] = await getIndexPatternSavedObjects( + // @ts-ignore savedObjectsClient ); const settings: SavedObjectAttribute = { - showMapVisualizationTypes: config().get('xpack.maps.showMapVisualizationTypes'), + showMapVisualizationTypes: config.showMapVisualizationTypes, }; const mapsTelemetry = buildMapsTelemetry({ mapSavedObjects, indexPatternSavedObjects, settings }); return await savedObjectsClient.create(TELEMETRY_TYPE, mapsTelemetry, { diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/test_resources/sample_index_pattern_saved_objects.json b/x-pack/plugins/maps/server/maps_telemetry/test_resources/sample_index_pattern_saved_objects.json similarity index 100% rename from x-pack/legacy/plugins/maps/server/maps_telemetry/test_resources/sample_index_pattern_saved_objects.json rename to x-pack/plugins/maps/server/maps_telemetry/test_resources/sample_index_pattern_saved_objects.json diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/test_resources/sample_map_saved_objects.json b/x-pack/plugins/maps/server/maps_telemetry/test_resources/sample_map_saved_objects.json similarity index 100% rename from x-pack/legacy/plugins/maps/server/maps_telemetry/test_resources/sample_map_saved_objects.json rename to x-pack/plugins/maps/server/maps_telemetry/test_resources/sample_map_saved_objects.json diff --git a/x-pack/plugins/maps/server/plugin.ts b/x-pack/plugins/maps/server/plugin.ts index c50a00b2ec01..a265cf80c73c 100644 --- a/x-pack/plugins/maps/server/plugin.ts +++ b/x-pack/plugins/maps/server/plugin.ts @@ -4,20 +4,161 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; -import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'src/core/server'; +import { CoreSetup, CoreStart, Logger, Plugin, PluginInitializerContext } from 'src/core/server'; +import { take } from 'rxjs/operators'; import { PluginSetupContract as FeaturesPluginSetupContract } from '../../features/server'; - -import { APP_ID, APP_ICON, MAP_SAVED_OBJECT_TYPE } from '../common/constants'; +// @ts-ignore +import { getEcommerceSavedObjects } from './sample_data/ecommerce_saved_objects'; +// @ts-ignore +import { getFlightsSavedObjects } from './sample_data/flights_saved_objects.js'; +// @ts-ignore +import { getWebLogsSavedObjects } from './sample_data/web_logs_saved_objects.js'; +import { registerMapsUsageCollector } from './maps_telemetry/collectors/register'; +import { APP_ID, APP_ICON, MAP_SAVED_OBJECT_TYPE, createMapPath } from '../common/constants'; import { mapSavedObjects, mapsTelemetrySavedObjects } from './saved_objects'; +import { MapsXPackConfig } from '../config'; +// @ts-ignore +import { setInternalRepository } from './kibana_server_services'; +import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; +import { emsBoundariesSpecProvider } from './tutorials/ems'; +// @ts-ignore +import { initRoutes } from './routes'; +import { ILicense, LicensingPluginSetup } from '../../licensing/public'; +import { HomeServerPluginSetup } from '../../../../src/plugins/home/server'; interface SetupDeps { features: FeaturesPluginSetupContract; + usageCollection: UsageCollectionSetup; + home: HomeServerPluginSetup; + licensing: LicensingPluginSetup; } export class MapsPlugin implements Plugin { - constructor(initializerContext: PluginInitializerContext) {} - setup(core: CoreSetup, plugins: SetupDeps) { - plugins.features.registerFeature({ + readonly _initializerContext: PluginInitializerContext; + private readonly _logger: Logger; + private readonly kibanaVersion: string; + + constructor(initializerContext: PluginInitializerContext) { + this._logger = initializerContext.logger.get(); + this._initializerContext = initializerContext; + this.kibanaVersion = initializerContext.env.packageInfo.version; + } + + _initHomeData( + home: HomeServerPluginSetup, + prependBasePath: (path: string) => string, + mapConfig: any + ) { + const sampleDataLinkLabel = i18n.translate('xpack.maps.sampleDataLinkLabel', { + defaultMessage: 'Map', + }); + if (home) { + home.sampleData.addSavedObjectsToSampleDataset('ecommerce', getEcommerceSavedObjects()); + + home.sampleData.addAppLinksToSampleDataset('ecommerce', [ + { + path: createMapPath('2c9c1f60-1909-11e9-919b-ffe5949a18d2'), + label: sampleDataLinkLabel, + icon: APP_ICON, + }, + ]); + + home.sampleData.replacePanelInSampleDatasetDashboard({ + sampleDataId: 'ecommerce', + dashboardId: '722b74f0-b882-11e8-a6d9-e546fe2bba5f', + oldEmbeddableId: '9c6f83f0-bb4d-11e8-9c84-77068524bcab', + embeddableId: '2c9c1f60-1909-11e9-919b-ffe5949a18d2', + // @ts-ignore + embeddableType: 'map', + embeddableConfig: { + isLayerTOCOpen: false, + }, + }); + + home.sampleData.addSavedObjectsToSampleDataset('flights', getFlightsSavedObjects()); + + home.sampleData.addAppLinksToSampleDataset('flights', [ + { + path: createMapPath('5dd88580-1906-11e9-919b-ffe5949a18d2'), + label: sampleDataLinkLabel, + icon: APP_ICON, + }, + ]); + + home.sampleData.replacePanelInSampleDatasetDashboard({ + sampleDataId: 'flights', + dashboardId: '7adfa750-4c81-11e8-b3d7-01146121b73d', + oldEmbeddableId: '334084f0-52fd-11e8-a160-89cc2ad9e8e2', + embeddableId: '5dd88580-1906-11e9-919b-ffe5949a18d2', + // @ts-ignore + embeddableType: MAP_SAVED_OBJECT_TYPE, + embeddableConfig: { + isLayerTOCOpen: true, + }, + }); + + home.sampleData.addSavedObjectsToSampleDataset('logs', getWebLogsSavedObjects()); + home.sampleData.addAppLinksToSampleDataset('logs', [ + { + path: createMapPath('de71f4f0-1902-11e9-919b-ffe5949a18d2'), + label: sampleDataLinkLabel, + icon: APP_ICON, + }, + ]); + home.sampleData.replacePanelInSampleDatasetDashboard({ + sampleDataId: 'logs', + dashboardId: 'edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b', + oldEmbeddableId: '06cf9c40-9ee8-11e7-8711-e7a007dcef99', + embeddableId: 'de71f4f0-1902-11e9-919b-ffe5949a18d2', + // @ts-ignore + embeddableType: MAP_SAVED_OBJECT_TYPE, + embeddableConfig: { + isLayerTOCOpen: false, + }, + }); + + home.tutorials.registerTutorial( + emsBoundariesSpecProvider({ + prependBasePath, + emsLandingPageUrl: mapConfig.emsLandingPageUrl, + }) + ); + } + } + + // @ts-ignore + async setup(core: CoreSetup, plugins: SetupDeps) { + const { usageCollection, home, licensing, features } = plugins; + // @ts-ignore + const config$ = this._initializerContext.config.create(); + const currentConfig = await config$.pipe(take(1)).toPromise(); + + // @ts-ignore + const mapsEnabled = currentConfig.enabled; + // TODO: Consider dynamic way to disable maps app on config change + if (!mapsEnabled) { + this._logger.warn('Maps app disabled by configuration'); + return; + } + + let routesInitialized = false; + licensing.license$.subscribe((license: ILicense) => { + const { state } = license.check('maps', 'basic'); + if (state === 'valid' && !routesInitialized) { + routesInitialized = true; + initRoutes( + core.http.createRouter(), + license.uid, + currentConfig, + this.kibanaVersion, + this._logger + ); + } + }); + + this._initHomeData(home, core.http.basePath.prepend, currentConfig); + + features.registerFeature({ id: APP_ID, name: i18n.translate('xpack.maps.featureRegistry.mapsFeatureName', { defaultMessage: 'Maps', @@ -51,6 +192,15 @@ export class MapsPlugin implements Plugin { core.savedObjects.registerType(mapsTelemetrySavedObjects); core.savedObjects.registerType(mapSavedObjects); + registerMapsUsageCollector(usageCollection, currentConfig); + + return { + config: config$, + }; + } + + // @ts-ignore + start(core: CoreStart) { + setInternalRepository(core.savedObjects.createInternalRepository); } - start(core: CoreStart) {} } diff --git a/x-pack/legacy/plugins/maps/server/routes.js b/x-pack/plugins/maps/server/routes.js similarity index 52% rename from x-pack/legacy/plugins/maps/server/routes.js rename to x-pack/plugins/maps/server/routes.js index 6b83f4026f1d..de07472275c0 100644 --- a/x-pack/legacy/plugins/maps/server/routes.js +++ b/x-pack/plugins/maps/server/routes.js @@ -21,24 +21,21 @@ import { GIS_API_PATH, EMS_SPRITES_PATH, INDEX_SETTINGS_API_PATH, -} from '../../../../plugins/maps/common/constants'; +} from '../common/constants'; import { EMSClient } from '@elastic/ems-client'; import fetch from 'node-fetch'; import { i18n } from '@kbn/i18n'; import { getIndexPatternSettings } from './lib/get_index_pattern_settings'; - -import Boom from 'boom'; +import { schema } from '@kbn/config-schema'; const ROOT = `/${GIS_API_PATH}`; -export function initRoutes(server, licenseUid, mapConfig) { - const serverConfig = server.config(); - +export function initRoutes(router, licenseUid, mapConfig, kbnVersion, logger) { let emsClient; if (mapConfig.includeElasticMapsService) { emsClient = new EMSClient({ language: i18n.getLocale(), - appVersion: serverConfig.get('pkg.version'), + appVersion: kbnVersion, appName: EMS_APP_NAME, fileApiUrl: mapConfig.emsFileApiUrl, tileApiUrl: mapConfig.emsTileApiUrl, @@ -67,15 +64,25 @@ export function initRoutes(server, licenseUid, mapConfig) { }; } - server.route({ - method: 'GET', - path: `${ROOT}/${EMS_FILES_API_PATH}/${EMS_FILES_DEFAULT_JSON_PATH}`, - handler: async request => { - const { server } = request; - checkEMSProxyConfig(server); + router.get( + { + path: `${ROOT}/${EMS_FILES_API_PATH}/${EMS_FILES_DEFAULT_JSON_PATH}`, + validate: { + query: schema.object({ + id: schema.maybe(schema.string()), + x: schema.maybe(schema.number()), + y: schema.maybe(schema.number()), + z: schema.maybe(schema.number()), + }), + }, + }, + async (con, request, { ok, badRequest }) => { + if (!checkEMSProxyEnabled()) { + return badRequest('map.proxyElasticMapsServiceInMaps disabled'); + } if (!request.query.id) { - server.log('warning', 'Must supply id parameters to retrieve EMS file'); + logger.warn('Must supply id parameters to retrieve EMS file'); return null; } @@ -87,20 +94,24 @@ export function initRoutes(server, licenseUid, mapConfig) { try { const file = await fetch(layer.getDefaultFormatUrl()); - return await file.json(); + const fileJson = await file.json(); + return ok({ body: fileJson }); } catch (e) { - server.log('warning', `Cannot connect to EMS for file, error: ${e.message}`); - throw Boom.badRequest(`Cannot connect to EMS`); + logger.warn(`Cannot connect to EMS for file, error: ${e.message}`); + return badRequest(`Cannot connect to EMS`); } - }, - }); + } + ); - server.route({ - method: 'GET', - path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_TILES_RASTER_TILE_PATH}`, - handler: async (request, h) => { - const { server } = request; - checkEMSProxyConfig(server); + router.get( + { + path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_TILES_RASTER_TILE_PATH}`, + validate: false, + }, + async (con, request, { ok, badRequest }) => { + if (!checkEMSProxyEnabled()) { + return badRequest('map.proxyElasticMapsServiceInMaps disabled'); + } if ( !request.query.id || @@ -108,7 +119,7 @@ export function initRoutes(server, licenseUid, mapConfig) { typeof parseInt(request.query.y, 10) !== 'number' || typeof parseInt(request.query.z, 10) !== 'number' ) { - server.log('warning', 'Must supply id/x/y/z parameters to retrieve EMS raster tile'); + logger.warn('Must supply id/x/y/z parameters to retrieve EMS raster tile'); return null; } @@ -124,16 +135,19 @@ export function initRoutes(server, licenseUid, mapConfig) { .replace('{y}', request.query.y) .replace('{z}', request.query.z); - return await proxyResource(h, { url, contentType: 'image/png' }); - }, - }); + return await proxyResource({ url, contentType: 'image/png' }, { ok, badRequest }); + } + ); - server.route({ - method: 'GET', - path: `${ROOT}/${EMS_CATALOGUE_PATH}`, - handler: async request => { - const { server } = request; - checkEMSProxyConfig(server); + router.get( + { + path: `${ROOT}/${EMS_CATALOGUE_PATH}`, + validate: false, + }, + async (con, request, { ok, badRequest }) => { + if (!checkEMSProxyEnabled()) { + return badRequest('map.proxyElasticMapsServiceInMaps disabled'); + } const main = await emsClient.getMainManifest(); const proxiedManifest = { @@ -155,16 +169,21 @@ export function initRoutes(server, licenseUid, mapConfig) { manifest: `${GIS_API_PATH}/${EMS_FILES_CATALOGUE_PATH}`, }); } - return proxiedManifest; - }, - }); + return ok({ + body: proxiedManifest, + }); + } + ); - server.route({ - method: 'GET', - path: `${ROOT}/${EMS_FILES_CATALOGUE_PATH}/{emsVersion}/manifest`, - handler: async request => { - const { server } = request; - checkEMSProxyConfig(server); + router.get( + { + path: `${ROOT}/${EMS_FILES_CATALOGUE_PATH}/{emsVersion}/manifest`, + validate: false, + }, + async (con, request, { ok, badRequest }) => { + if (!checkEMSProxyEnabled()) { + return badRequest('map.proxyElasticMapsServiceInMaps disabled'); + } const file = await emsClient.getDefaultFileManifest(); const layers = file.layers.map(layer => { @@ -180,16 +199,21 @@ export function initRoutes(server, licenseUid, mapConfig) { return newLayer; }); //rewrite - return { layers }; - }, - }); + return ok({ + body: layers, + }); + } + ); - server.route({ - method: 'GET', - path: `${ROOT}/${EMS_TILES_CATALOGUE_PATH}/{emsVersion}/manifest`, - handler: async request => { - const { server } = request; - checkEMSProxyConfig(server); + router.get( + { + path: `${ROOT}/${EMS_TILES_CATALOGUE_PATH}/{emsVersion}/manifest`, + validate: false, + }, + async (con, request, { ok, badRequest }) => { + if (!checkEMSProxyEnabled()) { + return badRequest('map.proxyElasticMapsServiceInMaps disabled'); + } const tilesManifest = await emsClient.getDefaultTMSManifest(); const newServices = tilesManifest.services.map(service => { @@ -217,21 +241,30 @@ export function initRoutes(server, licenseUid, mapConfig) { return newService; }); - return { - services: newServices, - }; + return ok({ + body: { + services: newServices, + }, + }); + } + ); + + router.get( + { + path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_TILES_RASTER_STYLE_PATH}`, + validate: { + query: schema.object({ + id: schema.maybe(schema.string()), + }), + }, }, - }); - - server.route({ - method: 'GET', - path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_TILES_RASTER_STYLE_PATH}`, - handler: async request => { - const { server } = request; - checkEMSProxyConfig(server); + async (con, request, { ok, badRequest }) => { + if (!checkEMSProxyEnabled()) { + return badRequest('map.proxyElasticMapsServiceInMaps disabled'); + } if (!request.query.id) { - server.log('warning', 'Must supply id parameter to retrieve EMS raster style'); + logger.warn('Must supply id parameter to retrieve EMS raster style'); return null; } @@ -243,22 +276,31 @@ export function initRoutes(server, licenseUid, mapConfig) { const style = await tmsService.getDefaultRasterStyle(); const newUrl = `${EMS_TILES_RASTER_TILE_PATH}?id=${request.query.id}&x={x}&y={y}&z={z}`; - return { - ...style, - tiles: [newUrl], - }; + return ok({ + body: { + ...style, + tiles: [newUrl], + }, + }); + } + ); + + router.get( + { + path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_TILES_VECTOR_STYLE_PATH}`, + validate: { + query: schema.object({ + id: schema.maybe(schema.string()), + }), + }, }, - }); - - server.route({ - method: 'GET', - path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_TILES_VECTOR_STYLE_PATH}`, - handler: async request => { - const { server } = request; - checkEMSProxyConfig(server); + async (con, request, { ok, badRequest }) => { + if (!checkEMSProxyEnabled()) { + return badRequest('map.proxyElasticMapsServiceInMaps disabled'); + } if (!request.query.id) { - server.log('warning', 'Must supply id parameter to retrieve EMS vector style'); + logger.warn('Must supply id parameter to retrieve EMS vector style'); return null; } @@ -281,27 +323,34 @@ export function initRoutes(server, licenseUid, mapConfig) { const spritePath = `${EMS_SPRITES_PATH}/${request.query.id}/sprite`; - return { - ...vectorStyle, - glyphs: `${EMS_GLYPHS_PATH}/{fontstack}/{range}`, - sprite: spritePath, - sources: newSources, - }; + return ok({ + body: { + ...vectorStyle, + glyphs: `${EMS_GLYPHS_PATH}/{fontstack}/{range}`, + sprite: spritePath, + sources: newSources, + }, + }); + } + ); + + router.get( + { + path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_TILES_VECTOR_SOURCE_PATH}`, + validate: { + query: schema.object({ + id: schema.maybe(schema.string()), + sourceId: schema.maybe(schema.string()), + }), + }, }, - }); - - server.route({ - method: 'GET', - path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_TILES_VECTOR_SOURCE_PATH}`, - handler: async request => { - const { server } = request; - checkEMSProxyConfig(server); + async (con, request, { ok, badRequest }) => { + if (!checkEMSProxyEnabled()) { + return badRequest('map.proxyElasticMapsServiceInMaps disabled'); + } if (!request.query.id || !request.query.sourceId) { - server.log( - 'warning', - 'Must supply id and sourceId parameter to retrieve EMS vector source' - ); + logger.warn('Must supply id and sourceId parameter to retrieve EMS vector source'); return null; } @@ -315,19 +364,32 @@ export function initRoutes(server, licenseUid, mapConfig) { const sourceManifest = vectorStyle.sources[request.query.sourceId]; const newUrl = `${EMS_TILES_VECTOR_TILE_PATH}?id=${request.query.id}&sourceId=${request.query.sourceId}&x={x}&y={y}&z={z}`; - return { - ...sourceManifest, - tiles: [newUrl], - }; + return ok({ + body: { + ...sourceManifest, + tiles: [newUrl], + }, + }); + } + ); + + router.get( + { + path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_TILES_VECTOR_TILE_PATH}`, + validate: { + query: schema.object({ + id: schema.maybe(schema.string()), + sourceId: schema.maybe(schema.string()), + x: schema.maybe(schema.number()), + y: schema.maybe(schema.number()), + z: schema.maybe(schema.number()), + }), + }, }, - }); - - server.route({ - method: 'GET', - path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_TILES_VECTOR_TILE_PATH}`, - handler: async (request, h) => { - const { server } = request; - checkEMSProxyConfig(server); + async (con, request, { ok, badRequest }) => { + if (!checkEMSProxyEnabled()) { + return badRequest('map.proxyElasticMapsServiceInMaps disabled'); + } if ( !request.query.id || @@ -336,10 +398,7 @@ export function initRoutes(server, licenseUid, mapConfig) { typeof parseInt(request.query.y, 10) !== 'number' || typeof parseInt(request.query.z, 10) !== 'number' ) { - server.log( - 'warning', - 'Must supply id/sourceId/x/y/z parameters to retrieve EMS vector tile' - ); + logger.warn('Must supply id/sourceId/x/y/z parameters to retrieve EMS vector tile'); return null; } @@ -355,33 +414,43 @@ export function initRoutes(server, licenseUid, mapConfig) { .replace('{y}', request.query.y) .replace('{z}', request.query.z); - return await proxyResource(h, { url }); + return await proxyResource({ url }, { ok, badRequest }); + } + ); + + router.get( + { + path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_GLYPHS_PATH}/{fontstack}/{range}`, + validate: false, }, - }); - - server.route({ - method: 'GET', - path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_GLYPHS_PATH}/{fontstack}/{range}`, - handler: async (request, h) => { - const { server } = request; - checkEMSProxyConfig(server); + async (con, request, { ok, badRequest }) => { + if (!checkEMSProxyEnabled()) { + return badRequest('map.proxyElasticMapsServiceInMaps disabled'); + } const url = mapConfig.emsFontLibraryUrl .replace('{fontstack}', request.params.fontstack) .replace('{range}', request.params.range); - return await proxyResource(h, { url }); + return await proxyResource({ url }, { ok, badRequest }); + } + ); + + router.get( + { + path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_SPRITES_PATH}/{id}/sprite{scaling?}.{extension}`, + validate: { + params: schema.object({ + id: schema.string(), + }), + }, }, - }); - - server.route({ - method: 'GET', - path: `${ROOT}/${EMS_TILES_API_PATH}/${EMS_SPRITES_PATH}/{id}/sprite{scaling?}.{extension}`, - handler: async (request, h) => { - const { server } = request; - checkEMSProxyConfig(server); + async (con, request, { ok, badRequest }) => { + if (!checkEMSProxyEnabled()) { + return badRequest('map.proxyElasticMapsServiceInMaps disabled'); + } if (!request.params.id) { - server.log('warning', 'Must supply id parameter to retrieve EMS vector source sprite'); + logger.warn('Must supply id parameter to retrieve EMS vector source sprite'); return null; } @@ -398,70 +467,92 @@ export function initRoutes(server, licenseUid, mapConfig) { } else if (request.params.extension === 'png') { proxyPathUrl = await tmsService.getSpriteSheetPngPath(isRetina); } else { - server.log('warning', `Must have png or json extension for spritesheet`); + logger.warn(`Must have png or json extension for spritesheet`); return null; } - return await proxyResource(h, { - url: proxyPathUrl, - contentType: request.params.extension === 'png' ? 'image/png' : '', - }); + return await proxyResource( + { + url: proxyPathUrl, + contentType: request.params.extension === 'png' ? 'image/png' : '', + }, + { ok, badRequest } + ); + } + ); + + router.get( + { + path: `/${INDEX_SETTINGS_API_PATH}`, + validate: { + query: schema.object({ + indexPatternTitle: schema.string(), + }), + }, }, - }); - - server.route({ - method: 'GET', - path: `/${INDEX_SETTINGS_API_PATH}`, - handler: async (request, h) => { - const { server, query } = request; + async (con, request, response) => { + const { query } = request; if (!query.indexPatternTitle) { - server.log('warning', `Required query parameter 'indexPatternTitle' not provided.`); - return h.response().code(400); + logger.warn(`Required query parameter 'indexPatternTitle' not provided.`); + return response.custom({ + body: `Required query parameter 'indexPatternTitle' not provided.`, + statusCode: 400, + }); } - const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); try { - const resp = await callWithRequest(request, 'indices.getSettings', { - index: query.indexPatternTitle, + const resp = await con.core.elasticsearch.dataClient.callAsCurrentUser( + 'indices.getSettings', + { + index: query.indexPatternTitle, + } + ); + const indexPatternSettings = getIndexPatternSettings(resp); + return response.ok({ + body: indexPatternSettings, }); - return getIndexPatternSettings(resp); } catch (error) { - server.log( - 'warning', + logger.warn( `Cannot load index settings for index pattern '${query.indexPatternTitle}', error: ${error.message}.` ); - return h.response().code(400); + response.custom({ + body: 'Error loading index settings', + statusCode: 400, + }); } - }, - }); + } + ); - function checkEMSProxyConfig(server) { - if (!mapConfig.proxyElasticMapsServiceInMaps) { - server.log( - 'warning', + function checkEMSProxyEnabled() { + const proxyEMSInMaps = mapConfig.proxyElasticMapsServiceInMaps; + if (!proxyEMSInMaps) { + logger.warn( `Cannot load content from EMS when map.proxyElasticMapsServiceInMaps is turned off` ); - throw Boom.notFound(); } + return proxyEMSInMaps; } - async function proxyResource(h, { url, contentType }) { + async function proxyResource({ url, contentType }, { ok, badRequest }) { try { const resource = await fetch(url); const arrayBuffer = await resource.arrayBuffer(); - const buffer = Buffer.from(arrayBuffer); - let response = h.response(buffer); - response = response.bytes(buffer.length); - response = response.header('Content-Disposition', 'inline'); + const bufferedResponse = Buffer.from(arrayBuffer); + const headers = { + 'Content-Disposition': 'inline', + }; if (contentType) { - response = response.header('Content-type', contentType); + headers['Content-type'] = contentType; } - response = response.encoding('binary'); - return response; + + return ok({ + body: bufferedResponse, + headers, + }); } catch (e) { - server.log('warning', `Cannot connect to EMS for resource, error: ${e.message}`); - throw Boom.badRequest(`Cannot connect to EMS`); + logger.warn(`Cannot connect to EMS for resource, error: ${e.message}`); + return badRequest(`Cannot connect to EMS`); } } } diff --git a/x-pack/legacy/plugins/maps/server/sample_data/ecommerce_saved_objects.js b/x-pack/plugins/maps/server/sample_data/ecommerce_saved_objects.js similarity index 100% rename from x-pack/legacy/plugins/maps/server/sample_data/ecommerce_saved_objects.js rename to x-pack/plugins/maps/server/sample_data/ecommerce_saved_objects.js diff --git a/x-pack/legacy/plugins/maps/server/sample_data/flights_saved_objects.js b/x-pack/plugins/maps/server/sample_data/flights_saved_objects.js similarity index 100% rename from x-pack/legacy/plugins/maps/server/sample_data/flights_saved_objects.js rename to x-pack/plugins/maps/server/sample_data/flights_saved_objects.js diff --git a/x-pack/legacy/plugins/maps/server/sample_data/web_logs_saved_objects.js b/x-pack/plugins/maps/server/sample_data/web_logs_saved_objects.js similarity index 100% rename from x-pack/legacy/plugins/maps/server/sample_data/web_logs_saved_objects.js rename to x-pack/plugins/maps/server/sample_data/web_logs_saved_objects.js diff --git a/x-pack/legacy/plugins/maps/server/test_utils/index.js b/x-pack/plugins/maps/server/test_utils/index.js similarity index 100% rename from x-pack/legacy/plugins/maps/server/test_utils/index.js rename to x-pack/plugins/maps/server/test_utils/index.js diff --git a/x-pack/legacy/plugins/maps/server/tutorials/ems/index.ts b/x-pack/plugins/maps/server/tutorials/ems/index.ts similarity index 97% rename from x-pack/legacy/plugins/maps/server/tutorials/ems/index.ts rename to x-pack/plugins/maps/server/tutorials/ems/index.ts index 1006d36afa34..15dc403d942a 100644 --- a/x-pack/legacy/plugins/maps/server/tutorials/ems/index.ts +++ b/x-pack/plugins/maps/server/tutorials/ems/index.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { TutorialsCategory } from '../../../../../../../src/plugins/home/server'; +import { TutorialsCategory } from '../../../../../../src/plugins/home/server'; export function emsBoundariesSpecProvider({ emsLandingPageUrl,