Skip to content

Commit

Permalink
[Canvas] Add NP routing for custom elements (#52561)
Browse files Browse the repository at this point in the history
* [Canvas] Add NP routing for custom elements

* Remove unused type

* Cleanup

* Adding await to delete

* Cleanup
  • Loading branch information
poffdeluxe committed Dec 11, 2019
1 parent 8395596 commit 19fec54
Show file tree
Hide file tree
Showing 23 changed files with 909 additions and 215 deletions.
192 changes: 0 additions & 192 deletions x-pack/legacy/plugins/canvas/server/routes/custom_elements.ts

This file was deleted.

2 changes: 0 additions & 2 deletions x-pack/legacy/plugins/canvas/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
*/

import { esFields } from './es_fields';
import { customElements } from './custom_elements';
import { shareableWorkpads } from './shareables';
import { CoreSetup } from '../shim';

export function routes(setup: CoreSetup): void {
customElements(setup.http.route, setup.elasticsearch);
esFields(setup.http.route, setup.elasticsearch);
shareableWorkpads(setup.http.route);
}
102 changes: 102 additions & 0 deletions x-pack/plugins/canvas/server/routes/custom_elements/create.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import sinon from 'sinon';
import {
savedObjectsClientMock,
httpServiceMock,
httpServerMock,
loggingServiceMock,
} from 'src/core/server/mocks';
import { CUSTOM_ELEMENT_TYPE } from '../../../../../legacy/plugins/canvas/common/lib/constants';
import { initializeCreateCustomElementRoute } from './create';
import {
IRouter,
kibanaResponseFactory,
RequestHandlerContext,
RequestHandler,
} from 'src/core/server';

const mockRouteContext = ({
core: {
savedObjects: {
client: savedObjectsClientMock.create(),
},
},
} as unknown) as RequestHandlerContext;

const mockedUUID = '123abc';
const now = new Date();
const nowIso = now.toISOString();

jest.mock('uuid/v4', () => jest.fn().mockReturnValue('123abc'));

describe('POST custom element', () => {
let routeHandler: RequestHandler<any, any, any>;
let clock: sinon.SinonFakeTimers;

beforeEach(() => {
clock = sinon.useFakeTimers(now);

const httpService = httpServiceMock.createSetupContract();

const router = httpService.createRouter('') as jest.Mocked<IRouter>;
initializeCreateCustomElementRoute({
router,
logger: loggingServiceMock.create().get(),
});

routeHandler = router.post.mock.calls[0][1];
});

afterEach(() => {
clock.restore();
});

it(`returns 200 when the custom element is created`, async () => {
const mockCustomElement = {
displayName: 'My Custom Element',
};

const request = httpServerMock.createKibanaRequest({
method: 'post',
path: 'api/canvas/custom-element',
body: mockCustomElement,
});

const response = await routeHandler(mockRouteContext, request, kibanaResponseFactory);

expect(response.status).toBe(200);
expect(response.payload).toEqual({ ok: true });
expect(mockRouteContext.core.savedObjects.client.create).toBeCalledWith(
CUSTOM_ELEMENT_TYPE,
{
...mockCustomElement,
'@timestamp': nowIso,
'@created': nowIso,
},
{
id: `custom-element-${mockedUUID}`,
}
);
});

it(`returns bad request if create is unsuccessful`, async () => {
const request = httpServerMock.createKibanaRequest({
method: 'post',
path: 'api/canvas/custom-element',
body: {},
});

(mockRouteContext.core.savedObjects.client.create as jest.Mock).mockImplementation(() => {
throw mockRouteContext.core.savedObjects.client.errors.createBadRequestError('bad request');
});

const response = await routeHandler(mockRouteContext, request, kibanaResponseFactory);

expect(response.status).toBe(400);
});
});
54 changes: 54 additions & 0 deletions x-pack/plugins/canvas/server/routes/custom_elements/create.ts
Original file line number Diff line number Diff line change
@@ -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;
* you may not use this file except in compliance with the Elastic License.
*/

import { RouteInitializerDeps } from '../';
import {
CUSTOM_ELEMENT_TYPE,
API_ROUTE_CUSTOM_ELEMENT,
} from '../../../../../legacy/plugins/canvas/common/lib/constants';
import { getId } from '../../../../../legacy/plugins/canvas/public/lib/get_id';
import { CustomElementSchema } from './custom_element_schema';
import { CustomElementAttributes } from './custom_element_attributes';
import { okResponse } from '../ok_response';
import { catchErrorHandler } from '../catch_error_handler';

export function initializeCreateCustomElementRoute(deps: RouteInitializerDeps) {
const { router } = deps;
router.post(
{
path: `${API_ROUTE_CUSTOM_ELEMENT}`,
validate: {
body: CustomElementSchema,
},
options: {
body: {
maxBytes: 26214400, // 25MB payload limit
accepts: ['application/json'],
},
},
},
catchErrorHandler(async (context, request, response) => {
const customElement = request.body;

const now = new Date().toISOString();
const { id, ...payload } = customElement;

await context.core.savedObjects.client.create<CustomElementAttributes>(
CUSTOM_ELEMENT_TYPE,
{
...payload,
'@timestamp': now,
'@created': now,
},
{ id: id || getId('custom-element') }
);

return response.ok({
body: okResponse,
});
})
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { CustomElement } from '../../../../../legacy/plugins/canvas/types';

// Exclude ID attribute for the type used for SavedObjectClient
export type CustomElementAttributes = Pick<CustomElement, Exclude<keyof CustomElement, 'id'>> & {
'@timestamp': string;
'@created': string;
};
Loading

0 comments on commit 19fec54

Please sign in to comment.