From 2937c7d2c372df7e4d535cfe0af406bf4a4709af Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 21 Sep 2021 07:51:22 -0400 Subject: [PATCH] [SOM] Add `visibleInManagement` option to management metadata (#112073) (#112639) * implement SavedObjectsTypeManagementDefinition.visibleInManagement * update generated doc * improve FTR tests * fix FTR test Co-authored-by: Pierre Gayvallet --- ...in-core-server.deprecationsservicesetup.md | 1 + ...er.savedobjectstypemanagementdefinition.md | 1 + ...anagementdefinition.visibleinmanagement.md | 18 + .../saved_objects_type_registry.test.ts | 53 ++ .../saved_objects_type_registry.ts | 5 + src/core/server/saved_objects/types.ts | 9 + src/core/server/server.api.md | 1 + .../server/routes/get_allowed_types.ts | 1 + .../visible_in_management/data.json | 20 + .../visible_in_management/mappings.json | 477 ++++++++++++++++++ .../server/plugin.ts | 36 ++ .../_import_non_visible_in_management.ndjson | 1 + .../saved_objects_management/index.ts | 1 + .../visible_in_management.ts | 113 +++++ 14 files changed, 737 insertions(+) create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.visibleinmanagement.md create mode 100644 test/functional/fixtures/es_archiver/saved_objects_management/visible_in_management/data.json create mode 100644 test/functional/fixtures/es_archiver/saved_objects_management/visible_in_management/mappings.json create mode 100644 test/plugin_functional/test_suites/saved_objects_management/exports/_import_non_visible_in_management.ndjson create mode 100644 test/plugin_functional/test_suites/saved_objects_management/visible_in_management.ts diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md index 7b2cbdecd146a..2bc7f6cba594d 100644 --- a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md @@ -27,6 +27,7 @@ async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecations const deprecations: DeprecationsDetails[] = []; const count = await getFooCount(savedObjectsClient); if (count > 0) { + // Example of a manual correctiveAction deprecations.push({ title: i18n.translate('xpack.foo.deprecations.title', { defaultMessage: `Foo's are deprecated` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md index 8c42884eb0b31..2c3dd9f3f8434 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md @@ -25,4 +25,5 @@ export interface SavedObjectsTypeManagementDefinition | [isExportable](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.isexportable.md) | SavedObjectsExportablePredicate<Attributes> | Optional hook to specify whether an object should be exportable.If specified, isExportable will be called during export for each of this type's objects in the export, and the ones not matching the predicate will be excluded from the export.When implementing both isExportable and onExport, it is mandatory that isExportable returns the same value for an object before and after going though the export transform. E.g isExportable(objectBeforeTransform) === isExportable(objectAfterTransform) | | [onExport](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md) | SavedObjectsExportTransform<Attributes> | An optional export transform function that can be used transform the objects of the registered type during the export process.It can be used to either mutate the exported objects, or add additional objects (of any type) to the export list.See [the transform type documentation](./kibana-plugin-core-server.savedobjectsexporttransform.md) for more info and examples.When implementing both isExportable and onExport, it is mandatory that isExportable returns the same value for an object before and after going though the export transform. E.g isExportable(objectBeforeTransform) === isExportable(objectAfterTransform) | | [onImport](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md) | SavedObjectsImportHook<Attributes> | An optional [import hook](./kibana-plugin-core-server.savedobjectsimporthook.md) to use when importing given type.Import hooks are executed during the savedObjects import process and allow to interact with the imported objects. See the [hook documentation](./kibana-plugin-core-server.savedobjectsimporthook.md) for more info. | +| [visibleInManagement](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.visibleinmanagement.md) | boolean | When set to false, the type will not be listed or searchable in the SO management section. Main usage of setting this property to false for a type is when objects from the type should be included in the export via references or export hooks, but should not directly appear in the SOM. Defaults to true. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.visibleinmanagement.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.visibleinmanagement.md new file mode 100644 index 0000000000000..33ddc8e8c8307 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.visibleinmanagement.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsTypeManagementDefinition](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.md) > [visibleInManagement](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.visibleinmanagement.md) + +## SavedObjectsTypeManagementDefinition.visibleInManagement property + +When set to false, the type will not be listed or searchable in the SO management section. Main usage of setting this property to false for a type is when objects from the type should be included in the export via references or export hooks, but should not directly appear in the SOM. Defaults to `true`. + +Signature: + +```typescript +visibleInManagement?: boolean; +``` + +## Remarks + +`importableAndExportable` must be `true` to specify this property. + diff --git a/src/core/server/saved_objects/saved_objects_type_registry.test.ts b/src/core/server/saved_objects/saved_objects_type_registry.test.ts index 872b61706c526..c86a1a54f14a8 100644 --- a/src/core/server/saved_objects/saved_objects_type_registry.test.ts +++ b/src/core/server/saved_objects/saved_objects_type_registry.test.ts @@ -47,6 +47,59 @@ describe('SavedObjectTypeRegistry', () => { }).toThrowErrorMatchingInlineSnapshot(`"Type 'typeA' is already registered"`); }); + it('throws when `management.visibleInManagement` is specified but `management.importableAndExportable` is undefined or false', () => { + expect(() => { + registry.registerType( + createType({ + name: 'typeA', + management: { + visibleInManagement: true, + }, + }) + ); + }).toThrowErrorMatchingInlineSnapshot( + `"Type typeA: 'management.importableAndExportable' must be 'true' when specifying 'management.visibleInManagement'"` + ); + + expect(() => { + registry.registerType( + createType({ + name: 'typeA', + management: { + visibleInManagement: false, + }, + }) + ); + }).toThrowErrorMatchingInlineSnapshot( + `"Type typeA: 'management.importableAndExportable' must be 'true' when specifying 'management.visibleInManagement'"` + ); + + expect(() => { + registry.registerType( + createType({ + name: 'typeA', + management: { + importableAndExportable: false, + visibleInManagement: false, + }, + }) + ); + }).toThrowErrorMatchingInlineSnapshot( + `"Type typeA: 'management.importableAndExportable' must be 'true' when specifying 'management.visibleInManagement'"` + ); + expect(() => { + registry.registerType( + createType({ + name: 'typeA', + management: { + importableAndExportable: true, + visibleInManagement: false, + }, + }) + ); + }).not.toThrow(); + }); + it('throws when `management.onExport` is specified but `management.importableAndExportable` is undefined or false', () => { expect(() => { registry.registerType( diff --git a/src/core/server/saved_objects/saved_objects_type_registry.ts b/src/core/server/saved_objects/saved_objects_type_registry.ts index ba5960c59239d..444af58eee801 100644 --- a/src/core/server/saved_objects/saved_objects_type_registry.ts +++ b/src/core/server/saved_objects/saved_objects_type_registry.ts @@ -134,5 +134,10 @@ const validateType = ({ name, management }: SavedObjectsType) => { `Type ${name}: 'management.importableAndExportable' must be 'true' when specifying 'management.onExport'` ); } + if (management.visibleInManagement !== undefined && !management.importableAndExportable) { + throw new Error( + `Type ${name}: 'management.importableAndExportable' must be 'true' when specifying 'management.visibleInManagement'` + ); + } } }; diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index 83f46c521a836..b2a6be38bb526 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -356,6 +356,15 @@ export interface SavedObjectsTypeManagementDefinition { * Is the type importable or exportable. Defaults to `false`. */ importableAndExportable?: boolean; + /** + * When set to false, the type will not be listed or searchable in the SO management section. + * Main usage of setting this property to false for a type is when objects from the type should + * be included in the export via references or export hooks, but should not directly appear in the SOM. + * Defaults to `true`. + * + * @remarks `importableAndExportable` must be `true` to specify this property. + */ + visibleInManagement?: boolean; /** * The default search field to use for this type. Defaults to `id`. */ diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index bd959e2cb5a7d..a558a121625bb 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2728,6 +2728,7 @@ export interface SavedObjectsTypeManagementDefinition { isExportable?: SavedObjectsExportablePredicate; onExport?: SavedObjectsExportTransform; onImport?: SavedObjectsImportHook; + visibleInManagement?: boolean; } // @public diff --git a/src/plugins/saved_objects_management/server/routes/get_allowed_types.ts b/src/plugins/saved_objects_management/server/routes/get_allowed_types.ts index 13adf2764b555..ce371ea590230 100644 --- a/src/plugins/saved_objects_management/server/routes/get_allowed_types.ts +++ b/src/plugins/saved_objects_management/server/routes/get_allowed_types.ts @@ -17,6 +17,7 @@ export const registerGetAllowedTypesRoute = (router: IRouter) => { async (context, req, res) => { const allowedTypes = context.core.savedObjects.typeRegistry .getImportableAndExportableTypes() + .filter((type) => type.management!.visibleInManagement ?? true) .map((type) => type.name); return res.ok({ diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/visible_in_management/data.json b/test/functional/fixtures/es_archiver/saved_objects_management/visible_in_management/data.json new file mode 100644 index 0000000000000..236d7bbff7215 --- /dev/null +++ b/test/functional/fixtures/es_archiver/saved_objects_management/visible_in_management/data.json @@ -0,0 +1,20 @@ +{ + "type": "doc", + "value": { + "id": "test-not-visible-in-management:vim-1", + "index": ".kibana", + "source": { + "coreMigrationVersion": "7.14.0", + "references": [ + ], + "test-not-visible-in-management": { + "enabled": true, + "title": "vim-1" + }, + "type": "test-not-visible-in-management", + "updated_at": "2018-12-21T00:43:07.096Z" + }, + "type": "_doc" + } +} + diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/visible_in_management/mappings.json b/test/functional/fixtures/es_archiver/saved_objects_management/visible_in_management/mappings.json new file mode 100644 index 0000000000000..3c0a975a30be0 --- /dev/null +++ b/test/functional/fixtures/es_archiver/saved_objects_management/visible_in_management/mappings.json @@ -0,0 +1,477 @@ +{ + "type": "index", + "value": { + "aliases": { + ".kibana_$KIBANA_PACKAGE_VERSION": {}, + ".kibana": {} + }, + "index": ".kibana_$KIBANA_PACKAGE_VERSION_001", + "mappings": { + "_meta": { + "migrationMappingPropertyHashes": { + "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd", + "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724", + "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724", + "config": "c63748b75f39d0c54de12d12c1ccbc20", + "core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724", + "coreMigrationVersion": "2f4316de49999235636386fe51dc06c1", + "dashboard": "40554caf09725935e2c02e02563a2d07", + "index-pattern": "45915a1ad866812242df474eb0479052", + "kql-telemetry": "d12a98a6f19a2d273696597547e064ee", + "legacy-url-alias": "6155300fd11a00e23d5cbaa39f0fce0a", + "migrationVersion": "4a1746014a75ade3a714e1db5763276f", + "namespace": "2f4316de49999235636386fe51dc06c1", + "namespaces": "2f4316de49999235636386fe51dc06c1", + "originId": "2f4316de49999235636386fe51dc06c1", + "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9", + "references": "7997cf5a56cc02bdc9c93361bde732b0", + "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4", + "search": "db2c00e39b36f40930a3b9fc71c823e1", + "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724", + "telemetry": "36a616f7026dfa617d6655df850fe16d", + "type": "2f4316de49999235636386fe51dc06c1", + "ui-counter": "0d409297dc5ebe1e3a1da691c6ee32e3", + "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3", + "updated_at": "00da57df13e94e9d98437d13ace4bfe0", + "url": "c7f66a0df8b1b52f17c28c4adb111105", + "usage-counters": "8cc260bdceffec4ffc3ad165c97dc1b4", + "visualization": "f819cf6636b75c9e76ba733a0c6ef355" + } + }, + "dynamic": "strict", + "properties": { + "apm-telemetry": { + "dynamic": "false", + "type": "object" + }, + "application_usage_daily": { + "dynamic": "false", + "properties": { + "timestamp": { + "type": "date" + } + } + }, + "application_usage_totals": { + "dynamic": "false", + "type": "object" + }, + "application_usage_transactional": { + "dynamic": "false", + "type": "object" + }, + "canvas-workpad": { + "dynamic": "false", + "type": "object" + }, + "config": { + "dynamic": "false", + "properties": { + "buildNum": { + "type": "keyword" + } + } + }, + "core-usage-stats": { + "dynamic": "false", + "type": "object" + }, + "coreMigrationVersion": { + "type": "keyword" + }, + "dashboard": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "doc_values": false, + "index": false, + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "index": false, + "type": "text" + } + } + }, + "optionsJSON": { + "index": false, + "type": "text" + }, + "panelsJSON": { + "index": false, + "type": "text" + }, + "refreshInterval": { + "properties": { + "display": { + "doc_values": false, + "index": false, + "type": "keyword" + }, + "pause": { + "doc_values": false, + "index": false, + "type": "boolean" + }, + "section": { + "doc_values": false, + "index": false, + "type": "integer" + }, + "value": { + "doc_values": false, + "index": false, + "type": "integer" + } + } + }, + "timeFrom": { + "doc_values": false, + "index": false, + "type": "keyword" + }, + "timeRestore": { + "doc_values": false, + "index": false, + "type": "boolean" + }, + "timeTo": { + "doc_values": false, + "index": false, + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "graph-workspace": { + "dynamic": "false", + "type": "object" + }, + "index-pattern": { + "dynamic": "false", + "properties": { + "title": { + "type": "text" + }, + "type": { + "type": "keyword" + } + } + }, + "kql-telemetry": { + "properties": { + "optInCount": { + "type": "long" + }, + "optOutCount": { + "type": "long" + } + } + }, + "legacy-url-alias": { + "dynamic": "false", + "properties": { + "disabled": { + "type": "boolean" + }, + "sourceId": { + "type": "keyword" + }, + "targetType": { + "type": "keyword" + } + } + }, + "map": { + "dynamic": "false", + "type": "object" + }, + "migrationVersion": { + "dynamic": "true", + "type": "object" + }, + "namespace": { + "type": "keyword" + }, + "namespaces": { + "type": "keyword" + }, + "originId": { + "type": "keyword" + }, + "query": { + "properties": { + "description": { + "type": "text" + }, + "filters": { + "enabled": false, + "type": "object" + }, + "query": { + "properties": { + "language": { + "type": "keyword" + }, + "query": { + "index": false, + "type": "keyword" + } + } + }, + "timefilter": { + "enabled": false, + "type": "object" + }, + "title": { + "type": "text" + } + } + }, + "references": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, + "sample-data-telemetry": { + "properties": { + "installCount": { + "type": "long" + }, + "unInstallCount": { + "type": "long" + } + } + }, + "search": { + "properties": { + "columns": { + "doc_values": false, + "index": false, + "type": "keyword" + }, + "description": { + "type": "text" + }, + "grid": { + "enabled": false, + "type": "object" + }, + "hideChart": { + "doc_values": false, + "index": false, + "type": "boolean" + }, + "hits": { + "doc_values": false, + "index": false, + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "index": false, + "type": "text" + } + } + }, + "sort": { + "doc_values": false, + "index": false, + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "search-telemetry": { + "dynamic": "false", + "type": "object" + }, + "server": { + "dynamic": "false", + "type": "object" + }, + "space": { + "dynamic": "false", + "type": "object" + }, + "spaceId": { + "type": "keyword" + }, + "telemetry": { + "properties": { + "allowChangingOptInStatus": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "lastReported": { + "type": "date" + }, + "lastVersionChecked": { + "type": "keyword" + }, + "reportFailureCount": { + "type": "integer" + }, + "reportFailureVersion": { + "type": "keyword" + }, + "sendUsageFrom": { + "type": "keyword" + }, + "userHasSeenNotice": { + "type": "boolean" + } + } + }, + "test-export-add": { + "dynamic": "false", + "type": "object" + }, + "test-export-add-dep": { + "dynamic": "false", + "type": "object" + }, + "test-export-invalid-transform": { + "dynamic": "false", + "type": "object" + }, + "test-export-transform": { + "dynamic": "false", + "type": "object" + }, + "test-export-transform-error": { + "dynamic": "false", + "type": "object" + }, + "test-visible-in-management": { + "dynamic": "false", + "type": "object" + }, + "test-not-visible-in-management": { + "dynamic": "false", + "type": "object" + }, + "type": { + "type": "keyword" + }, + "ui-counter": { + "properties": { + "count": { + "type": "integer" + } + } + }, + "ui-metric": { + "properties": { + "count": { + "type": "integer" + } + } + }, + "updated_at": { + "type": "date" + }, + "url": { + "properties": { + "accessCount": { + "type": "long" + }, + "accessDate": { + "type": "date" + }, + "createDate": { + "type": "date" + }, + "url": { + "fields": { + "keyword": { + "ignore_above": 2048, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "usage-counters": { + "dynamic": "false", + "properties": { + "domainId": { + "type": "keyword" + } + } + }, + "visualization": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "index": false, + "type": "text" + } + } + }, + "savedSearchRefName": { + "doc_values": false, + "index": false, + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "index": false, + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "index": false, + "type": "text" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "number_of_replicas": "0", + "number_of_shards": "1", + "priority": "10", + "refresh_interval": "1s", + "routing_partition_size": "1" + } + } + } +} diff --git a/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts b/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts index 15afdb229b1fd..0cb6a5ba8eb5d 100644 --- a/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts +++ b/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts @@ -176,6 +176,42 @@ export class SavedObjectExportTransformsPlugin implements Plugin { }, }, }); + + // example of a SO type with `visibleInManagement: false` + savedObjects.registerType<{ enabled: boolean; title: string }>({ + name: 'test-not-visible-in-management', + hidden: false, + namespaceType: 'single', + mappings: { + properties: { + title: { type: 'text' }, + enabled: { type: 'boolean' }, + }, + }, + management: { + defaultSearchField: 'title', + importableAndExportable: true, + visibleInManagement: false, + }, + }); + + // example of a SO type with `visibleInManagement: true` + savedObjects.registerType<{ enabled: boolean; title: string }>({ + name: 'test-visible-in-management', + hidden: false, + namespaceType: 'single', + mappings: { + properties: { + title: { type: 'text' }, + enabled: { type: 'boolean' }, + }, + }, + management: { + defaultSearchField: 'title', + importableAndExportable: true, + visibleInManagement: true, + }, + }); } public start() {} diff --git a/test/plugin_functional/test_suites/saved_objects_management/exports/_import_non_visible_in_management.ndjson b/test/plugin_functional/test_suites/saved_objects_management/exports/_import_non_visible_in_management.ndjson new file mode 100644 index 0000000000000..754848a99d03d --- /dev/null +++ b/test/plugin_functional/test_suites/saved_objects_management/exports/_import_non_visible_in_management.ndjson @@ -0,0 +1 @@ +{"attributes": { "title": "Saved object type that is not visible in management" }, "id":"ff3773b0-9ate-11e7-ahb3-3dcb94193fab", "references":[], "type":"test-not-visible-in-management", "version":1} 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 03ac96b9a11f6..b7730a95d3c71 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/index.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/index.ts @@ -16,5 +16,6 @@ export default function ({ loadTestFile }: PluginFunctionalProviderContext) { loadTestFile(require.resolve('./export_transform')); loadTestFile(require.resolve('./import_warnings')); loadTestFile(require.resolve('./hidden_types')); + loadTestFile(require.resolve('./visible_in_management')); }); } diff --git a/test/plugin_functional/test_suites/saved_objects_management/visible_in_management.ts b/test/plugin_functional/test_suites/saved_objects_management/visible_in_management.ts new file mode 100644 index 0000000000000..dd43ba80a8e8e --- /dev/null +++ b/test/plugin_functional/test_suites/saved_objects_management/visible_in_management.ts @@ -0,0 +1,113 @@ +/* + * 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 { join } from 'path'; +import expect from '@kbn/expect'; +import type { Response } from 'supertest'; +import type { PluginFunctionalProviderContext } from '../../services'; +import { SavedObject } from '../../../../src/core/types'; + +function parseNdJson(input: string): Array> { + return input.split('\n').map((str) => JSON.parse(str)); +} + +export default function ({ getService }: PluginFunctionalProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('types with `visibleInManagement` ', () => { + before(async () => { + await esArchiver.load( + 'test/functional/fixtures/es_archiver/saved_objects_management/visible_in_management' + ); + }); + + after(async () => { + await esArchiver.unload( + 'test/functional/fixtures/es_archiver/saved_objects_management/visible_in_management' + ); + }); + + describe('export', () => { + it('allows to export them directly by id', async () => { + await supertest + .post('/api/saved_objects/_export') + .set('kbn-xsrf', 'true') + .send({ + objects: [ + { + type: 'test-not-visible-in-management', + id: 'vim-1', + }, + ], + excludeExportDetails: true, + }) + .expect(200) + .then((resp) => { + const objects = parseNdJson(resp.text); + expect(objects.map((obj) => obj.id)).to.eql(['vim-1']); + }); + }); + + it('allows to export them directly by type', async () => { + await supertest + .post('/api/saved_objects/_export') + .set('kbn-xsrf', 'true') + .send({ + type: ['test-not-visible-in-management'], + excludeExportDetails: true, + }) + .expect(200) + .then((resp) => { + const objects = parseNdJson(resp.text); + expect(objects.map((obj) => obj.id)).to.eql(['vim-1']); + }); + }); + }); + + describe('import', () => { + it('allows to import them', async () => { + await supertest + .post('/api/saved_objects/_import') + .set('kbn-xsrf', 'true') + .attach('file', join(__dirname, './exports/_import_non_visible_in_management.ndjson')) + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + success: true, + successCount: 1, + successResults: [ + { + id: 'ff3773b0-9ate-11e7-ahb3-3dcb94193fab', + meta: { + title: 'Saved object type that is not visible in management', + }, + type: 'test-not-visible-in-management', + }, + ], + warnings: [], + }); + }); + }); + }); + + describe('savedObjects management APIS', () => { + it('GET /api/kibana/management/saved_objects/_allowed_types should only return types that are `visibleInManagement: true`', async () => + await supertest + .get('/api/kibana/management/saved_objects/_allowed_types') + .set('kbn-xsrf', 'true') + .expect(200) + .then((response: Response) => { + const { types } = response.body; + expect(types.includes('test-is-exportable')).to.eql(true); + expect(types.includes('test-visible-in-management')).to.eql(true); + expect(types.includes('test-not-visible-in-management')).to.eql(false); + })); + }); + }); +}