From dcf79c653d795e16171af899928079fb0cd94a8a Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 3 Feb 2021 16:42:12 +0200 Subject: [PATCH 01/14] initial implementation --- ...-core-server.requesthandlercontext.core.md | 5 +++-- ...lugin-core-server.requesthandlercontext.md | 2 +- src/core/server/core_route_handler_context.ts | 17 +++++++++++------ src/core/server/index.ts | 6 ++++-- .../server/saved_objects/routes/delete.ts | 11 ++++++++++- .../server/saved_objects/routes/export.ts | 13 +++++++++---- .../server/saved_objects/routes/import.ts | 11 ++++++++++- .../routes/resolve_import_errors.ts | 13 ++++++++++++- src/core/server/server.api.md | 5 +++-- .../services/sample_data/routes/install.ts | 14 +++++++++++--- .../services/sample_data/routes/uninstall.ts | 8 +++++++- .../server/routes/find.ts | 19 +++++++++++++------ .../server/services/management.ts | 4 ++++ .../actions/server/saved_objects/index.ts | 6 ++++++ .../alerts/server/saved_objects/index.ts | 6 ++++++ x-pack/plugins/features/server/plugin.ts | 2 +- 16 files changed, 111 insertions(+), 31 deletions(-) diff --git a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md index 3a5e84ffdc372..268dcdd77d6b4 100644 --- a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md +++ b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md @@ -11,8 +11,9 @@ core: { savedObjects: { client: SavedObjectsClientContract; typeRegistry: ISavedObjectTypeRegistry; - exporter: ISavedObjectsExporter; - importer: ISavedObjectsImporter; + getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract; + getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter; + getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter; }; elasticsearch: { client: IScopedClusterClient; diff --git a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md index 5300c85cf9406..54d85910f823c 100644 --- a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md +++ b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md @@ -18,5 +18,5 @@ export interface RequestHandlerContext | Property | Type | Description | | --- | --- | --- | -| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | {
savedObjects: {
client: SavedObjectsClientContract;
typeRegistry: ISavedObjectTypeRegistry;
exporter: ISavedObjectsExporter;
importer: ISavedObjectsImporter;
};
elasticsearch: {
client: IScopedClusterClient;
legacy: {
client: ILegacyScopedClusterClient;
};
};
uiSettings: {
client: IUiSettingsClient;
};
} | | +| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | {
savedObjects: {
client: SavedObjectsClientContract;
typeRegistry: ISavedObjectTypeRegistry;
getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;
getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;
getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;
};
elasticsearch: {
client: IScopedClusterClient;
legacy: {
client: ILegacyScopedClusterClient;
};
};
uiSettings: {
client: IUiSettingsClient;
};
} | | diff --git a/src/core/server/core_route_handler_context.ts b/src/core/server/core_route_handler_context.ts index 23eed14e67c7c..85a14576795f3 100644 --- a/src/core/server/core_route_handler_context.ts +++ b/src/core/server/core_route_handler_context.ts @@ -15,6 +15,7 @@ import { ISavedObjectTypeRegistry, ISavedObjectsExporter, ISavedObjectsImporter, + SavedObjectsClientProviderOptions, } from './saved_objects'; import { InternalElasticsearchServiceStart, @@ -75,19 +76,23 @@ class CoreSavedObjectsRouteHandlerContext { return this.#typeRegistry; } - public get exporter() { + public getClient = (options?: SavedObjectsClientProviderOptions) => { + return this.savedObjectsStart.getScopedClient(this.request, options); + }; + + public getExporter = (client: SavedObjectsClientContract) => { if (this.#exporter == null) { - this.#exporter = this.savedObjectsStart.createExporter(this.client); + this.#exporter = this.savedObjectsStart.createExporter(client); } return this.#exporter; - } + }; - public get importer() { + public getImporter = (client: SavedObjectsClientContract) => { if (this.#importer == null) { - this.#importer = this.savedObjectsStart.createImporter(this.client); + this.#importer = this.savedObjectsStart.createImporter(client); } return this.#importer; - } + }; } class CoreUiSettingsRouteHandlerContext { diff --git a/src/core/server/index.ts b/src/core/server/index.ts index af6d511a58779..aebf3e3517ea2 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -49,6 +49,7 @@ import { SavedObjectsServiceStart, ISavedObjectsExporter, ISavedObjectsImporter, + SavedObjectsClientProviderOptions, } from './saved_objects'; import { CapabilitiesSetup, CapabilitiesStart } from './capabilities'; import { MetricsServiceSetup, MetricsServiceStart } from './metrics'; @@ -409,8 +410,9 @@ export interface RequestHandlerContext { savedObjects: { client: SavedObjectsClientContract; typeRegistry: ISavedObjectTypeRegistry; - exporter: ISavedObjectsExporter; - importer: ISavedObjectsImporter; + getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract; + getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter; + getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter; }; elasticsearch: { client: IScopedClusterClient; diff --git a/src/core/server/saved_objects/routes/delete.ts b/src/core/server/saved_objects/routes/delete.ts index a7846c3dc845b..eb73fb2675774 100644 --- a/src/core/server/saved_objects/routes/delete.ts +++ b/src/core/server/saved_objects/routes/delete.ts @@ -31,11 +31,20 @@ export const registerDeleteRoute = (router: IRouter, { coreUsageData }: RouteDep router.handleLegacyErrors(async (context, req, res) => { const { type, id } = req.params; const { force } = req.query; + const { getClient, typeRegistry } = context.core.savedObjects; const usageStatsClient = coreUsageData.getClient(); usageStatsClient.incrementSavedObjectsDelete({ request: req }).catch(() => {}); - const result = await context.core.savedObjects.client.delete(type, id, { force }); + const includedHiddenTypes = [type].filter( + (supportedType) => + typeRegistry.isHidden(supportedType) && + typeRegistry.isImportableAndExportable(supportedType) + ); + + const client = getClient({ includedHiddenTypes }); + + const result = await client.delete(type, id, { force }); return res.ok({ body: result }); }) ); diff --git a/src/core/server/saved_objects/routes/export.ts b/src/core/server/saved_objects/routes/export.ts index 9b40855afec2e..1dba4844eaee3 100644 --- a/src/core/server/saved_objects/routes/export.ts +++ b/src/core/server/saved_objects/routes/export.ts @@ -165,9 +165,9 @@ export const registerExportRoute = ( }, router.handleLegacyErrors(async (context, req, res) => { const cleaned = cleanOptions(req.body); - const supportedTypes = context.core.savedObjects.typeRegistry - .getImportableAndExportableTypes() - .map((t) => t.name); + const { typeRegistry, getExporter, getClient } = context.core.savedObjects; + const supportedTypes = typeRegistry.getImportableAndExportableTypes().map((t) => t.name); + let options: EitherExportOptions; try { options = validateOptions(cleaned, { @@ -181,7 +181,12 @@ export const registerExportRoute = ( }); } - const exporter = context.core.savedObjects.exporter; + const includedHiddenTypes = supportedTypes.filter((supportedType) => + typeRegistry.isHidden(supportedType) + ); + + const client = getClient({ includedHiddenTypes }); + const exporter = getExporter(client); const usageStatsClient = coreUsageData.getClient(); usageStatsClient diff --git a/src/core/server/saved_objects/routes/import.ts b/src/core/server/saved_objects/routes/import.ts index 6c4c759460ce3..796ef32b3d943 100644 --- a/src/core/server/saved_objects/routes/import.ts +++ b/src/core/server/saved_objects/routes/import.ts @@ -63,6 +63,7 @@ export const registerImportRoute = ( }, router.handleLegacyErrors(async (context, req, res) => { const { overwrite, createNewCopies } = req.query; + const { getClient, getImporter, typeRegistry } = context.core.savedObjects; const usageStatsClient = coreUsageData.getClient(); usageStatsClient @@ -84,7 +85,15 @@ export const registerImportRoute = ( }); } - const { importer } = context.core.savedObjects; + const supportedTypes = typeRegistry.getImportableAndExportableTypes().map((t) => t.name); + + const includedHiddenTypes = supportedTypes.filter((supportedType) => + typeRegistry.isHidden(supportedType) + ); + + const client = getClient({ includedHiddenTypes }); + const importer = getImporter(client); + try { const result = await importer.import({ readStream, diff --git a/src/core/server/saved_objects/routes/resolve_import_errors.ts b/src/core/server/saved_objects/routes/resolve_import_errors.ts index 0cf976c30b311..8f7f7f531b3d5 100644 --- a/src/core/server/saved_objects/routes/resolve_import_errors.ts +++ b/src/core/server/saved_objects/routes/resolve_import_errors.ts @@ -92,7 +92,18 @@ export const registerResolveImportErrorsRoute = ( }); } - const { importer } = context.core.savedObjects; + const { getClient, getImporter, typeRegistry } = context.core.savedObjects; + + const includedHiddenTypes = req.body.retries + .map((retry) => retry.type) + .filter( + (supportedType) => + typeRegistry.isHidden(supportedType) && + typeRegistry.isImportableAndExportable(supportedType) + ); + + const client = getClient({ includedHiddenTypes }); + const importer = getImporter(client); try { const result = await importer.resolveImportErrors({ diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 40a12290be31b..cc2d111ab70fd 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -1913,8 +1913,9 @@ export interface RequestHandlerContext { savedObjects: { client: SavedObjectsClientContract; typeRegistry: ISavedObjectTypeRegistry; - exporter: ISavedObjectsExporter; - importer: ISavedObjectsImporter; + getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract; + getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter; + getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter; }; elasticsearch: { client: IScopedClusterClient; diff --git a/src/plugins/home/server/services/sample_data/routes/install.ts b/src/plugins/home/server/services/sample_data/routes/install.ts index fdab390752774..28a09d159b1d0 100644 --- a/src/plugins/home/server/services/sample_data/routes/install.ts +++ b/src/plugins/home/server/services/sample_data/routes/install.ts @@ -143,7 +143,15 @@ export function createInstallRoute( let createResults; try { - createResults = await context.core.savedObjects.client.bulkCreate( + const { getClient, typeRegistry } = context.core.savedObjects; + + const includedHiddenTypes = sampleDataset.savedObjects + .map((object) => object.type) + .filter((supportedType) => typeRegistry.isHidden(supportedType)); + + const client = getClient({ includedHiddenTypes }); + + createResults = await client.bulkCreate( sampleDataset.savedObjects.map(({ version, ...savedObject }) => savedObject), { overwrite: true } ); @@ -156,8 +164,8 @@ export function createInstallRoute( return Boolean(savedObjectCreateResult.error); }); if (errors.length > 0) { - const errMsg = `sample_data install errors while loading saved objects. Errors: ${errors.join( - ',' + const errMsg = `sample_data install errors while loading saved objects. Errors: ${JSON.stringify( + errors )}`; logger.warn(errMsg); return res.customError({ body: errMsg, statusCode: 403 }); diff --git a/src/plugins/home/server/services/sample_data/routes/uninstall.ts b/src/plugins/home/server/services/sample_data/routes/uninstall.ts index 8261bbf9f8719..bd9039fdb9ef9 100644 --- a/src/plugins/home/server/services/sample_data/routes/uninstall.ts +++ b/src/plugins/home/server/services/sample_data/routes/uninstall.ts @@ -33,7 +33,7 @@ export function createUninstallRoute( client: { callAsCurrentUser }, }, }, - savedObjects: { client: savedObjectsClient }, + savedObjects: { getClient: getSavedObjectsClient, typeRegistry }, }, }, request, @@ -61,6 +61,12 @@ export function createUninstallRoute( } } + const includedHiddenTypes = sampleDataset.savedObjects + .map((object) => object.type) + .filter((supportedType) => typeRegistry.isHidden(supportedType)); + + const savedObjectsClient = getSavedObjectsClient({ includedHiddenTypes }); + const deletePromises = sampleDataset.savedObjects.map(({ type, id }) => savedObjectsClient.delete(type, id) ); diff --git a/src/plugins/saved_objects_management/server/routes/find.ts b/src/plugins/saved_objects_management/server/routes/find.ts index b5ae0198cbed1..9ff73a37c93a5 100644 --- a/src/plugins/saved_objects_management/server/routes/find.ts +++ b/src/plugins/saved_objects_management/server/routes/find.ts @@ -45,17 +45,24 @@ export const registerFindRoute = ( }, }, router.handleLegacyErrors(async (context, req, res) => { + const { query } = req; const managementService = await managementServicePromise; - const { client } = context.core.savedObjects; - const searchTypes = Array.isArray(req.query.type) ? req.query.type : [req.query.type]; - const includedFields = Array.isArray(req.query.fields) - ? req.query.fields - : [req.query.fields]; + const { getClient } = context.core.savedObjects; + + const searchTypes = Array.isArray(query.type) ? query.type : [query.type]; + const includedFields = Array.isArray(query.fields) ? query.fields : [query.fields]; + const importAndExportableTypes = searchTypes.filter((type) => managementService.isImportAndExportable(type) ); + const includedHiddenTypes = importAndExportableTypes.filter((type) => + managementService.isHidden(type) + ); + + const client = getClient({ includedHiddenTypes }); const searchFields = new Set(); + importAndExportableTypes.forEach((type) => { const searchField = managementService.getDefaultSearchField(type); if (searchField) { @@ -64,7 +71,7 @@ export const registerFindRoute = ( }); const findResponse = await client.find({ - ...req.query, + ...query, fields: undefined, searchFields: [...searchFields], }); diff --git a/src/plugins/saved_objects_management/server/services/management.ts b/src/plugins/saved_objects_management/server/services/management.ts index 1ba16f1113403..7d82f182ab29d 100644 --- a/src/plugins/saved_objects_management/server/services/management.ts +++ b/src/plugins/saved_objects_management/server/services/management.ts @@ -18,6 +18,10 @@ export class SavedObjectsManagement { return this.registry.isImportableAndExportable(type); } + public isHidden(type: string) { + return this.registry.isHidden(type); + } + public getDefaultSearchField(type: string) { return this.registry.getType(type)?.management?.defaultSearchField; } diff --git a/x-pack/plugins/actions/server/saved_objects/index.ts b/x-pack/plugins/actions/server/saved_objects/index.ts index db811e7cd3a4f..aa6bfdd4bd674 100644 --- a/x-pack/plugins/actions/server/saved_objects/index.ts +++ b/x-pack/plugins/actions/server/saved_objects/index.ts @@ -23,6 +23,12 @@ export function setupSavedObjects( namespaceType: 'single', mappings: mappings.action, migrations: getMigrations(encryptedSavedObjects), + management: { + importableAndExportable: true, + icon: 'tokenEvent', + defaultSearchField: 'name', + getTitle: ({ attributes }) => attributes.name, + }, }); // Encrypted attributes diff --git a/x-pack/plugins/alerts/server/saved_objects/index.ts b/x-pack/plugins/alerts/server/saved_objects/index.ts index dfe122f56bc48..cfd615e3e5f1e 100644 --- a/x-pack/plugins/alerts/server/saved_objects/index.ts +++ b/x-pack/plugins/alerts/server/saved_objects/index.ts @@ -42,6 +42,12 @@ export function setupSavedObjects( namespaceType: 'single', migrations: getMigrations(encryptedSavedObjects), mappings: mappings.alert, + management: { + importableAndExportable: true, + icon: 'alert', + defaultSearchField: 'name', + getTitle: ({ attributes }) => attributes.name, + }, }); savedObjects.registerType({ diff --git a/x-pack/plugins/features/server/plugin.ts b/x-pack/plugins/features/server/plugin.ts index c3e2ad06fb85c..aa45412173f5a 100644 --- a/x-pack/plugins/features/server/plugin.ts +++ b/x-pack/plugins/features/server/plugin.ts @@ -113,7 +113,7 @@ export class Plugin { private registerOssFeatures(savedObjects: SavedObjectsServiceStart) { const registry = savedObjects.getTypeRegistry(); - const savedObjectTypes = registry.getVisibleTypes().map((t) => t.name); + const savedObjectTypes = registry.getImportableAndExportableTypes().map((t) => t.name); this.logger.debug( `Registering OSS features with SO types: ${savedObjectTypes.join(', ')}. "includeTimelion": ${ From c6c6719fc4a04f81180e5327656d6674c9fa02e2 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Wed, 3 Feb 2021 16:46:02 +0200 Subject: [PATCH 02/14] revert testing changes --- x-pack/plugins/actions/server/saved_objects/index.ts | 6 ------ x-pack/plugins/alerts/server/saved_objects/index.ts | 6 ------ 2 files changed, 12 deletions(-) diff --git a/x-pack/plugins/actions/server/saved_objects/index.ts b/x-pack/plugins/actions/server/saved_objects/index.ts index aa6bfdd4bd674..db811e7cd3a4f 100644 --- a/x-pack/plugins/actions/server/saved_objects/index.ts +++ b/x-pack/plugins/actions/server/saved_objects/index.ts @@ -23,12 +23,6 @@ export function setupSavedObjects( namespaceType: 'single', mappings: mappings.action, migrations: getMigrations(encryptedSavedObjects), - management: { - importableAndExportable: true, - icon: 'tokenEvent', - defaultSearchField: 'name', - getTitle: ({ attributes }) => attributes.name, - }, }); // Encrypted attributes diff --git a/x-pack/plugins/alerts/server/saved_objects/index.ts b/x-pack/plugins/alerts/server/saved_objects/index.ts index cfd615e3e5f1e..dfe122f56bc48 100644 --- a/x-pack/plugins/alerts/server/saved_objects/index.ts +++ b/x-pack/plugins/alerts/server/saved_objects/index.ts @@ -42,12 +42,6 @@ export function setupSavedObjects( namespaceType: 'single', migrations: getMigrations(encryptedSavedObjects), mappings: mappings.alert, - management: { - importableAndExportable: true, - icon: 'alert', - defaultSearchField: 'name', - getTitle: ({ attributes }) => attributes.name, - }, }); savedObjects.registerType({ From 98236392cfbb8ffe1ac7d9b14f306c2ada1df821 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Fri, 5 Feb 2021 15:58:07 +0200 Subject: [PATCH 03/14] some code review fixes --- src/core/server/core_route_handler_context.ts | 12 ++---------- .../saved_objects/routes/resolve_import_errors.ts | 13 +++++++------ x-pack/plugins/features/server/plugin.ts | 2 +- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/core/server/core_route_handler_context.ts b/src/core/server/core_route_handler_context.ts index 85a14576795f3..938196c2e1b48 100644 --- a/src/core/server/core_route_handler_context.ts +++ b/src/core/server/core_route_handler_context.ts @@ -59,8 +59,6 @@ class CoreSavedObjectsRouteHandlerContext { ) {} #scopedSavedObjectsClient?: SavedObjectsClientContract; #typeRegistry?: ISavedObjectTypeRegistry; - #exporter?: ISavedObjectsExporter; - #importer?: ISavedObjectsImporter; public get client() { if (this.#scopedSavedObjectsClient == null) { @@ -81,17 +79,11 @@ class CoreSavedObjectsRouteHandlerContext { }; public getExporter = (client: SavedObjectsClientContract) => { - if (this.#exporter == null) { - this.#exporter = this.savedObjectsStart.createExporter(client); - } - return this.#exporter; + return this.savedObjectsStart.createExporter(client); }; public getImporter = (client: SavedObjectsClientContract) => { - if (this.#importer == null) { - this.#importer = this.savedObjectsStart.createImporter(client); - } - return this.#importer; + return this.savedObjectsStart.createImporter(client); }; } diff --git a/src/core/server/saved_objects/routes/resolve_import_errors.ts b/src/core/server/saved_objects/routes/resolve_import_errors.ts index 8f7f7f531b3d5..e914635e73081 100644 --- a/src/core/server/saved_objects/routes/resolve_import_errors.ts +++ b/src/core/server/saved_objects/routes/resolve_import_errors.ts @@ -9,6 +9,7 @@ import { extname } from 'path'; import { Readable } from 'stream'; import { schema } from '@kbn/config-schema'; +import { chain } from 'lodash'; import { IRouter } from '../../http'; import { CoreUsageDataSetup } from '../../core_usage_data'; import { SavedObjectConfig } from '../saved_objects_config'; @@ -94,13 +95,13 @@ export const registerResolveImportErrorsRoute = ( const { getClient, getImporter, typeRegistry } = context.core.savedObjects; - const includedHiddenTypes = req.body.retries - .map((retry) => retry.type) + const includedHiddenTypes = chain(req.body.retries) + .map('type') + .uniq() .filter( - (supportedType) => - typeRegistry.isHidden(supportedType) && - typeRegistry.isImportableAndExportable(supportedType) - ); + (type) => typeRegistry.isHidden(type) && typeRegistry.isImportableAndExportable(type) + ) + .value(); const client = getClient({ includedHiddenTypes }); const importer = getImporter(client); diff --git a/x-pack/plugins/features/server/plugin.ts b/x-pack/plugins/features/server/plugin.ts index aa45412173f5a..c3e2ad06fb85c 100644 --- a/x-pack/plugins/features/server/plugin.ts +++ b/x-pack/plugins/features/server/plugin.ts @@ -113,7 +113,7 @@ export class Plugin { private registerOssFeatures(savedObjects: SavedObjectsServiceStart) { const registry = savedObjects.getTypeRegistry(); - const savedObjectTypes = registry.getImportableAndExportableTypes().map((t) => t.name); + const savedObjectTypes = registry.getVisibleTypes().map((t) => t.name); this.logger.debug( `Registering OSS features with SO types: ${savedObjectTypes.join(', ')}. "includeTimelion": ${ From d5a6ffa5fb092b84dcd0fde5a267c045f4ed9b8f Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Fri, 5 Feb 2021 18:00:06 +0200 Subject: [PATCH 04/14] remove unused types --- src/core/server/core_route_handler_context.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/server/core_route_handler_context.ts b/src/core/server/core_route_handler_context.ts index 938196c2e1b48..9b5a01589c42d 100644 --- a/src/core/server/core_route_handler_context.ts +++ b/src/core/server/core_route_handler_context.ts @@ -13,8 +13,6 @@ import { SavedObjectsClientContract } from './saved_objects/types'; import { InternalSavedObjectsServiceStart, ISavedObjectTypeRegistry, - ISavedObjectsExporter, - ISavedObjectsImporter, SavedObjectsClientProviderOptions, } from './saved_objects'; import { From cd3d2c313469f8378e4aead0dfdde063f8f80835 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sat, 6 Feb 2021 14:27:47 +0200 Subject: [PATCH 05/14] pr review updates + cleanup --- src/core/server/mocks.ts | 5 ++-- .../server/saved_objects/routes/delete.ts | 11 ++------- .../routes/integration_tests/export.test.ts | 2 +- .../routes/integration_tests/import.test.ts | 6 ++--- .../resolve_import_errors.test.ts | 6 ++--- .../server/routes/find.ts | 6 ++--- .../server/routes/scroll_count.ts | 24 +++++++++++++------ .../server/routes/scroll_export.ts | 15 ++++++++++-- .../server/services/management.ts | 4 ---- 9 files changed, 45 insertions(+), 34 deletions(-) diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index a4ce94b177612..19056ae1b9bc7 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -196,8 +196,9 @@ function createCoreRequestHandlerContextMock() { savedObjects: { client: savedObjectsClientMock.create(), typeRegistry: savedObjectsTypeRegistryMock.create(), - exporter: savedObjectsServiceMock.createExporter(), - importer: savedObjectsServiceMock.createImporter(), + getClient: savedObjectsClientMock.create, + getExporter: savedObjectsServiceMock.createExporter, + getImporter: savedObjectsServiceMock.createImporter, }, elasticsearch: { client: elasticsearchServiceMock.createScopedClusterClient(), diff --git a/src/core/server/saved_objects/routes/delete.ts b/src/core/server/saved_objects/routes/delete.ts index a462fe12e2459..5f5f522080629 100644 --- a/src/core/server/saved_objects/routes/delete.ts +++ b/src/core/server/saved_objects/routes/delete.ts @@ -31,19 +31,12 @@ export const registerDeleteRoute = (router: IRouter, { coreUsageData }: RouteDep router.handleLegacyErrors(async (context, req, res) => { const { type, id } = req.params; const { force } = req.query; - const { getClient, typeRegistry } = context.core.savedObjects; + const { getClient } = context.core.savedObjects; const usageStatsClient = coreUsageData.getClient(); usageStatsClient.incrementSavedObjectsDelete({ request: req }).catch(() => {}); - const includedHiddenTypes = [type].filter( - (supportedType) => - typeRegistry.isHidden(supportedType) && - typeRegistry.isImportableAndExportable(supportedType) - ); - - const client = getClient({ includedHiddenTypes }); - + const client = getClient(); const result = await client.delete(type, id, { force }); return res.ok({ body: result }); }) diff --git a/src/core/server/saved_objects/routes/integration_tests/export.test.ts b/src/core/server/saved_objects/routes/integration_tests/export.test.ts index 40f13064b53f0..5db0d62b6a691 100644 --- a/src/core/server/saved_objects/routes/integration_tests/export.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/export.test.ts @@ -40,7 +40,7 @@ describe('POST /api/saved_objects/_export', () => { handlerContext.savedObjects.typeRegistry.getImportableAndExportableTypes.mockReturnValue( allowedTypes.map(createExportableType) ); - exporter = handlerContext.savedObjects.exporter; + exporter = handlerContext.savedObjects.getExporter(); const router = httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); diff --git a/src/core/server/saved_objects/routes/integration_tests/import.test.ts b/src/core/server/saved_objects/routes/integration_tests/import.test.ts index 24122c61c9f42..600dde138fa36 100644 --- a/src/core/server/saved_objects/routes/integration_tests/import.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/import.test.ts @@ -68,9 +68,9 @@ describe(`POST ${URL}`, () => { typeRegistry: handlerContext.savedObjects.typeRegistry, importSizeLimit: 10000, }); - handlerContext.savedObjects.importer.import.mockImplementation((options) => - importer.import(options) - ); + handlerContext.savedObjects + .getImporter() + .import.mockImplementation((options) => importer.import(options)); const router = httpSetup.createRouter('/internal/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); diff --git a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts index b23211aef092f..653927c0dd4d5 100644 --- a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts @@ -74,9 +74,9 @@ describe(`POST ${URL}`, () => { typeRegistry: handlerContext.savedObjects.typeRegistry, importSizeLimit: 10000, }); - handlerContext.savedObjects.importer.resolveImportErrors.mockImplementation((options) => - importer.resolveImportErrors(options) - ); + handlerContext.savedObjects + .getImporter() + .resolveImportErrors.mockImplementation((options) => importer.resolveImportErrors(options)); const router = httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); diff --git a/src/plugins/saved_objects_management/server/routes/find.ts b/src/plugins/saved_objects_management/server/routes/find.ts index a49e42d3d2573..45fbd311c2ee0 100644 --- a/src/plugins/saved_objects_management/server/routes/find.ts +++ b/src/plugins/saved_objects_management/server/routes/find.ts @@ -47,17 +47,17 @@ export const registerFindRoute = ( router.handleLegacyErrors(async (context, req, res) => { const { query } = req; const managementService = await managementServicePromise; - const { getClient } = context.core.savedObjects; + const { getClient, typeRegistry } = context.core.savedObjects; const searchTypes = Array.isArray(query.type) ? query.type : [query.type]; const includedFields = Array.isArray(query.fields) ? query.fields : [query.fields]; const importAndExportableTypes = searchTypes.filter((type) => - managementService.isImportAndExportable(type) + typeRegistry.isImportableAndExportable(type) ); const includedHiddenTypes = importAndExportableTypes.filter((type) => - managementService.isHidden(type) + typeRegistry.isHidden(type) ); const client = getClient({ includedHiddenTypes }); diff --git a/src/plugins/saved_objects_management/server/routes/scroll_count.ts b/src/plugins/saved_objects_management/server/routes/scroll_count.ts index dfe361e7b9649..89a895adf6008 100644 --- a/src/plugins/saved_objects_management/server/routes/scroll_count.ts +++ b/src/plugins/saved_objects_management/server/routes/scroll_count.ts @@ -8,6 +8,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter, SavedObjectsFindOptions } from 'src/core/server'; +import { chain } from 'lodash'; import { findAll } from '../lib'; export const registerScrollForCountRoute = (router: IRouter) => { @@ -30,18 +31,27 @@ export const registerScrollForCountRoute = (router: IRouter) => { }, }, router.handleLegacyErrors(async (context, req, res) => { - const { client } = context.core.savedObjects; + const { getClient, typeRegistry } = context.core.savedObjects; + const { typesToInclude, searchString, references } = req.body; + const includedHiddenTypes = chain(typesToInclude) + .uniq() + .filter( + (type) => typeRegistry.isHidden(type) && typeRegistry.isImportableAndExportable(type) + ) + .value(); + + const client = getClient({ includedHiddenTypes }); const findOptions: SavedObjectsFindOptions = { - type: req.body.typesToInclude, + type: typesToInclude, perPage: 1000, }; - if (req.body.searchString) { - findOptions.search = `${req.body.searchString}*`; + if (searchString) { + findOptions.search = `${searchString}*`; findOptions.searchFields = ['title']; } - if (req.body.references) { - findOptions.hasReference = req.body.references; + if (references) { + findOptions.hasReference = references; findOptions.hasReferenceOperator = 'OR'; } @@ -54,7 +64,7 @@ export const registerScrollForCountRoute = (router: IRouter) => { return accum; }, {} as Record); - for (const type of req.body.typesToInclude) { + for (const type of typesToInclude) { if (!counts[type]) { counts[type] = 0; } diff --git a/src/plugins/saved_objects_management/server/routes/scroll_export.ts b/src/plugins/saved_objects_management/server/routes/scroll_export.ts index 3417efa709e5f..8d11437af661b 100644 --- a/src/plugins/saved_objects_management/server/routes/scroll_export.ts +++ b/src/plugins/saved_objects_management/server/routes/scroll_export.ts @@ -8,6 +8,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from 'src/core/server'; +import { chain } from 'lodash'; import { findAll } from '../lib'; export const registerScrollForExportRoute = (router: IRouter) => { @@ -21,10 +22,20 @@ export const registerScrollForExportRoute = (router: IRouter) => { }, }, router.handleLegacyErrors(async (context, req, res) => { - const { client } = context.core.savedObjects; + const { typesToInclude } = req.body; + const { getClient, typeRegistry } = context.core.savedObjects; + const includedHiddenTypes = chain(typesToInclude) + .uniq() + .filter( + (type) => typeRegistry.isHidden(type) && typeRegistry.isImportableAndExportable(type) + ) + .value(); + + const client = getClient({ includedHiddenTypes }); + const objects = await findAll(client, { perPage: 1000, - type: req.body.typesToInclude, + type: typesToInclude, }); return res.ok({ diff --git a/src/plugins/saved_objects_management/server/services/management.ts b/src/plugins/saved_objects_management/server/services/management.ts index 8755b59f8e59d..395ba639846a8 100644 --- a/src/plugins/saved_objects_management/server/services/management.ts +++ b/src/plugins/saved_objects_management/server/services/management.ts @@ -18,10 +18,6 @@ export class SavedObjectsManagement { return this.registry.isImportableAndExportable(type); } - public isHidden(type: string) { - return this.registry.isHidden(type); - } - public getDefaultSearchField(type: string) { return this.registry.getType(type)?.management?.defaultSearchField; } From 36143d197554967489b02165ddb6bfd79508c5d6 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Mon, 8 Feb 2021 13:42:22 +0200 Subject: [PATCH 06/14] update all SOM routes to show includedHiddenTypes --- .../export/saved_objects_exporter.mock.ts | 4 ++-- .../import/saved_objects_importer.mock.ts | 4 ++-- .../routes/integration_tests/delete.test.ts | 3 ++- .../routes/integration_tests/export.test.ts | 5 +++++ .../routes/integration_tests/import.test.ts | 6 +++--- .../resolve_import_errors.test.ts | 6 +++--- .../service/saved_objects_client.mock.ts | 9 ++++++--- .../server/routes/get.ts | 8 ++++++-- .../server/routes/relationships.ts | 20 ++++++++++++++----- 9 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/core/server/saved_objects/export/saved_objects_exporter.mock.ts b/src/core/server/saved_objects/export/saved_objects_exporter.mock.ts index 1186f0ce9b20c..5217d311e5996 100644 --- a/src/core/server/saved_objects/export/saved_objects_exporter.mock.ts +++ b/src/core/server/saved_objects/export/saved_objects_exporter.mock.ts @@ -8,14 +8,14 @@ import { ISavedObjectsExporter } from './saved_objects_exporter'; -const createExporterMock = () => { +const createExporterMock = jest.fn(() => { const mock: jest.Mocked = { exportByObjects: jest.fn(), exportByTypes: jest.fn(), }; return mock; -}; +}); export const savedObjectsExporterMock = { create: createExporterMock, diff --git a/src/core/server/saved_objects/import/saved_objects_importer.mock.ts b/src/core/server/saved_objects/import/saved_objects_importer.mock.ts index 9f2d79c997a38..18b4f0ff26487 100644 --- a/src/core/server/saved_objects/import/saved_objects_importer.mock.ts +++ b/src/core/server/saved_objects/import/saved_objects_importer.mock.ts @@ -8,14 +8,14 @@ import { ISavedObjectsImporter } from './saved_objects_importer'; -const createImporterMock = () => { +const createImporterMock = jest.fn(() => { const mock: jest.Mocked = { import: jest.fn(), resolveImportErrors: jest.fn(), }; return mock; -}; +}); export const savedObjectsImporterMock = { create: createImporterMock, diff --git a/src/core/server/saved_objects/routes/integration_tests/delete.test.ts b/src/core/server/saved_objects/routes/integration_tests/delete.test.ts index 7b7a71b7ca858..60382d3bce34f 100644 --- a/src/core/server/saved_objects/routes/integration_tests/delete.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/delete.test.ts @@ -26,7 +26,8 @@ describe('DELETE /api/saved_objects/{type}/{id}', () => { beforeEach(async () => { ({ server, httpSetup, handlerContext } = await setupServer()); - savedObjectsClient = handlerContext.savedObjects.client; + savedObjectsClient = handlerContext.savedObjects.getClient(); + handlerContext.savedObjects.getClient.mockImplementation(() => savedObjectsClient); const router = httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); diff --git a/src/core/server/saved_objects/routes/integration_tests/export.test.ts b/src/core/server/saved_objects/routes/integration_tests/export.test.ts index 5db0d62b6a691..ec95c57fc4b88 100644 --- a/src/core/server/saved_objects/routes/integration_tests/export.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/export.test.ts @@ -43,6 +43,10 @@ describe('POST /api/saved_objects/_export', () => { exporter = handlerContext.savedObjects.getExporter(); const router = httpSetup.createRouter('/api/saved_objects/'); + handlerContext.savedObjects.getExporter.mockImplementation( + () => exporter as ReturnType + ); + coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsExport.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); @@ -77,6 +81,7 @@ describe('POST /api/saved_objects/_export', () => { ], }, ]; + exporter.exportByTypes.mockResolvedValueOnce(createListStream(sortedObjects)); const result = await supertest(httpSetup.server.listener) diff --git a/src/core/server/saved_objects/routes/integration_tests/import.test.ts b/src/core/server/saved_objects/routes/integration_tests/import.test.ts index 600dde138fa36..76aa49c60aaef 100644 --- a/src/core/server/saved_objects/routes/integration_tests/import.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/import.test.ts @@ -68,9 +68,9 @@ describe(`POST ${URL}`, () => { typeRegistry: handlerContext.savedObjects.typeRegistry, importSizeLimit: 10000, }); - handlerContext.savedObjects - .getImporter() - .import.mockImplementation((options) => importer.import(options)); + handlerContext.savedObjects.getImporter.mockImplementation( + () => importer as jest.Mocked + ); const router = httpSetup.createRouter('/internal/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); diff --git a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts index 653927c0dd4d5..5c371494a8387 100644 --- a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts @@ -74,9 +74,9 @@ describe(`POST ${URL}`, () => { typeRegistry: handlerContext.savedObjects.typeRegistry, importSizeLimit: 10000, }); - handlerContext.savedObjects - .getImporter() - .resolveImportErrors.mockImplementation((options) => importer.resolveImportErrors(options)); + handlerContext.savedObjects.getImporter.mockImplementation( + () => importer as jest.Mocked + ); const router = httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); diff --git a/src/core/server/saved_objects/service/saved_objects_client.mock.ts b/src/core/server/saved_objects/service/saved_objects_client.mock.ts index 72f5561aa7027..ab81992f8e149 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.mock.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.mock.ts @@ -9,8 +9,8 @@ import { SavedObjectsClientContract } from '../types'; import { SavedObjectsErrorHelpers } from './lib/errors'; -const create = () => - (({ +const create = jest.fn(() => { + const mocked = ({ errors: SavedObjectsErrorHelpers, create: jest.fn(), bulkCreate: jest.fn(), @@ -25,6 +25,9 @@ const create = () => addToNamespaces: jest.fn(), deleteFromNamespaces: jest.fn(), removeReferencesTo: jest.fn(), - } as unknown) as jest.Mocked); + } as unknown) as jest.Mocked; + + return mocked; +}); export const savedObjectsClientMock = { create }; diff --git a/src/plugins/saved_objects_management/server/routes/get.ts b/src/plugins/saved_objects_management/server/routes/get.ts index 1e0115db9e43c..5a48f2f2affa7 100644 --- a/src/plugins/saved_objects_management/server/routes/get.ts +++ b/src/plugins/saved_objects_management/server/routes/get.ts @@ -26,10 +26,14 @@ export const registerGetRoute = ( }, }, router.handleLegacyErrors(async (context, req, res) => { + const { type, id } = req.params; const managementService = await managementServicePromise; - const { client } = context.core.savedObjects; + const { getClient, typeRegistry } = context.core.savedObjects; + const includedHiddenTypes = [type].filter( + (entry) => typeRegistry.isHidden(entry) && typeRegistry.isImportableAndExportable(entry) + ); - const { type, id } = req.params; + const client = getClient({ includedHiddenTypes }); const findResponse = await client.get(type, id); const enhancedSavedObject = injectMetaAttributes(findResponse, managementService); diff --git a/src/plugins/saved_objects_management/server/routes/relationships.ts b/src/plugins/saved_objects_management/server/routes/relationships.ts index 5e30f49cde67f..9e2c2031d8abd 100644 --- a/src/plugins/saved_objects_management/server/routes/relationships.ts +++ b/src/plugins/saved_objects_management/server/routes/relationships.ts @@ -8,6 +8,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from 'src/core/server'; +import { chain } from 'lodash'; import { findRelationships } from '../lib'; import { ISavedObjectsManagement } from '../services'; @@ -31,12 +32,21 @@ export const registerRelationshipsRoute = ( }, router.handleLegacyErrors(async (context, req, res) => { const managementService = await managementServicePromise; - const { client } = context.core.savedObjects; + const { getClient, typeRegistry } = context.core.savedObjects; const { type, id } = req.params; - const { size } = req.query; - const savedObjectTypes = Array.isArray(req.query.savedObjectTypes) - ? req.query.savedObjectTypes - : [req.query.savedObjectTypes]; + const { size, savedObjectTypes: maybeArraySavedObjectTypes } = req.query; + const savedObjectTypes = Array.isArray(maybeArraySavedObjectTypes) + ? maybeArraySavedObjectTypes + : [maybeArraySavedObjectTypes]; + + const includedHiddenTypes = chain(maybeArraySavedObjectTypes) + .uniq() + .filter( + (entry) => typeRegistry.isHidden(entry) && typeRegistry.isImportableAndExportable(entry) + ) + .value(); + + const client = getClient({ includedHiddenTypes }); const findRelationsResponse = await findRelationships({ type, From 55a6974e48be0367c800e294603003f9db61ad9c Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Mon, 8 Feb 2021 17:35:31 +0200 Subject: [PATCH 07/14] fix tests --- .../saved_objects/export/saved_objects_exporter.mock.ts | 4 ++-- .../saved_objects/import/saved_objects_importer.mock.ts | 4 ++-- .../routes/integration_tests/delete.test.ts | 2 +- .../routes/integration_tests/export.test.ts | 6 +++--- .../routes/integration_tests/import.test.ts | 6 +++--- .../integration_tests/resolve_import_errors.test.ts | 9 +++++---- .../saved_objects/service/saved_objects_client.mock.ts | 9 +++------ 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/core/server/saved_objects/export/saved_objects_exporter.mock.ts b/src/core/server/saved_objects/export/saved_objects_exporter.mock.ts index 5217d311e5996..1186f0ce9b20c 100644 --- a/src/core/server/saved_objects/export/saved_objects_exporter.mock.ts +++ b/src/core/server/saved_objects/export/saved_objects_exporter.mock.ts @@ -8,14 +8,14 @@ import { ISavedObjectsExporter } from './saved_objects_exporter'; -const createExporterMock = jest.fn(() => { +const createExporterMock = () => { const mock: jest.Mocked = { exportByObjects: jest.fn(), exportByTypes: jest.fn(), }; return mock; -}); +}; export const savedObjectsExporterMock = { create: createExporterMock, diff --git a/src/core/server/saved_objects/import/saved_objects_importer.mock.ts b/src/core/server/saved_objects/import/saved_objects_importer.mock.ts index 18b4f0ff26487..9f2d79c997a38 100644 --- a/src/core/server/saved_objects/import/saved_objects_importer.mock.ts +++ b/src/core/server/saved_objects/import/saved_objects_importer.mock.ts @@ -8,14 +8,14 @@ import { ISavedObjectsImporter } from './saved_objects_importer'; -const createImporterMock = jest.fn(() => { +const createImporterMock = () => { const mock: jest.Mocked = { import: jest.fn(), resolveImportErrors: jest.fn(), }; return mock; -}); +}; export const savedObjectsImporterMock = { create: createImporterMock, diff --git a/src/core/server/saved_objects/routes/integration_tests/delete.test.ts b/src/core/server/saved_objects/routes/integration_tests/delete.test.ts index 60382d3bce34f..eaec6e16cbd8c 100644 --- a/src/core/server/saved_objects/routes/integration_tests/delete.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/delete.test.ts @@ -27,7 +27,7 @@ describe('DELETE /api/saved_objects/{type}/{id}', () => { beforeEach(async () => { ({ server, httpSetup, handlerContext } = await setupServer()); savedObjectsClient = handlerContext.savedObjects.getClient(); - handlerContext.savedObjects.getClient.mockImplementation(() => savedObjectsClient); + handlerContext.savedObjects.getClient = jest.fn().mockImplementation(() => savedObjectsClient); const router = httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); diff --git a/src/core/server/saved_objects/routes/integration_tests/export.test.ts b/src/core/server/saved_objects/routes/integration_tests/export.test.ts index ec95c57fc4b88..09d475f29f362 100644 --- a/src/core/server/saved_objects/routes/integration_tests/export.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/export.test.ts @@ -43,9 +43,9 @@ describe('POST /api/saved_objects/_export', () => { exporter = handlerContext.savedObjects.getExporter(); const router = httpSetup.createRouter('/api/saved_objects/'); - handlerContext.savedObjects.getExporter.mockImplementation( - () => exporter as ReturnType - ); + handlerContext.savedObjects.getExporter = jest + .fn() + .mockImplementation(() => exporter as ReturnType); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsExport.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail diff --git a/src/core/server/saved_objects/routes/integration_tests/import.test.ts b/src/core/server/saved_objects/routes/integration_tests/import.test.ts index 76aa49c60aaef..be4d2160a967b 100644 --- a/src/core/server/saved_objects/routes/integration_tests/import.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/import.test.ts @@ -68,9 +68,9 @@ describe(`POST ${URL}`, () => { typeRegistry: handlerContext.savedObjects.typeRegistry, importSizeLimit: 10000, }); - handlerContext.savedObjects.getImporter.mockImplementation( - () => importer as jest.Mocked - ); + handlerContext.savedObjects.getImporter = jest + .fn() + .mockImplementation(() => importer as jest.Mocked); const router = httpSetup.createRouter('/internal/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); diff --git a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts index 5c371494a8387..d84b56156b543 100644 --- a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts @@ -66,7 +66,7 @@ describe(`POST ${URL}`, () => { } as any) ); - savedObjectsClient = handlerContext.savedObjects.client; + savedObjectsClient = handlerContext.savedObjects.getClient(); savedObjectsClient.checkConflicts.mockResolvedValue({ errors: [] }); const importer = new SavedObjectsImporter({ @@ -74,9 +74,10 @@ describe(`POST ${URL}`, () => { typeRegistry: handlerContext.savedObjects.typeRegistry, importSizeLimit: 10000, }); - handlerContext.savedObjects.getImporter.mockImplementation( - () => importer as jest.Mocked - ); + + handlerContext.savedObjects.getImporter = jest + .fn() + .mockImplementation(() => importer as jest.Mocked); const router = httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); diff --git a/src/core/server/saved_objects/service/saved_objects_client.mock.ts b/src/core/server/saved_objects/service/saved_objects_client.mock.ts index ab81992f8e149..72f5561aa7027 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.mock.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.mock.ts @@ -9,8 +9,8 @@ import { SavedObjectsClientContract } from '../types'; import { SavedObjectsErrorHelpers } from './lib/errors'; -const create = jest.fn(() => { - const mocked = ({ +const create = () => + (({ errors: SavedObjectsErrorHelpers, create: jest.fn(), bulkCreate: jest.fn(), @@ -25,9 +25,6 @@ const create = jest.fn(() => { addToNamespaces: jest.fn(), deleteFromNamespaces: jest.fn(), removeReferencesTo: jest.fn(), - } as unknown) as jest.Mocked; - - return mocked; -}); + } as unknown) as jest.Mocked); export const savedObjectsClientMock = { create }; From 3b83707506cfcff11f0bbf56e55a8cdd3b45939a Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 11 Feb 2021 12:27:36 +0200 Subject: [PATCH 08/14] add ftr tests --- .../apis/saved_objects/delete.ts | 32 +++++++ .../apis/saved_objects/export.ts | 31 +++++++ .../apis/saved_objects/find.ts | 30 ++++++- .../apis/saved_objects/import.ts | 60 +++++++++++++ .../saved_objects/resolve_import_errors.ts | 84 ++++++++++++++++++ .../apis/saved_objects_management/find.ts | 48 +++++++++- .../apis/saved_objects_management/get.ts | 21 +++++ .../saved_objects_management/scroll_count.ts | 17 ++++ .../saved_objects/scroll_count/data.json.gz | Bin 1295 -> 1454 bytes .../saved_objects/scroll_count/mappings.json | 14 +++ .../saved_objects/basic/data.json.gz | Bin 2038 -> 2246 bytes .../saved_objects/basic/mappings.json | 14 +++ test/common/config.js | 7 ++ .../kibana.json | 8 ++ .../package.json | 14 +++ .../server/index.ts | 11 +++ .../server/plugin.ts | 44 +++++++++ .../tsconfig.json | 16 ++++ 18 files changed, 449 insertions(+), 2 deletions(-) create mode 100644 test/common/fixtures/plugins/test_saved_objects_hidden_type/kibana.json create mode 100644 test/common/fixtures/plugins/test_saved_objects_hidden_type/package.json create mode 100644 test/common/fixtures/plugins/test_saved_objects_hidden_type/server/index.ts create mode 100644 test/common/fixtures/plugins/test_saved_objects_hidden_type/server/plugin.ts create mode 100644 test/common/fixtures/plugins/test_saved_objects_hidden_type/tsconfig.json diff --git a/test/api_integration/apis/saved_objects/delete.ts b/test/api_integration/apis/saved_objects/delete.ts index 0dfece825d3a1..81ad810720689 100644 --- a/test/api_integration/apis/saved_objects/delete.ts +++ b/test/api_integration/apis/saved_objects/delete.ts @@ -38,6 +38,38 @@ export default function ({ getService }: FtrProviderContext) { message: 'Saved object [dashboard/not-a-real-id] not found', }); })); + + describe('hidden saved object types', () => { + it('should return generic 404 when trying to delete a doc with importableAndExportable types', async () => + await supertest + .delete( + `/api/saved_objects/test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab` + ) + .expect(404) + .then((resp) => { + expect(resp.body).to.eql({ + statusCode: 404, + error: 'Not Found', + message: + 'Saved object [test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab] not found', + }); + })); + + it('returns empty response for non importableAndExportable types', async () => + await supertest + .delete( + `/api/saved_objects/test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc` + ) + .expect(404) + .then((resp) => { + expect(resp.body).to.eql({ + statusCode: 404, + error: 'Not Found', + message: + 'Saved object [test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc] not found', + }); + })); + }); }); describe('without kibana index', () => { diff --git a/test/api_integration/apis/saved_objects/export.ts b/test/api_integration/apis/saved_objects/export.ts index 5206d51054745..62690330655c8 100644 --- a/test/api_integration/apis/saved_objects/export.ts +++ b/test/api_integration/apis/saved_objects/export.ts @@ -181,6 +181,37 @@ export default function ({ getService }: FtrProviderContext) { }); }); + describe('hidden saved object types', () => { + it('returns objects with importableAndExportable types', async () => + await supertest + .post('/api/saved_objects/_export') + .send({ + type: ['test-hidden-importable-exportable'], + }) + .expect(200) + .then((resp) => { + const objects = ndjsonToObject(resp.text); + expect(objects).to.have.length(2); + expect(objects[0]).to.have.property('id', 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab'); + expect(objects[0]).to.have.property('type', 'test-hidden-importable-exportable'); + })); + + it('excludes objects with non importableAndExportable types', async () => + await supertest + .post('/api/saved_objects/_export') + .send({ + type: ['test-hidden-non-importable-exportable'], + }) + .then((resp) => { + expect(resp.body).to.eql({ + statusCode: 400, + error: 'Bad Request', + message: + 'Trying to export non-exportable type(s): test-hidden-non-importable-exportable', + }); + })); + }); + it(`should return 400 when exporting unsupported type`, async () => { await supertest .post('/api/saved_objects/_export') diff --git a/test/api_integration/apis/saved_objects/find.ts b/test/api_integration/apis/saved_objects/find.ts index 66c2a083c79e5..6c136bfc60729 100644 --- a/test/api_integration/apis/saved_objects/find.ts +++ b/test/api_integration/apis/saved_objects/find.ts @@ -209,7 +209,7 @@ export default function ({ getService }: FtrProviderContext) { score: 0, type: 'visualization', updated_at: '2017-09-21T18:51:23.794Z', - version: 'WzIyLDJd', + version: 'WzE4LDJd', }, ], }); @@ -294,6 +294,34 @@ export default function ({ getService }: FtrProviderContext) { })); }); + describe('hidden saved object types', () => { + it('returns empty response for importableAndExportable types', async () => + await supertest + .get('/api/saved_objects/_find?type=test-hidden-importable-exportable&fields=title') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + page: 1, + per_page: 20, + total: 0, + saved_objects: [], + }); + })); + + it('returns empty response for non importableAndExportable types', async () => + await supertest + .get('/api/saved_objects/_find?type=test-hidden-non-importable-exportable&fields=title') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + page: 1, + per_page: 20, + total: 0, + saved_objects: [], + }); + })); + }); + describe('`has_reference` and `has_reference_operator` parameters', () => { before(() => esArchiver.load('saved_objects/references')); after(() => esArchiver.unload('saved_objects/references')); diff --git a/test/api_integration/apis/saved_objects/import.ts b/test/api_integration/apis/saved_objects/import.ts index b0aa9b0eef8fc..0633f4e473e7f 100644 --- a/test/api_integration/apis/saved_objects/import.ts +++ b/test/api_integration/apis/saved_objects/import.ts @@ -164,6 +164,66 @@ export default function ({ getService }: FtrProviderContext) { }); }); + describe('hidden saved object types', () => { + it('imports objects with importableAndExportable type', async () => { + const fileBuffer = Buffer.from( + '{"id":"some-id-1","type":"test-hidden-importable-exportable","attributes":{"title":"my title"},"references":[]}', + 'utf8' + ); + await supertest + .post('/api/saved_objects/_import') + .attach('file', fileBuffer, 'export.ndjson') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + successCount: 1, + success: true, + warnings: [], + successResults: [ + { + type: 'test-hidden-importable-exportable', + id: 'some-id-1', + meta: { + title: 'my title', + }, + }, + ], + }); + }); + }); + + it('does not import objects with non importableAndExportable type', async () => { + const fileBuffer = Buffer.from( + '{"id":"some-id-1","type":"test-hidden-non-importable-exportable","attributes":{"title":"my title"},"references":[]}', + 'utf8' + ); + await supertest + .post('/api/saved_objects/_import') + .attach('file', fileBuffer, 'export.ndjson') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + successCount: 0, + success: false, + warnings: [], + errors: [ + { + id: 'some-id-1', + type: 'test-hidden-non-importable-exportable', + title: 'my title', + meta: { + title: 'my title', + }, + error: { + type: 'unsupported_type', + }, + }, + ], + }); + }); + }); + }); + it('should return 400 when trying to import more than 10,000 objects', async () => { const fileChunks = []; for (let i = 0; i < 10001; i++) { diff --git a/test/api_integration/apis/saved_objects/resolve_import_errors.ts b/test/api_integration/apis/saved_objects/resolve_import_errors.ts index b203a2c7b7071..a615ae919fdc2 100644 --- a/test/api_integration/apis/saved_objects/resolve_import_errors.ts +++ b/test/api_integration/apis/saved_objects/resolve_import_errors.ts @@ -385,6 +385,90 @@ export default function ({ getService }: FtrProviderContext) { ]); }); }); + + describe('hidden saved object types', () => { + it('resolves objects with importableAndExportable types', async () => { + const fileBuffer = Buffer.from( + '{"id":"ff3733a0-9fty-11e7-ahb3-3dcb94193fab","type":"test-hidden-importable-exportable","attributes":{"title":"new title!"},"references":[]}', + 'utf8' + ); + + await supertest + .post('/api/saved_objects/_resolve_import_errors') + .field( + 'retries', + JSON.stringify([ + { + id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab', + type: 'test-hidden-importable-exportable', + overwrite: true, + }, + ]) + ) + .attach('file', fileBuffer, 'import.ndjson') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + successCount: 1, + success: true, + warnings: [], + successResults: [ + { + type: 'test-hidden-importable-exportable', + id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab', + meta: { + title: 'new title!', + }, + overwrite: true, + }, + ], + }); + }); + }); + + it('rejects objects with non importableAndExportable types', async () => { + const fileBuffer = Buffer.from( + '{"id":"op3767a1-9rcg-53u7-jkb3-3dnb74193awc","type":"test-hidden-non-importable-exportable","attributes":{"title":"new title!"},"references":[]}', + 'utf8' + ); + + await supertest + .post('/api/saved_objects/_resolve_import_errors') + .field( + 'retries', + JSON.stringify([ + { + id: 'op3767a1-9rcg-53u7-jkb3-3dnb74193awc', + type: 'test-hidden-non-importable-exportable', + overwrite: true, + }, + ]) + ) + .attach('file', fileBuffer, 'import.ndjson') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + successCount: 0, + success: false, + warnings: [], + errors: [ + { + id: 'op3767a1-9rcg-53u7-jkb3-3dnb74193awc', + type: 'test-hidden-non-importable-exportable', + title: 'new title!', + meta: { + title: 'new title!', + }, + error: { + type: 'unsupported_type', + }, + overwrite: true, + }, + ], + }); + }); + }); + }); }); }); }); diff --git a/test/api_integration/apis/saved_objects_management/find.ts b/test/api_integration/apis/saved_objects_management/find.ts index 6ab2352ebb05f..63bd892b3ee4c 100644 --- a/test/api_integration/apis/saved_objects_management/find.ts +++ b/test/api_integration/apis/saved_objects_management/find.ts @@ -42,7 +42,7 @@ export default function ({ getService }: FtrProviderContext) { { type: 'visualization', id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', - version: 'WzE4LDJd', + version: 'WzIyLDJd', attributes: { title: 'Count of requests', }, @@ -120,6 +120,52 @@ export default function ({ getService }: FtrProviderContext) { })); }); + describe('hidden saved object types', () => { + it('returns saved objects for importableAndExportable types', async () => + await supertest + .get( + '/api/kibana/management/saved_objects/_find?type=test-hidden-importable-exportable&fields=title' + ) + .expect(200) + .then((resp: Response) => { + expect(resp.body).to.eql({ + page: 1, + per_page: 20, + total: 1, + saved_objects: [ + { + type: 'test-hidden-importable-exportable', + id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab', + attributes: { + title: 'Hidden Saved object type that is importable/exportable.', + }, + references: [], + updated_at: '2021-02-11T18:51:23.794Z', + version: 'WzE4LDJd', + namespaces: ['default'], + score: 0, + meta: {}, + }, + ], + }); + })); + + it('returns empty response for non importableAndExportable types', async () => + await supertest + .get( + '/api/kibana/management/saved_objects/_find?type=test-hidden-non-importable-exportable' + ) + .expect(200) + .then((resp: Response) => { + expect(resp.body).to.eql({ + page: 1, + per_page: 20, + total: 0, + saved_objects: [], + }); + })); + }); + describe('`hasReference` and `hasReferenceOperator` parameters', () => { before(() => esArchiver.load('saved_objects/references')); after(() => esArchiver.unload('saved_objects/references')); diff --git a/test/api_integration/apis/saved_objects_management/get.ts b/test/api_integration/apis/saved_objects_management/get.ts index 4dfd06a61eecf..0d52cf6431558 100644 --- a/test/api_integration/apis/saved_objects_management/get.ts +++ b/test/api_integration/apis/saved_objects_management/get.ts @@ -17,6 +17,10 @@ export default function ({ getService }: FtrProviderContext) { describe('get', () => { const existingObject = 'visualization/dd7caf20-9efd-11e7-acb3-3dab96693fab'; + const hiddenTypeExportableImportable = + 'test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab'; + const hiddenTypeNonExportableImportable = + 'test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc'; const nonexistentObject = 'wigwags/foo'; describe('with kibana index', () => { @@ -35,10 +39,27 @@ export default function ({ getService }: FtrProviderContext) { expect(meta).to.not.equal(undefined); })); + it('should return 200 for hidden types that are importableAndExportable', async () => + await supertest + .get(`/api/kibana/management/saved_objects/${hiddenTypeExportableImportable}`) + .expect(200) + .then((resp: Response) => { + const { body } = resp; + const { type, id, meta } = body; + expect(type).to.eql('test-hidden-importable-exportable'); + expect(id).to.eql('ff3733a0-9fty-11e7-ahb3-3dcb94193fab'); + expect(meta).to.not.equal(undefined); + })); + it('should return 404 for object that does not exist', async () => await supertest .get(`/api/kibana/management/saved_objects/${nonexistentObject}`) .expect(404)); + + it('should return 404 for hidden types that are not importableAndExportable', async () => + await supertest + .get(`/api/kibana/management/saved_objects/${hiddenTypeNonExportableImportable}`) + .expect(404)); }); describe('without kibana index', () => { diff --git a/test/api_integration/apis/saved_objects_management/scroll_count.ts b/test/api_integration/apis/saved_objects_management/scroll_count.ts index 78fd316eb4ecb..944732fdac68f 100644 --- a/test/api_integration/apis/saved_objects_management/scroll_count.ts +++ b/test/api_integration/apis/saved_objects_management/scroll_count.ts @@ -87,5 +87,22 @@ export default function ({ getService }: FtrProviderContext) { search: 0, }); }); + + it('only counts hidden types that are importableAndExportable', async () => { + const res = await supertest + .post(apiUrl) + .send({ + typesToInclude: [ + 'test-hidden-non-importable-exportable', + 'test-hidden-importable-exportable', + ], + }) + .expect(200); + + expect(res.body).to.eql({ + 'test-hidden-importable-exportable': 1, + 'test-hidden-non-importable-exportable': 0, + }); + }); }); } diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json.gz b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json.gz index 1c327e7e0769b5981367d5bc6e651dbdfa9f0658..254208106ec780cb1c8be1a78643b7f259b0bb8b 100644 GIT binary patch literal 1454 zcmV;f1yTARiwFp5`y^lh17u-zVJ>QOZ*BnXnOkq$HWYy0^D7MPZHPQwY)jT#(V|<1 zrYT~h537TM5-FLDOnMZRO9TD)9a6GIB~BtY%aQ>#kVHBp4-e1fBk9~63ou&zLCK$Q?IM|FYcqx*09>bE3&Zavwmurk9!C#S7ojk`4ZO6C0aPGK~6Gr}M z=uMr!+WuWN?L2BGDsw$mfi6HJkH3*b7Qb%CLYI`192ct3mz#yf(26XqXkmS&cwrqb zw5?iDNI_YqWeG2t1fc`ZMIz`LtcBMU1U=$lI)nV5bwZhk9PLXgyy5_KQ6%(RGnE(u~i3~-_=2NaB%Zd|vGjwc}ub0SuoI3TO{6d~SrI9&BfgeL3Qx6b+a8#tsLY|QS!pk}KATJHfJf7b z;|CsjBH(LfynP6?0*TODWCNldwNwPiLfsZ^ME3{k@Ka>bPN z%T@^D1|8N`c4mwzxR7@TC?Xn@HJ0qwa6v>-+vgh6Iv6vxPo3y(>X=B>S^Cx?Gi~0V zvy+c%jZo;#{s5KTCwX+;FKM>S;YYs7^R|c^(^|pbB@x%~dec5CoJ77>k|UOtD6658 zmkD9;SV2QdbEyCmeL1UICsfatwHLG~QBJ=j75E5^yu=xYPfXs9&Yn3ujoffJ^(RIS zch&4p<NvW3BUtjw zPe@3L@>70UnEL^=Kw{FQc%w4s1Gyl1ryZ)JR$159QInah%yVeQR6u6e8Ky*4qjJtA z$_+JAy}vJ6QtzDQs!l7|dDLX;pr*DoXma&Z2ve)VZQ5>^+iY)ob6b)X(n7^!n%r_i zRY9s6zAmYDwNYi@{l;5{=k{GNe0uV#XhV3UlY9>*KNDw+vc8WE4{+fnNPuzZI`NB; zz=z#z;_pdMwod9+@)vp*uVoK zEFs><9Ghq5vLL6B3B&{hR0$WewibUEgs_3+gHwVH&2Lq=M%}{t$l2x~58^^AZ8(qu z?3&}N9h_m-pZ;T7;7f`4tk25{O z7@()PEiB4-POfBI4Jl`GM!ze~69?-5g+bPrKd<7L@;@LBM#VDbNZ=?AoFqU`Jv49i z^(M{O8BQGY%+adYO__Ihrr3Qxejq#6h(UF2f~yia6BNILTVWj^Rc_u$9W+%@j^W{| zDbwrbFWuyQ)j4=BEb}_otZ1>cq?mkC3z(~vYQJ@O zoF9^|;M!J5bzi!B7k&y|_JzY8y7ajc{l`SX4-h5vUJ+3?=a!#j`AL?aWO=n@k>DR2 zT#N~`>1qvkR~1H^Tx}ksH1z}DM~*#B<+aL!z(&j1w|$(%(~&#%Qxrc=oJZ%mpG2N( zJ046tcf)AxMxH+mrXzzykE`BIs6X_OfzE(I{g0r5GIt=CNDgQ*XqEleDjPoEH?8JE z7{4zbeC-F50J-*5B$++-%fSA2uH(VtK*a-HCi}(X-nssrnB1@a2jjxH+$%Q!0MUF_ IIPDw&0J);R9{>OV literal 1295 zcmV+q1@QVGiwFq+nP^@B17u-zVJ>QOZ*BnXm|IWdI23^2`4v_6ZAGgjy`_0WgIKW| zE}|6=OVP-Q-PAj7+_jw!rOJQbV<&AK=rZXd7FGfYCONi`kI&`v$!v~VEk~`F#0gst z=CO0E1uMidE!n^eywVht2R)(lokl1{W|Ed;Ei|L;B~prrGz>ynYp5(h;(003RKbW{)=muf8 z*YQX0AJzQ2nra`t6IIM?CD95r^5{QX@vJ`;R# z%Hvxd47t^kAJ=WsC;T|($e0UKHz&;&5fKNQvlTwEXDe=OkV&z+MYixAOe*a7AQ5|- z%l|T32b-dY@_VN&w)|-OH$TdcjyA7{Qq0pCO~PTv?YM2kmUHC&oI1s#=C~Pk{9a(; zrd(g+Oq5ZEFS7+mgWh0h;YATf7DS14$d~F|snVEtEm6!_wn(+~ zZYKnBi4JEcySLUzF4Xe{nuykBr6v0{tcZ|>eV!#Pf-%M3-M73^My-K;mhe@Q_d{Ux1o5E5s}{ zO240FX3_t8Vq^nC?wUV!d2Stj$2-D=5m{p1u{a-V;VnkLY_ma zTE5PxakW)t;Qi8Dmgf#VF#I&+m8?Q|Zj$@}CchD9tg`+mHoU-v_aFhrf#*i=LV_;b zW`pj5Bsf{1N9Yn;w|lp2jDUL0@6C6pCX6SXGewtHZ-?<$l91Hy0r%wkxXWxZ# z@I(1c57nTzec@2|b_}_Rth6c=Bk_F#czHtc3nUVn$_h(!ipjM;z(l81^}h~3=ZB&T z_-vC(e=j}%7Jdy~4u!)rx-|JD`j3f%Um!~0e;}f4`<73#e3IppEN?=VzX36INOHv) F001+VcESJv diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json index 8270c573e4c1e..5699db7771501 100644 --- a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json +++ b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json @@ -206,6 +206,20 @@ "type": "text" } } + }, + "test-hidden-non-importable-exportable": { + "properties": { + "title": { + "type": "text" + } + } + }, + "test-hidden-importable-exportable": { + "properties": { + "title": { + "type": "text" + } + } } } } diff --git a/test/api_integration/fixtures/es_archiver/saved_objects/basic/data.json.gz b/test/api_integration/fixtures/es_archiver/saved_objects/basic/data.json.gz index c72f46370fa122258294d3000e630b607d3db3f1..e9d4615540696d205fbb2b3d39b937b12ad0038f 100644 GIT binary patch literal 2246 zcmV;%2s!s3iwFoF_#|Ke17u-zVJ>QOZ*BnXTw8DBHWq%*uQ0rCi^wb4nK;%{yR(?x zS0Vj%h4kW@27He&_HUS{A>@lfhsp9&$AF z2SZ51;i)RP1*A|VkMe{3h%<=pRfEwD4nPKUBUKJnp{{juAOvEWKl8?}3tZQkp$Iyj zho%k)gNZYNAefz>&n6KF>i(P-ENtiLAnA=+HJ8;z4uL>$4uonncDIfZTtQ(?L2BGEQp?p(3lIr6X)+uKV6-o4;T^n1*E#!52{2qO!IEDNHyWA z{?*%bGa({F#?1mRfGTw z6A%#9QLsXlfjDL;2BIphn=%C82S(F>(eP(wHD1>(PFEosF>tp>R8{FJP^xMPlK?R{ zh$02YEPiU2>myQo;1GD`7#@b26~>zDt!)k*9#Xcn-LoPM5Zf9~UHCd@o|mz;kEmOC z07xYcLo6m^p_;G^M~6nugQf%r}wdIw-af+an8DGpYj-xv$J7bxSHX686g1IZ)@ ziV+=!lro4j@Whp5uHxC>EtFRr;yYeJA%iS4@5JSc| zd*$cvX(rS&2*3mm3G!14afA_^tEZ4=Jb+w-G%o^zd2$R;ISPeQj}D&4X;KzlgH(Xn zcs3dMvLN!dY z`Q%ujxml<1XF!_GrG6d5WF9p@!#UjV@2jt;P{J~s!GaN!36$^*=1<&V^`4a<0%p)d zlV?C40hh;cFkgZ72$(hdh~7ha1Z=8PhVf)7kVn9!*+-!sN`u)nIh7li$NyLC_hpZ* z>C%AA;)v%o<3{bv5|K$P@f?K9uX-JlqY{rv3?1$r*r!;G3Xz7z#6pAy{hD;o4cb%^ z%z-WSeOTSVS)A1WE>0FFCy%ec%oNfr!m&Rcxg*yBBu{|%@@=KE(>B+XChoX%O{wbN zyPp&kn7}VZDoZcU&ZnI_M-WAzAmU@aj*V_y?TxTo%nLy9A3%NY^C6suAR52&_E&Gr z&1ik+`QyoGIy>vo+8<{1?XUOBSqC&4RA&y}z1<}TxD;|q)llw$>R>Lt{YkI>W&qN2 zbx95wNR`_@uBwfhdM8oUg>sUZvWHJNYj>U6E8;=VsG3khneP8Lgk;%baoYC#@m_aR zchK~Z5@Az=x#RWW)xAoHRDLbej~8T3K!u>?OG-SUckNbefGqT;1~sZ?Od^r1_jgo1 z0RbY_s{6yp|FTfWP~UT1)wbsJak2O=KWf)|x|*NM;$|sLEc%2Zv1*BWoTuv}viWOP zC#zEm%d(8J6p)uz%%~{WtD<3qiBRu-H1>Ul5BVp$7p=D`i+|VQlVQZa)sFRBJEI;B zt?|SLHWwhgsorXm+X<9&=>>ErJ8ii4$|XV>^0j;Z6Nx*7vTy3`ecs_vf_RTvNKmIx zHbE?>q+DW;$J^SZPYtZs2_U?pl;}$zO`3r46N*s=+ajVrf9o2VwZ9mu`*VtwL6@3L&w^+I_sL8(trCC8CXqlZ0Iez-FTQ@F$4oq=2mpNcw=Wp+{ zx>*8c%nf8Atd_L+zUW5D0_!08-^;IGszAx}hZ0-mb?xaPD+nn!0%=UJ=#AESil|2G zg=55cS?qO6%cOJ(ZV~(%{EkBL841vf_A1xtL&v4gI31wXo7j?rO_Hc)soBHYsbutL z)mrO6uZOxF0a;w=M~uqvix6cxXb&4yi@l{}2zU}uz@Q(X$#gOSdR6Ezr{iY44O8*d zKXXSHUgufFCpeR0S{`}uTj+Ls4ZG>wSqEPc5CY0;I^A-M*(5m z{rn^#Br^FBm4JTK5v~gHm7(hIFK-b9B1)Z%`@0lpP%&ITQEA6-ceqt*@$_-Yz!74XctyOM#12(O4!w$%_$_-Yz!B{G-a)VWFFq2KI+^`!SO~0vV zl^b@zpiy_3ta8I1ShUIwd!zI?PUlv+!74YH&868#A*pX&yL1@L&b$pJWL}(Seb5+tjyskUuRG(vJoM^d@*mx0pgmwfwF?Xs+<{1d7+^kV z2m41m*l2&>wYm$*=sJ7Qd@?07NlInE(I) literal 2038 zcmc)8`9Bkk0{~!mYVyjJV`F1!?z1_Tq={Km4ILY4Bt~z@Q7DAm=UzEtv#D8#j=7J_ zHFJ~R&3$z!_w_oOm)_6!ulPPcKB_6=0{&5P)iDrEUh?8m~SBW%KxfJJV#IIiPe&e(mFCA}1`y2k)2OZpQvIbAV$oMR> z+$a*pQ#+mtWQp603~4sseYazvI|qG=C_ll>Jo#ccuJF($K4w1rI^XaDM%u|HQ(UHs zz<4Dcr-^)^gGzP2hBuWHnKO-f&DvT|!JWa4=sp^OC;@^GpOusihtM$GGniv+>C9va z;7xw1!`qCmy%zX-pXPMBFHeUz*#HNc8GZYb-{^g@0sLh;V6iPhajPk{BEn{>P4~Rk z0|A^N2+$vTH6|lYSaVNDPmYw~F_a;o;pzM)!7U}0yLF}Wf}U(Q^t&SPs}I=Ph?ckh zpsT*c1gXuSYyU8RoqfblP?47;_ZNdM9^D#EFS4l}MhcJX@Djmcu5G7isa`|phX=O% zmv)$APX4#n>aWU6mShW&ekk@g3m!9*m!w}qWAlbmQ_aDrs`J3UXqqfq9BtpjJ_R&6 zmR5aU(2FerwpL)aKmFhrTb5~)s;))X>Ya_TM*V${*=lTC5YHiS0C=wTlS&KiS)WzZs_?Zw%LgkBWL|!2 zPZ#XIG_1mTT5boBs*|Md>@T)oD{*h-5g-blqQ0R|w_gvGntRJVLlNHNmt&rYH9V12 z-a2!W8tvuo|LHM|8V&E)6K*m(-sMfZH0n~Mf^HdqM(%0-z7Yjbvp(pmc}iG7&7aMp z{mZlwvA<+w2NC?ovaUne9yx&!ZcG++P85-s0mupQ^MfIR=GkJE-?J@1*G&U*5ZkO? z%J+c*Zo9s5+}RW&u&;A^R2hy#d8#hlD2{@~fo)mpTaEfHq4F<@n=KQ!EngIrZpW!&7+=Tc-0UhM z443?)KEgXKWliBo&T~4>c_t`Zhon^lE^sf?K*nMl6u*j(>ql&^9C@{KWSa5cBYLH-$R;7xUs7R z2|TFmYIZY7IIMSUI!lMjL{2w&2z&Zal(;2IFEHw+KOSK$k$|=`+%Eg)Z{|?vP|NPw z&o#USZeUoMYQ;ju!2BiLB&Im&;u?z1bNJMQqo{uFS2aT1q6E59ROi$#F27X-yzTjw zPgKA%`sy>hBK$uk9A>$e@W%U+spIRKFcQ_boj;yVWRsM2K1A!v9b;X4onM703e-VF zuM!&5Ru2M`ZzepsSI9aMav8PLO`gsLfqbRjm5M7a$S!Kwd?RN&EiY`8yA5+iYqo3@ zRD%YVi!(GF2>+&cK-=%1s2rp=r09(6$Il;*gxhR@k?5p3dev$(xi?9O}Z z>L<+SsU(a%@F-BHD;Q2uLuhZdFVvB0-L(ouA5ZTQm^1e5io|W7y{-J^f~$A^u0JkN zv`aSv#Vl1+e;w}~PJbG3JId{-c+%x_eNfsBc-u8dGroks+dC*ObmGS= zj97;K0Kua!;?;1EzvZN%soA_3XL2@A85k6M$1kAoczS*7{~=c!)`Rth64Lxk4ya=w zt>SYU-R-s(k0hkh1=|eIn~8~Y1m+aLK;e!I#tKI*W)yZ8kt5ELp1Y|QsdA|!s*7;s JpdnU3;6I3>=+giI diff --git a/test/api_integration/fixtures/es_archiver/saved_objects/basic/mappings.json b/test/api_integration/fixtures/es_archiver/saved_objects/basic/mappings.json index e601c43431437..350d46d618383 100644 --- a/test/api_integration/fixtures/es_archiver/saved_objects/basic/mappings.json +++ b/test/api_integration/fixtures/es_archiver/saved_objects/basic/mappings.json @@ -260,6 +260,20 @@ "type": "text" } } + }, + "test-hidden-non-importable-exportable": { + "properties": { + "title": { + "type": "text" + } + } + }, + "test-hidden-importable-exportable": { + "properties": { + "title": { + "type": "text" + } + } } } } diff --git a/test/common/config.js b/test/common/config.js index 46cd07b2ec370..ea48097c10bd4 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -51,6 +51,13 @@ export default function () { '--telemetry.url=https://telemetry-staging.elastic.co/xpack/v2/send', '--telemetry.optInStatusUrl=https://telemetry-staging.elastic.co/opt_in_status/v2/send', `--server.maxPayloadBytes=1679958`, + // test saved objects hidden type + `--plugin-path=${path.join( + __dirname, + 'fixtures', + 'plugins', + 'test_saved_objects_hidden_type' + )}`, // newsfeed mock service `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'newsfeed')}`, `--newsfeed.service.urlRoot=${servers.kibana.protocol}://${servers.kibana.hostname}:${servers.kibana.port}`, diff --git a/test/common/fixtures/plugins/test_saved_objects_hidden_type/kibana.json b/test/common/fixtures/plugins/test_saved_objects_hidden_type/kibana.json new file mode 100644 index 0000000000000..a7e01fe1731e6 --- /dev/null +++ b/test/common/fixtures/plugins/test_saved_objects_hidden_type/kibana.json @@ -0,0 +1,8 @@ +{ + "id": "testSavedObjectsHiddenType", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["test_saved_objects_hidden_type"], + "server": true, + "ui": false +} diff --git a/test/common/fixtures/plugins/test_saved_objects_hidden_type/package.json b/test/common/fixtures/plugins/test_saved_objects_hidden_type/package.json new file mode 100644 index 0000000000000..37f97ac2f88c1 --- /dev/null +++ b/test/common/fixtures/plugins/test_saved_objects_hidden_type/package.json @@ -0,0 +1,14 @@ +{ + "name": "test_saved_objects_hidden_type", + "version": "1.0.0", + "main": "target/test/plugin_functional/plugins/test_saved_objects_hidden_type", + "kibana": { + "version": "kibana", + "templateVersion": "1.0.0" + }, + "license": "Apache-2.0", + "scripts": { + "kbn": "node ../../../../scripts/kbn.js", + "build": "rm -rf './target' && ../../../../node_modules/.bin/tsc" + } +} \ No newline at end of file diff --git a/test/common/fixtures/plugins/test_saved_objects_hidden_type/server/index.ts b/test/common/fixtures/plugins/test_saved_objects_hidden_type/server/index.ts new file mode 100644 index 0000000000000..e220ae6481728 --- /dev/null +++ b/test/common/fixtures/plugins/test_saved_objects_hidden_type/server/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { TestSavedObjectsHiddenTypePlugin } from './plugin'; + +export const plugin = () => new TestSavedObjectsHiddenTypePlugin(); diff --git a/test/common/fixtures/plugins/test_saved_objects_hidden_type/server/plugin.ts b/test/common/fixtures/plugins/test_saved_objects_hidden_type/server/plugin.ts new file mode 100644 index 0000000000000..003068a0e16b0 --- /dev/null +++ b/test/common/fixtures/plugins/test_saved_objects_hidden_type/server/plugin.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Plugin, CoreSetup } from 'kibana/server'; + +export class TestSavedObjectsHiddenTypePlugin implements Plugin { + public setup({ savedObjects }: CoreSetup, deps: {}) { + // example of a SO type that is hidden and importableAndExportable + savedObjects.registerType({ + name: 'test-hidden-importable-exportable', + hidden: true, + mappings: { + properties: { + title: { type: 'text' }, + }, + }, + management: { + importableAndExportable: true, + }, + }); + + // example of a SO type that is hidden and not importableAndExportable + savedObjects.registerType({ + name: 'test-hidden-non-importable-exportable', + hidden: true, + mappings: { + properties: { + title: { type: 'text' }, + }, + }, + management: { + importableAndExportable: false, + }, + }); + } + + public start() {} + public stop() {} +} diff --git a/test/common/fixtures/plugins/test_saved_objects_hidden_type/tsconfig.json b/test/common/fixtures/plugins/test_saved_objects_hidden_type/tsconfig.json new file mode 100644 index 0000000000000..da457c9ba32fc --- /dev/null +++ b/test/common/fixtures/plugins/test_saved_objects_hidden_type/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "index.ts", + "server/**/*.ts", + "../../../../typings/**/*", + ], + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] +} From 74d32ff600accfda43cd7ef726499f6c328e82c5 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 11 Feb 2021 12:29:20 +0200 Subject: [PATCH 09/14] return this.client if options undefined --- src/core/server/core_route_handler_context.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/server/core_route_handler_context.ts b/src/core/server/core_route_handler_context.ts index 294611a0c1f79..f5123a91e7100 100644 --- a/src/core/server/core_route_handler_context.ts +++ b/src/core/server/core_route_handler_context.ts @@ -73,6 +73,7 @@ class CoreSavedObjectsRouteHandlerContext { } public getClient = (options?: SavedObjectsClientProviderOptions) => { + if (!options) return this.client; return this.savedObjectsStart.getScopedClient(this.request, options); }; From 9581554e06dec910e529ef1af80bc6e66feb5079 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 11 Feb 2021 13:09:04 +0200 Subject: [PATCH 10/14] move to tests to plugin_functional --- data.json.gz | 0 .../apis/saved_objects/delete.ts | 32 -- .../apis/saved_objects/export.ts | 31 -- .../apis/saved_objects/find.ts | 30 +- .../apis/saved_objects/import.ts | 60 -- .../saved_objects/resolve_import_errors.ts | 84 --- .../apis/saved_objects_management/find.ts | 48 +- .../apis/saved_objects_management/get.ts | 21 - .../saved_objects_management/scroll_count.ts | 17 - .../saved_objects/scroll_count/data.json.gz | Bin 1454 -> 1295 bytes .../saved_objects/scroll_count/mappings.json | 14 - .../saved_objects/basic/data.json.gz | Bin 2246 -> 2038 bytes .../saved_objects/basic/mappings.json | 14 - test/common/config.js | 7 - .../kibana.json | 8 - .../hidden_saved_objects/data.json | 29 + .../hidden_saved_objects/mappings.json | 513 ++++++++++++++++++ test/plugin_functional/config.ts | 19 +- .../saved_objects_hidden_type/kibana.json | 8 + .../saved_objects_hidden_type}/package.json | 4 +- .../server/index.ts | 4 +- .../server/plugin.ts | 4 +- .../saved_objects_hidden_type}/tsconfig.json | 0 .../saved_objects_hidden_type/delete.ts | 60 ++ .../saved_objects_hidden_type/export.ts | 63 +++ .../saved_objects_hidden_type/find.ts | 56 ++ .../saved_objects_hidden_type/import.ts | 88 +++ .../saved_objects_hidden_type/index.ts | 19 + .../resolve_import_errors.ts | 112 ++++ .../saved_objects_management/find.ts | 78 +++ .../saved_objects_management/get.ts | 54 ++ .../saved_objects_management/index.ts | 3 + .../saved_objects_management/scroll_count.ts | 49 ++ 33 files changed, 1151 insertions(+), 378 deletions(-) create mode 100644 data.json.gz delete mode 100644 test/common/fixtures/plugins/test_saved_objects_hidden_type/kibana.json create mode 100644 test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/data.json create mode 100644 test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/mappings.json create mode 100644 test/plugin_functional/plugins/saved_objects_hidden_type/kibana.json rename test/{common/fixtures/plugins/test_saved_objects_hidden_type => plugin_functional/plugins/saved_objects_hidden_type}/package.json (67%) rename test/{common/fixtures/plugins/test_saved_objects_hidden_type => plugin_functional/plugins/saved_objects_hidden_type}/server/index.ts (73%) rename test/{common/fixtures/plugins/test_saved_objects_hidden_type => plugin_functional/plugins/saved_objects_hidden_type}/server/plugin.ts (90%) rename test/{common/fixtures/plugins/test_saved_objects_hidden_type => plugin_functional/plugins/saved_objects_hidden_type}/tsconfig.json (100%) create mode 100644 test/plugin_functional/test_suites/saved_objects_hidden_type/delete.ts create mode 100644 test/plugin_functional/test_suites/saved_objects_hidden_type/export.ts create mode 100644 test/plugin_functional/test_suites/saved_objects_hidden_type/find.ts create mode 100644 test/plugin_functional/test_suites/saved_objects_hidden_type/import.ts create mode 100644 test/plugin_functional/test_suites/saved_objects_hidden_type/index.ts create mode 100644 test/plugin_functional/test_suites/saved_objects_hidden_type/resolve_import_errors.ts create mode 100644 test/plugin_functional/test_suites/saved_objects_management/find.ts create mode 100644 test/plugin_functional/test_suites/saved_objects_management/get.ts create mode 100644 test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts diff --git a/data.json.gz b/data.json.gz new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/api_integration/apis/saved_objects/delete.ts b/test/api_integration/apis/saved_objects/delete.ts index 81ad810720689..0dfece825d3a1 100644 --- a/test/api_integration/apis/saved_objects/delete.ts +++ b/test/api_integration/apis/saved_objects/delete.ts @@ -38,38 +38,6 @@ export default function ({ getService }: FtrProviderContext) { message: 'Saved object [dashboard/not-a-real-id] not found', }); })); - - describe('hidden saved object types', () => { - it('should return generic 404 when trying to delete a doc with importableAndExportable types', async () => - await supertest - .delete( - `/api/saved_objects/test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab` - ) - .expect(404) - .then((resp) => { - expect(resp.body).to.eql({ - statusCode: 404, - error: 'Not Found', - message: - 'Saved object [test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab] not found', - }); - })); - - it('returns empty response for non importableAndExportable types', async () => - await supertest - .delete( - `/api/saved_objects/test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc` - ) - .expect(404) - .then((resp) => { - expect(resp.body).to.eql({ - statusCode: 404, - error: 'Not Found', - message: - 'Saved object [test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc] not found', - }); - })); - }); }); describe('without kibana index', () => { diff --git a/test/api_integration/apis/saved_objects/export.ts b/test/api_integration/apis/saved_objects/export.ts index 62690330655c8..5206d51054745 100644 --- a/test/api_integration/apis/saved_objects/export.ts +++ b/test/api_integration/apis/saved_objects/export.ts @@ -181,37 +181,6 @@ export default function ({ getService }: FtrProviderContext) { }); }); - describe('hidden saved object types', () => { - it('returns objects with importableAndExportable types', async () => - await supertest - .post('/api/saved_objects/_export') - .send({ - type: ['test-hidden-importable-exportable'], - }) - .expect(200) - .then((resp) => { - const objects = ndjsonToObject(resp.text); - expect(objects).to.have.length(2); - expect(objects[0]).to.have.property('id', 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab'); - expect(objects[0]).to.have.property('type', 'test-hidden-importable-exportable'); - })); - - it('excludes objects with non importableAndExportable types', async () => - await supertest - .post('/api/saved_objects/_export') - .send({ - type: ['test-hidden-non-importable-exportable'], - }) - .then((resp) => { - expect(resp.body).to.eql({ - statusCode: 400, - error: 'Bad Request', - message: - 'Trying to export non-exportable type(s): test-hidden-non-importable-exportable', - }); - })); - }); - it(`should return 400 when exporting unsupported type`, async () => { await supertest .post('/api/saved_objects/_export') diff --git a/test/api_integration/apis/saved_objects/find.ts b/test/api_integration/apis/saved_objects/find.ts index 6c136bfc60729..66c2a083c79e5 100644 --- a/test/api_integration/apis/saved_objects/find.ts +++ b/test/api_integration/apis/saved_objects/find.ts @@ -209,7 +209,7 @@ export default function ({ getService }: FtrProviderContext) { score: 0, type: 'visualization', updated_at: '2017-09-21T18:51:23.794Z', - version: 'WzE4LDJd', + version: 'WzIyLDJd', }, ], }); @@ -294,34 +294,6 @@ export default function ({ getService }: FtrProviderContext) { })); }); - describe('hidden saved object types', () => { - it('returns empty response for importableAndExportable types', async () => - await supertest - .get('/api/saved_objects/_find?type=test-hidden-importable-exportable&fields=title') - .expect(200) - .then((resp) => { - expect(resp.body).to.eql({ - page: 1, - per_page: 20, - total: 0, - saved_objects: [], - }); - })); - - it('returns empty response for non importableAndExportable types', async () => - await supertest - .get('/api/saved_objects/_find?type=test-hidden-non-importable-exportable&fields=title') - .expect(200) - .then((resp) => { - expect(resp.body).to.eql({ - page: 1, - per_page: 20, - total: 0, - saved_objects: [], - }); - })); - }); - describe('`has_reference` and `has_reference_operator` parameters', () => { before(() => esArchiver.load('saved_objects/references')); after(() => esArchiver.unload('saved_objects/references')); diff --git a/test/api_integration/apis/saved_objects/import.ts b/test/api_integration/apis/saved_objects/import.ts index 0633f4e473e7f..b0aa9b0eef8fc 100644 --- a/test/api_integration/apis/saved_objects/import.ts +++ b/test/api_integration/apis/saved_objects/import.ts @@ -164,66 +164,6 @@ export default function ({ getService }: FtrProviderContext) { }); }); - describe('hidden saved object types', () => { - it('imports objects with importableAndExportable type', async () => { - const fileBuffer = Buffer.from( - '{"id":"some-id-1","type":"test-hidden-importable-exportable","attributes":{"title":"my title"},"references":[]}', - 'utf8' - ); - await supertest - .post('/api/saved_objects/_import') - .attach('file', fileBuffer, 'export.ndjson') - .expect(200) - .then((resp) => { - expect(resp.body).to.eql({ - successCount: 1, - success: true, - warnings: [], - successResults: [ - { - type: 'test-hidden-importable-exportable', - id: 'some-id-1', - meta: { - title: 'my title', - }, - }, - ], - }); - }); - }); - - it('does not import objects with non importableAndExportable type', async () => { - const fileBuffer = Buffer.from( - '{"id":"some-id-1","type":"test-hidden-non-importable-exportable","attributes":{"title":"my title"},"references":[]}', - 'utf8' - ); - await supertest - .post('/api/saved_objects/_import') - .attach('file', fileBuffer, 'export.ndjson') - .expect(200) - .then((resp) => { - expect(resp.body).to.eql({ - successCount: 0, - success: false, - warnings: [], - errors: [ - { - id: 'some-id-1', - type: 'test-hidden-non-importable-exportable', - title: 'my title', - meta: { - title: 'my title', - }, - error: { - type: 'unsupported_type', - }, - }, - ], - }); - }); - }); - }); - it('should return 400 when trying to import more than 10,000 objects', async () => { const fileChunks = []; for (let i = 0; i < 10001; i++) { diff --git a/test/api_integration/apis/saved_objects/resolve_import_errors.ts b/test/api_integration/apis/saved_objects/resolve_import_errors.ts index a615ae919fdc2..b203a2c7b7071 100644 --- a/test/api_integration/apis/saved_objects/resolve_import_errors.ts +++ b/test/api_integration/apis/saved_objects/resolve_import_errors.ts @@ -385,90 +385,6 @@ export default function ({ getService }: FtrProviderContext) { ]); }); }); - - describe('hidden saved object types', () => { - it('resolves objects with importableAndExportable types', async () => { - const fileBuffer = Buffer.from( - '{"id":"ff3733a0-9fty-11e7-ahb3-3dcb94193fab","type":"test-hidden-importable-exportable","attributes":{"title":"new title!"},"references":[]}', - 'utf8' - ); - - await supertest - .post('/api/saved_objects/_resolve_import_errors') - .field( - 'retries', - JSON.stringify([ - { - id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab', - type: 'test-hidden-importable-exportable', - overwrite: true, - }, - ]) - ) - .attach('file', fileBuffer, 'import.ndjson') - .expect(200) - .then((resp) => { - expect(resp.body).to.eql({ - successCount: 1, - success: true, - warnings: [], - successResults: [ - { - type: 'test-hidden-importable-exportable', - id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab', - meta: { - title: 'new title!', - }, - overwrite: true, - }, - ], - }); - }); - }); - - it('rejects objects with non importableAndExportable types', async () => { - const fileBuffer = Buffer.from( - '{"id":"op3767a1-9rcg-53u7-jkb3-3dnb74193awc","type":"test-hidden-non-importable-exportable","attributes":{"title":"new title!"},"references":[]}', - 'utf8' - ); - - await supertest - .post('/api/saved_objects/_resolve_import_errors') - .field( - 'retries', - JSON.stringify([ - { - id: 'op3767a1-9rcg-53u7-jkb3-3dnb74193awc', - type: 'test-hidden-non-importable-exportable', - overwrite: true, - }, - ]) - ) - .attach('file', fileBuffer, 'import.ndjson') - .expect(200) - .then((resp) => { - expect(resp.body).to.eql({ - successCount: 0, - success: false, - warnings: [], - errors: [ - { - id: 'op3767a1-9rcg-53u7-jkb3-3dnb74193awc', - type: 'test-hidden-non-importable-exportable', - title: 'new title!', - meta: { - title: 'new title!', - }, - error: { - type: 'unsupported_type', - }, - overwrite: true, - }, - ], - }); - }); - }); - }); }); }); }); diff --git a/test/api_integration/apis/saved_objects_management/find.ts b/test/api_integration/apis/saved_objects_management/find.ts index 63bd892b3ee4c..6ab2352ebb05f 100644 --- a/test/api_integration/apis/saved_objects_management/find.ts +++ b/test/api_integration/apis/saved_objects_management/find.ts @@ -42,7 +42,7 @@ export default function ({ getService }: FtrProviderContext) { { type: 'visualization', id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', - version: 'WzIyLDJd', + version: 'WzE4LDJd', attributes: { title: 'Count of requests', }, @@ -120,52 +120,6 @@ export default function ({ getService }: FtrProviderContext) { })); }); - describe('hidden saved object types', () => { - it('returns saved objects for importableAndExportable types', async () => - await supertest - .get( - '/api/kibana/management/saved_objects/_find?type=test-hidden-importable-exportable&fields=title' - ) - .expect(200) - .then((resp: Response) => { - expect(resp.body).to.eql({ - page: 1, - per_page: 20, - total: 1, - saved_objects: [ - { - type: 'test-hidden-importable-exportable', - id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab', - attributes: { - title: 'Hidden Saved object type that is importable/exportable.', - }, - references: [], - updated_at: '2021-02-11T18:51:23.794Z', - version: 'WzE4LDJd', - namespaces: ['default'], - score: 0, - meta: {}, - }, - ], - }); - })); - - it('returns empty response for non importableAndExportable types', async () => - await supertest - .get( - '/api/kibana/management/saved_objects/_find?type=test-hidden-non-importable-exportable' - ) - .expect(200) - .then((resp: Response) => { - expect(resp.body).to.eql({ - page: 1, - per_page: 20, - total: 0, - saved_objects: [], - }); - })); - }); - describe('`hasReference` and `hasReferenceOperator` parameters', () => { before(() => esArchiver.load('saved_objects/references')); after(() => esArchiver.unload('saved_objects/references')); diff --git a/test/api_integration/apis/saved_objects_management/get.ts b/test/api_integration/apis/saved_objects_management/get.ts index 0d52cf6431558..4dfd06a61eecf 100644 --- a/test/api_integration/apis/saved_objects_management/get.ts +++ b/test/api_integration/apis/saved_objects_management/get.ts @@ -17,10 +17,6 @@ export default function ({ getService }: FtrProviderContext) { describe('get', () => { const existingObject = 'visualization/dd7caf20-9efd-11e7-acb3-3dab96693fab'; - const hiddenTypeExportableImportable = - 'test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab'; - const hiddenTypeNonExportableImportable = - 'test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc'; const nonexistentObject = 'wigwags/foo'; describe('with kibana index', () => { @@ -39,27 +35,10 @@ export default function ({ getService }: FtrProviderContext) { expect(meta).to.not.equal(undefined); })); - it('should return 200 for hidden types that are importableAndExportable', async () => - await supertest - .get(`/api/kibana/management/saved_objects/${hiddenTypeExportableImportable}`) - .expect(200) - .then((resp: Response) => { - const { body } = resp; - const { type, id, meta } = body; - expect(type).to.eql('test-hidden-importable-exportable'); - expect(id).to.eql('ff3733a0-9fty-11e7-ahb3-3dcb94193fab'); - expect(meta).to.not.equal(undefined); - })); - it('should return 404 for object that does not exist', async () => await supertest .get(`/api/kibana/management/saved_objects/${nonexistentObject}`) .expect(404)); - - it('should return 404 for hidden types that are not importableAndExportable', async () => - await supertest - .get(`/api/kibana/management/saved_objects/${hiddenTypeNonExportableImportable}`) - .expect(404)); }); describe('without kibana index', () => { diff --git a/test/api_integration/apis/saved_objects_management/scroll_count.ts b/test/api_integration/apis/saved_objects_management/scroll_count.ts index 944732fdac68f..78fd316eb4ecb 100644 --- a/test/api_integration/apis/saved_objects_management/scroll_count.ts +++ b/test/api_integration/apis/saved_objects_management/scroll_count.ts @@ -87,22 +87,5 @@ export default function ({ getService }: FtrProviderContext) { search: 0, }); }); - - it('only counts hidden types that are importableAndExportable', async () => { - const res = await supertest - .post(apiUrl) - .send({ - typesToInclude: [ - 'test-hidden-non-importable-exportable', - 'test-hidden-importable-exportable', - ], - }) - .expect(200); - - expect(res.body).to.eql({ - 'test-hidden-importable-exportable': 1, - 'test-hidden-non-importable-exportable': 0, - }); - }); }); } diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json.gz b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json.gz index 254208106ec780cb1c8be1a78643b7f259b0bb8b..1c327e7e0769b5981367d5bc6e651dbdfa9f0658 100644 GIT binary patch literal 1295 zcmV+q1@QVGiwFq+nP^@B17u-zVJ>QOZ*BnXm|IWdI23^2`4v_6ZAGgjy`_0WgIKW| zE}|6=OVP-Q-PAj7+_jw!rOJQbV<&AK=rZXd7FGfYCONi`kI&`v$!v~VEk~`F#0gst z=CO0E1uMidE!n^eywVht2R)(lokl1{W|Ed;Ei|L;B~prrGz>ynYp5(h;(003RKbW{)=muf8 z*YQX0AJzQ2nra`t6IIM?CD95r^5{QX@vJ`;R# z%Hvxd47t^kAJ=WsC;T|($e0UKHz&;&5fKNQvlTwEXDe=OkV&z+MYixAOe*a7AQ5|- z%l|T32b-dY@_VN&w)|-OH$TdcjyA7{Qq0pCO~PTv?YM2kmUHC&oI1s#=C~Pk{9a(; zrd(g+Oq5ZEFS7+mgWh0h;YATf7DS14$d~F|snVEtEm6!_wn(+~ zZYKnBi4JEcySLUzF4Xe{nuykBr6v0{tcZ|>eV!#Pf-%M3-M73^My-K;mhe@Q_d{Ux1o5E5s}{ zO240FX3_t8Vq^nC?wUV!d2Stj$2-D=5m{p1u{a-V;VnkLY_ma zTE5PxakW)t;Qi8Dmgf#VF#I&+m8?Q|Zj$@}CchD9tg`+mHoU-v_aFhrf#*i=LV_;b zW`pj5Bsf{1N9Yn;w|lp2jDUL0@6C6pCX6SXGewtHZ-?<$l91Hy0r%wkxXWxZ# z@I(1c57nTzec@2|b_}_Rth6c=Bk_F#czHtc3nUVn$_h(!ipjM;z(l81^}h~3=ZB&T z_-vC(e=j}%7Jdy~4u!)rx-|JD`j3f%Um!~0e;}f4`<73#e3IppEN?=VzX36INOHv) F001+VcESJv literal 1454 zcmV;f1yTARiwFp5`y^lh17u-zVJ>QOZ*BnXnOkq$HWYy0^D7MPZHPQwY)jT#(V|<1 zrYT~h537TM5-FLDOnMZRO9TD)9a6GIB~BtY%aQ>#kVHBp4-e1fBk9~63ou&zLCK$Q?IM|FYcqx*09>bE3&Zavwmurk9!C#S7ojk`4ZO6C0aPGK~6Gr}M z=uMr!+WuWN?L2BGDsw$mfi6HJkH3*b7Qb%CLYI`192ct3mz#yf(26XqXkmS&cwrqb zw5?iDNI_YqWeG2t1fc`ZMIz`LtcBMU1U=$lI)nV5bwZhk9PLXgyy5_KQ6%(RGnE(u~i3~-_=2NaB%Zd|vGjwc}ub0SuoI3TO{6d~SrI9&BfgeL3Qx6b+a8#tsLY|QS!pk}KATJHfJf7b z;|CsjBH(LfynP6?0*TODWCNldwNwPiLfsZ^ME3{k@Ka>bPN z%T@^D1|8N`c4mwzxR7@TC?Xn@HJ0qwa6v>-+vgh6Iv6vxPo3y(>X=B>S^Cx?Gi~0V zvy+c%jZo;#{s5KTCwX+;FKM>S;YYs7^R|c^(^|pbB@x%~dec5CoJ77>k|UOtD6658 zmkD9;SV2QdbEyCmeL1UICsfatwHLG~QBJ=j75E5^yu=xYPfXs9&Yn3ujoffJ^(RIS zch&4p<NvW3BUtjw zPe@3L@>70UnEL^=Kw{FQc%w4s1Gyl1ryZ)JR$159QInah%yVeQR6u6e8Ky*4qjJtA z$_+JAy}vJ6QtzDQs!l7|dDLX;pr*DoXma&Z2ve)VZQ5>^+iY)ob6b)X(n7^!n%r_i zRY9s6zAmYDwNYi@{l;5{=k{GNe0uV#XhV3UlY9>*KNDw+vc8WE4{+fnNPuzZI`NB; zz=z#z;_pdMwod9+@)vp*uVoK zEFs><9Ghq5vLL6B3B&{hR0$WewibUEgs_3+gHwVH&2Lq=M%}{t$l2x~58^^AZ8(qu z?3&}N9h_m-pZ;T7;7f`4tk25{O z7@()PEiB4-POfBI4Jl`GM!ze~69?-5g+bPrKd<7L@;@LBM#VDbNZ=?AoFqU`Jv49i z^(M{O8BQGY%+adYO__Ihrr3Qxejq#6h(UF2f~yia6BNILTVWj^Rc_u$9W+%@j^W{| zDbwrbFWuyQ)j4=BEb}_otZ1>cq?mkC3z(~vYQJ@O zoF9^|;M!J5bzi!B7k&y|_JzY8y7ajc{l`SX4-h5vUJ+3?=a!#j`AL?aWO=n@k>DR2 zT#N~`>1qvkR~1H^Tx}ksH1z}DM~*#B<+aL!z(&j1w|$(%(~&#%Qxrc=oJZ%mpG2N( zJ046tcf)AxMxH+mrXzzykE`BIs6X_OfzE(I{g0r5GIt=CNDgQ*XqEleDjPoEH?8JE z7{4zbeC-F50J-*5B$++-%fSA2uH(VtK*a-HCi}(X-nssrnB1@a2jjxH+$%Q!0MUF_ IIPDw&0J);R9{>OV diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json index 5699db7771501..8270c573e4c1e 100644 --- a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json +++ b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json @@ -206,20 +206,6 @@ "type": "text" } } - }, - "test-hidden-non-importable-exportable": { - "properties": { - "title": { - "type": "text" - } - } - }, - "test-hidden-importable-exportable": { - "properties": { - "title": { - "type": "text" - } - } } } } diff --git a/test/api_integration/fixtures/es_archiver/saved_objects/basic/data.json.gz b/test/api_integration/fixtures/es_archiver/saved_objects/basic/data.json.gz index e9d4615540696d205fbb2b3d39b937b12ad0038f..c72f46370fa122258294d3000e630b607d3db3f1 100644 GIT binary patch literal 2038 zcmc)8`9Bkk0{~!mYVyjJV`F1!?z1_Tq={Km4ILY4Bt~z@Q7DAm=UzEtv#D8#j=7J_ zHFJ~R&3$z!_w_oOm)_6!ulPPcKB_6=0{&5P)iDrEUh?8m~SBW%KxfJJV#IIiPe&e(mFCA}1`y2k)2OZpQvIbAV$oMR> z+$a*pQ#+mtWQp603~4sseYazvI|qG=C_ll>Jo#ccuJF($K4w1rI^XaDM%u|HQ(UHs zz<4Dcr-^)^gGzP2hBuWHnKO-f&DvT|!JWa4=sp^OC;@^GpOusihtM$GGniv+>C9va z;7xw1!`qCmy%zX-pXPMBFHeUz*#HNc8GZYb-{^g@0sLh;V6iPhajPk{BEn{>P4~Rk z0|A^N2+$vTH6|lYSaVNDPmYw~F_a;o;pzM)!7U}0yLF}Wf}U(Q^t&SPs}I=Ph?ckh zpsT*c1gXuSYyU8RoqfblP?47;_ZNdM9^D#EFS4l}MhcJX@Djmcu5G7isa`|phX=O% zmv)$APX4#n>aWU6mShW&ekk@g3m!9*m!w}qWAlbmQ_aDrs`J3UXqqfq9BtpjJ_R&6 zmR5aU(2FerwpL)aKmFhrTb5~)s;))X>Ya_TM*V${*=lTC5YHiS0C=wTlS&KiS)WzZs_?Zw%LgkBWL|!2 zPZ#XIG_1mTT5boBs*|Md>@T)oD{*h-5g-blqQ0R|w_gvGntRJVLlNHNmt&rYH9V12 z-a2!W8tvuo|LHM|8V&E)6K*m(-sMfZH0n~Mf^HdqM(%0-z7Yjbvp(pmc}iG7&7aMp z{mZlwvA<+w2NC?ovaUne9yx&!ZcG++P85-s0mupQ^MfIR=GkJE-?J@1*G&U*5ZkO? z%J+c*Zo9s5+}RW&u&;A^R2hy#d8#hlD2{@~fo)mpTaEfHq4F<@n=KQ!EngIrZpW!&7+=Tc-0UhM z443?)KEgXKWliBo&T~4>c_t`Zhon^lE^sf?K*nMl6u*j(>ql&^9C@{KWSa5cBYLH-$R;7xUs7R z2|TFmYIZY7IIMSUI!lMjL{2w&2z&Zal(;2IFEHw+KOSK$k$|=`+%Eg)Z{|?vP|NPw z&o#USZeUoMYQ;ju!2BiLB&Im&;u?z1bNJMQqo{uFS2aT1q6E59ROi$#F27X-yzTjw zPgKA%`sy>hBK$uk9A>$e@W%U+spIRKFcQ_boj;yVWRsM2K1A!v9b;X4onM703e-VF zuM!&5Ru2M`ZzepsSI9aMav8PLO`gsLfqbRjm5M7a$S!Kwd?RN&EiY`8yA5+iYqo3@ zRD%YVi!(GF2>+&cK-=%1s2rp=r09(6$Il;*gxhR@k?5p3dev$(xi?9O}Z z>L<+SsU(a%@F-BHD;Q2uLuhZdFVvB0-L(ouA5ZTQm^1e5io|W7y{-J^f~$A^u0JkN zv`aSv#Vl1+e;w}~PJbG3JId{-c+%x_eNfsBc-u8dGroks+dC*ObmGS= zj97;K0Kua!;?;1EzvZN%soA_3XL2@A85k6M$1kAoczS*7{~=c!)`Rth64Lxk4ya=w zt>SYU-R-s(k0hkh1=|eIn~8~Y1m+aLK;e!I#tKI*W)yZ8kt5ELp1Y|QsdA|!s*7;s JpdnU3;6I3>=+giI literal 2246 zcmV;%2s!s3iwFoF_#|Ke17u-zVJ>QOZ*BnXTw8DBHWq%*uQ0rCi^wb4nK;%{yR(?x zS0Vj%h4kW@27He&_HUS{A>@lfhsp9&$AF z2SZ51;i)RP1*A|VkMe{3h%<=pRfEwD4nPKUBUKJnp{{juAOvEWKl8?}3tZQkp$Iyj zho%k)gNZYNAefz>&n6KF>i(P-ENtiLAnA=+HJ8;z4uL>$4uonncDIfZTtQ(?L2BGEQp?p(3lIr6X)+uKV6-o4;T^n1*E#!52{2qO!IEDNHyWA z{?*%bGa({F#?1mRfGTw z6A%#9QLsXlfjDL;2BIphn=%C82S(F>(eP(wHD1>(PFEosF>tp>R8{FJP^xMPlK?R{ zh$02YEPiU2>myQo;1GD`7#@b26~>zDt!)k*9#Xcn-LoPM5Zf9~UHCd@o|mz;kEmOC z07xYcLo6m^p_;G^M~6nugQf%r}wdIw-af+an8DGpYj-xv$J7bxSHX686g1IZ)@ ziV+=!lro4j@Whp5uHxC>EtFRr;yYeJA%iS4@5JSc| zd*$cvX(rS&2*3mm3G!14afA_^tEZ4=Jb+w-G%o^zd2$R;ISPeQj}D&4X;KzlgH(Xn zcs3dMvLN!dY z`Q%ujxml<1XF!_GrG6d5WF9p@!#UjV@2jt;P{J~s!GaN!36$^*=1<&V^`4a<0%p)d zlV?C40hh;cFkgZ72$(hdh~7ha1Z=8PhVf)7kVn9!*+-!sN`u)nIh7li$NyLC_hpZ* z>C%AA;)v%o<3{bv5|K$P@f?K9uX-JlqY{rv3?1$r*r!;G3Xz7z#6pAy{hD;o4cb%^ z%z-WSeOTSVS)A1WE>0FFCy%ec%oNfr!m&Rcxg*yBBu{|%@@=KE(>B+XChoX%O{wbN zyPp&kn7}VZDoZcU&ZnI_M-WAzAmU@aj*V_y?TxTo%nLy9A3%NY^C6suAR52&_E&Gr z&1ik+`QyoGIy>vo+8<{1?XUOBSqC&4RA&y}z1<}TxD;|q)llw$>R>Lt{YkI>W&qN2 zbx95wNR`_@uBwfhdM8oUg>sUZvWHJNYj>U6E8;=VsG3khneP8Lgk;%baoYC#@m_aR zchK~Z5@Az=x#RWW)xAoHRDLbej~8T3K!u>?OG-SUckNbefGqT;1~sZ?Od^r1_jgo1 z0RbY_s{6yp|FTfWP~UT1)wbsJak2O=KWf)|x|*NM;$|sLEc%2Zv1*BWoTuv}viWOP zC#zEm%d(8J6p)uz%%~{WtD<3qiBRu-H1>Ul5BVp$7p=D`i+|VQlVQZa)sFRBJEI;B zt?|SLHWwhgsorXm+X<9&=>>ErJ8ii4$|XV>^0j;Z6Nx*7vTy3`ecs_vf_RTvNKmIx zHbE?>q+DW;$J^SZPYtZs2_U?pl;}$zO`3r46N*s=+ajVrf9o2VwZ9mu`*VtwL6@3L&w^+I_sL8(trCC8CXqlZ0Iez-FTQ@F$4oq=2mpNcw=Wp+{ zx>*8c%nf8Atd_L+zUW5D0_!08-^;IGszAx}hZ0-mb?xaPD+nn!0%=UJ=#AESil|2G zg=55cS?qO6%cOJ(ZV~(%{EkBL841vf_A1xtL&v4gI31wXo7j?rO_Hc)soBHYsbutL z)mrO6uZOxF0a;w=M~uqvix6cxXb&4yi@l{}2zU}uz@Q(X$#gOSdR6Ezr{iY44O8*d zKXXSHUgufFCpeR0S{`}uTj+Ls4ZG>wSqEPc5CY0;I^A-M*(5m z{rn^#Br^FBm4JTK5v~gHm7(hIFK-b9B1)Z%`@0lpP%&ITQEA6-ceqt*@$_-Yz!74XctyOM#12(O4!w$%_$_-Yz!B{G-a)VWFFq2KI+^`!SO~0vV zl^b@zpiy_3ta8I1ShUIwd!zI?PUlv+!74YH&868#A*pX&yL1@L&b$pJWL}(Seb5+tjyskUuRG(vJoM^d@*mx0pgmwfwF?Xs+<{1d7+^kV z2m41m*l2&>wYm$*=sJ7Qd@?07NlInE(I) diff --git a/test/api_integration/fixtures/es_archiver/saved_objects/basic/mappings.json b/test/api_integration/fixtures/es_archiver/saved_objects/basic/mappings.json index 350d46d618383..e601c43431437 100644 --- a/test/api_integration/fixtures/es_archiver/saved_objects/basic/mappings.json +++ b/test/api_integration/fixtures/es_archiver/saved_objects/basic/mappings.json @@ -260,20 +260,6 @@ "type": "text" } } - }, - "test-hidden-non-importable-exportable": { - "properties": { - "title": { - "type": "text" - } - } - }, - "test-hidden-importable-exportable": { - "properties": { - "title": { - "type": "text" - } - } } } } diff --git a/test/common/config.js b/test/common/config.js index ea48097c10bd4..46cd07b2ec370 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -51,13 +51,6 @@ export default function () { '--telemetry.url=https://telemetry-staging.elastic.co/xpack/v2/send', '--telemetry.optInStatusUrl=https://telemetry-staging.elastic.co/opt_in_status/v2/send', `--server.maxPayloadBytes=1679958`, - // test saved objects hidden type - `--plugin-path=${path.join( - __dirname, - 'fixtures', - 'plugins', - 'test_saved_objects_hidden_type' - )}`, // newsfeed mock service `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'newsfeed')}`, `--newsfeed.service.urlRoot=${servers.kibana.protocol}://${servers.kibana.hostname}:${servers.kibana.port}`, diff --git a/test/common/fixtures/plugins/test_saved_objects_hidden_type/kibana.json b/test/common/fixtures/plugins/test_saved_objects_hidden_type/kibana.json deleted file mode 100644 index a7e01fe1731e6..0000000000000 --- a/test/common/fixtures/plugins/test_saved_objects_hidden_type/kibana.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "testSavedObjectsHiddenType", - "version": "0.0.1", - "kibanaVersion": "kibana", - "configPath": ["test_saved_objects_hidden_type"], - "server": true, - "ui": false -} diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/data.json b/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/data.json new file mode 100644 index 0000000000000..6a272dc16e462 --- /dev/null +++ b/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/data.json @@ -0,0 +1,29 @@ +{ + "type": "doc", + "value": { + "index": ".kibana", + "id": "test-hidden-importable-exportable:ff3733a0-9fty-11e7-ahb3-3dcb94193fab", + "source": { + "type": "test-hidden-importable-exportable", + "updated_at": "2021-02-11T18:51:23.794Z", + "test-hidden-importable-exportable": { + "title": "Hidden Saved object type that is importable/exportable." + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana", + "id": "test-hidden-non-importable-exportable:op3767a1-9rcg-53u7-jkb3-3dnb74193awc", + "source": { + "type": "test-hidden-non-importable-exportable", + "updated_at": "2021-02-11T18:51:23.794Z", + "test-hidden-non-importable-exportable": { + "title": "Hidden Saved object type that is not importable/exportable." + } + } + } +} diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/mappings.json b/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/mappings.json new file mode 100644 index 0000000000000..00d349a27795d --- /dev/null +++ b/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/mappings.json @@ -0,0 +1,513 @@ +{ + "type": "index", + "value": { + "index": ".kibana", + "settings": { + "index": { + "number_of_shards": "1", + "auto_expand_replicas": "0-1", + "number_of_replicas": "0" + } + }, + "mappings": { + "dynamic": "strict", + "properties": { + "test-export-transform": { + "properties": { + "title": { "type": "text" }, + "enabled": { "type": "boolean" } + } + }, + "test-export-add": { + "properties": { + "title": { "type": "text" } + } + }, + "test-export-add-dep": { + "properties": { + "title": { "type": "text" } + } + }, + "test-export-transform-error": { + "properties": { + "title": { "type": "text" } + } + }, + "test-export-invalid-transform": { + "properties": { + "title": { "type": "text" } + } + }, + "apm-telemetry": { + "properties": { + "has_any_services": { + "type": "boolean" + }, + "services_per_agent": { + "properties": { + "go": { + "type": "long", + "null_value": 0 + }, + "java": { + "type": "long", + "null_value": 0 + }, + "js-base": { + "type": "long", + "null_value": 0 + }, + "nodejs": { + "type": "long", + "null_value": 0 + }, + "python": { + "type": "long", + "null_value": 0 + }, + "ruby": { + "type": "long", + "null_value": 0 + } + } + } + } + }, + "canvas-workpad": { + "dynamic": "false", + "properties": { + "@created": { + "type": "date" + }, + "@timestamp": { + "type": "date" + }, + "id": { + "type": "text", + "index": false + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword" + } + } + } + } + }, + "config": { + "dynamic": "true", + "properties": { + "accessibility:disableAnimations": { + "type": "boolean" + }, + "buildNum": { + "type": "keyword" + }, + "dateFormat:tz": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "defaultIndex": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "telemetry:optIn": { + "type": "boolean" + } + } + }, + "dashboard": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "optionsJSON": { + "type": "text" + }, + "panelsJSON": { + "type": "text" + }, + "refreshInterval": { + "properties": { + "display": { + "type": "keyword" + }, + "pause": { + "type": "boolean" + }, + "section": { + "type": "integer" + }, + "value": { + "type": "integer" + } + } + }, + "timeFrom": { + "type": "keyword" + }, + "timeRestore": { + "type": "boolean" + }, + "timeTo": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "map": { + "properties": { + "bounds": { + "type": "geo_shape", + "tree": "quadtree" + }, + "description": { + "type": "text" + }, + "layerListJSON": { + "type": "text" + }, + "mapStateJSON": { + "type": "text" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "graph-workspace": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "numLinks": { + "type": "integer" + }, + "numVertices": { + "type": "integer" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "wsState": { + "type": "text" + } + } + }, + "index-pattern": { + "properties": { + "fieldFormatMap": { + "type": "text" + }, + "fields": { + "type": "text" + }, + "intervalName": { + "type": "keyword" + }, + "notExpandable": { + "type": "boolean" + }, + "sourceFilters": { + "type": "text" + }, + "timeFieldName": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "type": { + "type": "keyword" + }, + "typeMeta": { + "type": "keyword" + } + } + }, + "kql-telemetry": { + "properties": { + "optInCount": { + "type": "long" + }, + "optOutCount": { + "type": "long" + } + } + }, + "migrationVersion": { + "dynamic": "true", + "properties": { + "index-pattern": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "space": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "namespace": { + "type": "keyword" + }, + "search": { + "properties": { + "columns": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "sort": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "server": { + "properties": { + "uuid": { + "type": "keyword" + } + } + }, + "space": { + "properties": { + "_reserved": { + "type": "boolean" + }, + "color": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "disabledFeatures": { + "type": "keyword" + }, + "initials": { + "type": "keyword" + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 2048 + } + } + } + } + }, + "spaceId": { + "type": "keyword" + }, + "telemetry": { + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "timelion-sheet": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "timelion_chart_height": { + "type": "integer" + }, + "timelion_columns": { + "type": "integer" + }, + "timelion_interval": { + "type": "keyword" + }, + "timelion_other_interval": { + "type": "keyword" + }, + "timelion_rows": { + "type": "integer" + }, + "timelion_sheet": { + "type": "text" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "url": { + "properties": { + "accessCount": { + "type": "long" + }, + "accessDate": { + "type": "date" + }, + "createDate": { + "type": "date" + }, + "url": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 2048 + } + } + } + } + }, + "visualization": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "savedSearchId": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "type": "text" + } + } + }, + "references": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, + "test-hidden-non-importable-exportable": { + "properties": { + "title": { + "type": "text" + } + } + }, + "test-hidden-importable-exportable": { + "properties": { + "title": { + "type": "text" + } + } + } + } + } + } +} diff --git a/test/plugin_functional/config.ts b/test/plugin_functional/config.ts index bd5ef814ae6c0..869e36837a1d7 100644 --- a/test/plugin_functional/config.ts +++ b/test/plugin_functional/config.ts @@ -21,15 +21,16 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { return { testFiles: [ - require.resolve('./test_suites/core'), - require.resolve('./test_suites/custom_visualizations'), - require.resolve('./test_suites/panel_actions'), - require.resolve('./test_suites/core_plugins'), - require.resolve('./test_suites/management'), - require.resolve('./test_suites/doc_views'), - require.resolve('./test_suites/application_links'), - require.resolve('./test_suites/data_plugin'), - require.resolve('./test_suites/saved_objects_management'), + // require.resolve('./test_suites/core'), + // require.resolve('./test_suites/custom_visualizations'), + // require.resolve('./test_suites/panel_actions'), + // require.resolve('./test_suites/core_plugins'), + // require.resolve('./test_suites/management'), + // require.resolve('./test_suites/doc_views'), + // require.resolve('./test_suites/application_links'), + // require.resolve('./test_suites/data_plugin'), + // require.resolve('./test_suites/saved_objects_management'), + require.resolve('./test_suites/saved_objects_hidden_type'), ], services: { ...functionalConfig.get('services'), diff --git a/test/plugin_functional/plugins/saved_objects_hidden_type/kibana.json b/test/plugin_functional/plugins/saved_objects_hidden_type/kibana.json new file mode 100644 index 0000000000000..baef662c695d4 --- /dev/null +++ b/test/plugin_functional/plugins/saved_objects_hidden_type/kibana.json @@ -0,0 +1,8 @@ +{ + "id": "savedObjectsHiddenType", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["saved_objects_hidden_type"], + "server": true, + "ui": false +} diff --git a/test/common/fixtures/plugins/test_saved_objects_hidden_type/package.json b/test/plugin_functional/plugins/saved_objects_hidden_type/package.json similarity index 67% rename from test/common/fixtures/plugins/test_saved_objects_hidden_type/package.json rename to test/plugin_functional/plugins/saved_objects_hidden_type/package.json index 37f97ac2f88c1..af5212209d574 100644 --- a/test/common/fixtures/plugins/test_saved_objects_hidden_type/package.json +++ b/test/plugin_functional/plugins/saved_objects_hidden_type/package.json @@ -1,7 +1,7 @@ { - "name": "test_saved_objects_hidden_type", + "name": "saved_objects_hidden_type", "version": "1.0.0", - "main": "target/test/plugin_functional/plugins/test_saved_objects_hidden_type", + "main": "target/test/plugin_functional/plugins/saved_objects_hidden_type", "kibana": { "version": "kibana", "templateVersion": "1.0.0" diff --git a/test/common/fixtures/plugins/test_saved_objects_hidden_type/server/index.ts b/test/plugin_functional/plugins/saved_objects_hidden_type/server/index.ts similarity index 73% rename from test/common/fixtures/plugins/test_saved_objects_hidden_type/server/index.ts rename to test/plugin_functional/plugins/saved_objects_hidden_type/server/index.ts index e220ae6481728..2093b6e8449a4 100644 --- a/test/common/fixtures/plugins/test_saved_objects_hidden_type/server/index.ts +++ b/test/plugin_functional/plugins/saved_objects_hidden_type/server/index.ts @@ -6,6 +6,6 @@ * Side Public License, v 1. */ -import { TestSavedObjectsHiddenTypePlugin } from './plugin'; +import { SavedObjectsHiddenTypePlugin } from './plugin'; -export const plugin = () => new TestSavedObjectsHiddenTypePlugin(); +export const plugin = () => new SavedObjectsHiddenTypePlugin(); diff --git a/test/common/fixtures/plugins/test_saved_objects_hidden_type/server/plugin.ts b/test/plugin_functional/plugins/saved_objects_hidden_type/server/plugin.ts similarity index 90% rename from test/common/fixtures/plugins/test_saved_objects_hidden_type/server/plugin.ts rename to test/plugin_functional/plugins/saved_objects_hidden_type/server/plugin.ts index 003068a0e16b0..da2a0a2def1c2 100644 --- a/test/common/fixtures/plugins/test_saved_objects_hidden_type/server/plugin.ts +++ b/test/plugin_functional/plugins/saved_objects_hidden_type/server/plugin.ts @@ -8,12 +8,13 @@ import { Plugin, CoreSetup } from 'kibana/server'; -export class TestSavedObjectsHiddenTypePlugin implements Plugin { +export class SavedObjectsHiddenTypePlugin implements Plugin { public setup({ savedObjects }: CoreSetup, deps: {}) { // example of a SO type that is hidden and importableAndExportable savedObjects.registerType({ name: 'test-hidden-importable-exportable', hidden: true, + namespaceType: 'single', mappings: { properties: { title: { type: 'text' }, @@ -28,6 +29,7 @@ export class TestSavedObjectsHiddenTypePlugin implements Plugin { savedObjects.registerType({ name: 'test-hidden-non-importable-exportable', hidden: true, + namespaceType: 'single', mappings: { properties: { title: { type: 'text' }, diff --git a/test/common/fixtures/plugins/test_saved_objects_hidden_type/tsconfig.json b/test/plugin_functional/plugins/saved_objects_hidden_type/tsconfig.json similarity index 100% rename from test/common/fixtures/plugins/test_saved_objects_hidden_type/tsconfig.json rename to test/plugin_functional/plugins/saved_objects_hidden_type/tsconfig.json diff --git a/test/plugin_functional/test_suites/saved_objects_hidden_type/delete.ts b/test/plugin_functional/test_suites/saved_objects_hidden_type/delete.ts new file mode 100644 index 0000000000000..666afe1acedca --- /dev/null +++ b/test/plugin_functional/test_suites/saved_objects_hidden_type/delete.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ getService }: PluginFunctionalProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('delete', () => { + before(() => + esArchiver.load( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + after(() => + esArchiver.unload( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + + it('should return generic 404 when trying to delete a doc with importableAndExportable types', async () => + await supertest + .delete( + `/api/saved_objects/test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab` + ) + .set('kbn-xsrf', 'true') + .expect(404) + .then((resp) => { + expect(resp.body).to.eql({ + statusCode: 404, + error: 'Not Found', + message: + 'Saved object [test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab] not found', + }); + })); + + it('returns empty response for non importableAndExportable types', async () => + await supertest + .delete( + `/api/saved_objects/test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc` + ) + .set('kbn-xsrf', 'true') + .expect(404) + .then((resp) => { + expect(resp.body).to.eql({ + statusCode: 404, + error: 'Not Found', + message: + 'Saved object [test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc] not found', + }); + })); + }); +} diff --git a/test/plugin_functional/test_suites/saved_objects_hidden_type/export.ts b/test/plugin_functional/test_suites/saved_objects_hidden_type/export.ts new file mode 100644 index 0000000000000..af25835db5a81 --- /dev/null +++ b/test/plugin_functional/test_suites/saved_objects_hidden_type/export.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { PluginFunctionalProviderContext } from '../../services'; + +function ndjsonToObject(input: string): string[] { + return input.split('\n').map((str) => JSON.parse(str)); +} + +export default function ({ getService }: PluginFunctionalProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('export', () => { + before(() => + esArchiver.load( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + after(() => + esArchiver.unload( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + + it('exports objects with importableAndExportable types', async () => + await supertest + .post('/api/saved_objects/_export') + .set('kbn-xsrf', 'true') + .send({ + type: ['test-hidden-importable-exportable'], + }) + .expect(200) + .then((resp) => { + const objects = ndjsonToObject(resp.text); + expect(objects).to.have.length(2); + expect(objects[0]).to.have.property('id', 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab'); + expect(objects[0]).to.have.property('type', 'test-hidden-importable-exportable'); + })); + + it('excludes objects with non importableAndExportable types', async () => + await supertest + .post('/api/saved_objects/_export') + .set('kbn-xsrf', 'true') + .send({ + type: ['test-hidden-non-importable-exportable'], + }) + .then((resp) => { + expect(resp.body).to.eql({ + statusCode: 400, + error: 'Bad Request', + message: + 'Trying to export non-exportable type(s): test-hidden-non-importable-exportable', + }); + })); + }); +} diff --git a/test/plugin_functional/test_suites/saved_objects_hidden_type/find.ts b/test/plugin_functional/test_suites/saved_objects_hidden_type/find.ts new file mode 100644 index 0000000000000..723140f5c6bf5 --- /dev/null +++ b/test/plugin_functional/test_suites/saved_objects_hidden_type/find.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ getService }: PluginFunctionalProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('find', () => { + before(() => + esArchiver.load( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + after(() => + esArchiver.unload( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + + it('returns empty response for importableAndExportable types', async () => + await supertest + .get('/api/saved_objects/_find?type=test-hidden-importable-exportable&fields=title') + .set('kbn-xsrf', 'true') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + page: 1, + per_page: 20, + total: 0, + saved_objects: [], + }); + })); + + it('returns empty response for non importableAndExportable types', async () => + await supertest + .get('/api/saved_objects/_find?type=test-hidden-non-importable-exportable&fields=title') + .set('kbn-xsrf', 'true') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + page: 1, + per_page: 20, + total: 0, + saved_objects: [], + }); + })); + }); +} diff --git a/test/plugin_functional/test_suites/saved_objects_hidden_type/import.ts b/test/plugin_functional/test_suites/saved_objects_hidden_type/import.ts new file mode 100644 index 0000000000000..5de7d8375dd8c --- /dev/null +++ b/test/plugin_functional/test_suites/saved_objects_hidden_type/import.ts @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ getService }: PluginFunctionalProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('import', () => { + before(() => + esArchiver.load( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + after(() => + esArchiver.unload( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + + it('imports objects with importableAndExportable type', async () => { + const fileBuffer = Buffer.from( + '{"id":"some-id-1","type":"test-hidden-importable-exportable","attributes":{"title":"my title"},"references":[]}', + 'utf8' + ); + await supertest + .post('/api/saved_objects/_import') + .set('kbn-xsrf', 'true') + .attach('file', fileBuffer, 'export.ndjson') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + successCount: 1, + success: true, + warnings: [], + successResults: [ + { + type: 'test-hidden-importable-exportable', + id: 'some-id-1', + meta: { + title: 'my title', + }, + }, + ], + }); + }); + }); + + it('does not import objects with non importableAndExportable type', async () => { + const fileBuffer = Buffer.from( + '{"id":"some-id-1","type":"test-hidden-non-importable-exportable","attributes":{"title":"my title"},"references":[]}', + 'utf8' + ); + await supertest + .post('/api/saved_objects/_import') + .set('kbn-xsrf', 'true') + .attach('file', fileBuffer, 'export.ndjson') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + successCount: 0, + success: false, + warnings: [], + errors: [ + { + id: 'some-id-1', + type: 'test-hidden-non-importable-exportable', + title: 'my title', + meta: { + title: 'my title', + }, + error: { + type: 'unsupported_type', + }, + }, + ], + }); + }); + }); + }); +} diff --git a/test/plugin_functional/test_suites/saved_objects_hidden_type/index.ts b/test/plugin_functional/test_suites/saved_objects_hidden_type/index.ts new file mode 100644 index 0000000000000..ba4835cdab089 --- /dev/null +++ b/test/plugin_functional/test_suites/saved_objects_hidden_type/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ loadTestFile }: PluginFunctionalProviderContext) { + describe('Saved objects with hidden type', function () { + loadTestFile(require.resolve('./import')); + loadTestFile(require.resolve('./export')); + loadTestFile(require.resolve('./resolve_import_errors')); + loadTestFile(require.resolve('./find')); + loadTestFile(require.resolve('./delete')); + }); +} diff --git a/test/plugin_functional/test_suites/saved_objects_hidden_type/resolve_import_errors.ts b/test/plugin_functional/test_suites/saved_objects_hidden_type/resolve_import_errors.ts new file mode 100644 index 0000000000000..dddee085ae22b --- /dev/null +++ b/test/plugin_functional/test_suites/saved_objects_hidden_type/resolve_import_errors.ts @@ -0,0 +1,112 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ getService }: PluginFunctionalProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('export', () => { + before(() => + esArchiver.load( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + after(() => + esArchiver.unload( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + + it('resolves objects with importableAndExportable types', async () => { + const fileBuffer = Buffer.from( + '{"id":"ff3733a0-9fty-11e7-ahb3-3dcb94193fab","type":"test-hidden-importable-exportable","attributes":{"title":"new title!"},"references":[]}', + 'utf8' + ); + + await supertest + .post('/api/saved_objects/_resolve_import_errors') + .set('kbn-xsrf', 'true') + .field( + 'retries', + JSON.stringify([ + { + id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab', + type: 'test-hidden-importable-exportable', + overwrite: true, + }, + ]) + ) + .attach('file', fileBuffer, 'import.ndjson') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + successCount: 1, + success: true, + warnings: [], + successResults: [ + { + type: 'test-hidden-importable-exportable', + id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab', + meta: { + title: 'new title!', + }, + overwrite: true, + }, + ], + }); + }); + }); + + it('rejects objects with non importableAndExportable types', async () => { + const fileBuffer = Buffer.from( + '{"id":"op3767a1-9rcg-53u7-jkb3-3dnb74193awc","type":"test-hidden-non-importable-exportable","attributes":{"title":"new title!"},"references":[]}', + 'utf8' + ); + + await supertest + .post('/api/saved_objects/_resolve_import_errors') + .set('kbn-xsrf', 'true') + .field( + 'retries', + JSON.stringify([ + { + id: 'op3767a1-9rcg-53u7-jkb3-3dnb74193awc', + type: 'test-hidden-non-importable-exportable', + overwrite: true, + }, + ]) + ) + .attach('file', fileBuffer, 'import.ndjson') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + successCount: 0, + success: false, + warnings: [], + errors: [ + { + id: 'op3767a1-9rcg-53u7-jkb3-3dnb74193awc', + type: 'test-hidden-non-importable-exportable', + title: 'new title!', + meta: { + title: 'new title!', + }, + error: { + type: 'unsupported_type', + }, + overwrite: true, + }, + ], + }); + }); + }); + }); +} diff --git a/test/plugin_functional/test_suites/saved_objects_management/find.ts b/test/plugin_functional/test_suites/saved_objects_management/find.ts new file mode 100644 index 0000000000000..91f98d80b576c --- /dev/null +++ b/test/plugin_functional/test_suites/saved_objects_management/find.ts @@ -0,0 +1,78 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ getService }: PluginFunctionalProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('find', () => { + before(() => + esArchiver.load( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + after(() => + esArchiver.unload( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + + describe('saved objects with hidden types', () => { + it('returns saved objects with importableAndExportable types', async () => + await supertest + .get( + '/api/kibana/management/saved_objects/_find?type=test-hidden-importable-exportable&fields=title' + ) + .set('kbn-xsrf', 'true') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + page: 1, + per_page: 20, + total: 1, + saved_objects: [ + { + type: 'test-hidden-importable-exportable', + id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab', + attributes: { + title: 'Hidden Saved object type that is importable/exportable.', + }, + references: [], + updated_at: '2021-02-11T18:51:23.794Z', + version: 'WzIsMl0=', + namespaces: ['default'], + score: 0, + meta: { + namespaceType: 'single', + }, + }, + ], + }); + })); + + it('returns empty response for non importableAndExportable types', async () => + await supertest + .get( + '/api/kibana/management/saved_objects/_find?type=test-hidden-non-importable-exportable' + ) + .set('kbn-xsrf', 'true') + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + page: 1, + per_page: 20, + total: 0, + saved_objects: [], + }); + })); + }); + }); +} diff --git a/test/plugin_functional/test_suites/saved_objects_management/get.ts b/test/plugin_functional/test_suites/saved_objects_management/get.ts new file mode 100644 index 0000000000000..56ed1035c7018 --- /dev/null +++ b/test/plugin_functional/test_suites/saved_objects_management/get.ts @@ -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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ getService }: PluginFunctionalProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('get', () => { + before(() => + esArchiver.load( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + after(() => + esArchiver.unload( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + + describe('saved objects with hidden types', () => { + const hiddenTypeExportableImportable = + 'test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab'; + const hiddenTypeNonExportableImportable = + 'test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc'; + + it('should return 200 for hidden types that are importableAndExportable', async () => + await supertest + .get(`/api/kibana/management/saved_objects/${hiddenTypeExportableImportable}`) + .set('kbn-xsrf', 'true') + .expect(200) + .then((resp) => { + const { body } = resp; + const { type, id, meta } = body; + expect(type).to.eql('test-hidden-importable-exportable'); + expect(id).to.eql('ff3733a0-9fty-11e7-ahb3-3dcb94193fab'); + expect(meta).to.not.equal(undefined); + })); + + it('should return 404 for hidden types that are not importableAndExportable', async () => + await supertest + .get(`/api/kibana/management/saved_objects/${hiddenTypeNonExportableImportable}`) + .set('kbn-xsrf', 'true') + .expect(404)); + }); + }); +} diff --git a/test/plugin_functional/test_suites/saved_objects_management/index.ts b/test/plugin_functional/test_suites/saved_objects_management/index.ts index f6d383e60388d..9f2d28b582f78 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/index.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/index.ts @@ -10,6 +10,9 @@ import { PluginFunctionalProviderContext } from '../../services'; export default function ({ loadTestFile }: PluginFunctionalProviderContext) { describe('Saved Objects Management', function () { + loadTestFile(require.resolve('./find')); + loadTestFile(require.resolve('./scroll_count')); + loadTestFile(require.resolve('./get')); loadTestFile(require.resolve('./export_transform')); loadTestFile(require.resolve('./import_warnings')); }); diff --git a/test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts b/test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts new file mode 100644 index 0000000000000..054a35e4333a8 --- /dev/null +++ b/test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ getService }: PluginFunctionalProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + const apiUrl = '/api/kibana/management/saved_objects/scroll/counts'; + + describe('scroll_count', () => { + before(() => + esArchiver.load( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + after(() => + esArchiver.unload( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + + describe('saved objects with hidden types', () => { + it('only counts hidden types that are importableAndExportable', async () => { + const res = await supertest + .post(apiUrl) + .set('kbn-xsrf', 'true') + .send({ + typesToInclude: [ + 'test-hidden-non-importable-exportable', + 'test-hidden-importable-exportable', + ], + }) + .expect(200); + + expect(res.body).to.eql({ + 'test-hidden-importable-exportable': 1, + 'test-hidden-non-importable-exportable': 0, + }); + }); + }); + }); +} From 3c2bef49b4c82d817cdaabdee329766c90403afd Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 11 Feb 2021 13:11:03 +0200 Subject: [PATCH 11/14] self codereview --- data.json.gz | 0 test/plugin_functional/config.ts | 18 +++++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) delete mode 100644 data.json.gz diff --git a/data.json.gz b/data.json.gz deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/test/plugin_functional/config.ts b/test/plugin_functional/config.ts index 869e36837a1d7..fc747fcd71f17 100644 --- a/test/plugin_functional/config.ts +++ b/test/plugin_functional/config.ts @@ -21,15 +21,15 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { return { testFiles: [ - // require.resolve('./test_suites/core'), - // require.resolve('./test_suites/custom_visualizations'), - // require.resolve('./test_suites/panel_actions'), - // require.resolve('./test_suites/core_plugins'), - // require.resolve('./test_suites/management'), - // require.resolve('./test_suites/doc_views'), - // require.resolve('./test_suites/application_links'), - // require.resolve('./test_suites/data_plugin'), - // require.resolve('./test_suites/saved_objects_management'), + require.resolve('./test_suites/core'), + require.resolve('./test_suites/custom_visualizations'), + require.resolve('./test_suites/panel_actions'), + require.resolve('./test_suites/core_plugins'), + require.resolve('./test_suites/management'), + require.resolve('./test_suites/doc_views'), + require.resolve('./test_suites/application_links'), + require.resolve('./test_suites/data_plugin'), + require.resolve('./test_suites/saved_objects_management'), require.resolve('./test_suites/saved_objects_hidden_type'), ], services: { From fcce36a1e3fe1da0ce258640a1f9fdde5906fe0f Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 11 Feb 2021 13:17:28 +0200 Subject: [PATCH 12/14] fix typo --- .../test_suites/saved_objects_management/find.ts | 2 +- .../test_suites/saved_objects_management/get.ts | 2 +- .../test_suites/saved_objects_management/scroll_count.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/plugin_functional/test_suites/saved_objects_management/find.ts b/test/plugin_functional/test_suites/saved_objects_management/find.ts index 91f98d80b576c..5e2f193ea44d9 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/find.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/find.ts @@ -25,7 +25,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { ) ); - describe('saved objects with hidden types', () => { + describe('saved objects with hidden type', () => { it('returns saved objects with importableAndExportable types', async () => await supertest .get( diff --git a/test/plugin_functional/test_suites/saved_objects_management/get.ts b/test/plugin_functional/test_suites/saved_objects_management/get.ts index 56ed1035c7018..1d558cb0837c4 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/get.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/get.ts @@ -25,7 +25,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { ) ); - describe('saved objects with hidden types', () => { + describe('saved objects with hidden type', () => { const hiddenTypeExportableImportable = 'test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab'; const hiddenTypeNonExportableImportable = diff --git a/test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts b/test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts index 054a35e4333a8..be1dc125390d3 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts @@ -26,7 +26,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { ) ); - describe('saved objects with hidden types', () => { + describe('saved objects with hidden type', () => { it('only counts hidden types that are importableAndExportable', async () => { const res = await supertest .post(apiUrl) From c437d55ad20dfcd74cfab3af793c910f2e0c1bfe Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 11 Feb 2021 13:18:30 +0200 Subject: [PATCH 13/14] tidying up things --- .../saved_objects_management/find.ts | 21 +++++++++--------- .../saved_objects_management/get.ts | 21 +++++++++--------- .../saved_objects_management/scroll_count.ts | 22 +++++++++---------- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/test/plugin_functional/test_suites/saved_objects_management/find.ts b/test/plugin_functional/test_suites/saved_objects_management/find.ts index 5e2f193ea44d9..5dce8f43339a1 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/find.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/find.ts @@ -14,18 +14,17 @@ export default function ({ getService }: PluginFunctionalProviderContext) { const esArchiver = getService('esArchiver'); describe('find', () => { - before(() => - esArchiver.load( - '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' - ) - ); - after(() => - esArchiver.unload( - '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' - ) - ); - describe('saved objects with hidden type', () => { + before(() => + esArchiver.load( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + after(() => + esArchiver.unload( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); it('returns saved objects with importableAndExportable types', async () => await supertest .get( diff --git a/test/plugin_functional/test_suites/saved_objects_management/get.ts b/test/plugin_functional/test_suites/saved_objects_management/get.ts index 1d558cb0837c4..fa35983df8301 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/get.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/get.ts @@ -14,18 +14,17 @@ export default function ({ getService }: PluginFunctionalProviderContext) { const esArchiver = getService('esArchiver'); describe('get', () => { - before(() => - esArchiver.load( - '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' - ) - ); - after(() => - esArchiver.unload( - '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' - ) - ); - describe('saved objects with hidden type', () => { + before(() => + esArchiver.load( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + after(() => + esArchiver.unload( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); const hiddenTypeExportableImportable = 'test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab'; const hiddenTypeNonExportableImportable = diff --git a/test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts b/test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts index be1dc125390d3..f74cd5b938447 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/scroll_count.ts @@ -15,18 +15,18 @@ export default function ({ getService }: PluginFunctionalProviderContext) { const apiUrl = '/api/kibana/management/saved_objects/scroll/counts'; describe('scroll_count', () => { - before(() => - esArchiver.load( - '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' - ) - ); - after(() => - esArchiver.unload( - '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' - ) - ); - describe('saved objects with hidden type', () => { + before(() => + esArchiver.load( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + after(() => + esArchiver.unload( + '../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects' + ) + ); + it('only counts hidden types that are importableAndExportable', async () => { const res = await supertest .post(apiUrl) From f8cf3fbfae9c2b6c32636ac9f5b86bcba92c9f12 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sun, 14 Feb 2021 16:45:09 +0200 Subject: [PATCH 14/14] add FTR test for SOM UI --- .../components/import_summary.tsx | 5 +- .../management/saved_objects_page.ts | 12 ++++ .../saved_objects_hidden_type/index.ts | 1 + .../exports/_import_hidden_importable.ndjson | 1 + .../_import_hidden_non_importable.ndjson | 1 + .../interface/saved_objects_management.ts | 55 +++++++++++++++++++ 6 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 test/plugin_functional/test_suites/saved_objects_hidden_type/interface/exports/_import_hidden_importable.ndjson create mode 100644 test/plugin_functional/test_suites/saved_objects_hidden_type/interface/exports/_import_hidden_non_importable.ndjson create mode 100644 test/plugin_functional/test_suites/saved_objects_hidden_type/interface/saved_objects_management.ts diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.tsx index b1570bb1fff0d..8b07351f6c2c2 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/import_summary.tsx @@ -123,7 +123,10 @@ const CountIndicators: FC<{ importItems: ImportItem[] }> = ({ importItems }) => {errorCount && ( -

+

{ + before(() => esArchiver.emptyKibanaIndex()); + beforeEach(async () => { + await PageObjects.settings.navigateTo(); + await PageObjects.settings.clickKibanaSavedObjects(); + }); + describe('importable/exportable hidden type', () => { + it('imports objects successfully', async () => { + await PageObjects.savedObjects.importFile(fixturePaths.hiddenImportable); + await PageObjects.savedObjects.checkImportSucceeded(); + }); + + it('shows test-hidden-importable-exportable in table', async () => { + await PageObjects.savedObjects.searchForObject('type:(test-hidden-importable-exportable)'); + const results = await PageObjects.savedObjects.getTableSummary(); + expect(results.length).to.be(1); + + const { title } = results[0]; + expect(title).to.be( + 'test-hidden-importable-exportable [id=ff3733a0-9fty-11e7-ahb3-3dcb94193fab]' + ); + }); + }); + + describe('non-importable/exportable hidden type', () => { + it('fails to import object', async () => { + await PageObjects.savedObjects.importFile(fixturePaths.hiddenNonImportable); + await PageObjects.savedObjects.checkImportSucceeded(); + + const errorsCount = await PageObjects.savedObjects.getImportErrorsCount(); + expect(errorsCount).to.be(1); + }); + }); + }); +}