Add content management mSearch to viz, lens, and event annotation group (#162450)

## Summary

Adds content management api mSearch functionality to `lens`,
`visualization`, and `event_annotation_group` types via abstracted
function and types.

Part of https://github.com/elastic/kibana/issues/161545

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Stratoula Kalafateli <efstratia.kalafateli@elastic.co>
This commit is contained in:
Matthew Kime 2023-07-26 08:37:45 -05:00 committed by GitHub
parent f6a90974e9
commit 0f889618a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 147 additions and 5 deletions

View file

@ -10,3 +10,4 @@ export * from './src/types';
export * from './src/schema';
export * from './src/saved_object_content_storage';
export * from './src/utils';
export * from './src/msearch';

View file

@ -0,0 +1,96 @@
/*
* 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 Boom from '@hapi/boom';
import { pick } from 'lodash';
import type { StorageContext } from '@kbn/content-management-plugin/server';
import type {
SavedObjectsFindResult,
SavedObject,
SavedObjectReference,
} from '@kbn/core-saved-objects-api-server';
import type { ServicesDefinitionSet, SOWithMetadata, SOWithMetadataPartial } from './types';
type PartialSavedObject<T> = Omit<SavedObject<Partial<T>>, 'references'> & {
references: SavedObjectReference[] | undefined;
};
interface GetMSearchParams {
savedObjectType: string;
cmServicesDefinition: ServicesDefinitionSet;
allowedSavedObjectAttributes: string[];
}
function savedObjectToItem<Attributes extends object>(
savedObject: SavedObject<Attributes> | PartialSavedObject<Attributes>,
allowedSavedObjectAttributes: string[]
): SOWithMetadata | SOWithMetadataPartial {
const {
id,
type,
updated_at: updatedAt,
created_at: createdAt,
attributes,
references,
error,
namespaces,
version,
} = savedObject;
return {
id,
type,
updatedAt,
createdAt,
attributes: pick(attributes, allowedSavedObjectAttributes),
references,
error,
namespaces,
version,
};
}
export interface GetMSearchType<ReturnItem> {
savedObjectType: string;
toItemResult: (ctx: StorageContext, savedObject: SavedObjectsFindResult) => ReturnItem;
}
export const getMSearch = <ReturnItem, SOAttributes extends object>({
savedObjectType,
cmServicesDefinition,
allowedSavedObjectAttributes,
}: GetMSearchParams) => {
return {
savedObjectType,
toItemResult: (ctx: StorageContext, savedObject: SavedObjectsFindResult): ReturnItem => {
const transforms = ctx.utils.getTransforms(cmServicesDefinition);
// Validate DB response and DOWN transform to the request version
const { value, error: resultError } = transforms.mSearch.out.result.down<
ReturnItem,
ReturnItem
>(
// Ran into a case where a schema was broken by a SO attribute that wasn't part of the definition
// so we specify which attributes are allowed
savedObjectToItem<SOAttributes>(
savedObject as SavedObjectsFindResult<SOAttributes>,
allowedSavedObjectAttributes
)
);
if (resultError) {
throw Boom.badRequest(`Invalid response. ${resultError.message}`);
}
return value;
},
};
};

View file

@ -15,6 +15,8 @@ import type {
SavedObjectsFindOptions,
} from '@kbn/core-saved-objects-api-server';
import { getMSearch, type GetMSearchType } from '@kbn/content-management-utils';
import { EVENT_ANNOTATION_GROUP_TYPE } from '@kbn/event-annotation-common';
import { cmServicesDefinition } from '../../common/content_management/cm_services';
import type {
@ -96,7 +98,20 @@ export class EventAnnotationGroupStorage
implements
ContentStorage<EventAnnotationGroupSavedObject, PartialEventAnnotationGroupSavedObject>
{
constructor() {}
mSearch: GetMSearchType<EventAnnotationGroupSavedObject>;
constructor() {
this.mSearch = getMSearch<EventAnnotationGroupSavedObject, EventAnnotationGroupSearchOut>({
savedObjectType: SO_TYPE,
cmServicesDefinition,
allowedSavedObjectAttributes: [
'title',
'description',
'ignoreGlobalFilters',
'annotations',
'dataViewSpec',
],
});
}
async get(ctx: StorageContext, id: string): Promise<EventAnnotationGroupGetOut> {
const {

View file

@ -41,7 +41,8 @@
"@kbn/core-lifecycle-browser",
"@kbn/saved-objects-tagging-oss-plugin",
"@kbn/dom-drag-drop",
"@kbn/kibana-utils-plugin"
"@kbn/kibana-utils-plugin",
"@kbn/content-management-utils"
],
"exclude": [
"target/**/*",

View file

@ -14,6 +14,8 @@ import type {
SavedObjectsFindOptions,
} from '@kbn/core-saved-objects-api-server';
import { getMSearch, type GetMSearchType } from '@kbn/content-management-utils';
import { CONTENT_ID } from '../../common/content_management';
import { cmServicesDefinition } from '../../common/content_management/cm_services';
import type {
@ -103,7 +105,23 @@ const SO_TYPE: VisualizationContentType = 'visualization';
export class VisualizationsStorage
implements ContentStorage<VisualizationSavedObject, PartialVisualizationSavedObject>
{
constructor() {}
mSearch: GetMSearchType<VisualizationSavedObject>;
constructor() {
this.mSearch = getMSearch<VisualizationSavedObject, VisualizationSearchOut>({
savedObjectType: SO_TYPE,
cmServicesDefinition,
allowedSavedObjectAttributes: [
'title',
'description',
'version',
'kibanaSavedObjectMeta',
'uiStateJSON',
'visState',
'savedSearchRefName',
],
});
}
async get(ctx: StorageContext, id: string): Promise<VisualizationGetOut> {
const {

View file

@ -61,7 +61,8 @@
"@kbn/core-saved-objects-utils-server",
"@kbn/content-management-table-list-view-table",
"@kbn/content-management-tabbed-table-list-view",
"@kbn/content-management-table-list-view"
"@kbn/content-management-table-list-view",
"@kbn/content-management-utils"
],
"exclude": [
"target/**/*",

View file

@ -13,6 +13,8 @@ import type {
SavedObjectsFindOptions,
} from '@kbn/core-saved-objects-api-server';
import { getMSearch, type GetMSearchType } from '@kbn/content-management-utils';
import { CONTENT_ID } from '../../common/content_management';
import { cmServicesDefinition } from '../../common/content_management/cm_services';
import type {
@ -91,7 +93,14 @@ function savedObjectToLensSavedObject(
const SO_TYPE: LensContentType = 'lens';
export class LensStorage implements ContentStorage<LensSavedObject, PartialLensSavedObject> {
constructor() {}
mSearch: GetMSearchType<LensSavedObject>;
constructor() {
this.mSearch = getMSearch<LensSavedObject, LensSearchOut>({
savedObjectType: SO_TYPE,
cmServicesDefinition,
allowedSavedObjectAttributes: ['title', 'description', 'visualizationType', 'state'],
});
}
async get(ctx: StorageContext, id: string): Promise<LensGetOut> {
const {

View file

@ -83,6 +83,7 @@
"@kbn/core-overlays-browser-mocks",
"@kbn/core-theme-browser-mocks",
"@kbn/event-annotation-components",
"@kbn/content-management-utils",
],
"exclude": [
"target/**/*",