Skip to content

Commit

Permalink
[data views] Content management api implementation (#155803)
Browse files Browse the repository at this point in the history
## Summary

Data views implements the content management api and associated minor
changes. The bulk of the changes are in
`(common|public|server)/content_management)`

Closes #157069

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Lukas Olson <olson.lukas@gmail.com>
  • Loading branch information
3 people authored May 24, 2023
1 parent 282305f commit 5fa2226
Show file tree
Hide file tree
Showing 43 changed files with 592 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type {
SavedObjectsUpdateOptions,
SavedObjectsFindResult,
} from '@kbn/core-saved-objects-api-server';
import { pick } from 'lodash';
import type {
CMCrudTypes,
ServicesDefinitionSet,
Expand All @@ -44,16 +45,19 @@ type PartialSavedObject<T> = Omit<SavedObject<Partial<T>>, 'references'> & {

function savedObjectToItem<Attributes extends object, Item extends SOWithMetadata>(
savedObject: SavedObject<Attributes>,
allowedSavedObjectAttributes: string[],
partial: false
): Item;

function savedObjectToItem<Attributes extends object, PartialItem extends SOWithMetadata>(
savedObject: PartialSavedObject<Attributes>,
allowedSavedObjectAttributes: string[],
partial: true
): PartialItem;

function savedObjectToItem<Attributes extends object>(
savedObject: SavedObject<Attributes> | PartialSavedObject<Attributes>
savedObject: SavedObject<Attributes> | PartialSavedObject<Attributes>,
allowedSavedObjectAttributes: string[]
): SOWithMetadata | SOWithMetadataPartial {
const {
id,
Expand All @@ -64,17 +68,19 @@ function savedObjectToItem<Attributes extends object>(
references,
error,
namespaces,
version,
} = savedObject;

return {
id,
type,
updatedAt,
createdAt,
attributes,
attributes: pick(attributes, allowedSavedObjectAttributes),
references,
error,
namespaces,
version,
};
}

Expand Down Expand Up @@ -123,6 +129,8 @@ export type UpdateArgsToSoUpdateOptions<Types extends CMCrudTypes> = (
export interface SOContentStorageConstrutorParams<Types extends CMCrudTypes> {
savedObjectType: string;
cmServicesDefinition: ServicesDefinitionSet;
// this is necessary since unexpected saved object attributes could cause schema validation to fail
allowedSavedObjectAttributes: string[];
createArgsToSoCreateOptions?: CreateArgsToSoCreateOptions<Types>;
updateArgsToSoUpdateOptions?: UpdateArgsToSoUpdateOptions<Types>;
searchArgsToSOFindOptions?: SearchArgsToSOFindOptions<Types>;
Expand All @@ -144,6 +152,7 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
updateArgsToSoUpdateOptions,
searchArgsToSOFindOptions,
enableMSearch,
allowedSavedObjectAttributes,
}: SOContentStorageConstrutorParams<Types>) {
this.savedObjectType = savedObjectType;
this.cmServicesDefinition = cmServicesDefinition;
Expand All @@ -152,6 +161,7 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
this.updateArgsToSoUpdateOptions =
updateArgsToSoUpdateOptions || updateArgsToSoUpdateOptionsDefault;
this.searchArgsToSOFindOptions = searchArgsToSOFindOptions || searchArgsToSOFindOptionsDefault;
this.allowedSavedObjectAttributes = allowedSavedObjectAttributes;

if (enableMSearch) {
this.mSearch = {
Expand All @@ -163,7 +173,13 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
const { value, error: resultError } = transforms.mSearch.out.result.down<
Types['Item'],
Types['Item']
>(savedObjectToItem(savedObject as SavedObjectsFindResult<Types['Attributes']>, false));
>(
savedObjectToItem(
savedObject as SavedObjectsFindResult<Types['Attributes']>,
this.allowedSavedObjectAttributes,
false
)
);

if (resultError) {
throw Boom.badRequest(`Invalid response. ${resultError.message}`);
Expand All @@ -180,6 +196,7 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
private createArgsToSoCreateOptions: CreateArgsToSoCreateOptions<Types>;
private updateArgsToSoUpdateOptions: UpdateArgsToSoUpdateOptions<Types>;
private searchArgsToSOFindOptions: SearchArgsToSOFindOptions<Types>;
private allowedSavedObjectAttributes: string[];

mSearch?: {
savedObjectType: string;
Expand All @@ -199,7 +216,7 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
} = await soClient.resolve<Types['Attributes']>(this.savedObjectType, id);

const response: Types['GetOut'] = {
item: savedObjectToItem(savedObject, false),
item: savedObjectToItem(savedObject, this.allowedSavedObjectAttributes, false),
meta: {
aliasPurpose,
aliasTargetId,
Expand Down Expand Up @@ -264,7 +281,7 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
Types['CreateOut'],
Types['CreateOut']
>({
item: savedObjectToItem(savedObject, false),
item: savedObjectToItem(savedObject, this.allowedSavedObjectAttributes, false),
});

if (resultError) {
Expand Down Expand Up @@ -315,7 +332,7 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
Types['UpdateOut'],
Types['UpdateOut']
>({
item: savedObjectToItem(partialSavedObject, true),
item: savedObjectToItem(partialSavedObject, this.allowedSavedObjectAttributes, true),
});

if (resultError) {
Expand All @@ -325,9 +342,14 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
return value;
}

async delete(ctx: StorageContext, id: string): Promise<Types['DeleteOut']> {
async delete(
ctx: StorageContext,
id: string,
// force is necessary to delete saved objects that exist in multiple namespaces
options?: { force: boolean }
): Promise<Types['DeleteOut']> {
const soClient = await savedObjectClientFromRequest(ctx);
await soClient.delete(this.savedObjectType, id);
await soClient.delete(this.savedObjectType, id, { force: options?.force ?? false });
return { success: true };
}

Expand Down Expand Up @@ -361,7 +383,9 @@ export abstract class SOContentStorage<Types extends CMCrudTypes>
Types['SearchOut'],
Types['SearchOut']
>({
hits: response.saved_objects.map((so) => savedObjectToItem(so, false)),
hits: response.saved_objects.map((so) =>
savedObjectToItem(so, this.allowedSavedObjectAttributes, false)
),
pagination: {
total: response.total,
},
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-content-management-utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export interface SavedObjectUpdateOptions<Attributes = unknown> {
}

/** Return value for Saved Object get, T is item returned */
export type GetResultSO<T extends object> = GetResult<
export type GetResultSO<T extends object = object> = GetResult<
T,
{
outcome: 'exactMatch' | 'aliasMatch' | 'conflict';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@ describe('kibanaContextFn', () => {
delete: jest.fn(),
find: jest.fn(),
get: jest.fn(),
getSavedSearch: jest.fn(),
update: jest.fn(),
},
};
});

it('merges and deduplicates queries from different sources', async () => {
const { fn } = kibanaContextFn;
startServicesMock.savedObjectsClient.get.mockResolvedValue({
startServicesMock.savedObjectsClient.getSavedSearch.mockResolvedValue({
attributes: {
kibanaSavedObjectMeta: {
searchSourceJSON: JSON.stringify({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export const getKibanaContextFn = (
let filters = [...(input?.filters || [])];

if (args.savedSearchId) {
const obj = await savedObjectsClient.get('search', args.savedSearchId);
const obj = await savedObjectsClient.getSavedSearch(args.savedSearchId);
const search = (obj.attributes as any).kibanaSavedObjectMeta.searchSourceJSON as string;
const { query, filter } = getParsedValue(search, {});

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export class IndexedFieldsTable extends Component<
fields.map((field) => {
return {
...field.spec,
id: field.name,
type: field.esTypes?.join(', ') || '',
kbnType: field.type,
displayName: field.displayName,
Expand Down Expand Up @@ -114,6 +115,7 @@ export class IndexedFieldsTable extends Component<
},
},
name,
id: name,
type: 'composite',
kbnType: '',
displayName: name,
Expand Down
21 changes: 21 additions & 0 deletions src/plugins/data_views/common/content_management/cm_services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 type {
ContentManagementServicesDefinition as ServicesDefinition,
Version,
} from '@kbn/object-versioning';

// We export the versionned service definition from this file and not the barrel to avoid adding
// the schemas in the "public" js bundle

import { serviceDefinition as v1 } from './v1/cm_services';

export const cmServicesDefinition: { [version: Version]: ServicesDefinition } = {
1: v1,
};
9 changes: 9 additions & 0 deletions src/plugins/data_views/common/content_management/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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.
*/

export * from './v1';
Loading

0 comments on commit 5fa2226

Please sign in to comment.