diff --git a/docs/development/core/development-basepath.asciidoc b/docs/development/core/development-basepath.asciidoc index 2da65079350150..c86ab6c5e797d8 100644 --- a/docs/development/core/development-basepath.asciidoc +++ b/docs/development/core/development-basepath.asciidoc @@ -55,8 +55,8 @@ Append `request.getBasePath()` to any absolute URL path. const basePath = server.config().get('server.basePath'); server.route({ path: '/redirect', - handler(request, reply) { - reply.redirect(`${request.getBasePath()}/otherLocation`); + handler(request, h) { + return h.redirect(`${request.getBasePath()}/otherLocation`); } }); ----------- @@ -84,4 +84,4 @@ or `yarn start`. ["source","shell"] ----------- yarn start --no-base-path ------------ \ No newline at end of file +----------- diff --git a/package.json b/package.json index ce1818c63011ba..5981a96e0879e1 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "dependencies": { "@elastic/eui": "4.5.1", "@elastic/filesaver": "1.1.2", + "@elastic/good": "8.1.1-kibana1", "@elastic/numeral": "2.3.2", "@elastic/ui-ace": "0.2.3", "@kbn/babel-preset": "link:packages/kbn-babel-preset", @@ -92,7 +93,7 @@ "babel-polyfill": "6.20.0", "babel-register": "6.18.0", "bluebird": "2.9.34", - "boom": "5.2.0", + "boom": "^7.2.0", "brace": "0.11.1", "cache-loader": "1.0.3", "chalk": "^2.4.1", @@ -108,7 +109,6 @@ "elasticsearch": "^15.1.1", "elasticsearch-browser": "^15.1.1", "encode-uri-query": "1.0.0", - "even-better": "7.0.2", "execa": "^0.10.0", "expiry-js": "0.1.7", "extract-text-webpack-plugin": "3.0.1", @@ -118,16 +118,15 @@ "glob": "^7.1.2", "glob-all": "^3.1.0", "good-squeeze": "2.1.0", - "h2o2": "5.1.1", - "h2o2-latest": "npm:h2o2@8.1.2", + "h2o2": "^8.1.2", "handlebars": "4.0.5", - "hapi": "14.2.0", - "hapi-latest": "npm:hapi@17.5.0", + "hapi": "^17.5.3", "hjson": "3.1.0", + "hoek": "^5.0.4", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.1", - "inert": "4.0.2", - "joi": "10.4.1", + "inert": "^5.1.0", + "joi": "^13.5.2", "jquery": "^3.3.1", "js-yaml": "3.4.1", "json-stringify-pretty-compact": "1.0.4", @@ -151,6 +150,7 @@ "ngreact": "0.5.1", "no-ui-slider": "1.2.0", "node-fetch": "1.3.2", + "oppsy": "^2.0.0", "pegjs": "0.9.0", "postcss-loader": "2.0.6", "prop-types": "15.5.8", @@ -203,11 +203,11 @@ "vega-lite": "^2.4.0", "vega-schema-url-parser": "1.0.0", "vega-tooltip": "^0.9.14", - "vision": "4.1.0", + "vision": "^5.3.3", "webpack": "3.6.0", "webpack-merge": "4.1.0", "whatwg-fetch": "^2.0.3", - "wreck": "12.4.0", + "wreck": "^14.0.2", "x-pack": "link:x-pack", "yauzl": "2.7.0" }, @@ -238,10 +238,11 @@ "@types/fetch-mock": "^5.12.2", "@types/getopts": "^2.0.0", "@types/glob": "^5.0.35", - "@types/hapi-latest": "npm:@types/hapi@17.0.12", + "@types/hapi": "^17.0.18", "@types/has-ansi": "^3.0.0", + "@types/hoek": "^4.1.3", "@types/jest": "^23.3.1", - "@types/joi": "^10.4.4", + "@types/joi": "^13.4.2", "@types/jquery": "^3.3.6", "@types/js-yaml": "^3.11.1", "@types/listr": "^0.13.0", diff --git a/packages/kbn-config-schema/src/internals/index.ts b/packages/kbn-config-schema/src/internals/index.ts index b6dbcd7a001839..78216e18555b34 100644 --- a/packages/kbn-config-schema/src/internals/index.ts +++ b/packages/kbn-config-schema/src/internals/index.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import * as Joi from 'joi'; +import Joi from 'joi'; import { AnySchema, JoiRoot, diff --git a/packages/kbn-config-schema/src/types/type.ts b/packages/kbn-config-schema/src/types/type.ts index 61f39d8ae42fc1..e8d0370a443dcf 100644 --- a/packages/kbn-config-schema/src/types/type.ts +++ b/packages/kbn-config-schema/src/types/type.ts @@ -101,12 +101,7 @@ export abstract class Type { return error; } - const { context = {}, type, path: rawPath, message } = error; - - // Before v11.0.0 Joi reported paths as `.`-delimited strings, but more - // recent version use arrays instead. Once we upgrade Joi, we should just - // remove this split logic and use `path` provided by Joi directly. - const path = rawPath ? rawPath.split('.') : []; + const { context = {}, type, path, message } = error; const errorHandleResult = this.handleError(type, context, path); if (errorHandleResult instanceof SchemaTypeError) { diff --git a/packages/kbn-plugin-generator/sao_template/template/server/routes/example.js b/packages/kbn-plugin-generator/sao_template/template/server/routes/example.js index f4f67431b196b7..5a612645f48fc3 100755 --- a/packages/kbn-plugin-generator/sao_template/template/server/routes/example.js +++ b/packages/kbn-plugin-generator/sao_template/template/server/routes/example.js @@ -3,8 +3,8 @@ export default function (server) { server.route({ path: '/api/<%= name %>/example', method: 'GET', - handler(req, reply) { - reply({ time: (new Date()).toISOString() }); + handler() { + return { time: (new Date()).toISOString() }; } }); diff --git a/src/cli/serve/integration_tests/__snapshots__/reload_logging_config.test.js.snap b/src/cli/serve/integration_tests/__snapshots__/reload_logging_config.test.js.snap deleted file mode 100644 index fa3e0bcbc8204b..00000000000000 --- a/src/cli/serve/integration_tests/__snapshots__/reload_logging_config.test.js.snap +++ /dev/null @@ -1,76 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Server logging configuration should be reloadable via SIGHUP process signaling 1`] = ` -Object { - "code": 0, - "lines": Array [ - Object { - "@timestamp": "## @timestamp ##", - "message": "Plugin initialization disabled.", - "pid": "## PID ##", - "tags": Array [ - "info", - ], - "type": "log", - }, - Object { - "@timestamp": "## @timestamp ##", - "message": "The elasticsearch plugin is disabled. Skipping migrations.", - "pid": "## PID ##", - "tags": Array [ - "warning", - "migration", - ], - "type": "log", - }, - Object { - "@timestamp": "## @timestamp ##", - "message": "Server running at http://localhost:8274", - "pid": "## PID ##", - "tags": Array [ - "info", - "http", - "server", - "listening", - ], - "type": "log", - }, - Object { - "@timestamp": "## @timestamp ##", - "message": "Reloading logging configuration due to SIGHUP.", - "pid": "## PID ##", - "tags": Array [ - "info", - "config", - ], - "type": "log", - }, - Object { - "@timestamp": "## @timestamp ##", - "message": "New logging configuration: -{ - \\"ops\\": { - \\"interval\\": 5000 - }, - \\"logging\\": { - \\"json\\": false, - \\"silent\\": false, - \\"quiet\\": false, - \\"verbose\\": false, - \\"events\\": {}, - \\"dest\\": \\"stdout\\", - \\"filter\\": {}, - \\"useUTC\\": true - } -}", - "pid": "## PID ##", - "tags": Array [ - "info", - "config", - ], - "type": "log", - }, - " log [## timestamp ##] [info][config] Reloaded logging configuration due to SIGHUP.", - ], -} -`; diff --git a/src/cli/serve/integration_tests/reload_logging_config.test.js b/src/cli/serve/integration_tests/reload_logging_config.test.js index 61e590f2b51d51..e80a3d9d4fb818 100644 --- a/src/cli/serve/integration_tests/reload_logging_config.test.js +++ b/src/cli/serve/integration_tests/reload_logging_config.test.js @@ -22,8 +22,7 @@ import { writeFileSync } from 'fs'; import { relative, resolve } from 'path'; import { safeDump } from 'js-yaml'; import es from 'event-stream'; -import stripAnsi from 'strip-ansi'; -import { getConfigFromFiles } from '../../../core/server/config'; +import { getConfigFromFiles } from '../../../core/server/config/read_config'; const testConfigFile = follow('__fixtures__/reload_logging_config/kibana.test.yml'); const kibanaPath = follow('../../../../scripts/kibana.js'); @@ -42,19 +41,7 @@ function setLoggingJson(enabled) { writeFileSync(testConfigFile, yaml); } -const prepareJson = obj => ({ - ...obj, - pid: '## PID ##', - '@timestamp': '## @timestamp ##' -}); - -const prepareLogLine = str => - stripAnsi(str.replace( - /\[\d{2}:\d{2}:\d{2}.\d{3}\]/, - '[## timestamp ##]' - )); - -describe.skip('Server logging configuration', function () { +describe('Server logging configuration', function () { let child; let isJson; @@ -80,7 +67,7 @@ describe.skip('Server logging configuration', function () { }); } else { it('should be reloadable via SIGHUP process signaling', function (done) { - expect.assertions(1); + expect.assertions(3); child = spawn('node', [kibanaPath, '--config', testConfigFile]); @@ -88,12 +75,15 @@ describe.skip('Server logging configuration', function () { done(new Error(`error in child process while attempting to reload config. ${err.stack || err.message || err}`)); }); - const lines = []; + let sawJson = false; + let sawNonjson = false; child.on('exit', _code => { const code = _code === null ? 0 : _code; - expect({ code, lines }).toMatchSnapshot(); + expect(code).toEqual(0); + expect(sawJson).toEqual(true); + expect(sawNonjson).toEqual(true); done(); }); @@ -107,23 +97,18 @@ describe.skip('Server logging configuration', function () { if (isJson) { const data = JSON.parse(line); - lines.push(prepareJson(data)); + sawJson = true; if (data.tags.includes('listening')) { switchToPlainTextLog(); } } else if (line.startsWith('{')) { // We have told Kibana to stop logging json, but it hasn't completed - // the switch yet, so we verify the messages that are logged while - // switching over. - - const data = JSON.parse(line); - lines.push(prepareJson(data)); + // the switch yet, so we ignore before switching over. } else { - // Kibana has successfully stopped logging json, so we verify the - // log line and kill the server. + // Kibana has successfully stopped logging json, so kill the server. - lines.push(prepareLogLine(line)); + sawNonjson = true; child.kill(); child = undefined; diff --git a/src/cli_plugin/install/downloaders/http.js b/src/cli_plugin/install/downloaders/http.js index a704f3df77c1d9..cd9a1f8f3309de 100644 --- a/src/cli_plugin/install/downloaders/http.js +++ b/src/cli_plugin/install/downloaders/http.js @@ -19,7 +19,6 @@ import Wreck from 'wreck'; import Progress from '../progress'; -import { fromNode as fn } from 'bluebird'; import { createWriteStream } from 'fs'; import HttpProxyAgent from 'http-proxy-agent'; import HttpsProxyAgent from 'https-proxy-agent'; @@ -41,32 +40,31 @@ function getProxyAgent(sourceUrl, logger) { } } -function sendRequest({ sourceUrl, timeout }, logger) { +async function sendRequest({ sourceUrl, timeout }, logger) { const maxRedirects = 11; //Because this one goes to 11. - return fn(cb => { - const reqOptions = { timeout, redirects: maxRedirects }; - const proxyAgent = getProxyAgent(sourceUrl, logger); + const reqOptions = { timeout, redirects: maxRedirects }; + const proxyAgent = getProxyAgent(sourceUrl, logger); - if (proxyAgent) { - reqOptions.agent = proxyAgent; - } - - const req = Wreck.request('GET', sourceUrl, reqOptions, (err, resp) => { - if (err) { - if (err.code === 'ECONNREFUSED') { - err = new Error('ENOTFOUND'); - } + if (proxyAgent) { + reqOptions.agent = proxyAgent; + } - return cb(err); - } + try { + const promise = Wreck.request('GET', sourceUrl, reqOptions); + const req = promise.req; + const resp = await promise; + if (resp.statusCode >= 400) { + throw new Error('ENOTFOUND'); + } - if (resp.statusCode >= 400) { - return cb(new Error('ENOTFOUND')); - } + return { req, resp }; + } catch (err) { + if (err.code === 'ECONNREFUSED') { + err = new Error('ENOTFOUND'); + } - cb(null, { req, resp }); - }); - }); + throw err; + } } function downloadResponse({ resp, targetPath, progress }) { diff --git a/src/core/server/http/__snapshots__/http_server.test.ts.snap b/src/core/server/http/__snapshots__/http_server.test.ts.snap index 8e868e803602fa..d3ddb6e0cff696 100644 --- a/src/core/server/http/__snapshots__/http_server.test.ts.snap +++ b/src/core/server/http/__snapshots__/http_server.test.ts.snap @@ -10,12 +10,15 @@ Object { "maxBytes": 1024, }, "validate": Object { + "failAction": [Function], "options": Object { "abortEarly": false, }, }, }, "state": Object { + "isHttpOnly": true, + "isSameSite": false, "strictHeader": false, }, } diff --git a/src/core/server/http/base_path_proxy_server.ts b/src/core/server/http/base_path_proxy_server.ts index 4f0b92db48d5e1..705445a46c83dc 100644 --- a/src/core/server/http/base_path_proxy_server.ts +++ b/src/core/server/http/base_path_proxy_server.ts @@ -18,7 +18,7 @@ */ import { ByteSizeValue } from '@kbn/config-schema'; -import { Server } from 'hapi-latest'; +import { Server } from 'hapi'; import { Agent as HttpsAgent, ServerOptions as TlsOptions } from 'https'; import { sample } from 'lodash'; import { DevConfig } from '../dev'; @@ -66,7 +66,7 @@ export class BasePathProxyServer { // Register hapi plugin that adds proxying functionality. It can be configured // through the route configuration object (see { handler: { proxy: ... } }). - await this.server.register({ plugin: require('h2o2-latest') }); + await this.server.register({ plugin: require('h2o2') }); if (this.httpConfig.ssl.enabled) { const tlsOptions = serverOptions.tls as TlsOptions; diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts index c828ff4df5408e..7b7e415415b30c 100644 --- a/src/core/server/http/http_server.ts +++ b/src/core/server/http/http_server.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Server, ServerOptions } from 'hapi-latest'; +import { Server, ServerOptions } from 'hapi'; import { modifyUrl } from '../../utils'; import { Logger } from '../logging'; diff --git a/src/core/server/http/http_tools.test.ts b/src/core/server/http/http_tools.test.ts new file mode 100644 index 00000000000000..c062b71f3c5213 --- /dev/null +++ b/src/core/server/http/http_tools.test.ts @@ -0,0 +1,59 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Request, ResponseToolkit } from 'hapi'; +import Joi from 'joi'; +import { defaultValidationErrorHandler, HapiValidationError } from './http_tools'; + +const emptyOutput = { + statusCode: 400, + headers: {}, + payload: { + statusCode: 400, + error: '', + validation: { + source: '', + keys: [], + }, + }, +}; + +describe('defaultValidationErrorHandler', () => { + it('formats value validation errors correctly', () => { + expect.assertions(1); + const schema = Joi.array().items( + Joi.object({ + type: Joi.string().required(), + }).required() + ); + + const error = schema.validate([{}], { abortEarly: false }).error as HapiValidationError; + + // Emulate what Hapi v17 does by default + error.output = { ...emptyOutput }; + error.output.payload.validation.keys = ['0.type', '']; + + try { + defaultValidationErrorHandler({} as Request, {} as ResponseToolkit, error); + } catch (err) { + // Verify the empty string gets corrected to 'value' + expect(err.output.payload.validation.keys).toEqual(['0.type', 'value']); + } + }); +}); diff --git a/src/core/server/http/http_tools.ts b/src/core/server/http/http_tools.ts index 4f88588a552a38..faf7ba4e94542e 100644 --- a/src/core/server/http/http_tools.ts +++ b/src/core/server/http/http_tools.ts @@ -18,8 +18,10 @@ */ import { readFileSync } from 'fs'; -import { Server, ServerOptions } from 'hapi-latest'; +import { Lifecycle, Request, ResponseToolkit, Server, ServerOptions, Util } from 'hapi'; +import Hoek from 'hoek'; import { ServerOptions as TLSOptions } from 'https'; +import { ValidationError } from 'joi'; import { HttpConfig } from './http_config'; /** @@ -39,6 +41,7 @@ export function getServerOptions(config: HttpConfig, { configureTLS = true } = { maxBytes: config.maxPayload.getValueInBytes(), }, validate: { + failAction: defaultValidationErrorHandler, options: { abortEarly: false, }, @@ -46,6 +49,8 @@ export function getServerOptions(config: HttpConfig, { configureTLS = true } = { }, state: { strictHeader: false, + isHttpOnly: true, + isSameSite: false, // necessary to allow using Kibana inside an iframe }, }; @@ -88,3 +93,55 @@ export function createServer(options: ServerOptions) { return server; } + +/** + * Hapi extends the ValidationError interface to add this output key with more data. + */ +export interface HapiValidationError extends ValidationError { + output: { + statusCode: number; + headers: Util.Dictionary; + payload: { + statusCode: number; + error: string; + message?: string; + validation: { + source: string; + keys: string[]; + }; + }; + }; +} + +/** + * Used to replicate Hapi v16 and below's validation responses. Should be used in the routes.validate.failAction key. + */ +export function defaultValidationErrorHandler( + request: Request, + h: ResponseToolkit, + err?: Error +): Lifecycle.ReturnValue { + // Newer versions of Joi don't format the key for missing params the same way. This shim + // provides backwards compatibility. Unfortunately, Joi doesn't export it's own Error class + // in JS so we have to rely on the `name` key before we can cast it. + // + // The Hapi code we're 'overwriting' can be found here: + // https://github.com/hapijs/hapi/blob/master/lib/validation.js#L102 + if (err && err.name === 'ValidationError' && err.hasOwnProperty('output')) { + const validationError: HapiValidationError = err as HapiValidationError; + const validationKeys: string[] = []; + + validationError.details.forEach(detail => { + if (detail.path.length > 0) { + validationKeys.push(Hoek.escapeHtml(detail.path.join('.'))); + } else { + // If no path, use the value sigil to signal the entire value had an issue. + validationKeys.push('value'); + } + }); + + validationError.output.payload.validation.keys = validationKeys; + } + + throw err; +} diff --git a/src/core/server/http/https_redirect_server.ts b/src/core/server/http/https_redirect_server.ts index b2664c5e24b550..789b3890c01121 100644 --- a/src/core/server/http/https_redirect_server.ts +++ b/src/core/server/http/https_redirect_server.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Request, ResponseToolkit, Server } from 'hapi-latest'; +import { Request, ResponseToolkit, Server } from 'hapi'; import { format as formatUrl } from 'url'; import { Logger } from '../logging'; diff --git a/src/core/server/http/router/request.ts b/src/core/server/http/router/request.ts index fb07fa2191d14e..8ee07eac2cca3f 100644 --- a/src/core/server/http/router/request.ts +++ b/src/core/server/http/router/request.ts @@ -18,7 +18,7 @@ */ import { ObjectType, TypeOf } from '@kbn/config-schema'; -import { Request } from 'hapi-latest'; +import { Request } from 'hapi'; import { filterHeaders, Headers } from './headers'; import { RouteSchemas } from './route'; diff --git a/src/core/server/http/router/router.ts b/src/core/server/http/router/router.ts index e0a9d7f691b31f..37bfe053f81819 100644 --- a/src/core/server/http/router/router.ts +++ b/src/core/server/http/router/router.ts @@ -18,7 +18,7 @@ */ import { ObjectType, schema, TypeOf } from '@kbn/config-schema'; -import { Request, ResponseObject, ResponseToolkit } from 'hapi-latest'; +import { Request, ResponseObject, ResponseToolkit } from 'hapi'; import { KibanaRequest } from './request'; import { KibanaResponse, ResponseFactory, responseFactory } from './response'; diff --git a/src/core/server/legacy_compat/legacy_service.ts b/src/core/server/legacy_compat/legacy_service.ts index 092057874fa737..6531c51b161b05 100644 --- a/src/core/server/legacy_compat/legacy_service.ts +++ b/src/core/server/legacy_compat/legacy_service.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Server as HapiServer } from 'hapi-latest'; +import { Server as HapiServer } from 'hapi'; import { combineLatest, ConnectableObservable, EMPTY, Subscription } from 'rxjs'; import { first, map, mergeMap, publishReplay, tap } from 'rxjs/operators'; import { CoreService } from '../../types/core_service'; diff --git a/src/core/server/legacy_compat/logging/legacy_logging_server.test.ts b/src/core/server/legacy_compat/logging/legacy_logging_server.test.ts index ab74c250abb4dd..70256392023f32 100644 --- a/src/core/server/legacy_compat/logging/legacy_logging_server.test.ts +++ b/src/core/server/legacy_compat/logging/legacy_logging_server.test.ts @@ -26,7 +26,7 @@ import { LegacyLoggingServer } from './legacy_logging_server'; test('correctly forwards log records.', () => { const loggingServer = new LegacyLoggingServer({ events: {} }); const onLogMock = jest.fn(); - loggingServer.on('log', onLogMock); + loggingServer.events.on('log', onLogMock); const timestamp = 1554433221100; const firstLogRecord = { diff --git a/src/core/server/legacy_compat/logging/legacy_logging_server.ts b/src/core/server/legacy_compat/logging/legacy_logging_server.ts index 5a31fb366a5ed1..784983a3bb6094 100644 --- a/src/core/server/legacy_compat/logging/legacy_logging_server.ts +++ b/src/core/server/legacy_compat/logging/legacy_logging_server.ts @@ -17,7 +17,8 @@ * under the License. */ -import { EventEmitter } from 'events'; +import { ServerExtType } from 'hapi'; +import Podium from 'podium'; // @ts-ignore: implicit any for JS file import { Config, transformDeprecations } from '../../../../server/config'; // @ts-ignore: implicit any for JS file @@ -25,12 +26,11 @@ import { setupLogging } from '../../../../server/logging'; import { LogRecord } from '../../logging/log_record'; interface PluginRegisterParams { - register: { + plugin: { register: ( server: LegacyLoggingServer, - options: PluginRegisterParams['options'], - cb: () => void - ) => void; + options: PluginRegisterParams['options'] + ) => Promise; }; options: Record; } @@ -41,12 +41,14 @@ interface PluginRegisterParams { * same as the rest of the records generated by the "legacy" Kibana. But to reduce * overhead of having full blown Hapi server instance we create our own "light" version. */ -export class LegacyLoggingServer extends EventEmitter { +export class LegacyLoggingServer { public connections = []; + // Emulates Hapi's usage of the podium event bus. + public events: Podium = new Podium(['log', 'request', 'response']); - constructor(legacyLoggingConfig: Readonly>) { - super(); + private onPostStopCallback?: () => void; + constructor(legacyLoggingConfig: Readonly>) { // We set `ops.interval` to max allowed number and `ops` filter to value // that doesn't exist to avoid logging of ops at all, if turned on it will be // logged by the "legacy" Kibana. @@ -64,12 +66,12 @@ export class LegacyLoggingServer extends EventEmitter { setupLogging(this, Config.withDefaultSchema(transformDeprecations(config))); } - public register({ register: plugin, options }: PluginRegisterParams, cb: () => void) { - plugin.register(this, options, cb); + public register({ plugin: { register }, options }: PluginRegisterParams): Promise { + return register(this, options); } public log({ level, context, message, error, timestamp, meta = {} }: LogRecord) { - this.emit('log', { + this.events.emit('log', { data: error || message, tags: [level.id.toLowerCase(), ...context.split('.'), ...(meta.tags || [])], timestamp: timestamp.getTime(), @@ -77,7 +79,18 @@ export class LegacyLoggingServer extends EventEmitter { } public stop() { - this.emit('stop'); + // Tell the plugin we're stopping. + if (this.onPostStopCallback !== undefined) { + this.onPostStopCallback(); + } + } + + public ext(eventName: ServerExtType, callback: () => void) { + // method is called by plugin that's being registered. + if (eventName === 'onPostStop') { + this.onPostStopCallback = callback; + } + // We don't care about any others the plugin resgisters } public expose() { diff --git a/src/core_plugins/console/api_server/server.js b/src/core_plugins/console/api_server/server.js index 913d27c98dbad1..b9a42a457b90d1 100644 --- a/src/core_plugins/console/api_server/server.js +++ b/src/core_plugins/console/api_server/server.js @@ -21,7 +21,7 @@ import _ from 'lodash'; const KNOWN_APIS = ['es_6_0']; -export function resolveApi(senseVersion, apis, reply) { +export function resolveApi(senseVersion, apis, h) { const result = {}; _.each(apis, function (name) { { @@ -33,5 +33,5 @@ export function resolveApi(senseVersion, apis, reply) { } }); - return reply(result).type('application/json'); + return h.response(result).type('application/json'); } diff --git a/src/core_plugins/console/api_server/server.test.js b/src/core_plugins/console/api_server/server.test.js index cf612464710315..ea78611a6060e4 100644 --- a/src/core_plugins/console/api_server/server.test.js +++ b/src/core_plugins/console/api_server/server.test.js @@ -21,7 +21,7 @@ import { resolveApi } from './server'; describe('resolveApi', () => { it('allows known APIs to be resolved', () => { const mockReply = jest.fn((result) => ({ type: () => result })); - const result = resolveApi('Sense Version', ['es_6_0'], mockReply); + const result = resolveApi('Sense Version', ['es_6_0'], { response: mockReply }); expect(result).toMatchObject({ es_6_0: { endpoints: expect.any(Object), @@ -33,13 +33,13 @@ describe('resolveApi', () => { it('does not resolve APIs that are not known', () => { const mockReply = jest.fn((result) => ({ type: () => result })); - const result = resolveApi('Sense Version', ['unknown'], mockReply); + const result = resolveApi('Sense Version', ['unknown'], { response: mockReply }); expect(result).toEqual({}); }); it('handles request for apis that are known and unknown', () => { const mockReply = jest.fn((result) => ({ type: () => result })); - const result = resolveApi('Sense Version', ['es_6_0'], mockReply); + const result = resolveApi('Sense Version', ['es_6_0'], { response: mockReply }); expect(result).toMatchObject({ es_6_0: { endpoints: expect.any(Object), @@ -48,4 +48,4 @@ describe('resolveApi', () => { } }); }); -}); \ No newline at end of file +}); diff --git a/src/core_plugins/console/index.js b/src/core_plugins/console/index.js index b2e88cdd73db53..ad3881f8250043 100644 --- a/src/core_plugins/console/index.js +++ b/src/core_plugins/console/index.js @@ -113,14 +113,13 @@ export default function (kibana) { server.route({ path: '/api/console/api_server', method: ['GET', 'POST'], - handler: function (req, reply) { + handler: function (req, h) { const { sense_version: version, apis } = req.query; if (!apis) { - reply(Boom.badRequest('"apis" is a required param.')); - return; + throw Boom.badRequest('"apis" is a required param.'); } - return resolveApi(version, apis.split(','), reply); + return resolveApi(version, apis.split(','), h); } }); }, diff --git a/src/core_plugins/console/server/__tests__/proxy_route/body.js b/src/core_plugins/console/server/__tests__/proxy_route/body.js index 28ad08d72ab6af..9dae2ec8047ff1 100644 --- a/src/core_plugins/console/server/__tests__/proxy_route/body.js +++ b/src/core_plugins/console/server/__tests__/proxy_route/body.js @@ -36,8 +36,6 @@ describe('Console Proxy Route', () => { sandbox.stub(Wreck, 'request').callsFake(createWreckResponseStub(response)); const server = new Server(); - - server.connection({ port: 0 }); server.route(createProxyRoute({ baseUrl: 'http://localhost:9200' })); diff --git a/src/core_plugins/console/server/__tests__/proxy_route/headers.js b/src/core_plugins/console/server/__tests__/proxy_route/headers.js index 3bf32ce78871ad..2d3ddf11e020f5 100644 --- a/src/core_plugins/console/server/__tests__/proxy_route/headers.js +++ b/src/core_plugins/console/server/__tests__/proxy_route/headers.js @@ -38,8 +38,6 @@ describe('Console Proxy Route', () => { setup = () => { const server = new Server(); - - server.connection({ port: 0 }); server.route(createProxyRoute({ baseUrl: 'http://localhost:9200' })); diff --git a/src/core_plugins/console/server/__tests__/proxy_route/params.js b/src/core_plugins/console/server/__tests__/proxy_route/params.js index 7635a52b9d133f..4ceccc8855d6a5 100644 --- a/src/core_plugins/console/server/__tests__/proxy_route/params.js +++ b/src/core_plugins/console/server/__tests__/proxy_route/params.js @@ -38,7 +38,6 @@ describe('Console Proxy Route', () => { setup = () => { const server = new Server(); - server.connection({ port: 0 }); teardowns.push(() => server.stop()); return { server }; }; diff --git a/src/core_plugins/console/server/__tests__/proxy_route/query_string.js b/src/core_plugins/console/server/__tests__/proxy_route/query_string.js index 59e164dfb2521e..c5b44cf39713d9 100644 --- a/src/core_plugins/console/server/__tests__/proxy_route/query_string.js +++ b/src/core_plugins/console/server/__tests__/proxy_route/query_string.js @@ -36,8 +36,6 @@ describe('Console Proxy Route', () => { request = async (method, path) => { const server = new Server(); - - server.connection({ port: 0 }); server.route(createProxyRoute({ baseUrl: 'http://localhost:9200' })); diff --git a/src/core_plugins/console/server/__tests__/proxy_route/stubs.js b/src/core_plugins/console/server/__tests__/proxy_route/stubs.js index 3318f7a4b27409..78efef84c97501 100644 --- a/src/core_plugins/console/server/__tests__/proxy_route/stubs.js +++ b/src/core_plugins/console/server/__tests__/proxy_route/stubs.js @@ -20,7 +20,7 @@ import { Readable } from 'stream'; export function createWreckResponseStub(response) { - return (...args) => { + return async () => { const resp = new Readable({ read() { if (response) { @@ -37,6 +37,6 @@ export function createWreckResponseStub(response) { 'content-length': String(response ? response.length : 0) }; - args.pop()(null, resp); + return resp; }; } diff --git a/src/core_plugins/console/server/proxy_route.js b/src/core_plugins/console/server/proxy_route.js index a66ed870739f26..a7062133dcd36d 100644 --- a/src/core_plugins/console/server/proxy_route.js +++ b/src/core_plugins/console/server/proxy_route.js @@ -46,7 +46,7 @@ function getProxyHeaders(req) { // see https://git.io/vytQ7 extendCommaList(headers, 'x-forwarded-for', req.info.remoteAddress); extendCommaList(headers, 'x-forwarded-port', req.info.remotePort); - extendCommaList(headers, 'x-forwarded-proto', req.connection.info.protocol); + extendCommaList(headers, 'x-forwarded-proto', req.server.info.protocol); extendCommaList(headers, 'x-forwarded-host', req.info.host); } @@ -82,21 +82,21 @@ export const createProxyRoute = ({ }, pre: [ - function filterPath(req, reply) { + function filterPath(req) { const { path } = req.query; - if (!pathFilters.some(re => re.test(path))) { - const err = Boom.forbidden(); - err.output.payload = `Error connecting to '${path}':\n\nUnable to send requests to that path.`; - err.output.headers['content-type'] = 'text/plain'; - reply(err); - } else { - reply(); + if (pathFilters.some(re => re.test(path))) { + return null; } + + const err = Boom.forbidden(); + err.output.payload = `Error connecting to '${path}':\n\nUnable to send requests to that path.`; + err.output.headers['content-type'] = 'text/plain'; + throw err; }, ], - handler(req, reply) { + handler: async (req, h) => { const { payload, query } = req; const { path, method } = query; const uri = resolveUri(baseUrl, path); @@ -119,23 +119,18 @@ export const createProxyRoute = ({ }, }; - Wreck.request(method, uri, wreckOptions, (err, esResponse) => { - if (err) { - return reply(err); - } + const esResponse = await Wreck.request(method, uri, wreckOptions); - if (method.toUpperCase() !== 'HEAD') { - reply(esResponse) - .code(esResponse.statusCode) - .header('warning', esResponse.headers.warning); - return; - } - - reply(`${esResponse.statusCode} - ${esResponse.statusMessage}`) + if (method.toUpperCase() !== 'HEAD') { + return h.response(esResponse) .code(esResponse.statusCode) - .type('text/plain') .header('warning', esResponse.headers.warning); - }); + } + + return h.response(`${esResponse.statusCode} - ${esResponse.statusMessage}`) + .code(esResponse.statusCode) + .type('text/plain') + .header('warning', esResponse.headers.warning); } } }); diff --git a/src/core_plugins/elasticsearch/index.js b/src/core_plugins/elasticsearch/index.js index 2b5df76d743fb1..7536a8d4813d48 100644 --- a/src/core_plugins/elasticsearch/index.js +++ b/src/core_plugins/elasticsearch/index.js @@ -35,34 +35,32 @@ export default function (kibana) { return new kibana.Plugin({ require: ['kibana'], config(Joi) { - const { array, boolean, number, object, string, ref } = Joi; - - const sslSchema = object({ - verificationMode: string().valid('none', 'certificate', 'full').default('full'), - certificateAuthorities: array().single().items(string()), - certificate: string(), - key: string(), - keyPassphrase: string(), - alwaysPresentCertificate: boolean().default(false), + const sslSchema = Joi.object({ + verificationMode: Joi.string().valid('none', 'certificate', 'full').default('full'), + certificateAuthorities: Joi.array().single().items(Joi.string()), + certificate: Joi.string(), + key: Joi.string(), + keyPassphrase: Joi.string(), + alwaysPresentCertificate: Joi.boolean().default(false), }).default(); - return object({ - enabled: boolean().default(true), - url: string().uri({ scheme: ['http', 'https'] }).default('http://localhost:9200'), - preserveHost: boolean().default(true), - username: string(), - password: string(), - shardTimeout: number().default(30000), - requestTimeout: number().default(30000), - requestHeadersWhitelist: array().items().single().default(DEFAULT_REQUEST_HEADERS), - customHeaders: object().default({}), - pingTimeout: number().default(ref('requestTimeout')), - startupTimeout: number().default(5000), - logQueries: boolean().default(false), + return Joi.object({ + enabled: Joi.boolean().default(true), + url: Joi.string().uri({ scheme: ['http', 'https'] }).default('http://localhost:9200'), + preserveHost: Joi.boolean().default(true), + username: Joi.string(), + password: Joi.string(), + shardTimeout: Joi.number().default(30000), + requestTimeout: Joi.number().default(30000), + requestHeadersWhitelist: Joi.array().items().single().default(DEFAULT_REQUEST_HEADERS), + customHeaders: Joi.object().default({}), + pingTimeout: Joi.number().default(Joi.ref('requestTimeout')), + startupTimeout: Joi.number().default(5000), + logQueries: Joi.boolean().default(false), ssl: sslSchema, apiVersion: Joi.string().default('master'), - healthCheck: object({ - delay: number().default(2500) + healthCheck: Joi.object({ + delay: Joi.number().default(2500) }).default(), }).default(); }, diff --git a/src/core_plugins/elasticsearch/lib/__tests__/create_clusters.js b/src/core_plugins/elasticsearch/lib/__tests__/create_clusters.js index ce9ebc739a6510..c10e8e6ebae0e2 100644 --- a/src/core_plugins/elasticsearch/lib/__tests__/create_clusters.js +++ b/src/core_plugins/elasticsearch/lib/__tests__/create_clusters.js @@ -36,7 +36,9 @@ describe('plugins/elasticsearch', function () { elasticsearch: {} }, expose: sinon.mock(), - on: sinon.stub(), + events: { + on: sinon.stub(), + } }; clusters = createClusters(server); @@ -86,7 +88,6 @@ describe('plugins/elasticsearch', function () { it('closes all clusters', async () => { const server = new Hapi.Server(); - server.connection({ port: 0 }); const clusters = createClusters(server); const cluster = clusters.create('name', { config: true }); expect(cluster).to.have.property('stub', true); diff --git a/src/core_plugins/elasticsearch/lib/__tests__/health_check.js b/src/core_plugins/elasticsearch/lib/__tests__/health_check.js index 50cbe34a8985a1..bc3dae10b99c3c 100644 --- a/src/core_plugins/elasticsearch/lib/__tests__/health_check.js +++ b/src/core_plugins/elasticsearch/lib/__tests__/health_check.js @@ -114,13 +114,10 @@ describe('plugins/elasticsearch', () => { sinon.assert.calledOnce(server.ext); sinon.assert.calledWithExactly(server.ext, sinon.match.string, sinon.match.func); - // call the server extension - const reply = sinon.stub(); const [, handler] = server.ext.firstCall.args; - handler({}, reply); + handler(); // this should be health.stop - // ensure that the handler called reply and unregistered the time - sinon.assert.calledOnce(reply); + // ensure that the handler unregistered the timer expect(getTimerCount()).to.be(0); }); diff --git a/src/core_plugins/elasticsearch/lib/create_clusters.js b/src/core_plugins/elasticsearch/lib/create_clusters.js index e5a5c60b91612c..8847e466478481 100644 --- a/src/core_plugins/elasticsearch/lib/create_clusters.js +++ b/src/core_plugins/elasticsearch/lib/create_clusters.js @@ -22,7 +22,7 @@ import { Cluster } from './cluster'; export function createClusters(server) { const clusters = new Map(); - server.on('stop', () => { + server.events.on('stop', () => { for (const [name, cluster] of clusters) { cluster.close(); clusters.delete(name); diff --git a/src/core_plugins/elasticsearch/lib/create_proxy.js b/src/core_plugins/elasticsearch/lib/create_proxy.js index 64f5f94fe71b44..2ddfaa4c6c789f 100644 --- a/src/core_plugins/elasticsearch/lib/create_proxy.js +++ b/src/core_plugins/elasticsearch/lib/create_proxy.js @@ -33,10 +33,9 @@ export function createProxy(server, method, path, config) { ['/elasticsearch', server.plugins.elasticsearch.getCluster('data')], ]); - const responseHandler = function (err, upstreamResponse, request, reply) { + const responseHandler = function (err, upstreamResponse) { if (err) { - reply(err); - return; + throw err; } if (upstreamResponse.headers.location) { @@ -44,7 +43,7 @@ export function createProxy(server, method, path, config) { upstreamResponse.headers.location = encodeURI(upstreamResponse.headers.location); } - reply(null, upstreamResponse); + return upstreamResponse; }; for (const [proxyPrefix, cluster] of proxies) { diff --git a/src/core_plugins/elasticsearch/lib/health_check.js b/src/core_plugins/elasticsearch/lib/health_check.js index 7395c305df76b0..167cb3044b4a1f 100644 --- a/src/core_plugins/elasticsearch/lib/health_check.js +++ b/src/core_plugins/elasticsearch/lib/health_check.js @@ -95,10 +95,7 @@ export default function (plugin, server) { return true; } - server.ext('onPreStop', (request, reply) => { - stopChecking(); - reply(); - }); + server.ext('onPreStop', stopChecking); return { waitUntilReady: waitUntilReady, @@ -107,5 +104,4 @@ export default function (plugin, server) { stop: stopChecking, isRunning: function () { return !!timeoutId; }, }; - } diff --git a/src/core_plugins/elasticsearch/lib/map_uri.js b/src/core_plugins/elasticsearch/lib/map_uri.js index 11c9b99c6da3b6..8d127d6658a5b8 100644 --- a/src/core_plugins/elasticsearch/lib/map_uri.js +++ b/src/core_plugins/elasticsearch/lib/map_uri.js @@ -27,7 +27,7 @@ export default function mapUri(cluster, proxyPrefix) { return trimRight(pathA, '/') + '/' + trimLeft(pathB, '/'); } - return function (request, done) { + return function (request) { const { protocol: esUrlProtocol, slashes: esUrlHasSlashes, @@ -60,6 +60,6 @@ export default function mapUri(cluster, proxyPrefix) { const filteredHeaders = filterHeaders(request.headers, cluster.getRequestHeadersWhitelist()); const mappedHeaders = setHeaders(filteredHeaders, cluster.getCustomHeaders()); const mappedUrl = formatUrl(mappedUrlComponents); - done(null, mappedUrl, mappedHeaders); + return { uri: mappedUrl, headers: mappedHeaders }; }; } diff --git a/src/core_plugins/kibana/server/routes/api/export/index.js b/src/core_plugins/kibana/server/routes/api/export/index.js index 34f45e9a6b2dad..a2469d8f5c5ae7 100644 --- a/src/core_plugins/kibana/server/routes/api/export/index.js +++ b/src/core_plugins/kibana/server/routes/api/export/index.js @@ -36,18 +36,18 @@ export function exportApi(server) { tags: ['api'], }, method: ['GET'], - handler: (req, reply) => { + handler: async (req, h) => { const currentDate = moment.utc(); return exportDashboards(req) .then(resp => { const json = JSON.stringify(resp, null, ' '); const filename = `kibana-dashboards.${currentDate.format('YYYY-MM-DD-HH-mm-ss')}.json`; - reply(json) + return h.response(json) .header('Content-Disposition', `attachment; filename="${filename}"`) .header('Content-Type', 'application/json') .header('Content-Length', Buffer.byteLength(json, 'utf8')); }) - .catch(err => reply(Boom.boomify(err, { statusCode: 400 }))); + .catch(err => Boom.boomify(err, { statusCode: 400 })); } }); } diff --git a/src/core_plugins/kibana/server/routes/api/home/register_tutorials.js b/src/core_plugins/kibana/server/routes/api/home/register_tutorials.js index 89f1ff6213a14e..861ed1c244d13e 100644 --- a/src/core_plugins/kibana/server/routes/api/home/register_tutorials.js +++ b/src/core_plugins/kibana/server/routes/api/home/register_tutorials.js @@ -22,8 +22,8 @@ export function registerTutorials(server) { server.route({ path: '/api/kibana/home/tutorials', method: ['GET'], - handler: async function (req, reply) { - reply(server.getTutorials(req)); + handler: function (req) { + return server.getTutorials(req); } }); } diff --git a/src/core_plugins/kibana/server/routes/api/import/index.js b/src/core_plugins/kibana/server/routes/api/import/index.js index 945bd02059507d..c7291798c6d65e 100644 --- a/src/core_plugins/kibana/server/routes/api/import/index.js +++ b/src/core_plugins/kibana/server/routes/api/import/index.js @@ -39,10 +39,12 @@ export function importApi(server) { tags: ['api'], }, - handler: (req, reply) => { - return importDashboards(req) - .then((resp) => reply(resp)) - .catch(err => reply(Boom.boomify(err, { statusCode: 400 }))); + handler: async (req) => { + try { + return await importDashboards(req); + } catch (err) { + throw Boom.boomify(err, { statusCode: 400 }); + } } }); } diff --git a/src/core_plugins/kibana/server/routes/api/kql_telemetry/index.js b/src/core_plugins/kibana/server/routes/api/kql_telemetry/index.js index 028f3062be9e8f..242c691aa06de2 100644 --- a/src/core_plugins/kibana/server/routes/api/kql_telemetry/index.js +++ b/src/core_plugins/kibana/server/routes/api/kql_telemetry/index.js @@ -32,7 +32,7 @@ export function registerKqlTelemetryApi(server) { }, tags: ['api'], }, - handler: async function (request, reply) { + handler: async function (request) { const { savedObjects: { getSavedObjectsRepository } } = server; const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); const internalRepository = getSavedObjectsRepository(callWithInternalUser); @@ -51,10 +51,10 @@ export function registerKqlTelemetryApi(server) { ); } catch (error) { - reply(new Boom('Something went wrong', { statusCode: error.status, data: { success: false } })); + return new Boom('Something went wrong', { statusCode: error.status, data: { success: false } }); } - reply({ success: true }); + return { success: true }; }, }); } diff --git a/src/core_plugins/kibana/server/routes/api/management/saved_objects/relationships.js b/src/core_plugins/kibana/server/routes/api/management/saved_objects/relationships.js index 34eca71cc26109..2525fbebd69683 100644 --- a/src/core_plugins/kibana/server/routes/api/management/saved_objects/relationships.js +++ b/src/core_plugins/kibana/server/routes/api/management/saved_objects/relationships.js @@ -38,20 +38,19 @@ export function registerRelationships(server) { }, }, - handler: async (req, reply) => { + handler: async (req) => { const type = req.params.type; const id = req.params.id; const size = req.query.size || 10; try { - const response = await findRelationships(type, id, size, req.getSavedObjectsClient()); - reply(response); + return await findRelationships(type, id, size, req.getSavedObjectsClient()); } catch (err) { if (isNotFoundError(err)) { - reply(Boom.boomify(new Error('Resource not found'), { statusCode: 404 })); - return; + throw Boom.boomify(new Error('Resource not found'), { statusCode: 404 }); } - reply(Boom.boomify(err, { statusCode: 500 })); + + throw Boom.boomify(err, { statusCode: 500 }); } }, }); diff --git a/src/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js b/src/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js index a085b9581c726a..76cc66c05385c4 100644 --- a/src/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js +++ b/src/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js @@ -45,13 +45,14 @@ export function registerScrollForExportRoute(server) { }, }, - handler: async (req, reply) => { + handler: async (req) => { const savedObjectsClient = req.getSavedObjectsClient(); const objects = await findAll(savedObjectsClient, { perPage: 1000, type: req.payload.typesToInclude }); - const response = objects.map(hit => { + + return objects.map(hit => { const type = hit.type; return { _id: hit.id, @@ -63,8 +64,6 @@ export function registerScrollForExportRoute(server) { _migrationVersion: hit.migrationVersion, }; }); - - reply(response); } }); } @@ -82,7 +81,7 @@ export function registerScrollForCountRoute(server) { }, }, - handler: async (req, reply) => { + handler: async (req) => { const savedObjectsClient = req.getSavedObjectsClient(); const findOptions = { type: req.payload.typesToInclude, @@ -108,7 +107,7 @@ export function registerScrollForCountRoute(server) { } } - reply(counts); + return counts; } }); } diff --git a/src/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.test.js b/src/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.test.js index d64519f7ddd013..ad6f2f9ebc4b95 100644 --- a/src/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.test.js +++ b/src/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.test.js @@ -20,8 +20,15 @@ import Hapi from 'hapi'; import { registerScrollForExportRoute } from './scroll'; const createMockServer = () => { - const mockServer = new Hapi.Server({ debug: false }); - mockServer.connection({ port: 8080 }); + const mockServer = new Hapi.Server({ + debug: false, + port: 8080, + routes: { + validate: { + failAction: (r, h, err) => { throw err; } + } + } + }); return mockServer; }; diff --git a/src/core_plugins/kibana/server/routes/api/scripts/register_languages.js b/src/core_plugins/kibana/server/routes/api/scripts/register_languages.js index f8520ea97b77a1..6b27d24dda7854 100644 --- a/src/core_plugins/kibana/server/routes/api/scripts/register_languages.js +++ b/src/core_plugins/kibana/server/routes/api/scripts/register_languages.js @@ -21,8 +21,8 @@ export function registerLanguages(server) { server.route({ path: '/api/kibana/scripts/languages', method: 'GET', - handler: function (request, reply) { - reply(['painless', 'expression']); + handler: function () { + return ['painless', 'expression']; } }); } diff --git a/src/core_plugins/kibana/server/routes/api/scroll_search/index.js b/src/core_plugins/kibana/server/routes/api/scroll_search/index.js index 48301ded0523ec..734fce97d87655 100644 --- a/src/core_plugins/kibana/server/routes/api/scroll_search/index.js +++ b/src/core_plugins/kibana/server/routes/api/scroll_search/index.js @@ -23,7 +23,7 @@ export function scrollSearchApi(server) { server.route({ path: '/api/kibana/legacy_scroll_start', method: ['POST'], - handler: (req, reply) => { + handler: async (req) => { const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); const { index, size, body } = req.payload; const params = { @@ -33,21 +33,26 @@ export function scrollSearchApi(server) { scroll: '1m', sort: '_doc', }; - return callWithRequest(req, 'search', params) - .then(reply) - .catch(error => reply(handleESError(error))); + + try { + return await callWithRequest(req, 'search', params); + } catch (err) { + throw handleESError(err); + } } }); server.route({ path: '/api/kibana/legacy_scroll_continue', method: ['POST'], - handler: (req, reply) => { + handler: async (req) => { const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); const { scrollId } = req.payload; - return callWithRequest(req, 'scroll', { scrollId, scroll: '1m' }) - .then(reply) - .catch(error => reply(handleESError(error))); + try { + return await callWithRequest(req, 'scroll', { scrollId, scroll: '1m' }); + } catch (err) { + throw handleESError(err); + } } }); } diff --git a/src/core_plugins/kibana/server/routes/api/search/count/register_count.js b/src/core_plugins/kibana/server/routes/api/search/count/register_count.js index 3a1fd9ee62e773..c3b24c31339943 100644 --- a/src/core_plugins/kibana/server/routes/api/search/count/register_count.js +++ b/src/core_plugins/kibana/server/routes/api/search/count/register_count.js @@ -24,22 +24,20 @@ export default function registerCount(server) { server.route({ path: '/api/kibana/{id}/_count', method: ['POST', 'GET'], - handler: function (req, reply) { + handler: async function (req) { const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); const boundCallWithRequest = _.partial(callWithRequest, req); - boundCallWithRequest('count', { - allowNoIndices: false, - index: req.params.id - }) - .then( - function (res) { - reply({ count: res.count }); - }, - function (error) { - reply(handleESError(error)); - } - ); + try { + const res = await boundCallWithRequest('count', { + allowNoIndices: false, + index: req.params.id + }); + + return { count: res.count }; + } catch (err) { + throw handleESError(err); + } } }); } diff --git a/src/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js b/src/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js index e8be66959d666c..54adefc5405456 100644 --- a/src/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js +++ b/src/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js @@ -24,7 +24,7 @@ export function registerValueSuggestions(server) { server.route({ path: '/api/kibana/suggestions/values/{index}', method: ['POST'], - handler: async function (req, reply) { + handler: async function (req) { const { index } = req.params; const { field, query, boolFilter } = req.payload; const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); @@ -33,9 +33,9 @@ export function registerValueSuggestions(server) { const response = await callWithRequest(req, 'search', { index, body }); const buckets = get(response, 'aggregations.suggestions.buckets') || []; const suggestions = map(buckets, 'key'); - reply(suggestions); + return suggestions; } catch (error) { - reply(handleESError(error)); + throw handleESError(error); } } }); diff --git a/src/core_plugins/metrics/server/lib/get_index_pattern_service.js b/src/core_plugins/metrics/server/lib/get_index_pattern_service.js index c8f9d173b3cabe..e0bf9cbb2d6160 100644 --- a/src/core_plugins/metrics/server/lib/get_index_pattern_service.js +++ b/src/core_plugins/metrics/server/lib/get_index_pattern_service.js @@ -20,11 +20,11 @@ import { IndexPatternsService } from '../../../../server/index_patterns/service'; export const getIndexPatternService = { assign: 'indexPatternsService', - method(req, reply) { + method(req) { const dataCluster = req.server.plugins.elasticsearch.getCluster('data'); const callDataCluster = (...args) => { return dataCluster.callWithRequest(req, ...args); }; - reply(new IndexPatternsService(callDataCluster)); + return new IndexPatternsService(callDataCluster); } }; diff --git a/src/core_plugins/metrics/server/routes/fields.js b/src/core_plugins/metrics/server/routes/fields.js index 1b3472c4c576f2..762d551217ee3b 100644 --- a/src/core_plugins/metrics/server/routes/fields.js +++ b/src/core_plugins/metrics/server/routes/fields.js @@ -27,15 +27,17 @@ export default (server) => { }, path: '/api/metrics/fields', method: 'GET', - handler: (req, reply) => { - getFields(req) - .then(reply) - .catch((err) => { - if (err.isBoom && err.status === 401) return reply(err); - reply([]); - }); + handler: async (req) => { + try { + return await getFields(req); + } catch (err) { + if (err.isBoom && err.status === 401) { + return err; + } + + return []; + } } }); }; - diff --git a/src/core_plugins/metrics/server/routes/vis.js b/src/core_plugins/metrics/server/routes/vis.js index 1c6428233eee8f..9af52211f17aae 100644 --- a/src/core_plugins/metrics/server/routes/vis.js +++ b/src/core_plugins/metrics/server/routes/vis.js @@ -24,13 +24,16 @@ export default (server) => { server.route({ path: '/api/metrics/vis/data', method: 'POST', - handler: (req, reply) => { - getVisData(req) - .then(reply) - .catch(err => { - if (err.isBoom && err.status === 401) return reply(err); - reply(Boom.boomify(err, { statusCode: 500 })); - }); + handler: async (req) => { + try { + return await getVisData(req); + } catch(err) { + if (err.isBoom && err.status === 401) { + return err; + } + + throw Boom.boomify(err, { statusCode: 500 }); + } } }); diff --git a/src/core_plugins/timelion/server/routes/functions.js b/src/core_plugins/timelion/server/routes/functions.js index dde87f4453fff2..2fd97e38a00572 100644 --- a/src/core_plugins/timelion/server/routes/functions.js +++ b/src/core_plugins/timelion/server/routes/functions.js @@ -23,12 +23,13 @@ export default function (server) { server.route({ method: 'GET', path: '/api/timelion/functions', - handler: function (request, reply) { + handler: () => { const functionArray = _.map(server.plugins.timelion.functions, function (val, key) { // TODO: This won't work on frozen objects, it should be removed when everything is converted to datasources and chainables return _.extend({}, val, { name: key }); }); - reply(_.sortBy(functionArray, 'name')); + + return _.sortBy(functionArray, 'name'); } }); } diff --git a/src/core_plugins/timelion/server/routes/run.js b/src/core_plugins/timelion/server/routes/run.js index 197abbeeb516c3..e4c3b447b3970a 100644 --- a/src/core_plugins/timelion/server/routes/run.js +++ b/src/core_plugins/timelion/server/routes/run.js @@ -22,8 +22,8 @@ import _ from 'lodash'; import chainRunnerFn from '../handlers/chain_runner.js'; const timelionDefaults = require('../lib/get_namespaced_settings')(); -function replyWithError(e, reply) { - reply({ +function formatErrorResponse(e, h) { + return h.response({ title: e.toString(), message: e.toString() }).code(500); @@ -34,7 +34,7 @@ export default function (server) { server.route({ method: ['POST', 'GET'], path: '/api/timelion/run', - handler: async (request, reply) => { + handler: async (request, h) => { try { const uiSettings = await request.getUiSettingsService().getAll(); @@ -55,18 +55,18 @@ export default function (server) { } })); - reply({ + return { sheet, stats: chainRunner.getStats() - }); + }; } catch (err) { server.log(['timelion', 'error'], `${err.toString()}: ${err.stack}`); // TODO Maybe we should just replace everywhere we throw with Boom? Probably. if (err.isBoom) { - reply(err); + return err; } else { - replyWithError(err, reply); + return formatErrorResponse(err, h); } } } diff --git a/src/core_plugins/timelion/server/routes/validate_es.js b/src/core_plugins/timelion/server/routes/validate_es.js index dd76bf00f3e4ad..d2b4e366c0ba4b 100644 --- a/src/core_plugins/timelion/server/routes/validate_es.js +++ b/src/core_plugins/timelion/server/routes/validate_es.js @@ -23,7 +23,7 @@ export default function (server) { server.route({ method: 'GET', path: '/api/timelion/validate/es', - handler: async function (request, reply) { + handler: async function (request) { const uiSettings = await request.getUiSettingsService().getAll(); const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); @@ -57,19 +57,18 @@ export default function (server) { } if (_.has(resp, 'aggregations.maxAgg.value') && _.has(resp, 'aggregations.minAgg.value')) { - reply({ + return { ok: true, field: timefield, min: _.get(resp, 'aggregations.minAgg.value'), max: _.get(resp, 'aggregations.maxAgg.value') - }); - return; + }; } - reply({ + return { ok: false, resp: resp - }); + }; } }); } diff --git a/src/dev/build/tasks/nodejs/download.js b/src/dev/build/tasks/nodejs/download.js index f759d722345db7..736dbb6f2fe180 100644 --- a/src/dev/build/tasks/nodejs/download.js +++ b/src/dev/build/tasks/nodejs/download.js @@ -52,11 +52,7 @@ export async function download(options) { try { log.debug(`Attempting download of ${url}`, chalk.dim(sha256)); - const request = wreck.request('GET', url); - const response = await Promise.race([ - new Promise(resolve => request.once('response', resolve)), - new Promise((resolve, reject) => request.once('error', reject)), - ]); + const response = await wreck.request('GET', url); if (response.statusCode !== 200) { throw new Error( diff --git a/src/optimize/base_optimizer.js b/src/optimize/base_optimizer.js index ff8cae3fd2bc1b..dceb7b8c44be4e 100644 --- a/src/optimize/base_optimizer.js +++ b/src/optimize/base_optimizer.js @@ -427,8 +427,7 @@ export default class BaseOptimizer { Stats.presetToOptions('minimal') )); - return Boom.create( - 500, + throw Boom.internal( `Optimizations failure.\n${details.split('\n').join('\n ')}\n`, stats.toJson(Stats.presetToOptions('detailed')) ); diff --git a/src/optimize/bundles_route/__tests__/bundles_route.js b/src/optimize/bundles_route/__tests__/bundles_route.js index 147e8bd3335f5b..305bfb085d81f7 100644 --- a/src/optimize/bundles_route/__tests__/bundles_route.js +++ b/src/optimize/bundles_route/__tests__/bundles_route.js @@ -47,7 +47,6 @@ describe('optimizer/bundle route', () => { } = options; const server = new Hapi.Server(); - server.connection({ port: 0 }); server.register([Inert]); server.route(createBundlesRoute({ @@ -217,18 +216,18 @@ describe('optimizer/bundle route', () => { }); describe('js file outside bundlesPath', () => { - it('responds with a 403', async () => { + it('responds with a 404', async () => { const server = createServer(); const response = await server.inject({ url: '/bundles/../outside_output.js' }); - expect(response.statusCode).to.be(403); + expect(response.statusCode).to.be(404); expect(response.result).to.eql({ - error: 'Forbidden', - message: 'Forbidden', - statusCode: 403 + error: 'Not Found', + message: 'Not Found', + statusCode: 404 }); }); }); diff --git a/src/optimize/bundles_route/bundles_route.js b/src/optimize/bundles_route/bundles_route.js index 29e6ac28512c0f..40b708a9c7b59e 100644 --- a/src/optimize/bundles_route/bundles_route.js +++ b/src/optimize/bundles_route/bundles_route.js @@ -58,18 +58,19 @@ export function createBundlesRoute({ bundlesPath, basePublicPath }) { auth: false, ext: { onPreHandler: { - method(request, reply) { + method(request, h) { const ext = extname(request.params.path); if (ext !== '.js' && ext !== '.css') { - return reply.continue(); + return h.continue; } - reply(createDynamicAssetResponse({ + return createDynamicAssetResponse({ request, + h, bundlesPath, fileHashCache, publicPath: `${basePublicPath}/bundles/` - })); + }); } } }, diff --git a/src/optimize/bundles_route/dynamic_asset_response.js b/src/optimize/bundles_route/dynamic_asset_response.js index 56d3ff3ba2d0e1..d9106c7dc30906 100644 --- a/src/optimize/bundles_route/dynamic_asset_response.js +++ b/src/optimize/bundles_route/dynamic_asset_response.js @@ -54,6 +54,7 @@ import { replacePlaceholder } from '../public_path_placeholder'; export async function createDynamicAssetResponse(options) { const { request, + h, bundlesPath, publicPath, fileHashCache, @@ -65,7 +66,7 @@ export async function createDynamicAssetResponse(options) { // prevent path traversal, only process paths that resolve within bundlesPath if (!path.startsWith(bundlesPath)) { - return Boom.forbidden(null, 'EACCES'); + throw Boom.forbidden(null, 'EACCES'); } // we use and manage a file descriptor mostly because @@ -83,13 +84,12 @@ export async function createDynamicAssetResponse(options) { }); fd = null; // read stream is now responsible for fd - const response = request.generateResponse(replacePlaceholder(read, publicPath)); - response.code(200); - response.etag(`${hash}-${publicPath}`); - response.header('cache-control', 'must-revalidate'); - response.type(request.server.mime.path(path).type); - return response; - + return h.response(replacePlaceholder(read, publicPath)) + .takeover() + .code(200) + .etag(`${hash}-${publicPath}`) + .header('cache-control', 'must-revalidate') + .type(request.server.mime.path(path).type); } catch (error) { if (fd) { try { @@ -101,9 +101,9 @@ export async function createDynamicAssetResponse(options) { } if (error.code === 'ENOENT') { - return Boom.notFound(); + throw Boom.notFound(); } - return Boom.boomify(error); + throw Boom.boomify(error); } } diff --git a/src/optimize/watch/watch_optimizer.js b/src/optimize/watch/watch_optimizer.js index 215361a8cbf582..8adacf880680d1 100644 --- a/src/optimize/watch/watch_optimizer.js +++ b/src/optimize/watch/watch_optimizer.js @@ -63,10 +63,9 @@ export default class WatchOptimizer extends BaseOptimizer { // pause all requests received while the compiler is running // and continue once an outcome is reached (aborting the request // with an error if it was a failure). - server.ext('onRequest', (request, reply) => { - this.onceBuildOutcome() - .then(() => reply.continue()) - .catch(reply); + server.ext('onRequest', async (request, h) => { + await this.onceBuildOutcome(); + return h.continue; }); server.route(createBundlesRoute({ diff --git a/src/optimize/watch/watch_server.js b/src/optimize/watch/watch_server.js index 68c7e581aa8484..b45a8c8782e9dd 100644 --- a/src/optimize/watch/watch_server.js +++ b/src/optimize/watch/watch_server.js @@ -19,26 +19,23 @@ import { Server } from 'hapi'; -import { fromNode } from 'bluebird'; import { registerHapiPlugins } from '../../server/http/register_hapi_plugins'; export default class WatchServer { constructor(host, port, basePath, optimizer) { this.basePath = basePath; this.optimizer = optimizer; - this.server = new Server(); - - registerHapiPlugins(this.server); - - this.server.connection({ + this.server = new Server({ host: host, port: port }); + + registerHapiPlugins(this.server); } async init() { await this.optimizer.init(); this.optimizer.bindToServer(this.server, this.basePath); - await fromNode(cb => this.server.start(cb)); + await this.server.start(); } } diff --git a/src/server/config/__tests__/deprecation_warnings.js b/src/server/config/__tests__/deprecation_warnings.js index 9935a2e4bddbff..f910d9604fd97b 100644 --- a/src/server/config/__tests__/deprecation_warnings.js +++ b/src/server/config/__tests__/deprecation_warnings.js @@ -31,7 +31,7 @@ describe('config/deprecation warnings mixin', function () { let stdio = ''; let proc = null; - before(() => new Promise((resolve, reject) => { + before(async () => { proc = spawn(process.execPath, [ '-r', SETUP_NODE_ENV, RUN_KBN_SERVER_STARTUP @@ -50,23 +50,35 @@ describe('config/deprecation warnings mixin', function () { } }); - proc.stdout.on('data', (chunk) => { - stdio += chunk.toString('utf8'); - }); + // Either time out in 10 seconds, or resolve once the line is in our buffer + return Promise.race([ + new Promise((resolve) => setTimeout(resolve, 10000)), + new Promise((resolve, reject) => { + proc.stdout.on('data', (chunk) => { + stdio += chunk.toString('utf8'); + if (chunk.toString('utf8').includes('deprecation')) { + resolve(); + } + }); - proc.stderr.on('data', (chunk) => { - stdio += chunk.toString('utf8'); - }); + proc.stderr.on('data', (chunk) => { + stdio += chunk.toString('utf8'); + if (chunk.toString('utf8').includes('deprecation')) { + resolve(); + } + }); - proc.on('exit', (code) => { - proc = null; - if (code > 0) { - reject(new Error(`Kibana server exited with ${code} -- stdout:\n\n${stdio}\n`)); - } else { - resolve(); - } - }); - })); + proc.on('exit', (code) => { + proc = null; + if (code > 0) { + reject(new Error(`Kibana server exited with ${code} -- stdout:\n\n${stdio}\n`)); + } else { + resolve(); + } + }); + }) + ]); + }); after(() => { if (proc) { diff --git a/src/server/config/schema.test.js b/src/server/config/schema.test.js index 2ccb75cd368632..f27a25fefc585c 100644 --- a/src/server/config/schema.test.js +++ b/src/server/config/schema.test.js @@ -51,20 +51,20 @@ describe('Config schema', function () { it('rejects strings with trailing slashes', function () { const { error } = validate({ server: { basePath: '/path/' } }); expect(error).toHaveProperty('details'); - expect(error.details[0]).toHaveProperty('path', 'server.basePath'); + expect(error.details[0]).toHaveProperty('path', ['server', 'basePath']); }); it('rejects strings without leading slashes', function () { const { error } = validate({ server: { basePath: 'path' } }); expect(error).toHaveProperty('details'); - expect(error.details[0]).toHaveProperty('path', 'server.basePath'); + expect(error.details[0]).toHaveProperty('path', ['server', 'basePath']); }); it('rejects things that are not strings', function () { for (const value of [1, true, {}, [], /foo/]) { const { error } = validate({ server: { basePath: value } }); expect(error).toHaveProperty('details'); - expect(error.details[0]).toHaveProperty('path', 'server.basePath'); + expect(error.details[0]).toHaveProperty('path', ['server', 'basePath']); } }); }); @@ -91,13 +91,13 @@ describe('Config schema', function () { it('rejects true if basePath not set', function () { const { error } = validate({ server: { rewriteBasePath: true } }); expect(error).toHaveProperty('details'); - expect(error.details[0]).toHaveProperty('path', 'server.rewriteBasePath'); + expect(error.details[0]).toHaveProperty('path', ['server', 'rewriteBasePath']); }); it('rejects strings', function () { const { error } = validate({ server: { rewriteBasePath: 'foo' } }); expect(error).toHaveProperty('details'); - expect(error.details[0]).toHaveProperty('path', 'server.rewriteBasePath'); + expect(error.details[0]).toHaveProperty('path', ['server', 'rewriteBasePath']); }); }); @@ -110,7 +110,7 @@ describe('Config schema', function () { const { error } = validate(config); expect(error).toBeInstanceOf(Object); expect(error).toHaveProperty('details'); - expect(error.details[0]).toHaveProperty('path', 'server.ssl.enabled'); + expect(error.details[0]).toHaveProperty('path', ['server', 'ssl', 'enabled']); }); it('can be true', function () { @@ -146,7 +146,7 @@ describe('Config schema', function () { const { error } = validate(config); expect(error).toBeInstanceOf(Object); expect(error).toHaveProperty('details'); - expect(error.details[0]).toHaveProperty('path', 'server.ssl.certificate'); + expect(error.details[0]).toHaveProperty('path', ['server', 'ssl', 'certificate']); }); }); @@ -165,7 +165,7 @@ describe('Config schema', function () { const { error } = validate(config); expect(error).toBeInstanceOf(Object); expect(error).toHaveProperty('details'); - expect(error.details[0]).toHaveProperty('path', 'server.ssl.key'); + expect(error.details[0]).toHaveProperty('path', ['server', 'ssl', 'key']); }); }); @@ -202,7 +202,7 @@ describe('Config schema', function () { const { error } = validate(config); expect(error).toBeInstanceOf(Object); expect(error).toHaveProperty('details'); - expect(error.details[0]).toHaveProperty('path', 'server.ssl.supportedProtocols.0'); + expect(error.details[0]).toHaveProperty('path', ['server', 'ssl', 'supportedProtocols', 0]); }); it('rejects SSLv3', function () { @@ -211,7 +211,7 @@ describe('Config schema', function () { const { error } = validate(config); expect(error).toBeInstanceOf(Object); expect(error).toHaveProperty('details'); - expect(error.details[0]).toHaveProperty('path', 'server.ssl.supportedProtocols.0'); + expect(error.details[0]).toHaveProperty('path', ['server', 'ssl', 'supportedProtocols', 0]); }); it('accepts TLSv1, TLSv1.1, TLSv1.2', function () { @@ -243,7 +243,7 @@ describe('Config schema', function () { const { error } = validate(config); expect(error).toBeInstanceOf(Object); expect(error).toHaveProperty('details'); - expect(error.details[0]).toHaveProperty('path', 'server.xsrf.whitelist.0'); + expect(error.details[0]).toHaveProperty('path', ['server', 'xsrf', 'whitelist', 0]); }); it('whitelist accepts paths that start with a slash.', () => { diff --git a/src/server/http/index.js b/src/server/http/index.js index d7a79b0d02fa7a..9a571052e45909 100644 --- a/src/server/http/index.js +++ b/src/server/http/index.js @@ -28,14 +28,12 @@ import { setupBasePathProvider } from './setup_base_path_provider'; import { setupXsrf } from './xsrf'; export default async function (kbnServer, server, config) { - kbnServer.server = new Hapi.Server(); + kbnServer.server = new Hapi.Server(kbnServer.core.serverOptions); server = kbnServer.server; - server.connection(kbnServer.core.serverOptions); - setupBasePathProvider(server, config); - registerHapiPlugins(server); + await registerHapiPlugins(server); // provide a simple way to expose static directories server.decorate('server', 'exposeStaticDir', function (routePath, dirPath) { @@ -63,7 +61,7 @@ export default async function (kbnServer, server, config) { }); // attach the app name to the server, so we can be sure we are actually talking to kibana - server.ext('onPreResponse', function (req, reply) { + server.ext('onPreResponse', function onPreResponse(req, h) { const response = req.response; const customHeaders = { @@ -82,32 +80,34 @@ export default async function (kbnServer, server, config) { }); } - return reply.continue(); + return h.continue; }); server.route({ path: '/', method: 'GET', - handler(req, reply) { + handler(req, h) { const basePath = req.getBasePath(); const defaultRoute = config.get('server.defaultRoute'); - reply.redirect(`${basePath}${defaultRoute}`); + return h.redirect(`${basePath}${defaultRoute}`); } }); server.route({ method: 'GET', path: '/{p*}', - handler: function (req, reply) { + handler: function (req, h) { const path = req.path; if (path === '/' || path.charAt(path.length - 1) !== '/') { - return reply(Boom.notFound()); + throw Boom.notFound(); } + const pathPrefix = req.getBasePath() ? `${req.getBasePath()}/` : ''; - return reply.redirect(format({ - search: req.url.search, - pathname: pathPrefix + path.slice(0, -1), - })) + return h + .redirect(format({ + search: req.url.search, + pathname: pathPrefix + path.slice(0, -1), + })) .permanent(true); } }); diff --git a/src/server/http/integration_tests/max_payload_size.test.js b/src/server/http/integration_tests/max_payload_size.test.js index 3fa7ca721e1efb..5349cda4bf4872 100644 --- a/src/server/http/integration_tests/max_payload_size.test.js +++ b/src/server/http/integration_tests/max_payload_size.test.js @@ -29,7 +29,7 @@ beforeAll(async () => { path: '/payload_size_check/test/route', method: 'POST', config: { payload: { maxBytes: 200 } }, - handler: (req, reply) => reply(null, req.payload.data.slice(0, 5)), + handler: (req) => req.payload.data.slice(0, 5), }); }, 30000); @@ -41,12 +41,12 @@ test('accepts payload with a size larger than default but smaller than route con .expect(200, '+++++'); }); -test('fails with 400 if payload size is larger than default and route config allows', async () => { +test('fails with 413 if payload size is larger than default and route config allows', async () => { await kbnTestServer.request.post(root, '/payload_size_check/test/route') .send({ data: Array(250).fill('+').join('') }) - .expect(400, { - statusCode: 400, - error: 'Bad Request', + .expect(413, { + statusCode: 413, + error: 'Request Entity Too Large', message: 'Payload content length greater than maximum allowed: 200' }); }); diff --git a/src/server/http/integration_tests/version_check.test.js b/src/server/http/integration_tests/version_check.test.js index 676391ce3233bf..3b3d70e5f35add 100644 --- a/src/server/http/integration_tests/version_check.test.js +++ b/src/server/http/integration_tests/version_check.test.js @@ -35,8 +35,8 @@ describe('version_check request filter', function () { kbnTestServer.getKbnServer(root).server.route({ path: '/version_check/test/route', method: 'GET', - handler: function (req, reply) { - reply(null, 'ok'); + handler: function () { + return 'ok'; } }); }, 30000); diff --git a/src/server/http/integration_tests/xsrf.test.js b/src/server/http/integration_tests/xsrf.test.js index a8c87653e9b409..61c38e2878c306 100644 --- a/src/server/http/integration_tests/xsrf.test.js +++ b/src/server/http/integration_tests/xsrf.test.js @@ -44,8 +44,8 @@ describe('xsrf request filter', () => { kbnServer.server.route({ path: testPath, method: 'GET', - handler: function (req, reply) { - reply(null, 'ok'); + handler: async function () { + return 'ok'; } }); @@ -58,8 +58,8 @@ describe('xsrf request filter', () => { parse: false } }, - handler: function (req, reply) { - reply(null, 'ok'); + handler: async function () { + return 'ok'; } }); @@ -72,8 +72,8 @@ describe('xsrf request filter', () => { parse: false } }, - handler: function (req, reply) { - reply(null, 'ok'); + handler: async function () { + return 'ok'; } }); }, 30000); diff --git a/src/server/http/register_hapi_plugins.js b/src/server/http/register_hapi_plugins.js index 8f8f4700b4c8a1..103e4a77cb4b2b 100644 --- a/src/server/http/register_hapi_plugins.js +++ b/src/server/http/register_hapi_plugins.js @@ -20,14 +20,11 @@ import HapiTemplates from 'vision'; import HapiStaticFiles from 'inert'; import HapiProxy from 'h2o2'; -import { fromNode } from 'bluebird'; const plugins = [HapiTemplates, HapiStaticFiles, HapiProxy]; async function registerPlugins(server) { - await fromNode(cb => { - server.register(plugins, cb); - }); + return await server.register(plugins); } export function registerHapiPlugins(server) { diff --git a/src/server/http/version_check.js b/src/server/http/version_check.js index c428e985a6e51e..8bd2bb6e22df18 100644 --- a/src/server/http/version_check.js +++ b/src/server/http/version_check.js @@ -23,16 +23,16 @@ export function setupVersionCheck(server, config) { const versionHeader = 'kbn-version'; const actualVersion = config.get('pkg.version'); - server.ext('onPostAuth', function (req, reply) { + server.ext('onPostAuth', function onPostAuthVersionCheck(req, h) { const versionRequested = req.headers[versionHeader]; if (versionRequested && versionRequested !== actualVersion) { - return reply(badRequest('Browser client is out of date, please refresh the page', { + throw badRequest('Browser client is out of date, please refresh the page', { expected: actualVersion, got: versionRequested - })); + }); } - return reply.continue(); + return h.continue; }); } diff --git a/src/server/http/xsrf.js b/src/server/http/xsrf.js index 8f98b113f7a2dc..79ac3af6d9f905 100644 --- a/src/server/http/xsrf.js +++ b/src/server/http/xsrf.js @@ -25,13 +25,13 @@ export function setupXsrf(server, config) { const versionHeader = 'kbn-version'; const xsrfHeader = 'kbn-xsrf'; - server.ext('onPostAuth', function (req, reply) { + server.ext('onPostAuth', function onPostAuthXsrf(req, h) { if (disabled) { - return reply.continue(); + return h.continue; } if (whitelist.includes(req.path)) { - return reply.continue(); + return h.continue; } const isSafeMethod = req.method === 'get' || req.method === 'head'; @@ -39,9 +39,9 @@ export function setupXsrf(server, config) { const hasXsrfHeader = xsrfHeader in req.headers; if (!isSafeMethod && !hasVersionHeader && !hasXsrfHeader) { - return reply(badRequest(`Request must contain a ${xsrfHeader} header.`)); + throw badRequest(`Request must contain a ${xsrfHeader} header.`); } - return reply.continue(); + return h.continue; }); } diff --git a/src/server/index_patterns/mixin.js b/src/server/index_patterns/mixin.js index c5d0c1d8f27325..1903af7683c2eb 100644 --- a/src/server/index_patterns/mixin.js +++ b/src/server/index_patterns/mixin.js @@ -32,8 +32,8 @@ export function indexPatternsMixin(kbnServer, server) { */ getIndexPatternsService: { assign: 'indexPatterns', - method(request, reply) { - reply(request.getIndexPatternsService()); + method(request) { + return request.getIndexPatternsService(); } } }; diff --git a/src/server/index_patterns/routes/fields_for_time_pattern_route.js b/src/server/index_patterns/routes/fields_for_time_pattern_route.js index e9b959e6761448..f7ec6e751c7e73 100644 --- a/src/server/index_patterns/routes/fields_for_time_pattern_route.js +++ b/src/server/index_patterns/routes/fields_for_time_pattern_route.js @@ -31,7 +31,7 @@ export const createFieldsForTimePatternRoute = pre => ({ meta_fields: Joi.array().items(Joi.string()).default([]), }).default() }, - handler(req, reply) { + async handler(req) { const { indexPatterns } = req.pre; const { pattern, @@ -40,15 +40,14 @@ export const createFieldsForTimePatternRoute = pre => ({ meta_fields: metaFields, } = req.query; - reply( - indexPatterns.getFieldsForTimePattern({ - pattern, - interval, - lookBack, - metaFields - }) - .then(fields => ({ fields })) - ); + const fields = await indexPatterns.getFieldsForTimePattern({ + pattern, + interval, + lookBack, + metaFields + }); + + return { fields }; } } }); diff --git a/src/server/index_patterns/routes/fields_for_wildcard_route.js b/src/server/index_patterns/routes/fields_for_wildcard_route.js index 2ca6a007bd182e..953bba3e0b16dd 100644 --- a/src/server/index_patterns/routes/fields_for_wildcard_route.js +++ b/src/server/index_patterns/routes/fields_for_wildcard_route.js @@ -30,20 +30,19 @@ export const createFieldsForWildcardRoute = pre => ({ meta_fields: Joi.array().items(Joi.string()).default([]), }).default() }, - handler(req, reply) { + async handler(req) { const { indexPatterns } = req.pre; const { pattern, meta_fields: metaFields, } = req.query; - reply( - indexPatterns.getFieldsForWildcard({ - pattern, - metaFields - }) - .then(fields => ({ fields })) - ); + const fields = await indexPatterns.getFieldsForWildcard({ + pattern, + metaFields + }); + + return { fields }; } } }); diff --git a/src/server/kbn_server.js b/src/server/kbn_server.js index 042a2973399e7c..977f3abf586c89 100644 --- a/src/server/kbn_server.js +++ b/src/server/kbn_server.js @@ -18,7 +18,6 @@ */ import { constant, once, compact, flatten } from 'lodash'; -import { fromNode } from 'bluebird'; import { isWorker } from 'cluster'; import { fromRoot, pkg } from '../utils'; import { Config } from './config'; @@ -161,7 +160,7 @@ export default class KbnServer { return; } - await fromNode(cb => this.server.stop(cb)); + await this.server.stop(); } async inject(opts) { @@ -185,6 +184,6 @@ export default class KbnServer { }; const plain = JSON.stringify(subset, null, 2); this.server.log(['info', 'config'], 'New logging configuration:\n' + plain); - this.server.plugins['even-better'].monitor.reconfigure(loggingOptions); + this.server.plugins['@elastic/good'].reconfigure(loggingOptions); } } diff --git a/src/server/logging/configuration.js b/src/server/logging/configuration.js index 59019ad8731290..44b128f5846712 100644 --- a/src/server/logging/configuration.js +++ b/src/server/logging/configuration.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import logReporter from './log_reporter'; +import { getLoggerStream } from './log_reporter'; export default function loggingConfiguration(config) { const events = config.get('logging.events'); @@ -51,33 +51,37 @@ export default function loggingConfiguration(config) { }); } - const options = { - opsInterval: config.get('ops.interval'), - requestHeaders: true, - requestPayload: true, - reporters: [ - { - reporter: logReporter, - config: { - json: config.get('logging.json'), - dest: config.get('logging.dest'), - timezone: config.get('logging.timezone'), + const loggerStream = getLoggerStream({ + config: { + json: config.get('logging.json'), + dest: config.get('logging.dest'), + timezone: config.get('logging.timezone'), + + // I'm adding the default here because if you add another filter + // using the commandline it will remove authorization. I want users + // to have to explicitly set --logging.filter.authorization=none or + // --logging.filter.cookie=none to have it show up in the logs. + filter: _.defaults(config.get('logging.filter'), { + authorization: 'remove', + cookie: 'remove' + }) + }, + events: _.transform(events, function (filtered, val, key) { + // provide a string compatible way to remove events + if (val !== '!') filtered[key] = val; + }, {}) + }); - // I'm adding the default here because if you add another filter - // using the commandline it will remove authorization. I want users - // to have to explicitly set --logging.filter.authorization=none or - // --logging.filter.cookie=none to have it show up in the logs. - filter: _.defaults(config.get('logging.filter'), { - authorization: 'remove', - cookie: 'remove' - }) - }, - events: _.transform(events, function (filtered, val, key) { - // provide a string compatible way to remove events - if (val !== '!') filtered[key] = val; - }, {}) - } - ] + const options = { + ops: { + interval: config.get('ops.interval') + }, + includes: { + request: ['headers', 'payload'] + }, + reporters: { + logReporter: [loggerStream] + } }; return options; } diff --git a/src/server/logging/index.js b/src/server/logging/index.js index 975f3092792bb9..b6d9f64de21eb0 100644 --- a/src/server/logging/index.js +++ b/src/server/logging/index.js @@ -17,16 +17,13 @@ * under the License. */ -import { fromNode } from 'bluebird'; -import evenBetter from 'even-better'; +import good from '@elastic/good'; import loggingConfiguration from './configuration'; -export function setupLogging(server, config) { - return fromNode((cb) => { - server.register({ - register: evenBetter, - options: loggingConfiguration(config) - }, cb); +export async function setupLogging(server, config) { + return await server.register({ + plugin: good, + options: loggingConfiguration(config) }); } diff --git a/src/server/logging/log_interceptor.js b/src/server/logging/log_interceptor.js index 5c32330739bd9f..eaddae122aa49b 100644 --- a/src/server/logging/log_interceptor.js +++ b/src/server/logging/log_interceptor.js @@ -35,7 +35,7 @@ function doesMessageMatch(errorMessage, match) { // converts the given event into a debug log if it's an error of the given type function downgradeIfErrorType(errorType, event, field = 'errno') { const isClientError = doTagsMatch(event, ['connection', 'client', 'error']); - const matchesErrorType = isClientError && get(event, `data.${field}`) === errorType; + const matchesErrorType = isClientError && get(event, `error.${field}`) === errorType; if (!matchesErrorType) return null; @@ -52,7 +52,7 @@ function downgradeIfErrorType(errorType, event, field = 'errno') { function downgradeIfErrorMessage(match, event) { const isClientError = doTagsMatch(event, ['connection', 'client', 'error']); - const errorMessage = get(event, 'data.message'); + const errorMessage = get(event, 'error.message'); const matchesErrorMessage = isClientError && doesMessageMatch(errorMessage, match); if (!matchesErrorMessage) return null; diff --git a/src/server/logging/log_interceptor.test.js b/src/server/logging/log_interceptor.test.js index b93ab01ffce4f2..43290f9b497375 100644 --- a/src/server/logging/log_interceptor.test.js +++ b/src/server/logging/log_interceptor.test.js @@ -27,7 +27,7 @@ function stubClientErrorEvent(errorMeta) { pid: 1234, timestamp: Date.now(), tags: ['connection', 'client', 'error'], - data: error + error }; } diff --git a/src/server/logging/log_reporter.js b/src/server/logging/log_reporter.js index 2d8f5c476e0987..3a1b421a48c2fa 100644 --- a/src/server/logging/log_reporter.js +++ b/src/server/logging/log_reporter.js @@ -24,38 +24,29 @@ import LogFormatJson from './log_format_json'; import LogFormatString from './log_format_string'; import { LogInterceptor } from './log_interceptor'; -export default class KbnLogger { - constructor(events, config) { - this.squeeze = new Squeeze(events); - this.format = config.json ? new LogFormatJson(config) : new LogFormatString(config); - this.logInterceptor = new LogInterceptor(); +export function getLoggerStream({ events, config }) { + const squeeze = new Squeeze(events); + const format = config.json ? new LogFormatJson(config) : new LogFormatString(config); + const logInterceptor = new LogInterceptor(); + + let dest; + if (config.dest === 'stdout') { + dest = process.stdout; + } else { + dest = writeStr(config.dest, { + flags: 'a', + encoding: 'utf8' + }); - if (config.dest === 'stdout') { - this.dest = process.stdout; - } else { - this.dest = writeStr(config.dest, { - flags: 'a', - encoding: 'utf8' - }); - } + logInterceptor.on('end', () => { + dest.end(); + }); } - init(readstream, emitter, callback) { - - this.output = readstream - .pipe(this.logInterceptor) - .pipe(this.squeeze) - .pipe(this.format); - - this.output.pipe(this.dest); + logInterceptor + .pipe(squeeze) + .pipe(format) + .pipe(dest); - emitter.on('stop', () => { - this.output.unpipe(this.dest); - if (this.dest !== process.stdout) { - this.dest.end(); - } - }); - - callback(); - } + return logInterceptor; } diff --git a/src/server/pid/index.js b/src/server/pid/index.js index 1f67f7ac0d695f..30592c525390c5 100644 --- a/src/server/pid/index.js +++ b/src/server/pid/index.js @@ -40,7 +40,7 @@ export default Promise.method(function (kbnServer, server, config) { }; if (config.get('pid.exclusive')) { - throw Boom.create(500, _.template(log.tmpl)(log), log); + throw Boom.internal(_.template(log.tmpl)(log), log); } else { server.log(['pid', 'warning'], log); } diff --git a/src/server/plugins/lib/plugin.js b/src/server/plugins/lib/plugin.js index b8bd335d911f46..7399804c818fe7 100644 --- a/src/server/plugins/lib/plugin.js +++ b/src/server/plugins/lib/plugin.js @@ -62,7 +62,7 @@ export class Plugin { const { config } = kbnServer; // setup the hapi register function and get on with it - const asyncRegister = async (server, options) => { + const register = async (server, options) => { this._server = server; this._options = options; @@ -85,15 +85,8 @@ export class Plugin { } }; - const register = (server, options, next) => { - asyncRegister(server, options) - .then(() => next(), next); - }; - - register.attributes = { name: id, version: version }; - await kbnServer.server.register({ - register: register, + plugin: { register, name: id, version }, options: config.has(configPrefix) ? config.get(configPrefix) : null }); diff --git a/src/server/sample_data/routes/install.js b/src/server/sample_data/routes/install.js index fc3323c9611094..13111bd6775bc8 100644 --- a/src/server/sample_data/routes/install.js +++ b/src/server/sample_data/routes/install.js @@ -17,6 +17,7 @@ * under the License. */ +import Boom from 'boom'; import Joi from 'joi'; import { loadData } from './lib/load_data'; @@ -75,13 +76,13 @@ export const createInstallRoute = () => ({ id: Joi.string().required(), }).required() }, - handler: async (request, reply) => { + handler: async (request, h) => { const server = request.server; const sampleDataset = server.getSampleDatasets().find(sampleDataset => { return sampleDataset.id === request.params.id; }); if (!sampleDataset) { - return reply().code(404); + return h.response().code(404); } const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); @@ -122,7 +123,7 @@ export const createInstallRoute = () => ({ } catch (err) { const errMsg = `Unable to create sample data index "${index}", error: ${err.message}`; server.log(['warning'], errMsg); - return reply(errMsg).code(err.status); + return h.response(errMsg).code(err.status); } try { @@ -131,7 +132,7 @@ export const createInstallRoute = () => ({ counts[index] = count; } catch (err) { server.log(['warning'], `sample_data install errors while loading data. Error: ${err}`); - return reply(err.message).code(500); + return h.response(err.message).code(500); } } @@ -140,17 +141,17 @@ export const createInstallRoute = () => ({ createResults = await request.getSavedObjectsClient().bulkCreate(sampleDataset.savedObjects, { overwrite: true }); } catch (err) { server.log(['warning'], `bulkCreate failed, error: ${err.message}`); - return reply(`Unable to load kibana saved objects, see kibana logs for details`).code(500); + return Boom.badImplementation(`Unable to load kibana saved objects, see kibana logs for details`); } const errors = createResults.saved_objects.filter(savedObjectCreateResult => { return savedObjectCreateResult.hasOwnProperty('error'); }); if (errors.length > 0) { server.log(['warning'], `sample_data install errors while loading saved objects. Errors: ${errors.join(',')}`); - return reply(`Unable to load kibana saved objects, see kibana logs for details`).code(403); + return h.response(`Unable to load kibana saved objects, see kibana logs for details`).code(403); } - return reply({ elasticsearchIndicesCreated: counts, kibanaSavedObjectsLoaded: sampleDataset.savedObjects.length }); + return h.response({ elasticsearchIndicesCreated: counts, kibanaSavedObjectsLoaded: sampleDataset.savedObjects.length }); } } }); diff --git a/src/server/sample_data/routes/list.js b/src/server/sample_data/routes/list.js index a58a7fb5d1f7db..33e0af5ad73d56 100644 --- a/src/server/sample_data/routes/list.js +++ b/src/server/sample_data/routes/list.js @@ -28,7 +28,7 @@ export const createListRoute = () => ({ path: '/api/sample_data', method: 'GET', config: { - handler: async (request, reply) => { + handler: async (request) => { const { callWithRequest } = request.server.plugins.elasticsearch.getCluster('data'); const sampleDatasets = request.server.getSampleDatasets().map(sampleDataset => { @@ -86,7 +86,7 @@ export const createListRoute = () => ({ }); await Promise.all(isInstalledPromises); - reply(sampleDatasets); + return sampleDatasets; } } }); diff --git a/src/server/sample_data/routes/uninstall.js b/src/server/sample_data/routes/uninstall.js index 94bb9b59bce4cf..caa865ee2363fc 100644 --- a/src/server/sample_data/routes/uninstall.js +++ b/src/server/sample_data/routes/uninstall.js @@ -31,15 +31,14 @@ export const createUninstallRoute = () => ({ id: Joi.string().required(), }).required() }, - handler: async (request, reply) => { + handler: async (request, h) => { const server = request.server; const sampleDataset = server.getSampleDatasets().find(({ id }) => { return id === request.params.id; }); if (!sampleDataset) { - reply().code(404); - return; + return h.response().code(404); } const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); @@ -51,7 +50,7 @@ export const createUninstallRoute = () => ({ try { await callWithRequest(request, 'indices.delete', { index: index }); } catch (err) { - return reply(`Unable to delete sample data index "${index}", error: ${err.message}`).code(err.status); + return h.response(`Unable to delete sample data index "${index}", error: ${err.message}`).code(err.status); } } @@ -63,11 +62,11 @@ export const createUninstallRoute = () => ({ } catch (err) { // ignore 404s since users could have deleted some of the saved objects via the UI if (_.get(err, 'output.statusCode') !== 404) { - return reply(`Unable to delete sample dataset saved objects, error: ${err.message}`).code(403); + return h.response(`Unable to delete sample dataset saved objects, error: ${err.message}`).code(403); } } - reply({}); + return {}; } } }); diff --git a/src/server/saved_objects/routes/_mock_server.js b/src/server/saved_objects/routes/_mock_server.js index 72251522ab82cb..1a3b94e3884547 100644 --- a/src/server/saved_objects/routes/_mock_server.js +++ b/src/server/saved_objects/routes/_mock_server.js @@ -17,14 +17,22 @@ * under the License. */ -const Hapi = require('hapi'); +import Hapi from 'hapi'; +import { defaultValidationErrorHandler } from '../../../core/server/http/http_tools'; + const defaultConfig = { 'kibana.index': '.kibana' }; export function MockServer(config = defaultConfig) { - const server = new Hapi.Server(); - server.connection({ port: 8080 }); + const server = new Hapi.Server({ + port: 0, + routes: { + validate: { + failAction: defaultValidationErrorHandler + } + } + }); server.config = function () { return { get: (key) => { diff --git a/src/server/saved_objects/routes/bulk_create.js b/src/server/saved_objects/routes/bulk_create.js index bd5b365133c51b..943b2520a331d7 100644 --- a/src/server/saved_objects/routes/bulk_create.js +++ b/src/server/saved_objects/routes/bulk_create.js @@ -40,11 +40,11 @@ export const createBulkCreateRoute = prereqs => ({ }).required() ), }, - handler(request, reply) { + handler(request) { const { overwrite } = request.query; const { savedObjectsClient } = request.pre; - reply(savedObjectsClient.bulkCreate(request.payload, { overwrite })); + return savedObjectsClient.bulkCreate(request.payload, { overwrite }); }, }, }); diff --git a/src/server/saved_objects/routes/bulk_get.js b/src/server/saved_objects/routes/bulk_get.js index fc7145a7625522..25c1a9964d6b17 100644 --- a/src/server/saved_objects/routes/bulk_get.js +++ b/src/server/saved_objects/routes/bulk_get.js @@ -30,10 +30,10 @@ export const createBulkGetRoute = (prereqs) => ({ id: Joi.string().required(), }).required()) }, - handler(request, reply) { + handler(request) { const { savedObjectsClient } = request.pre; - reply(savedObjectsClient.bulkGet(request.payload)); + return savedObjectsClient.bulkGet(request.payload); } } }); diff --git a/src/server/saved_objects/routes/bulk_get.test.js b/src/server/saved_objects/routes/bulk_get.test.js index db66c1d5430af8..e646629970fd43 100644 --- a/src/server/saved_objects/routes/bulk_get.test.js +++ b/src/server/saved_objects/routes/bulk_get.test.js @@ -22,7 +22,7 @@ import { createBulkGetRoute } from './bulk_get'; import { MockServer } from './_mock_server'; describe('POST /api/saved_objects/_bulk_get', () => { - const savedObjectsClient = { bulkGet: sinon.stub() }; + const savedObjectsClient = { bulkGet: sinon.stub().returns('') }; let server; beforeEach(() => { @@ -31,8 +31,8 @@ describe('POST /api/saved_objects/_bulk_get', () => { const prereqs = { getSavedObjectsClient: { assign: 'savedObjectsClient', - method(request, reply) { - reply(savedObjectsClient); + method() { + return savedObjectsClient; } }, }; diff --git a/src/server/saved_objects/routes/create.js b/src/server/saved_objects/routes/create.js index 4bb7ffae80a262..46d47d0f338910 100644 --- a/src/server/saved_objects/routes/create.js +++ b/src/server/saved_objects/routes/create.js @@ -23,7 +23,7 @@ export const createCreateRoute = prereqs => { return { path: '/api/saved_objects/{type}/{id?}', method: 'POST', - config: { + options: { pre: [prereqs.getSavedObjectsClient], validate: { query: Joi.object() @@ -42,14 +42,14 @@ export const createCreateRoute = prereqs => { migrationVersion: Joi.object().optional(), }).required(), }, - handler(request, reply) { + handler(request) { const { savedObjectsClient } = request.pre; const { type, id } = request.params; const { overwrite } = request.query; const { migrationVersion } = request.payload; const options = { id, overwrite, migrationVersion }; - reply(savedObjectsClient.create(type, request.payload.attributes, options)); + return savedObjectsClient.create(type, request.payload.attributes, options); }, }, }; diff --git a/src/server/saved_objects/routes/create.test.js b/src/server/saved_objects/routes/create.test.js index dd088101c86626..48b6cb970e56b5 100644 --- a/src/server/saved_objects/routes/create.test.js +++ b/src/server/saved_objects/routes/create.test.js @@ -22,7 +22,7 @@ import { createCreateRoute } from './create'; import { MockServer } from './_mock_server'; describe('POST /api/saved_objects/{type}', () => { - const savedObjectsClient = { create: sinon.stub() }; + const savedObjectsClient = { create: sinon.stub().returns('') }; let server; beforeEach(() => { @@ -31,8 +31,8 @@ describe('POST /api/saved_objects/{type}', () => { const prereqs = { getSavedObjectsClient: { assign: 'savedObjectsClient', - method(request, reply) { - reply(savedObjectsClient); + method() { + return savedObjectsClient; } }, }; @@ -100,7 +100,7 @@ describe('POST /api/saved_objects/{type}', () => { expect(savedObjectsClient.create.calledOnce).toBe(true); const args = savedObjectsClient.create.getCall(0).args; - const options = { overwrite: false, id: undefined }; + const options = { overwrite: false, id: undefined, migrationVersion: undefined }; const attributes = { title: 'Testing' }; expect(args).toEqual(['index-pattern', attributes, options]); diff --git a/src/server/saved_objects/routes/delete.js b/src/server/saved_objects/routes/delete.js index f3678e44f419ad..93db9bf9f9caeb 100644 --- a/src/server/saved_objects/routes/delete.js +++ b/src/server/saved_objects/routes/delete.js @@ -30,11 +30,11 @@ export const createDeleteRoute = (prereqs) => ({ id: Joi.string().required(), }).required() }, - handler(request, reply) { + handler(request) { const { savedObjectsClient } = request.pre; const { type, id } = request.params; - reply(savedObjectsClient.delete(type, id)); + return savedObjectsClient.delete(type, id); } } }); diff --git a/src/server/saved_objects/routes/delete.test.js b/src/server/saved_objects/routes/delete.test.js index b750a7b9080dd3..ef130048f3c565 100644 --- a/src/server/saved_objects/routes/delete.test.js +++ b/src/server/saved_objects/routes/delete.test.js @@ -31,8 +31,8 @@ describe('DELETE /api/saved_objects/{type}/{id}', () => { const prereqs = { getSavedObjectsClient: { assign: 'savedObjectsClient', - method(request, reply) { - reply(savedObjectsClient); + method() { + return savedObjectsClient; } }, }; diff --git a/src/server/saved_objects/routes/find.js b/src/server/saved_objects/routes/find.js index 35185f19726861..c5890120e14413 100644 --- a/src/server/saved_objects/routes/find.js +++ b/src/server/saved_objects/routes/find.js @@ -36,9 +36,9 @@ export const createFindRoute = (prereqs) => ({ fields: Joi.array().items(Joi.string()).single() }).default() }, - handler(request, reply) { + handler(request) { const options = keysToCamelCaseShallow(request.query); - reply(request.pre.savedObjectsClient.find(options)); + return request.pre.savedObjectsClient.find(options); } } }); diff --git a/src/server/saved_objects/routes/find.test.js b/src/server/saved_objects/routes/find.test.js index 7bb599be6cfd57..3b1de7490367e1 100644 --- a/src/server/saved_objects/routes/find.test.js +++ b/src/server/saved_objects/routes/find.test.js @@ -22,7 +22,7 @@ import { createFindRoute } from './find'; import { MockServer } from './_mock_server'; describe('GET /api/saved_objects/_find', () => { - const savedObjectsClient = { find: sinon.stub() }; + const savedObjectsClient = { find: sinon.stub().returns('') }; let server; beforeEach(() => { @@ -31,8 +31,8 @@ describe('GET /api/saved_objects/_find', () => { const prereqs = { getSavedObjectsClient: { assign: 'savedObjectsClient', - method(request, reply) { - reply(savedObjectsClient); + method() { + return savedObjectsClient; } }, }; diff --git a/src/server/saved_objects/routes/get.js b/src/server/saved_objects/routes/get.js index ae0466fbac01d0..859dc6d8902b61 100644 --- a/src/server/saved_objects/routes/get.js +++ b/src/server/saved_objects/routes/get.js @@ -30,11 +30,11 @@ export const createGetRoute = (prereqs) => ({ id: Joi.string().required(), }).required() }, - handler(request, reply) { + handler(request) { const { savedObjectsClient } = request.pre; const { type, id } = request.params; - reply(savedObjectsClient.get(type, id)); + return savedObjectsClient.get(type, id); } } }); diff --git a/src/server/saved_objects/routes/get.test.js b/src/server/saved_objects/routes/get.test.js index 066c9feee9ef16..63246bcf3a329c 100644 --- a/src/server/saved_objects/routes/get.test.js +++ b/src/server/saved_objects/routes/get.test.js @@ -22,7 +22,7 @@ import { createGetRoute } from './get'; import { MockServer } from './_mock_server'; describe('GET /api/saved_objects/{type}/{id}', () => { - const savedObjectsClient = { get: sinon.stub() }; + const savedObjectsClient = { get: sinon.stub().returns('') }; let server; beforeEach(() => { @@ -31,8 +31,8 @@ describe('GET /api/saved_objects/{type}/{id}', () => { const prereqs = { getSavedObjectsClient: { assign: 'savedObjectsClient', - method(request, reply) { - reply(savedObjectsClient); + method() { + return savedObjectsClient; } }, }; diff --git a/src/server/saved_objects/routes/update.js b/src/server/saved_objects/routes/update.js index 14a6ed4a03d2e0..cc7e2c0a4b4d16 100644 --- a/src/server/saved_objects/routes/update.js +++ b/src/server/saved_objects/routes/update.js @@ -35,13 +35,13 @@ export const createUpdateRoute = (prereqs) => { version: Joi.number().min(1) }).required() }, - handler(request, reply) { + handler(request) { const { savedObjectsClient } = request.pre; const { type, id } = request.params; const { attributes, version } = request.payload; const options = { version }; - reply(savedObjectsClient.update(type, id, attributes, options)); + return savedObjectsClient.update(type, id, attributes, options); } } }; diff --git a/src/server/saved_objects/routes/update.test.js b/src/server/saved_objects/routes/update.test.js index d41d8a3fa9c13b..ac4d938794fda7 100644 --- a/src/server/saved_objects/routes/update.test.js +++ b/src/server/saved_objects/routes/update.test.js @@ -22,7 +22,7 @@ import { createUpdateRoute } from './update'; import { MockServer } from './_mock_server'; describe('PUT /api/saved_objects/{type}/{id?}', () => { - const savedObjectsClient = { update: sinon.stub() }; + const savedObjectsClient = { update: sinon.stub().returns('') }; let server; beforeEach(() => { @@ -31,8 +31,8 @@ describe('PUT /api/saved_objects/{type}/{id?}', () => { const prereqs = { getSavedObjectsClient: { assign: 'savedObjectsClient', - method(request, reply) { - reply(savedObjectsClient); + method() { + return savedObjectsClient; } }, }; diff --git a/src/server/saved_objects/saved_objects_mixin.js b/src/server/saved_objects/saved_objects_mixin.js index e9d53b8ede794b..ffde12d81a57aa 100644 --- a/src/server/saved_objects/saved_objects_mixin.js +++ b/src/server/saved_objects/saved_objects_mixin.js @@ -51,8 +51,8 @@ export function savedObjectsMixin(kbnServer, server) { const prereqs = { getSavedObjectsClient: { assign: 'savedObjectsClient', - method(req, reply) { - reply(req.getSavedObjectsClient()); + method(req) { + return req.getSavedObjectsClient(); }, }, }; diff --git a/src/server/status/index.js b/src/server/status/index.js index f05a14e3367af9..02b0f4d3a8e1d1 100644 --- a/src/server/status/index.js +++ b/src/server/status/index.js @@ -21,6 +21,8 @@ import ServerStatus from './server_status'; import { Metrics } from './lib/metrics'; import { registerStatusPage, registerStatusApi, registerStatsApi } from './routes'; import { getOpsStatsCollector } from './collectors'; +import Oppsy from 'oppsy'; +import { cloneDeep } from 'lodash'; export function statusMixin(kbnServer, server, config) { kbnServer.status = new ServerStatus(kbnServer.server); @@ -29,15 +31,23 @@ export function statusMixin(kbnServer, server, config) { const { collectorSet } = server.usage; collectorSet.register(statsCollector); - const { ['even-better']: evenBetter } = server.plugins; + const metrics = new Metrics(config, server); - if (evenBetter) { - const metrics = new Metrics(config, server); + const oppsy = new Oppsy(server); + oppsy.on('ops', event => { + // Oppsy has a bad race condition that will modify this data before + // we ship it off to the buffer. Let's create our copy first. + event = cloneDeep(event); + // Oppsy used to provide this, but doesn't anymore. Grab it ourselves. + server.listener.getConnections((_, count) => { + event.concurrent_connections = count; - evenBetter.monitor.on('ops', event => { - metrics.capture(event).then(data => { kbnServer.metrics = data; }); // captures (performs transforms on) the latest event data and stashes the metrics for status/stats API payload + // captures (performs transforms on) the latest event data and stashes + // the metrics for status/stats API payload + metrics.capture(event).then(data => { kbnServer.metrics = data; }); }); - } + }); + oppsy.start(config.get('ops.interval')); // init routes registerStatusPage(kbnServer, server, config); diff --git a/src/server/status/lib/metrics.js b/src/server/status/lib/metrics.js index a16f1f8822cae2..dc5b99aefc7aac 100644 --- a/src/server/status/lib/metrics.js +++ b/src/server/status/lib/metrics.js @@ -23,6 +23,12 @@ import { get, isObject, merge } from 'lodash'; import { keysToSnakeCaseShallow } from '../../../utils/case_conversion'; import { getAllStats as cGroupStats } from './cgroup'; +const requestDefaults = { + disconnects: 0, + statusCodes: {}, + total: 0, +}; + export class Metrics { constructor(config, server) { this.config = config; @@ -98,8 +104,11 @@ export class Metrics { avg_in_millis: isNaN(avgInMillis) ? undefined : avgInMillis, // convert NaN to undefined max_in_millis: maxInMillis }, - requests: keysToSnakeCaseShallow(get(hapiEvent, ['requests', port])), - concurrent_connections: get(hapiEvent, ['concurrents', port]), + requests: { + ...requestDefaults, + ...keysToSnakeCaseShallow(get(hapiEvent, ['requests', port])) + }, + concurrent_connections: hapiEvent.concurrent_connections }; } diff --git a/src/server/status/lib/metrics.test.js b/src/server/status/lib/metrics.test.js index 00da1a40c01be2..d8b86164cbe0eb 100644 --- a/src/server/status/lib/metrics.test.js +++ b/src/server/status/lib/metrics.test.js @@ -100,7 +100,7 @@ describe('Metrics', function () { 'osup': 1008991, 'psup': 7.168, 'psmem': { 'rss': 193716224, 'heapTotal': 168194048, 'heapUsed': 130553400, 'external': 1779619 }, - 'concurrents': { '5603': 0 }, + 'concurrent_connections': 0, 'psdelay': 1.6091690063476562, 'host': 'blahblah.local' }; diff --git a/src/server/status/routes/api/register_stats.js b/src/server/status/routes/api/register_stats.js index d7497d8f58640c..e98229dd04db53 100644 --- a/src/server/status/routes/api/register_stats.js +++ b/src/server/status/routes/api/register_stats.js @@ -58,7 +58,7 @@ export function registerStatsApi(kbnServer, server, config) { }, tags: ['api'], }, - async handler(req, reply) { + async handler(req) { const isExtended = req.query.extended !== undefined && req.query.extended !== 'false'; const isLegacy = req.query.legacy !== undefined && req.query.legacy !== 'false'; @@ -118,7 +118,7 @@ export function registerStatsApi(kbnServer, server, config) { }); } } catch (e) { - return reply(boomify(e)); + throw boomify(e); } } @@ -129,10 +129,10 @@ export function registerStatsApi(kbnServer, server, config) { let kibanaStats = await kibanaStatsCollector.fetch(); kibanaStats = collectorSet.toApiFieldNames(kibanaStats); - reply({ + return { ...kibanaStats, ...extended, - }); + }; }, }) ); diff --git a/src/server/status/routes/api/register_status.js b/src/server/status/routes/api/register_status.js index 98c454de4f58d8..89628bd8ecd728 100644 --- a/src/server/status/routes/api/register_status.js +++ b/src/server/status/routes/api/register_status.js @@ -30,8 +30,8 @@ export function registerStatusApi(kbnServer, server, config) { config: { tags: ['api'] }, - async handler(request, reply) { - const status = { + async handler() { + return { name: config.get('server.name'), uuid: config.get('server.uuid'), version: { @@ -43,8 +43,6 @@ export function registerStatusApi(kbnServer, server, config) { status: kbnServer.status.toJSON(), metrics: kbnServer.metrics }; - - return reply(status); } })); } diff --git a/src/server/status/routes/page/register_status.js b/src/server/status/routes/page/register_status.js index 2a155cd8977f51..a99162ab4f47b3 100644 --- a/src/server/status/routes/page/register_status.js +++ b/src/server/status/routes/page/register_status.js @@ -22,24 +22,23 @@ import { wrapAuthConfig } from '../../wrap_auth_config'; export function registerStatusPage(kbnServer, server, config) { const wrapAuth = wrapAuthConfig(config.get('status.allowAnonymous')); - server.decorate('reply', 'renderStatusPage', async function () { + server.decorate('toolkit', 'renderStatusPage', async function () { const app = server.getHiddenUiAppById('status_page'); - const reply = this; + const h = this; const response = app - ? await reply.renderApp(app) - : reply(kbnServer.status.toString()); + ? await h.renderApp(app) + : h.response(kbnServer.status.toString()); if (response) { - response.code(kbnServer.status.isGreen() ? 200 : 503); - return response; + return response.code(kbnServer.status.isGreen() ? 200 : 503); } }); server.route(wrapAuth({ method: 'GET', path: '/status', - handler(request, reply) { - reply.renderStatusPage(); + handler(request, h) { + return h.renderStatusPage(); } })); } diff --git a/src/server/status/wrap_auth_config.test.js b/src/server/status/wrap_auth_config.test.js index d2d6e8be2a064b..36934b2ec7cff9 100644 --- a/src/server/status/wrap_auth_config.test.js +++ b/src/server/status/wrap_auth_config.test.js @@ -26,8 +26,8 @@ describe('Status wrapAuthConfig', () => { options = { method: 'GET', path: '/status', - handler: function (request, reply) { - return reply(); + handler: function (request, h) { + return h.response(); } }; }); diff --git a/src/server/url_shortening/routes/goto.js b/src/server/url_shortening/routes/goto.js index 298d5715c00f4c..4dc569951d75c6 100644 --- a/src/server/url_shortening/routes/goto.js +++ b/src/server/url_shortening/routes/goto.js @@ -23,7 +23,7 @@ import { shortUrlAssertValid } from './lib/short_url_assert_valid'; export const createGotoRoute = ({ server, config, shortUrlLookup }) => ({ method: 'GET', path: '/goto/{urlId}', - handler: async function (request, reply) { + handler: async function (request, h) { try { const url = await shortUrlLookup.getUrl(request.params.urlId, request); shortUrlAssertValid(url); @@ -31,16 +31,15 @@ export const createGotoRoute = ({ server, config, shortUrlLookup }) => ({ const uiSettings = request.getUiSettingsService(); const stateStoreInSessionStorage = await uiSettings.get('state:storeInSessionStorage'); if (!stateStoreInSessionStorage) { - reply().redirect(config.get('server.basePath') + url); - return; + return h.redirect(config.get('server.basePath') + url); } const app = server.getHiddenUiAppById('stateSessionStorageRedirect'); - reply.renderApp(app, { + return h.renderApp(app, { redirectUrl: url, }); } catch (err) { - reply(handleShortUrlError(err)); + throw handleShortUrlError(err); } } }); diff --git a/src/server/url_shortening/routes/shorten_url.js b/src/server/url_shortening/routes/shorten_url.js index 1d51c271126d1a..0203e9373384a8 100644 --- a/src/server/url_shortening/routes/shorten_url.js +++ b/src/server/url_shortening/routes/shorten_url.js @@ -23,13 +23,13 @@ import { shortUrlAssertValid } from './lib/short_url_assert_valid'; export const createShortenUrlRoute = ({ shortUrlLookup }) => ({ method: 'POST', path: '/api/shorten_url', - handler: async function (request, reply) { + handler: async function (request) { try { shortUrlAssertValid(request.payload.url); const urlId = await shortUrlLookup.generateUrlId(request.payload.url, request); - reply({ urlId }); + return { urlId }; } catch (err) { - reply(handleShortUrlError(err)); + throw handleShortUrlError(err); } } }); diff --git a/src/ui/__tests__/ui_exports_replace_injected_vars.js b/src/ui/__tests__/ui_exports_replace_injected_vars.js index cd1fe1f31878e0..bdb783b65a8f81 100644 --- a/src/ui/__tests__/ui_exports_replace_injected_vars.js +++ b/src/ui/__tests__/ui_exports_replace_injected_vars.js @@ -25,9 +25,11 @@ import sinon from 'sinon'; import cheerio from 'cheerio'; import { noop } from 'lodash'; +import * as getUiSettingsServiceForRequestNS from '../ui_settings/ui_settings_service_for_request'; import { createRoot, getKbnServer, request } from '../../test_utils/kbn_server'; const getInjectedVarsFromResponse = (resp) => { + expect(resp.statusCode).to.be(200); const $ = cheerio.load(resp.text); const data = $('kbn-injected-metadata').attr('data'); return JSON.parse(data).vars; @@ -45,6 +47,8 @@ const injectReplacer = (kbnServer, replacer) => { }; describe('UiExports', function () { + const sandbox = sinon.createSandbox(); + let root; let kbnServer; before(async () => { @@ -60,15 +64,19 @@ describe('UiExports', function () { kbnServer = getKbnServer(root); - // TODO: hopefully we can add better support for something - // like this in the new platform - kbnServer.server._requestor._decorations.getUiSettingsService = { - apply: undefined, - method: () => ({ getDefaults: noop, getUserProvided: noop }) - }; + // Mock out the ui settings which depends on ES + sandbox + .stub(getUiSettingsServiceForRequestNS, 'getUiSettingsServiceForRequest') + .returns({ + getDefaults: noop, + getUserProvided: noop + }); }); - after(async () => await root.shutdown()); + after(async () => { + await root.shutdown(); + sandbox.restore(); + }); let originalInjectedVarsReplacers; beforeEach(() => { @@ -154,7 +162,9 @@ describe('UiExports', function () { .expect(200); sinon.assert.calledOnce(stub); - expect(stub.firstCall.args[0]).to.eql({ from_defaults: true, from_test_app: true }); + const args = stub.lastCall.args[0]; + expect(args.from_defaults).to.be(true); + expect(args.from_test_app).to.be(true); }); }); }); diff --git a/src/ui/public/query_bar/components/query_bar.tsx b/src/ui/public/query_bar/components/query_bar.tsx index 7eb7c3995198d9..455e05cb1dea9d 100644 --- a/src/ui/public/query_bar/components/query_bar.tsx +++ b/src/ui/public/query_bar/components/query_bar.tsx @@ -23,7 +23,7 @@ declare module '@elastic/eui' { export const EuiOutsideClickDetector: SFC; } -import { debounce, uniq } from 'lodash'; +import { debounce } from 'lodash'; import React, { Component, SFC } from 'react'; import { getFromLegacyIndexPattern } from 'ui/index_patterns/static_utils'; import { kfetch } from 'ui/kfetch'; @@ -252,9 +252,10 @@ export class QueryBar extends Component { if (!this.persistedLog) { return []; } - const recentSearches = uniq(this.persistedLog.get().map(toUser)); + const recentSearches = this.persistedLog.get(); const matchingRecentSearches = recentSearches.filter(recentQuery => { - return recentQuery.includes(query); + const recentQueryString = typeof recentQuery === 'object' ? toUser(recentQuery) : recentQuery; + return recentQueryString.includes(query); }); return matchingRecentSearches.map(recentSearch => { const text = recentSearch; @@ -392,7 +393,7 @@ export class QueryBar extends Component { preventDefault(); } - if (this.persistedLog && this.state.query.query.trim() !== '') { + if (this.persistedLog) { this.persistedLog.add(this.state.query.query); } diff --git a/src/ui/ui_render/ui_render_mixin.js b/src/ui/ui_render/ui_render_mixin.js index dd0848215a0be8..03fb5379201e6d 100644 --- a/src/ui/ui_render/ui_render_mixin.js +++ b/src/ui/ui_render/ui_render_mixin.js @@ -54,59 +54,55 @@ export function uiRenderMixin(kbnServer, server, config) { path: '/bundles/app/{id}/bootstrap.js', method: 'GET', config: { auth: false }, - async handler(request, reply) { - try { - const { id } = request.params; - const app = server.getUiAppById(id) || server.getHiddenUiAppById(id); - if (!app) { - throw Boom.notFound(`Unknown app: ${id}`); + async handler(request, h) { + const { id } = request.params; + const app = server.getUiAppById(id) || server.getHiddenUiAppById(id); + if (!app) { + throw Boom.notFound(`Unknown app: ${id}`); + } + + const basePath = config.get('server.basePath'); + const bundlePath = `${basePath}/bundles`; + const styleSheetPaths = [ + `${bundlePath}/vendors.style.css`, + `${bundlePath}/commons.style.css`, + `${bundlePath}/${app.getId()}.style.css`, + ].concat(kbnServer.uiExports.styleSheetPaths.map(path => `${basePath}/${path.publicPath}`).reverse()); + + const bootstrap = new AppBootstrap({ + templateData: { + appId: app.getId(), + bundlePath, + styleSheetPaths, } + }); - const basePath = config.get('server.basePath'); - const bundlePath = `${basePath}/bundles`; - const styleSheetPaths = [ - `${bundlePath}/vendors.style.css`, - `${bundlePath}/commons.style.css`, - `${bundlePath}/${app.getId()}.style.css`, - ].concat(kbnServer.uiExports.styleSheetPaths.map(path => `${basePath}/${path.publicPath}`).reverse()); - - const bootstrap = new AppBootstrap({ - templateData: { - appId: app.getId(), - bundlePath, - styleSheetPaths, - } - }); - - const body = await bootstrap.getJsFile(); - const etag = await bootstrap.getJsFileHash(); - - reply(body) - .header('cache-control', 'must-revalidate') - .header('content-type', 'application/javascript') - .etag(etag); - } catch (err) { - reply(err); - } + const body = await bootstrap.getJsFile(); + const etag = await bootstrap.getJsFileHash(); + + return h.response(body) + .header('cache-control', 'must-revalidate') + .header('content-type', 'application/javascript') + .etag(etag); } }); server.route({ path: '/app/{id}', method: 'GET', - async handler(req, reply) { + async handler(req, h) { const id = req.params.id; const app = server.getUiAppById(id); - if (!app) return reply(Boom.notFound('Unknown app ' + id)); + if (!app) throw Boom.notFound('Unknown app ' + id); try { if (kbnServer.status.isGreen()) { - await reply.renderApp(app); + return await h.renderApp(app); } else { - await reply.renderStatusPage(); + return await h.renderStatusPage(); } } catch (err) { - reply(Boom.wrap(err)); + throw Boom.boomify(err); } } }); @@ -133,56 +129,53 @@ export function uiRenderMixin(kbnServer, server, config) { }; } - async function renderApp({ app, reply, includeUserProvidedConfig = true, injectedVarsOverrides = {} }) { - try { - const request = reply.request; - const translations = await server.getUiTranslations(); - const basePath = request.getBasePath(); - - return reply.view('ui_app', { - uiPublicUrl: `${basePath}/ui`, - bootstrapScriptUrl: `${basePath}/bundles/app/${app.getId()}/bootstrap.js`, - i18n: (id, options) => i18n.translate(id, options), - - injectedMetadata: { - version: kbnServer.version, - buildNumber: config.get('pkg.buildNum'), - basePath, - vars: await replaceInjectedVars( - request, - defaults( - injectedVarsOverrides, - await server.getInjectedUiAppVars(app.getId()), - defaultInjectedVars, - ), + async function renderApp({ app, h, includeUserProvidedConfig = true, injectedVarsOverrides = {} }) { + const request = h.request; + const translations = await server.getUiTranslations(); + const basePath = request.getBasePath(); + + return h.view('ui_app', { + uiPublicUrl: `${basePath}/ui`, + bootstrapScriptUrl: `${basePath}/bundles/app/${app.getId()}/bootstrap.js`, + i18n: (id, options) => i18n.translate(id, options), + + injectedMetadata: { + version: kbnServer.version, + buildNumber: config.get('pkg.buildNum'), + basePath, + vars: await replaceInjectedVars( + request, + defaults( + injectedVarsOverrides, + await server.getInjectedUiAppVars(app.getId()), + defaultInjectedVars, ), - legacyMetadata: await getLegacyKibanaPayload({ - app, - translations, - request, - includeUserProvidedConfig, - injectedVarsOverrides - }), - }, - }); - } catch (err) { - reply(err); - } + ), + + legacyMetadata: await getLegacyKibanaPayload({ + app, + translations, + request, + includeUserProvidedConfig, + injectedVarsOverrides + }), + }, + }); } - server.decorate('reply', 'renderApp', function (app, injectedVarsOverrides) { + server.decorate('toolkit', 'renderApp', function (app, injectedVarsOverrides) { return renderApp({ app, - reply: this, + h: this, includeUserProvidedConfig: true, injectedVarsOverrides, }); }); - server.decorate('reply', 'renderAppWithDefaultConfig', function (app) { + server.decorate('toolkit', 'renderAppWithDefaultConfig', function (app) { return renderApp({ app, - reply: this, + h: this, includeUserProvidedConfig: false, }); }); diff --git a/src/ui/ui_settings/routes/delete.js b/src/ui/ui_settings/routes/delete.js index 4fee12afd8081a..78e07bbceab01d 100644 --- a/src/ui/ui_settings/routes/delete.js +++ b/src/ui/ui_settings/routes/delete.js @@ -30,7 +30,7 @@ async function handleRequest(request) { export const deleteRoute = { path: '/api/kibana/settings/{key}', method: 'DELETE', - handler(request, reply) { - reply(handleRequest(request)); + handler: async (request, h) => { + return h.response(await handleRequest(request)); } }; diff --git a/src/ui/ui_settings/routes/get.js b/src/ui/ui_settings/routes/get.js index 9f6c99acbd8cfb..7e91bc46596b55 100644 --- a/src/ui/ui_settings/routes/get.js +++ b/src/ui/ui_settings/routes/get.js @@ -27,7 +27,7 @@ async function handleRequest(request) { export const getRoute = { path: '/api/kibana/settings', method: 'GET', - handler: function (request, reply) { - reply(handleRequest(request)); + handler: function (request) { + return handleRequest(request); } }; diff --git a/src/ui/ui_settings/routes/set.js b/src/ui/ui_settings/routes/set.js index 54be14584f1d2d..e50c9bf08de3e8 100644 --- a/src/ui/ui_settings/routes/set.js +++ b/src/ui/ui_settings/routes/set.js @@ -44,8 +44,8 @@ export const setRoute = { value: Joi.any().required() }).required() }, - handler(request, reply) { - reply(handleRequest(request)); + handler(request) { + return handleRequest(request); } } }; diff --git a/src/ui/ui_settings/routes/set_many.js b/src/ui/ui_settings/routes/set_many.js index d215b5f1a717d9..8e7882f48ef704 100644 --- a/src/ui/ui_settings/routes/set_many.js +++ b/src/ui/ui_settings/routes/set_many.js @@ -39,8 +39,8 @@ export const setManyRoute = { changes: Joi.object().unknown(true).required() }).required() }, - handler(request, reply) { - reply(handleRequest(request)); + handler(request) { + return handleRequest(request); } } }; diff --git a/test/common/services/kibana_server/status.js b/test/common/services/kibana_server/status.js index 19af8c4d6f2581..686f4c95b8d532 100644 --- a/test/common/services/kibana_server/status.js +++ b/test/common/services/kibana_server/status.js @@ -19,14 +19,12 @@ import { resolve as resolveUrl } from 'url'; -import { fromNode } from 'bluebird'; import Wreck from 'wreck'; -const get = async (url) => fromNode(cb => { - Wreck.get(url, { json: 'force' }, (err, resp, payload) => { - cb(err, payload); // resp is an Http#IncomingMessage, payload is the parsed version - }); -}); +const get = async (url) => { + const { payload } = await Wreck.get(url, { json: 'force' }); + return payload; +}; export class KibanaServerStatus { constructor(kibanaServerUrl) { diff --git a/x-pack/package.json b/x-pack/package.json index 820e2de61bdea1..1f556c0ba1d8ff 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -40,10 +40,10 @@ "@types/elasticsearch": "^5.0.26", "@types/expect.js": "^0.3.29", "@types/graphql": "^0.13.1", - "@types/hapi": "15.0.1", + "@types/hapi": "^17.0.18", "@types/history": "^4.6.2", "@types/jest": "^23.3.1", - "@types/joi": "^10.4.4", + "@types/joi": "^13.4.2", "@types/jsonwebtoken": "^7.2.7", "@types/lodash": "^3.10.1", "@types/mocha": "^5.2.5", @@ -89,7 +89,7 @@ "gulp-mocha": "^6.0.0", "gulp-multi-process": "^1.3.1", "gulp-pegjs": "^0.1.0", - "hapi": "14.2.0", + "hapi": "^17.5.3", "jest": "^23.5.0", "jest-cli": "^23.5.0", "jest-styled-components": "^6.1.1", @@ -148,7 +148,7 @@ "babel-runtime": "^6.26.0", "base64-js": "^1.2.1", "bluebird": "3.1.1", - "boom": "3.1.1", + "boom": "^7.2.0", "brace": "0.11.1", "chroma-js": "^1.3.6", "classnames": "2.2.5", @@ -174,14 +174,14 @@ "graphql-tag": "^2.9.2", "graphql-tools": "^3.0.2", "handlebars": "^4.0.10", - "hapi-auth-cookie": "6.1.1", + "hapi-auth-cookie": "^9.0.0", "history": "4.7.2", "humps": "2.0.1", "icalendar": "0.7.1", "inline-style": "^2.0.0", "iron": "4", "isomorphic-fetch": "2.2.1", - "joi": "6.10.1", + "joi": "^13.5.2", "jquery": "^3.3.1", "jsonwebtoken": "^8.3.0", "jstimezonedetect": "1.0.5", @@ -205,6 +205,7 @@ "ngreact": "^0.5.1", "nodemailer": "^4.6.4", "object-path-immutable": "^0.5.3", + "oppsy": "^2.0.0", "papaparse": "^4.6.0", "pdfmake": "0.1.33", "pivotal-ui": "13.0.1", diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts index b5bc84634dd3df..70773755c2c78a 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts @@ -6,23 +6,26 @@ /* tslint:disable no-console */ import { SearchParams, SearchResponse } from 'elasticsearch'; -import { Request, Server } from 'hapi'; +import { Request } from 'hapi'; import moment from 'moment'; function decodeEsQuery(esQuery?: string): object { return esQuery ? JSON.parse(decodeURIComponent(esQuery)) : null; } -interface KibanaServer extends Server { - config: () => KibanaConfig; +interface KibanaConfig { + get: (key: string) => any; } -interface KibanaRequest extends Request { - server: KibanaServer; -} +// Extend the defaults with the plugins and server methods we need. +declare module 'hapi' { + interface PluginProperties { + elasticsearch: any; + } -interface KibanaConfig { - get: (key: string) => any; + interface Server { + config: () => KibanaConfig; + } } type Client = (type: string, params: SearchParams) => SearchResponse; @@ -35,18 +38,23 @@ export interface Setup { config: KibanaConfig; } -export function setupRequest( - req: KibanaRequest, - reply: (setup: Setup) => void -) { +interface APMRequestQuery { + _debug: string; + start: string; + end: string; + esFilterQuery: string; +} + +export function setupRequest(req: Request) { + const query = (req.query as unknown) as APMRequestQuery; const cluster = req.server.plugins.elasticsearch.getCluster('data'); function client(type: string, params: SearchParams): SearchResponse { - if (req.query._debug) { + if (query._debug) { console.log(`DEBUG ES QUERY:`); console.log( `${req.method.toUpperCase()} ${req.url.pathname} ${JSON.stringify( - req.query + query )}` ); console.log(`GET ${params.index}/_search`); @@ -55,13 +63,11 @@ export function setupRequest( return cluster.callWithRequest(req, type, params); } - const setup = { - start: moment.utc(req.query.start).valueOf(), - end: moment.utc(req.query.end).valueOf(), - esFilterQuery: decodeEsQuery(req.query.esFilterQuery), + return { + start: moment.utc(query.start).valueOf(), + end: moment.utc(query.end).valueOf(), + esFilterQuery: decodeEsQuery(query.esFilterQuery), client, config: req.server.config() }; - - reply(setup); } diff --git a/x-pack/plugins/apm/server/routes/errors.js b/x-pack/plugins/apm/server/routes/errors.js index 8ff6abd41cc53c..775664abc90b66 100644 --- a/x-pack/plugins/apm/server/routes/errors.js +++ b/x-pack/plugins/apm/server/routes/errors.js @@ -15,9 +15,9 @@ import { withDefaultValidators } from '../lib/helpers/input_validation'; const pre = [{ method: setupRequest, assign: 'setup' }]; const ROOT = '/api/apm/services/{serviceName}/errors'; -const defaultErrorHandler = reply => err => { +const defaultErrorHandler = err => { console.error(err.stack); - reply(Boom.wrap(err, 400)); + throw Boom.boomify(err, { statusCode: 400 }); }; export function initErrorsApi(server) { @@ -33,7 +33,7 @@ export function initErrorsApi(server) { }) } }, - handler: (req, reply) => { + handler: req => { const { setup } = req.pre; const { serviceName } = req.params; const { sortField, sortDirection } = req.query; @@ -43,9 +43,7 @@ export function initErrorsApi(server) { sortField, sortDirection, setup - }) - .then(reply) - .catch(defaultErrorHandler(reply)); + }).catch(defaultErrorHandler); } }); @@ -58,12 +56,12 @@ export function initErrorsApi(server) { query: withDefaultValidators() } }, - handler: (req, reply) => { + handler: req => { const { setup } = req.pre; const { serviceName, groupId } = req.params; - return getErrorGroup({ serviceName, groupId, setup }) - .then(reply) - .catch(defaultErrorHandler(reply)); + return getErrorGroup({ serviceName, groupId, setup }).catch( + defaultErrorHandler + ); } }); @@ -76,13 +74,13 @@ export function initErrorsApi(server) { query: withDefaultValidators() } }, - handler: (req, reply) => { + handler: req => { const { setup } = req.pre; const { serviceName, groupId } = req.params; - return getDistribution({ serviceName, groupId, setup }) - .then(reply) - .catch(defaultErrorHandler(reply)); + return getDistribution({ serviceName, groupId, setup }).catch( + defaultErrorHandler + ); } }); } diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts index fab8b7809ee7e2..31cf772c5e5dc3 100644 --- a/x-pack/plugins/apm/server/routes/services.ts +++ b/x-pack/plugins/apm/server/routes/services.ts @@ -5,7 +5,7 @@ */ import Boom from 'boom'; -import { IReply, Request, Server } from 'hapi'; +import { Server } from 'hapi'; import { withDefaultValidators } from '../lib/helpers/input_validation'; import { setupRequest } from '../lib/helpers/setup_request'; import { getService } from '../lib/services/get_service'; @@ -13,46 +13,42 @@ import { getServices } from '../lib/services/get_services'; const ROOT = '/api/apm/services'; const pre = [{ method: setupRequest, assign: 'setup' }]; -const defaultErrorHandler = (reply: IReply) => (err: Error) => { +const defaultErrorHandler = (err: Error) => { // tslint:disable-next-line console.error(err.stack); // @ts-ignore - reply(Boom.wrap(err, 400)); + return Boom.boomify(err, { statusCode: 400 }); }; export function initServicesApi(server: Server) { server.route({ method: 'GET', path: ROOT, - config: { + options: { pre, validate: { query: withDefaultValidators() } }, - handler: (req: Request, reply: IReply) => { + handler: req => { const { setup } = req.pre; - return getServices(setup) - .then(reply) - .catch(defaultErrorHandler(reply)); + return getServices(setup).catch(defaultErrorHandler); } }); server.route({ method: 'GET', path: `${ROOT}/{serviceName}`, - config: { + options: { pre, validate: { query: withDefaultValidators() } }, - handler: (req: Request, reply: IReply) => { + handler: req => { const { setup } = req.pre; const { serviceName } = req.params; - return getService(serviceName, setup) - .then(reply) - .catch(defaultErrorHandler(reply)); + return getService(serviceName, setup).catch(defaultErrorHandler); } }); } diff --git a/x-pack/plugins/apm/server/routes/status_check.js b/x-pack/plugins/apm/server/routes/status_check.js index 700fb51fcf14c8..8e78fdc4b78481 100644 --- a/x-pack/plugins/apm/server/routes/status_check.js +++ b/x-pack/plugins/apm/server/routes/status_check.js @@ -12,9 +12,9 @@ import { setupRequest } from '../lib/helpers/setup_request'; const ROOT = '/api/apm/status'; const pre = [{ method: setupRequest, assign: 'setup' }]; -const defaultErrorHandler = reply => err => { +const defaultErrorHandler = err => { console.error(err.stack); - reply(Boom.wrap(err, 400)); + throw Boom.boomify(err, { statusCode: 400 }); }; export function initStatusApi(server) { @@ -29,11 +29,9 @@ export function initStatusApi(server) { }) } }, - handler: (req, reply) => { + handler: req => { const { setup } = req.pre; - return getServerStatus({ setup }) - .then(reply) - .catch(defaultErrorHandler(reply)); + return getServerStatus({ setup }).catch(defaultErrorHandler); } }); @@ -48,11 +46,9 @@ export function initStatusApi(server) { }) } }, - handler: (req, reply) => { + handler: req => { const { setup } = req.pre; - return getAgentStatus({ setup }) - .then(reply) - .catch(defaultErrorHandler(reply)); + return getAgentStatus({ setup }).catch(defaultErrorHandler); } }); } diff --git a/x-pack/plugins/apm/server/routes/traces.ts b/x-pack/plugins/apm/server/routes/traces.ts index 737f1d48cbf9af..56588130ba3dda 100644 --- a/x-pack/plugins/apm/server/routes/traces.ts +++ b/x-pack/plugins/apm/server/routes/traces.ts @@ -5,7 +5,7 @@ */ import Boom from 'boom'; -import { IReply, Request, Server } from 'hapi'; +import { Server } from 'hapi'; import { withDefaultValidators } from '../lib/helpers/input_validation'; import { setupRequest } from '../lib/helpers/setup_request'; import { getTopTraces } from '../lib/traces/get_top_traces'; @@ -13,11 +13,11 @@ import { getTrace } from '../lib/traces/get_trace'; const pre = [{ method: setupRequest, assign: 'setup' }]; const ROOT = '/api/apm/traces'; -const defaultErrorHandler = (reply: IReply) => (err: Error) => { +const defaultErrorHandler = (err: Error) => { // tslint:disable-next-line console.error(err.stack); // @ts-ignore - reply(Boom.wrap(err, 400)); + return Boom.boomify(err, { statusCode: 400 }); }; export function initTracesApi(server: Server) { @@ -25,18 +25,16 @@ export function initTracesApi(server: Server) { server.route({ method: 'GET', path: ROOT, - config: { + options: { pre, validate: { query: withDefaultValidators() } }, - handler: (req: Request, reply: IReply) => { + handler: req => { const { setup } = req.pre; - return getTopTraces(setup) - .then(reply) - .catch(defaultErrorHandler(reply)); + return getTopTraces(setup).catch(defaultErrorHandler); } }); @@ -44,18 +42,16 @@ export function initTracesApi(server: Server) { server.route({ method: 'GET', path: `${ROOT}/{traceId}`, - config: { + options: { pre, validate: { query: withDefaultValidators() } }, - handler: (req: Request, reply: IReply) => { + handler: req => { const { traceId } = req.params; const { setup } = req.pre; - return getTrace(traceId, setup) - .then(reply) - .catch(defaultErrorHandler(reply)); + return getTrace(traceId, setup).catch(defaultErrorHandler); } }); } diff --git a/x-pack/plugins/apm/server/routes/transactions.ts b/x-pack/plugins/apm/server/routes/transactions.ts index b525ee8f1499bb..2774e090e1d571 100644 --- a/x-pack/plugins/apm/server/routes/transactions.ts +++ b/x-pack/plugins/apm/server/routes/transactions.ts @@ -5,7 +5,7 @@ */ import Boom from 'boom'; -import { IReply, Request, Server } from 'hapi'; +import { Server } from 'hapi'; import Joi from 'joi'; import { withDefaultValidators } from '../lib/helpers/input_validation'; import { setupRequest } from '../lib/helpers/setup_request'; @@ -18,18 +18,18 @@ import { getSpans } from '../lib/transactions/spans/get_spans'; const pre = [{ method: setupRequest, assign: 'setup' }]; const ROOT = '/api/apm/services/{serviceName}/transactions'; -const defaultErrorHandler = (reply: IReply) => (err: Error) => { +const defaultErrorHandler = (err: Error) => { // tslint:disable-next-line console.error(err.stack); // @ts-ignore - reply(Boom.wrap(err, err.statusCode || 400)); + Boom.boomify(err, { statusCode: err.statusCode || 400 }); }; export function initTransactionsApi(server: Server) { server.route({ method: 'GET', path: ROOT, - config: { + options: { pre, validate: { query: withDefaultValidators({ @@ -38,25 +38,25 @@ export function initTransactionsApi(server: Server) { }) } }, - handler: (req: Request, reply: IReply) => { + handler: req => { const { serviceName } = req.params; - const { transaction_type: transactionType } = req.query; + const { transaction_type: transactionType } = req.query as { + transaction_type: string; + }; const { setup } = req.pre; return getTopTransactions({ serviceName, transactionType, setup - }) - .then(reply) - .catch(defaultErrorHandler(reply)); + }).catch(defaultErrorHandler); } }); server.route({ method: 'GET', path: `${ROOT}/{transactionId}`, - config: { + options: { pre, validate: { query: withDefaultValidators({ @@ -64,38 +64,36 @@ export function initTransactionsApi(server: Server) { }) } }, - handler: (req: Request, reply: IReply) => { + handler: req => { const { transactionId } = req.params; - const { traceId } = req.query; + const { traceId } = req.query as { traceId: string }; const { setup } = req.pre; - return getTransaction(transactionId, traceId, setup) - .then(reply) - .catch(defaultErrorHandler(reply)); + return getTransaction(transactionId, traceId, setup).catch( + defaultErrorHandler + ); } }); server.route({ method: 'GET', path: `${ROOT}/{transactionId}/spans`, - config: { + options: { pre, validate: { query: withDefaultValidators() } }, - handler: (req: Request, reply: IReply) => { + handler: req => { const { transactionId } = req.params; const { setup } = req.pre; - return getSpans(transactionId, setup) - .then(reply) - .catch(defaultErrorHandler(reply)); + return getSpans(transactionId, setup).catch(defaultErrorHandler); } }); server.route({ method: 'GET', path: `${ROOT}/charts`, - config: { + options: { pre, validate: { query: withDefaultValidators({ @@ -105,27 +103,29 @@ export function initTransactionsApi(server: Server) { }) } }, - handler: (req: Request, reply: IReply) => { + handler: req => { const { setup } = req.pre; const { serviceName } = req.params; - const transactionType = req.query.transaction_type; - const transactionName = req.query.transaction_name; + const { transaction_type: transactionType } = req.query as { + transaction_type: string; + }; + const { transaction_name: transactionName } = req.query as { + transaction_name: string; + }; return getTimeseriesData({ serviceName, transactionType, transactionName, setup - }) - .then(reply) - .catch(defaultErrorHandler(reply)); + }).catch(defaultErrorHandler); } }); server.route({ method: 'GET', path: `${ROOT}/distribution`, - config: { + options: { pre, validate: { query: withDefaultValidators({ @@ -133,13 +133,15 @@ export function initTransactionsApi(server: Server) { }) } }, - handler: (req: Request, reply: IReply) => { + handler: req => { const { setup } = req.pre; const { serviceName } = req.params; - const { transaction_name: transactionName } = req.query; - return getDistribution(serviceName, transactionName, setup) - .then(reply) - .catch(defaultErrorHandler(reply)); + const { transaction_name: transactionName } = req.query as { + transaction_name: string; + }; + return getDistribution(serviceName, transactionName, setup).catch( + defaultErrorHandler + ); } }); } diff --git a/x-pack/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts index 75cc26eeaf35d4..64dca03e68d566 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts @@ -3,13 +3,18 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { Lifecycle, ResponseToolkit } from 'hapi'; import { internalAuthData } from '../../../utils/wrap_request'; + export interface BackendFrameworkAdapter { internalUser: FrameworkInternalUser; version: string; getSetting(settingPath: string): any; exposeStaticDir(urlPath: string, dir: string): void; - registerRoute( + registerRoute< + RouteRequest extends FrameworkWrappableRequest, + RouteResponse extends FrameworkResponse + >( route: FrameworkRouteOptions ): void; } @@ -52,7 +57,7 @@ export interface FrameworkRequest< export interface FrameworkRouteOptions< RouteRequest extends FrameworkWrappableRequest, - RouteResponse + RouteResponse extends FrameworkResponse > { path: string; method: string | string[]; @@ -63,10 +68,10 @@ export interface FrameworkRouteOptions< config?: {}; } -export type FrameworkRouteHandler = ( - request: FrameworkRequest, - reply: any -) => void; +export type FrameworkRouteHandler< + RouteRequest extends FrameworkWrappableRequest, + RouteResponse extends FrameworkResponse +> = (request: FrameworkRequest, h: ResponseToolkit) => void; export interface FrameworkWrappableRequest< Payload = any, @@ -81,3 +86,5 @@ export interface FrameworkWrappableRequest< params: Params; query: Query; } + +export type FrameworkResponse = Lifecycle.ReturnValue; diff --git a/x-pack/plugins/beats_management/server/lib/adapters/framework/hapi_framework_adapter.ts b/x-pack/plugins/beats_management/server/lib/adapters/framework/hapi_framework_adapter.ts index dd122e59bdaef8..62e8b0599097d1 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/framework/hapi_framework_adapter.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/framework/hapi_framework_adapter.ts @@ -8,6 +8,7 @@ import { wrapRequest } from '../../../utils/wrap_request'; import { FrameworkInternalUser } from './adapter_types'; import { BackendFrameworkAdapter, + FrameworkResponse, FrameworkRouteOptions, FrameworkWrappableRequest, } from './adapter_types'; @@ -61,14 +62,15 @@ export class HapiBackendFrameworkAdapter implements BackendFrameworkAdapter { }); } - public registerRoute( - route: FrameworkRouteOptions - ) { + public registerRoute< + RouteRequest extends FrameworkWrappableRequest, + RouteResponse extends FrameworkResponse + >(route: FrameworkRouteOptions) { if (!this.server) { throw new Error('Must pass a hapi server into the adapter to use registerRoute'); } - const wrappedHandler = (licenseRequired: boolean) => (request: any, reply: any) => { - return route.handler(wrapRequest(request), reply); + const wrappedHandler = (licenseRequired: boolean) => (request: any, h: any) => { + return route.handler(wrapRequest(request), h); }; this.server.route({ diff --git a/x-pack/plugins/beats_management/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/beats_management/server/lib/adapters/framework/kibana_framework_adapter.ts index 2d41eea642dafd..427d82a18a8795 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/framework/kibana_framework_adapter.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/framework/kibana_framework_adapter.ts @@ -15,6 +15,7 @@ import { FrameworkRequest } from './adapter_types'; import { BackendFrameworkAdapter, FrameworkInternalUser, + FrameworkResponse, FrameworkRouteOptions, FrameworkWrappableRequest, } from './adapter_types'; @@ -75,22 +76,23 @@ export class KibanaBackendFrameworkAdapter implements BackendFrameworkAdapter { }); } - public registerRoute( - route: FrameworkRouteOptions - ) { + public registerRoute< + RouteRequest extends FrameworkWrappableRequest, + RouteResponse extends FrameworkResponse + >(route: FrameworkRouteOptions) { const wrappedHandler = (licenseRequired: boolean, requiredRoles?: string[]) => async ( request: any, - reply: any + h: any ) => { const xpackMainPlugin = this.server.plugins.xpack_main; const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults(); if (licenseRequired && !licenseCheckResults.licenseValid) { - reply(Boom.forbidden(licenseCheckResults.message)); + return Boom.forbidden(licenseCheckResults.message); } const wrappedRequest = wrapRequest(request); if (requiredRoles) { if (wrappedRequest.user.kind !== 'authenticated') { - return reply().code(403); + return h.response().code(403); } wrappedRequest.user = { ...wrappedRequest.user, @@ -102,10 +104,10 @@ export class KibanaBackendFrameworkAdapter implements BackendFrameworkAdapter { !wrappedRequest.user.roles.includes('superuser') && difference(requiredRoles, wrappedRequest.user.roles).length !== 0 ) { - return reply().code(403); + return h.response().code(403); } } - return route.handler(wrappedRequest, reply); + return route.handler(wrappedRequest, h); }; this.server.route({ diff --git a/x-pack/plugins/beats_management/server/rest_api/__tests__/test_harnes.ts b/x-pack/plugins/beats_management/server/rest_api/__tests__/test_harnes.ts index 18b59e0d9aeee4..ed93ffbe36e1e6 100644 --- a/x-pack/plugins/beats_management/server/rest_api/__tests__/test_harnes.ts +++ b/x-pack/plugins/beats_management/server/rest_api/__tests__/test_harnes.ts @@ -78,21 +78,20 @@ export const testHarnes = { }, getServerLibs: async () => { if (!serverLibs) { - const server = new Hapi.Server(); - server.connection({ port: 111111 }); + const server = new Hapi.Server({ port: 111111 }); const versionHeader = 'kbn-version'; const xsrfHeader = 'kbn-xsrf'; - server.ext('onPostAuth', (req: any, reply: any) => { + server.ext('onPostAuth', (req: any, h: any) => { const isSafeMethod = req.method === 'get' || req.method === 'head'; const hasVersionHeader = versionHeader in req.headers; const hasXsrfHeader = xsrfHeader in req.headers; if (!isSafeMethod && !hasVersionHeader && !hasXsrfHeader) { - return reply(badRequest(`Request must contain a ${xsrfHeader} header.`)); + throw badRequest(`Request must contain a ${xsrfHeader} header.`); } - return reply.continue(); + return h.continue; }); serverLibs = compose(server); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts b/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts index 48ae0f0b1de718..a24d6dee051328 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts @@ -24,7 +24,7 @@ export const createGetBeatConfigurationRoute = (libs: CMServerLibs) => ({ }, auth: false, }, - handler: async (request: any, reply: any) => { + handler: async (request: any, h: any) => { const beatId = request.params.beatId; const accessToken = request.headers['kbn-beats-access-token']; @@ -33,12 +33,12 @@ export const createGetBeatConfigurationRoute = (libs: CMServerLibs) => ({ try { beat = await libs.beats.getById(libs.framework.internalUser, beatId); if (beat === null) { - return reply({ message: `Beat "${beatId}" not found` }).code(404); + return h.response({ message: `Beat "${beatId}" not found` }).code(404); } const isAccessTokenValid = beat.access_token === accessToken; if (!isAccessTokenValid) { - return reply({ message: 'Invalid access token' }).code(401); + return h.response({ message: 'Invalid access token' }).code(401); } let newStatus: CMBeat['config_status'] = 'OK'; @@ -53,7 +53,7 @@ export const createGetBeatConfigurationRoute = (libs: CMServerLibs) => ({ tags = await libs.tags.getTagsWithIds(libs.framework.internalUser, beat.tags || []); } catch (err) { - return reply(wrapEsError(err)); + return wrapEsError(err); } const configurationBlocks = tags.reduce( @@ -75,8 +75,8 @@ export const createGetBeatConfigurationRoute = (libs: CMServerLibs) => ({ [] ); - reply({ + return { configuration_blocks: configurationBlocks, - }); + }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts b/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts index 03b46603c4d6c6..266e3baa3829f8 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts @@ -31,7 +31,7 @@ export const createBeatEnrollmentRoute = (libs: CMServerLibs) => ({ }).required(), }, }, - handler: async (request: FrameworkRequest, reply: any) => { + handler: async (request: FrameworkRequest, h: any) => { const { beatId } = request.params; const enrollmentToken = request.headers['kbn-beats-enrollment-token']; @@ -45,20 +45,24 @@ export const createBeatEnrollmentRoute = (libs: CMServerLibs) => ({ switch (status) { case BeatEnrollmentStatus.ExpiredEnrollmentToken: - return reply({ - message: BeatEnrollmentStatus.ExpiredEnrollmentToken, - }).code(400); + return h + .response({ + message: BeatEnrollmentStatus.ExpiredEnrollmentToken, + }) + .code(400); case BeatEnrollmentStatus.InvalidEnrollmentToken: - return reply({ - message: BeatEnrollmentStatus.InvalidEnrollmentToken, - }).code(400); + return h + .response({ + message: BeatEnrollmentStatus.InvalidEnrollmentToken, + }) + .code(400); case BeatEnrollmentStatus.Success: default: - return reply({ access_token: accessToken }).code(201); + return h.response({ access_token: accessToken }).code(201); } } catch (err) { // TODO move this to kibana route thing in adapter - return reply(wrapEsError(err)); + return wrapEsError(err); } }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/get.ts b/x-pack/plugins/beats_management/server/rest_api/beats/get.ts index 1b525345b5a9b0..49fac5e9f009cc 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/get.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/get.ts @@ -12,7 +12,7 @@ export const createGetBeatRoute = (libs: CMServerLibs) => ({ method: 'GET', path: '/api/beats/agent/{beatId}/{token?}', requiredRoles: ['beats_admin'], - handler: async (request: any, reply: any) => { + handler: async (request: any, h: any) => { const beatId = request.params.beatId; let beat: CMBeat | null; @@ -20,24 +20,24 @@ export const createGetBeatRoute = (libs: CMServerLibs) => ({ try { beat = await libs.beats.getByEnrollmentToken(request.user, request.params.token); if (beat === null) { - return reply().code(200); + return h.response().code(200); } } catch (err) { - return reply(wrapEsError(err)); + return wrapEsError(err); } } else { try { beat = await libs.beats.getById(request.user, beatId); if (beat === null) { - return reply({ message: 'Beat not found' }).code(404); + return h.response({ message: 'Beat not found' }).code(404); } } catch (err) { - return reply(wrapEsError(err)); + return wrapEsError(err); } } delete beat.access_token; - reply(beat); + return beat; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/list.ts b/x-pack/plugins/beats_management/server/rest_api/beats/list.ts index f9e1f37cb8338d..6dfec291f602ba 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/list.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/list.ts @@ -25,7 +25,7 @@ export const createListAgentsRoute = (libs: CMServerLibs) => ({ }), }, licenseRequired: true, - handler: async (request: FrameworkRequest, reply: any) => { + handler: async (request: FrameworkRequest) => { const listByAndValueParts = request.params.listByAndValue ? request.params.listByAndValue.split('/') : []; @@ -54,10 +54,10 @@ export const createListAgentsRoute = (libs: CMServerLibs) => ({ break; } - reply({ beats }); + return { beats }; } catch (err) { // TODO move this to kibana route thing in adapter - return reply(wrapEsError(err)); + return wrapEsError(err); } }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts b/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts index 98522e5627e236..91cda6e9524f9b 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts @@ -29,15 +29,15 @@ export const createTagAssignmentsRoute = (libs: CMServerLibs) => ({ }).required(), }, }, - handler: async (request: FrameworkRequest, reply: any) => { + handler: async (request: FrameworkRequest) => { const { assignments }: { assignments: BeatsTagAssignment[] } = request.payload; try { const response = await libs.beats.assignTagsToBeats(request.user, assignments); - reply(response); + return response; } catch (err) { // TODO move this to kibana route thing in adapter - return reply(wrapEsError(err)); + return wrapEsError(err); } }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts b/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts index 2ef210fd8dbb26..d1912d96fdcdb8 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts @@ -27,15 +27,15 @@ export const createTagRemovalsRoute = (libs: CMServerLibs) => ({ }).required(), }, }, - handler: async (request: FrameworkRequest, reply: any) => { + handler: async (request: FrameworkRequest) => { const { removals } = request.payload; try { const response = await libs.beats.removeTagsFromBeats(request.user, removals); - reply(response); + return response; } catch (err) { // TODO move this to kibana route thing in adapter - return reply(wrapEsError(err)); + return wrapEsError(err); } }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/update.ts b/x-pack/plugins/beats_management/server/rest_api/beats/update.ts index 73816af338f4aa..64e08330734d05 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/update.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/update.ts @@ -37,16 +37,16 @@ export const createBeatUpdateRoute = (libs: CMServerLibs) => ({ }), }, }, - handler: async (request: FrameworkRequest, reply: any) => { + handler: async (request: FrameworkRequest, h: any) => { const { beatId } = request.params; const accessToken = request.headers['kbn-beats-access-token']; const remoteAddress = request.info.remoteAddress; const userOrToken = accessToken || request.user; if (request.user.kind === 'unauthenticated' && request.payload.active !== undefined) { - return reply({ message: 'access-token is not a valid auth type to change beat status' }).code( - 401 - ); + return h + .response({ message: 'access-token is not a valid auth type to change beat status' }) + .code(401); } try { @@ -57,14 +57,14 @@ export const createBeatUpdateRoute = (libs: CMServerLibs) => ({ switch (status) { case 'beat-not-found': - return reply({ message: 'Beat not found', success: false }).code(404); + return h.response({ message: 'Beat not found', success: false }).code(404); case 'invalid-access-token': - return reply({ message: 'Invalid access token', success: false }).code(401); + return h.response({ message: 'Invalid access token', success: false }).code(401); } - reply({ success: true }).code(204); + return h.response({ success: true }).code(204); } catch (err) { - return reply(wrapEsError(err)); + return wrapEsError(err); } }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/delete.ts b/x-pack/plugins/beats_management/server/rest_api/tags/delete.ts index e93c201a80b494..0f138ecf04a149 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tags/delete.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tags/delete.ts @@ -12,7 +12,7 @@ export const createDeleteTagsWithIdsRoute = (libs: CMServerLibs) => ({ path: '/api/beats/tags/{tagIds}', requiredRoles: ['beats_admin'], licenseRequired: true, - handler: async (request: any, reply: any) => { + handler: async (request: any) => { const tagIdString: string = request.params.tagIds; const tagIds = tagIdString.split(',').filter((id: string) => id.length > 0); @@ -20,9 +20,9 @@ export const createDeleteTagsWithIdsRoute = (libs: CMServerLibs) => ({ try { success = await libs.tags.delete(request.user, tagIds); } catch (err) { - return reply(wrapEsError(err)); + return wrapEsError(err); } - reply({ success }); + return { success }; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/get.ts b/x-pack/plugins/beats_management/server/rest_api/tags/get.ts index 23c6f77c34f1fa..36d00208066c24 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tags/get.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tags/get.ts @@ -13,7 +13,7 @@ export const createGetTagsWithIdsRoute = (libs: CMServerLibs) => ({ path: '/api/beats/tags/{tagIds}', requiredRoles: ['beats_admin'], licenseRequired: true, - handler: async (request: any, reply: any) => { + handler: async (request: any) => { const tagIdString: string = request.params.tagIds; const tagIds = tagIdString.split(',').filter((id: string) => id.length > 0); @@ -21,9 +21,9 @@ export const createGetTagsWithIdsRoute = (libs: CMServerLibs) => ({ try { tags = await libs.tags.getTagsWithIds(request.user, tagIds); } catch (err) { - return reply(wrapEsError(err)); + return wrapEsError(err); } - reply(tags); + return tags; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/list.ts b/x-pack/plugins/beats_management/server/rest_api/tags/list.ts index 427c223fda2571..f255a627220d36 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tags/list.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tags/list.ts @@ -24,7 +24,7 @@ export const createListTagsRoute = (libs: CMServerLibs) => ({ }), }, licenseRequired: true, - handler: async (request: any, reply: any) => { + handler: async (request: any) => { let tags: BeatTag[]; try { tags = await libs.tags.getAll( @@ -32,9 +32,9 @@ export const createListTagsRoute = (libs: CMServerLibs) => ({ // request.query ? JSON.parse(request.query.ESQuery) : undefined ); } catch (err) { - return reply(wrapEsError(err)); + return wrapEsError(err); } - reply(tags); + return tags; }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/set.ts b/x-pack/plugins/beats_management/server/rest_api/tags/set.ts index afdec26b47302c..600eef42d90af3 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tags/set.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tags/set.ts @@ -38,20 +38,20 @@ export const createSetTagRoute = (libs: CMServerLibs) => ({ }).allow(null), }, }, - handler: async (request: FrameworkRequest, reply: any) => { + handler: async (request: FrameworkRequest, h: any) => { const defaultConfig = { configuration_blocks: [], color: '#DD0A73' }; const config = get(request, 'payload', defaultConfig) || defaultConfig; try { const { isValid, result } = await libs.tags.saveTag(request.user, request.params.tag, config); if (!isValid) { - return reply({ result, success: false }).code(400); + return h.response({ result, success: false }).code(400); } - reply({ success: true }).code(result === 'created' ? 201 : 200); + return h.response({ success: true }).code(result === 'created' ? 201 : 200); } catch (err) { // TODO move this to kibana route thing in adapter - return reply(wrapEsError(err)); + return wrapEsError(err); } }, }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts b/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts index d0d4b24fae5736..42604ced8a972a 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts @@ -27,15 +27,15 @@ export const createTokensRoute = (libs: CMServerLibs) => ({ }).allow(null), }, }, - handler: async (request: FrameworkRequest, reply: any) => { + handler: async (request: FrameworkRequest) => { const numTokens = get(request, 'payload.num_tokens', DEFAULT_NUM_TOKENS); try { const tokens = await libs.tokens.createEnrollmentTokens(request.user, numTokens); - reply({ tokens }); + return { tokens }; } catch (err) { // TODO move this to kibana route thing in adapter - return reply(wrapEsError(err)); + return wrapEsError(err); } }, }); diff --git a/x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.ts b/x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.ts index f0b683ce4aa66e..16c35fad7d63be 100644 --- a/x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.ts +++ b/x-pack/plugins/beats_management/server/utils/error_wrappers/wrap_es_error.ts @@ -20,12 +20,5 @@ export function wrapEsError(err: any) { return Boom.forbidden('Insufficient user permissions for managing Beats configuration'); } - // This is due to a typings error in the Boom typedef. - // @ts-ignore - if (Boom.wrap) { - // @ts-ignore - return Boom.wrap(err, err.statusCode); - } - return Boom.boomify(err, { statusCode: err.statusCode }); } diff --git a/x-pack/plugins/canvas/server/lib/__tests__/create_handlers.js b/x-pack/plugins/canvas/server/lib/__tests__/create_handlers.js index 4537d18ff5f18c..f3a92b573680ca 100644 --- a/x-pack/plugins/canvas/server/lib/__tests__/create_handlers.js +++ b/x-pack/plugins/canvas/server/lib/__tests__/create_handlers.js @@ -71,8 +71,7 @@ describe('server createHandlers', () => { throw new Error('elasticsearchClient should fail when authentication fails'); }) .catch(err => { - // note: boom pre-pends error messages with "Error: " - expect(err.message).to.be.equal(`Error: ${authError.message}`); + expect(err.message).to.be.equal(authError.message); }); }); diff --git a/x-pack/plugins/canvas/server/routes/es_fields/index.js b/x-pack/plugins/canvas/server/routes/es_fields/index.js index 9ceca324cc017a..8c6b53fb2610b8 100644 --- a/x-pack/plugins/canvas/server/routes/es_fields/index.js +++ b/x-pack/plugins/canvas/server/routes/es_fields/index.js @@ -14,11 +14,11 @@ export function esFields(server) { server.route({ method: 'GET', path: '/api/canvas/es_fields', - handler: function(request, reply) { + handler: function(request, h) { const { index, fields } = request.query; - if (!index) return reply({ error: '"index" query is required' }).code(400); + if (!index) return h.response({ error: '"index" query is required' }).code(400); - reply(getESFieldTypes(index, fields, partial(callWithRequest, request))); + return getESFieldTypes(index, fields, partial(callWithRequest, request)); }, }); } diff --git a/x-pack/plugins/canvas/server/routes/es_indices/index.js b/x-pack/plugins/canvas/server/routes/es_indices/index.js index 67a92fa72aecdb..71ce1122b0c832 100644 --- a/x-pack/plugins/canvas/server/routes/es_indices/index.js +++ b/x-pack/plugins/canvas/server/routes/es_indices/index.js @@ -16,8 +16,8 @@ export function esIndices(server) { server.route({ method: 'GET', path: '/api/canvas/es_indices', - handler: function(request, reply) { - reply(getESIndices(kbnIndex, partial(callWithRequest, request))); + handler: function(request) { + return getESIndices(kbnIndex, partial(callWithRequest, request)); }, }); } diff --git a/x-pack/plugins/canvas/server/routes/plugins.js b/x-pack/plugins/canvas/server/routes/plugins.js index 66e73c71876a3a..be94ef52ac9e4a 100644 --- a/x-pack/plugins/canvas/server/routes/plugins.js +++ b/x-pack/plugins/canvas/server/routes/plugins.js @@ -11,12 +11,12 @@ export function plugins(server) { server.route({ method: 'GET', path: '/api/canvas/plugins', - handler: function(request, reply) { + handler: function(request, h) { const { type } = request.query; - if (!pluginPaths[type]) return reply({ error: 'Invalid type' }).code(400); + if (!pluginPaths[type]) return h.response({ error: 'Invalid type' }).code(400); - reply(getPluginStream(type)); + return getPluginStream(type); }, config: { auth: false, diff --git a/x-pack/plugins/canvas/server/routes/translate.js b/x-pack/plugins/canvas/server/routes/translate.js index f2b412c37e9b94..6125898a7dab9e 100644 --- a/x-pack/plugins/canvas/server/routes/translate.js +++ b/x-pack/plugins/canvas/server/routes/translate.js @@ -13,22 +13,21 @@ export function translate(server) { server.route({ method: 'GET', path: '/api/canvas/ast', - handler: function(request, reply) { + handler: function(request, h) { if (!request.query.expression) - return reply({ error: '"expression" query is required' }).code(400); - reply(fromExpression(request.query.expression)); + return h.response({ error: '"expression" query is required' }).code(400); + return fromExpression(request.query.expression); }, }); server.route({ method: 'POST', path: '/api/canvas/expression', - handler: function(request, reply) { + handler: function(request, h) { try { - const exp = toExpression(request.payload); - reply(exp); + return toExpression(request.payload); } catch (e) { - reply({ error: e.message }).code(400); + return h.response({ error: e.message }).code(400); } }, }); diff --git a/x-pack/plugins/canvas/server/routes/workpad.js b/x-pack/plugins/canvas/server/routes/workpad.js index b1d2cfa63477bd..e873f99efa74f4 100644 --- a/x-pack/plugins/canvas/server/routes/workpad.js +++ b/x-pack/plugins/canvas/server/routes/workpad.js @@ -13,21 +13,19 @@ export function workpad(server) { const { errors: esErrors } = server.plugins.elasticsearch.getCluster('data'); const routePrefix = API_ROUTE_WORKPAD; - function formatResponse(reply, returnResponse = false) { - return resp => { - if (resp.isBoom) return reply(resp); // can't wrap it if it's already a boom error + function formatResponse(resp) { + if (resp.isBoom) return resp; // can't wrap it if it's already a boom error - if (resp instanceof esErrors['400']) return reply(boom.badRequest(resp)); + if (resp instanceof esErrors['400']) return boom.badRequest(resp); - if (resp instanceof esErrors['401']) return reply(boom.unauthorized()); + if (resp instanceof esErrors['401']) return boom.unauthorized(); - if (resp instanceof esErrors['403']) - return reply(boom.forbidden("Sorry, you don't have access to that")); + if (resp instanceof esErrors['403']) + return boom.forbidden("Sorry, you don't have access to that"); - if (resp instanceof esErrors['404']) return reply(boom.wrap(resp, 404)); + if (resp instanceof esErrors['404']) return boom.boomify(resp, { statusCode: 404 }); - return returnResponse ? resp : reply(resp); - }; + return resp; } function createWorkpad(req, id) { @@ -94,15 +92,15 @@ export function workpad(server) { server.route({ method: 'GET', path: `${routePrefix}/{id}`, - handler: function(req, reply) { + handler: function(req) { const savedObjectsClient = req.getSavedObjectsClient(); const { id } = req.params; return savedObjectsClient .get(CANVAS_TYPE, id) .then(obj => obj.attributes) - .then(formatResponse(reply)) - .catch(formatResponse(reply)); + .then(formatResponse) + .catch(formatResponse); }, }); @@ -111,10 +109,10 @@ export function workpad(server) { method: 'POST', path: routePrefix, config: { payload: { allow: 'application/json', maxBytes: 26214400 } }, // 25MB payload limit - handler: function(request, reply) { - createWorkpad(request) - .then(() => reply({ ok: true })) - .catch(formatResponse(reply)); + handler: function(request) { + return createWorkpad(request) + .then(() => ({ ok: true })) + .catch(formatResponse); }, }); @@ -123,10 +121,10 @@ export function workpad(server) { method: 'PUT', path: `${routePrefix}/{id}`, config: { payload: { allow: 'application/json', maxBytes: 26214400 } }, // 25MB payload limit - handler: function(request, reply) { - updateWorkpad(request) - .then(() => reply({ ok: true })) - .catch(formatResponse(reply)); + handler: function(request) { + return updateWorkpad(request) + .then(() => ({ ok: true })) + .catch(formatResponse); }, }); @@ -134,10 +132,10 @@ export function workpad(server) { server.route({ method: 'DELETE', path: `${routePrefix}/{id}`, - handler: function(request, reply) { - deleteWorkpad(request) - .then(() => reply({ ok: true })) - .catch(formatResponse(reply)); + handler: function(request) { + return deleteWorkpad(request) + .then(() => ({ ok: true })) + .catch(formatResponse); }, }); @@ -145,20 +143,20 @@ export function workpad(server) { server.route({ method: 'GET', path: `${routePrefix}/find`, - handler: function(request, reply) { - findWorkpad(request) - .then(formatResponse(reply, true)) + handler: function(request) { + return findWorkpad(request) + .then(formatResponse) .then(resp => { - reply({ + return { total: resp.total, workpads: resp.saved_objects.map(hit => hit.attributes), - }); + }; }) .catch(() => { - reply({ + return { total: 0, workpads: [], - }); + }; }); }, }); diff --git a/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js b/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js index e0ff4b3c0c600f..b8c46c9e97f150 100644 --- a/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js +++ b/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js @@ -26,21 +26,21 @@ function setup() { }; const server = new Hapi.Server(); - server.connection({ port: 0 }); // attach the extension server.ext(createDashboardModeRequestInterceptor(dashboardViewerApp)); // allow the extension to fake "render an app" - server.decorate('reply', 'renderApp', function (app) { - this({ renderApp: true, app }); + server.decorate('toolkit', 'renderApp', function (app) { + // `this` is the `h` response toolkit + return this.response({ renderApp: true, app }); }); server.route({ path: '/app/{appId}', method: 'GET', - handler(req, reply) { - reply.renderApp({ name: req.params.appId }); + handler(req, h) { + return h.renderApp({ name: req.params.appId }); } }); @@ -48,8 +48,8 @@ function setup() { server.route({ path: '/{path*}', method: 'GET', - handler(req, reply) { - reply({ catchAll: true, path: `/${req.params.path}` }); + handler(req) { + return { catchAll: true, path: `/${req.params.path}` }; } }); diff --git a/x-pack/plugins/dashboard_mode/server/dashboard_mode_request_interceptor.js b/x-pack/plugins/dashboard_mode/server/dashboard_mode_request_interceptor.js index 60de6bec0f57a0..275922deb3d602 100644 --- a/x-pack/plugins/dashboard_mode/server/dashboard_mode_request_interceptor.js +++ b/x-pack/plugins/dashboard_mode/server/dashboard_mode_request_interceptor.js @@ -23,7 +23,7 @@ export function createDashboardModeRequestInterceptor(dashboardViewerApp) { return { type: 'onPostAuth', - method(request, reply) { + async method(request, h) { const { auth, url } = request; const isAppRequest = url.path.startsWith('/app/'); @@ -33,15 +33,14 @@ export function createDashboardModeRequestInterceptor(dashboardViewerApp) { // that app and none others. Here we are intercepting all other routing and ensuring the viewer // app is the only one ever rendered. // Read more about Dashboard Only Mode here: https://github.com/elastic/x-pack-kibana/issues/180 - reply.renderApp(dashboardViewerApp); - return; + const response = await h.renderApp(dashboardViewerApp); + return response.takeover(); } - reply(Boom.notFound()); - return; + throw Boom.notFound(); } - reply.continue(); + return h.continue; } }; } diff --git a/x-pack/plugins/graph/server/lib/es/call_es_graph_explore_api.js b/x-pack/plugins/graph/server/lib/es/call_es_graph_explore_api.js index a20afb3d8d34e8..142d4ea266eae4 100644 --- a/x-pack/plugins/graph/server/lib/es/call_es_graph_explore_api.js +++ b/x-pack/plugins/graph/server/lib/es/call_es_graph_explore_api.js @@ -35,6 +35,6 @@ export async function callEsGraphExploreApi({ callCluster, index, query }) { throw Boom.badRequest(relevantCause.reason); } - throw Boom.wrap(error); + throw Boom.boomify(error); } } diff --git a/x-pack/plugins/graph/server/lib/es/call_es_search_api.js b/x-pack/plugins/graph/server/lib/es/call_es_search_api.js index 7636304a7469db..67fb5d115c3747 100644 --- a/x-pack/plugins/graph/server/lib/es/call_es_search_api.js +++ b/x-pack/plugins/graph/server/lib/es/call_es_search_api.js @@ -16,6 +16,6 @@ export async function callEsSearchApi({ callCluster, index, body }) { }) }; } catch (error) { - throw Boom.wrap(error, error.statusCode || 500); + throw Boom.boomify(error, { statusCode: error.statusCode || 500 }); } } diff --git a/x-pack/plugins/graph/server/lib/pre/get_call_cluster_pre.js b/x-pack/plugins/graph/server/lib/pre/get_call_cluster_pre.js index 67a25727c05031..383170a13d4cfa 100644 --- a/x-pack/plugins/graph/server/lib/pre/get_call_cluster_pre.js +++ b/x-pack/plugins/graph/server/lib/pre/get_call_cluster_pre.js @@ -6,8 +6,8 @@ export const getCallClusterPre = { assign: 'callCluster', - method(request, reply) { + method(request) { const cluster = request.server.plugins.elasticsearch.getCluster('data'); - reply((...args) => cluster.callWithRequest(request, ...args)); + return (...args) => cluster.callWithRequest(request, ...args); } }; diff --git a/x-pack/plugins/graph/server/lib/pre/verify_api_access_pre.js b/x-pack/plugins/graph/server/lib/pre/verify_api_access_pre.js index f253fdadae20a0..a26e7247d62879 100644 --- a/x-pack/plugins/graph/server/lib/pre/verify_api_access_pre.js +++ b/x-pack/plugins/graph/server/lib/pre/verify_api_access_pre.js @@ -6,14 +6,14 @@ import Boom from 'boom'; -export function verifyApiAccessPre(request, reply) { +export function verifyApiAccessPre(request, h) { const xpackInfo = request.server.plugins.xpack_main.info; const graph = xpackInfo.feature('graph'); const licenseCheckResults = graph.getLicenseCheckResults(); if (licenseCheckResults.showAppLink && licenseCheckResults.enableAppLink) { - reply(); + return null; } else { - reply(Boom.forbidden(licenseCheckResults.message)); + throw Boom.forbidden(licenseCheckResults.message); } } diff --git a/x-pack/plugins/graph/server/routes/graph_explore.js b/x-pack/plugins/graph/server/routes/graph_explore.js index 49248814a048f1..7f77903dd70506 100644 --- a/x-pack/plugins/graph/server/routes/graph_explore.js +++ b/x-pack/plugins/graph/server/routes/graph_explore.js @@ -26,12 +26,12 @@ export const graphExploreRoute = { query: Joi.object().required().unknown(true) }).default() }, - handler(request, reply) { - reply(callEsGraphExploreApi({ + handler(request) { + return callEsGraphExploreApi({ callCluster: request.pre.callCluster, index: request.payload.index, query: request.payload.query, - })); + }); } } }; diff --git a/x-pack/plugins/graph/server/routes/search_proxy.js b/x-pack/plugins/graph/server/routes/search_proxy.js index fc95c73ce8f2d8..55bdb3af056f5f 100644 --- a/x-pack/plugins/graph/server/routes/search_proxy.js +++ b/x-pack/plugins/graph/server/routes/search_proxy.js @@ -27,12 +27,12 @@ export const searchProxyRoute = { body: Joi.object().unknown(true).default() }).default() }, - handler(request, reply) { - reply(callEsSearchApi({ + handler(request) { + return callEsSearchApi({ callCluster: request.pre.callCluster, index: request.payload.index, body: request.payload.body - })); + }); } } }; diff --git a/x-pack/plugins/grokdebugger/server/lib/error_wrappers/wrap_es_error.js b/x-pack/plugins/grokdebugger/server/lib/error_wrappers/wrap_es_error.js index ccf42d31ba46fb..dfcd4e3b1e17c4 100644 --- a/x-pack/plugins/grokdebugger/server/lib/error_wrappers/wrap_es_error.js +++ b/x-pack/plugins/grokdebugger/server/lib/error_wrappers/wrap_es_error.js @@ -14,5 +14,5 @@ import Boom from 'boom'; * @return Object Boom error response */ export function wrapEsError(err) { - return Boom.wrap(err, err.statusCode); + return Boom.boomify(err, { statusCode: err.statusCode }); } diff --git a/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index 234bcca38f6009..9196b8b813470b 100644 --- a/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -34,31 +34,29 @@ describe('license_pre_routing_factory', () => { }; }); - it ('replies with 403', (done) => { + it('replies with 403', async () => { const licensePreRouting = licensePreRoutingFactory(mockServer); const stubRequest = {}; - licensePreRouting(stubRequest, (response) => { + expect(() => licensePreRouting(stubRequest)).to.throwException((response) => { expect(response).to.be.an(Error); expect(response.isBoom).to.be(true); expect(response.output.statusCode).to.be(403); - done(); }); }); }); - describe('isAvailable is true', () => { + describe('isAvailable is true', async () => { beforeEach(() => { mockLicenseCheckResults = { isAvailable: true }; }); - it ('replies with nothing', (done) => { + it('replies with forbidden', async () => { const licensePreRouting = licensePreRoutingFactory(mockServer); const stubRequest = {}; - licensePreRouting(stubRequest, (response) => { + expect(() => licensePreRouting(stubRequest)).to.throwException((response) => { expect(response).to.eql(Boom.forbidden()); - done(); }); }); }); diff --git a/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/license_pre_routing_factory.js b/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/license_pre_routing_factory.js index 7d112513531205..8a2ef40b86ffe2 100644 --- a/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/license_pre_routing_factory.js +++ b/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/license_pre_routing_factory.js @@ -11,13 +11,13 @@ export const licensePreRoutingFactory = (server) => { const xpackMainPlugin = server.plugins.xpack_main; // License checking and enable/disable logic - function licensePreRouting(request, reply) { + function licensePreRouting() { const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults(); if (!licenseCheckResults.enableAPIRoute) { - reply(Boom.forbidden(licenseCheckResults.message)); - } else { - reply(); + throw Boom.forbidden(licenseCheckResults.message); } + + return null; } return licensePreRouting; diff --git a/x-pack/plugins/grokdebugger/server/routes/api/grokdebugger/register_grok_simulate_route.js b/x-pack/plugins/grokdebugger/server/routes/api/grokdebugger/register_grok_simulate_route.js index 1af538f01e4813..23295c3af45559 100644 --- a/x-pack/plugins/grokdebugger/server/routes/api/grokdebugger/register_grok_simulate_route.js +++ b/x-pack/plugins/grokdebugger/server/routes/api/grokdebugger/register_grok_simulate_route.js @@ -22,15 +22,15 @@ export function registerGrokSimulateRoute(server) { server.route({ path: '/api/grokdebugger/simulate', method: 'POST', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const grokdebuggerRequest = GrokdebuggerRequest.fromDownstreamJSON(request.payload); return simulateGrok(callWithRequest, grokdebuggerRequest.upstreamJSON) .then((simulateResponseFromES) => { const grokdebuggerResponse = GrokdebuggerResponse.fromUpstreamJSON(simulateResponseFromES); - reply({ grokdebuggerResponse }); + return { grokdebuggerResponse }; }) - .catch(e => reply(wrapEsError(e))); + .catch(e => wrapEsError(e)); }, config: { pre: [ licensePreRouting ] diff --git a/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_custom_error.js b/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_custom_error.js index 890a366ac65c1e..3295113d38ee5a 100644 --- a/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_custom_error.js +++ b/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_custom_error.js @@ -14,5 +14,5 @@ import Boom from 'boom'; * @return Object Boom error response */ export function wrapCustomError(err, statusCode) { - return Boom.wrap(err, statusCode); + return Boom.boomify(err, { statusCode }); } diff --git a/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_es_error.js b/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_es_error.js index 3d69ff19a6c848..2df2e4b802e1a1 100644 --- a/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_es_error.js +++ b/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_es_error.js @@ -20,11 +20,11 @@ export function wrapEsError(err, statusCodeToMessageMap = {}) { // If no custom message if specified for the error's status code, just // wrap the error as a Boom error response and return it if (!statusCodeToMessageMap[statusCode]) { - return Boom.wrap(err, err.statusCode); + return Boom.boomify(err, { statusCode }); } // Otherwise, use the custom message to create a Boom error response and // return it const message = statusCodeToMessageMap[statusCode]; - return Boom.create(statusCode, message); -} \ No newline at end of file + return new Boom(message, { statusCode }); +} diff --git a/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_unknown_error.js b/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_unknown_error.js index ca72fa00309221..4b865880ae20de 100644 --- a/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_unknown_error.js +++ b/x-pack/plugins/index_management/server/lib/error_wrappers/wrap_unknown_error.js @@ -13,5 +13,5 @@ import Boom from 'boom'; * @return Object Boom error response */ export function wrapUnknownError(err) { - return Boom.wrap(err); + return Boom.boomify(err); } \ No newline at end of file diff --git a/x-pack/plugins/index_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/index_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index b72f8cc7697310..359b3fb2ce6f4f 100644 --- a/x-pack/plugins/index_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/index_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -40,14 +40,13 @@ describe('license_pre_routing_factory', () => { }; }); - it ('replies with 403', (done) => { + it ('replies with 403', () => { const licensePreRouting = licensePreRoutingFactory(mockServer); const stubRequest = {}; - licensePreRouting(stubRequest, (response) => { + expect(() => licensePreRouting(stubRequest)).to.throwException((response) => { expect(response).to.be.an(Error); expect(response.isBoom).to.be(true); expect(response.output.statusCode).to.be(403); - done(); }); }); }); @@ -59,13 +58,11 @@ describe('license_pre_routing_factory', () => { }; }); - it ('replies with nothing', (done) => { + it ('replies with nothing', () => { const licensePreRouting = licensePreRoutingFactory(mockServer); const stubRequest = {}; - licensePreRouting(stubRequest, (response) => { - expect(response).to.be(undefined); - done(); - }); + const response = licensePreRouting(stubRequest); + expect(response).to.be(null); }); }); }); diff --git a/x-pack/plugins/index_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js b/x-pack/plugins/index_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js index b3720ab265393b..11e01304b6e5cf 100644 --- a/x-pack/plugins/index_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js +++ b/x-pack/plugins/index_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js @@ -12,16 +12,15 @@ export const licensePreRoutingFactory = once((server) => { const xpackMainPlugin = server.plugins.xpack_main; // License checking and enable/disable logic - function licensePreRouting(request, reply) { + function licensePreRouting() { const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults(); if (!licenseCheckResults.isAvailable) { const error = new Error(licenseCheckResults.message); const statusCode = 403; - const wrappedError = wrapCustomError(error, statusCode); - reply(wrappedError); - } else { - reply(); + throw wrapCustomError(error, statusCode); } + + return null; } return licensePreRouting; diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_clear_cache_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_clear_cache_route.js index 0260c5f3023ea7..5dc22f023eb5c8 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_clear_cache_route.js +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_clear_cache_route.js @@ -30,7 +30,7 @@ export function registerClearCacheRoute(server) { server.route({ path: '/api/index_management/indices/clear_cache', method: 'POST', - handler: async (request, reply) => { + handler: async (request, h) => { const callWithRequest = callWithRequestFactory(server, request); const indices = getIndexArrayFromPayload(request.payload); @@ -38,13 +38,13 @@ export function registerClearCacheRoute(server) { await clearCache(callWithRequest, indices); //TODO: Should we check acknowledged = true? - reply(); + return h.response(); } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_close_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_close_route.js index b2e96cd6b796c7..763429de6d3e46 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_close_route.js +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_close_route.js @@ -30,7 +30,7 @@ export function registerCloseRoute(server) { server.route({ path: '/api/index_management/indices/close', method: 'POST', - handler: async (request, reply) => { + handler: async (request, h) => { const callWithRequest = callWithRequestFactory(server, request); const indices = getIndexArrayFromPayload(request.payload); @@ -38,13 +38,13 @@ export function registerCloseRoute(server) { await closeIndices(callWithRequest, indices); //TODO: Should we check acknowledged = true? - reply(); + return h.response(); } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_delete_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_delete_route.js index 58e1d99224057c..a2b2c87662959e 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_delete_route.js +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_delete_route.js @@ -30,19 +30,19 @@ export function registerDeleteRoute(server) { server.route({ path: '/api/index_management/indices/delete', method: 'POST', - handler: async (request, reply) => { + handler: async (request, h) => { const callWithRequest = callWithRequestFactory(server, request); const indices = getIndexArrayFromPayload(request.payload); try { await deleteIndices(callWithRequest, indices); - reply(); + return h.response(); } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_flush_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_flush_route.js index 4d59552bf53742..f66691b9577f13 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_flush_route.js +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_flush_route.js @@ -31,7 +31,7 @@ export function registerFlushRoute(server) { server.route({ path: '/api/index_management/indices/flush', method: 'POST', - handler: async (request, reply) => { + handler: async (request, h) => { const callWithRequest = callWithRequestFactory(server, request); const indices = getIndexArrayFromPayload(request.payload); @@ -39,13 +39,13 @@ export function registerFlushRoute(server) { await flushIndices(callWithRequest, indices); //TODO: Should we check acknowledged = true? - reply(); + return h.response(); } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_forcemerge_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_forcemerge_route.js index 7328101ebaa997..dcc926353d07b2 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_forcemerge_route.js +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_forcemerge_route.js @@ -28,7 +28,7 @@ export function registerForcemergeRoute(server) { server.route({ path: '/api/index_management/indices/forcemerge', method: 'POST', - handler: async (request, reply) => { + handler: async (request, h) => { const callWithRequest = callWithRequestFactory(server, request); const { payload } = request; const { indices = [], maxNumSegments } = payload; @@ -36,13 +36,13 @@ export function registerForcemergeRoute(server) { await forcemergeIndices(callWithRequest, indices, maxNumSegments); //TODO: Should we check acknowledged = true? - reply(); + return h.response(); } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_list_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_list_route.js index 37794c7e91b9eb..af2a03f5bc4aae 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_list_route.js +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_list_route.js @@ -41,19 +41,19 @@ export function registerListRoute(server) { server.route({ path: '/api/index_management/indices', method: 'GET', - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); try { const hits = await fetchIndices(callWithRequest); const response = formatHits(hits); - reply(response); + return response; } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_open_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_open_route.js index 9a8e164e0f6271..bbf38d4a51adf6 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_open_route.js +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_open_route.js @@ -30,7 +30,7 @@ export function registerOpenRoute(server) { server.route({ path: '/api/index_management/indices/open', method: 'POST', - handler: async (request, reply) => { + handler: async (request, h) => { const callWithRequest = callWithRequestFactory(server, request); const indices = getIndexArrayFromPayload(request.payload); @@ -38,13 +38,13 @@ export function registerOpenRoute(server) { await openIndices(callWithRequest, indices); //TODO: Should we check acknowledged = true? - reply(); + return h.response(); } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_refresh_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_refresh_route.js index 666197834248cd..49414f70a65889 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_refresh_route.js +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_refresh_route.js @@ -29,7 +29,7 @@ export function registerRefreshRoute(server) { server.route({ path: '/api/index_management/indices/refresh', method: 'POST', - handler: async (request, reply) => { + handler: async (request, h) => { const callWithRequest = callWithRequestFactory(server, request); const indices = getIndexArrayFromPayload(request.payload); @@ -37,13 +37,13 @@ export function registerRefreshRoute(server) { await refreshIndices(callWithRequest, indices); //TODO: Should we check acknowledged = true? - reply(); + return h.response(); } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_reload_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_reload_route.js index 8d8431535eb6b7..8aa486be06f374 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_reload_route.js +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_reload_route.js @@ -46,20 +46,20 @@ export function registerReloadRoute(server) { server.route({ path: '/api/index_management/indices/reload', method: 'POST', - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); const indexNames = getIndexNamesFromPayload(request.payload); try { const hits = await fetchIndices(callWithRequest, indexNames); const response = formatHits(hits); - reply(response); + return response; } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_settings_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_settings_route.js index a9208a9f1f297b..c15e9f51d64646 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_settings_route.js +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_settings_route.js @@ -46,20 +46,20 @@ export function registerSettingsRoute(server) { server.route({ path: '/api/index_management/indices/settings', method: 'POST', - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); const indexNames = getIndexNamesFromPayload(request.payload); try { const hits = await fetchSettings(callWithRequest, indexNames); const response = formatHits(hits); - reply(response); + return response; } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_shards_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_shards_route.js index b4b2a585743b9b..0d56e2146b612e 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_shards_route.js +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_shards_route.js @@ -46,20 +46,20 @@ export function registerShardsRoute(server) { server.route({ path: '/api/index_management/indices/shards', method: 'POST', - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); const indexNames = getIndexNamesFromPayload(request.payload); try { const hits = await fetchShards(callWithRequest, indexNames); const response = formatHits(hits); - reply(response); + return response; } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/mapping/register_mapping_route.js b/x-pack/plugins/index_management/server/routes/api/mapping/register_mapping_route.js index 93bb8a405ca26e..c988fdb1591199 100644 --- a/x-pack/plugins/index_management/server/routes/api/mapping/register_mapping_route.js +++ b/x-pack/plugins/index_management/server/routes/api/mapping/register_mapping_route.js @@ -33,7 +33,7 @@ export function registerMappingRoute(server) { server.route({ path: '/api/index_management/mapping/{indexName}', method: 'GET', - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); const { indexName } = request.params; @@ -41,13 +41,13 @@ export function registerMappingRoute(server) { const hit = await fetchMapping(callWithRequest, indexName); const response = formatHit(hit, indexName); - reply(response); + return response; } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/settings/register_load_route.js b/x-pack/plugins/index_management/server/routes/api/settings/register_load_route.js index 0493cd650b8ec4..658ab109fd7c63 100644 --- a/x-pack/plugins/index_management/server/routes/api/settings/register_load_route.js +++ b/x-pack/plugins/index_management/server/routes/api/settings/register_load_route.js @@ -35,20 +35,20 @@ export function registerLoadRoute(server) { server.route({ path: '/api/index_management/settings/{indexName}', method: 'GET', - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); const { indexName } = request.params; try { const hit = await fetchSettings(callWithRequest, indexName); const response = formatHit(hit); - reply(response); + return response; } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/settings/register_update_route.js b/x-pack/plugins/index_management/server/routes/api/settings/register_update_route.js index 5a3816481406be..49904d741f0572 100644 --- a/x-pack/plugins/index_management/server/routes/api/settings/register_update_route.js +++ b/x-pack/plugins/index_management/server/routes/api/settings/register_update_route.js @@ -29,18 +29,18 @@ export function registerUpdateRoute(server) { server.route({ path: '/api/index_management/settings/{indexName}', method: 'PUT', - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); const { indexName } = request.params; try { const response = await updateSettings(callWithRequest, indexName, request.payload); - reply(response); + return response; } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/index_management/server/routes/api/stats/register_stats_route.js b/x-pack/plugins/index_management/server/routes/api/stats/register_stats_route.js index 163b240782e028..a0a0455e273c88 100644 --- a/x-pack/plugins/index_management/server/routes/api/stats/register_stats_route.js +++ b/x-pack/plugins/index_management/server/routes/api/stats/register_stats_route.js @@ -34,7 +34,7 @@ export function registerStatsRoute(server) { server.route({ path: '/api/index_management/stats/{indexName}', method: 'GET', - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); const { indexName } = request.params; @@ -42,13 +42,13 @@ export function registerStatsRoute(server) { const hit = await fetchStats(callWithRequest, indexName); const response = formatHit(hit, indexName); - reply(response); + return response; } catch (err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/infra/package.json b/x-pack/plugins/infra/package.json index ce926e897b6816..a77eeaaf011b50 100644 --- a/x-pack/plugins/infra/package.json +++ b/x-pack/plugins/infra/package.json @@ -6,7 +6,7 @@ "build-graphql-types": "node scripts/generate_types_from_graphql.js" }, "devDependencies": { - "@types/boom": "3.2.2", + "@types/boom": "7.2.0", "@types/lodash": "^4.14.110" }, "dependencies": { diff --git a/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts index 17cf5064aeb4bd..28378248a6384e 100644 --- a/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts @@ -6,7 +6,7 @@ import { SearchResponse } from 'elasticsearch'; import { GraphQLSchema } from 'graphql'; -import { IRouteAdditionalConfigurationOptions, IStrictReply } from 'hapi'; +import { Lifecycle, ResponseToolkit, RouteOptions } from 'hapi'; import { InfraMetricModel } from '../metrics/adapter_types'; export * from '../../../../common/graphql/typed_resolvers'; @@ -18,7 +18,7 @@ export interface InfraBackendFrameworkAdapter { version: string; exposeStaticDir(urlPath: string, dir: string): void; registerGraphQLEndpoint(routePath: string, schema: GraphQLSchema): void; - registerRoute( + registerRoute( route: InfraFrameworkRouteOptions ): void; callWithRequest( @@ -75,6 +75,8 @@ export interface InfraWrappableRequest query: Query; } +export type InfraResponse = Lifecycle.ReturnValue; + export interface InfraFrameworkPluginOptions { register: any; options: any; @@ -82,22 +84,19 @@ export interface InfraFrameworkPluginOptions { export interface InfraFrameworkRouteOptions< RouteRequest extends InfraWrappableRequest, - RouteResponse + RouteResponse extends InfraResponse > { path: string; method: string | string[]; vhost?: string; handler: InfraFrameworkRouteHandler; - config?: Pick< - IRouteAdditionalConfigurationOptions, - Exclude - >; + options?: Pick>; } export type InfraFrameworkRouteHandler< RouteRequest extends InfraWrappableRequest, - RouteResponse -> = (request: InfraFrameworkRequest, reply: IStrictReply) => void; + RouteResponse extends InfraResponse +> = (request: InfraFrameworkRequest, h: ResponseToolkit) => RouteResponse; export interface InfraDatabaseResponse { took: number; diff --git a/x-pack/plugins/infra/server/lib/adapters/framework/apollo_server_hapi.ts b/x-pack/plugins/infra/server/lib/adapters/framework/apollo_server_hapi.ts index 9277a9619fc4e8..da858217468f17 100644 --- a/x-pack/plugins/infra/server/lib/adapters/framework/apollo_server_hapi.ts +++ b/x-pack/plugins/infra/server/lib/adapters/framework/apollo_server_hapi.ts @@ -6,60 +6,59 @@ import * as GraphiQL from 'apollo-server-module-graphiql'; import Boom from 'boom'; -import { IReply, Request, Server } from 'hapi'; +import { Plugin, Request, ResponseToolkit, RouteOptions, Server } from 'hapi'; import { GraphQLOptions, runHttpQuery } from 'apollo-server-core'; -export interface IRegister { - (server: Server, options: any, next: () => void): void; - attributes: { - name: string; - version?: string; - }; -} - -export type HapiOptionsFunction = (req?: Request) => GraphQLOptions | Promise; +export type HapiOptionsFunction = (req: Request) => GraphQLOptions | Promise; -export interface HapiPluginOptions { +export interface HapiGraphQLPluginOptions { path: string; vhost?: string; - route?: any; + route?: RouteOptions; graphqlOptions: GraphQLOptions | HapiOptionsFunction; } -export const graphqlHapi: IRegister = Object.assign( - (server: Server, options: HapiPluginOptions, next: () => void) => { +export const graphqlHapi: Plugin = { + name: 'graphql', + register: (server: Server, options: HapiGraphQLPluginOptions) => { if (!options || !options.graphqlOptions) { throw new Error('Apollo Server requires options.'); } server.route({ - config: options.route || {}, - handler: async (request: Request, reply: IReply) => { + options: options.route || {}, + handler: async (request: Request, h: ResponseToolkit) => { try { + const query = + request.method === 'post' + ? (request.payload as Record) + : (request.query as Record); + const gqlResponse = await runHttpQuery([request], { method: request.method.toUpperCase(), options: options.graphqlOptions, - query: request.method === 'post' ? request.payload : request.query, + query, }); - return reply(gqlResponse).type('application/json'); + return h.response(gqlResponse).type('application/json'); } catch (error) { if ('HttpQueryError' !== error.name) { - const queryError = Boom.wrap(error); + const queryError = Boom.boomify(error); queryError.output.payload.message = error.message; - return reply(queryError); + return queryError; } if (error.isGraphQLError === true) { - return reply(error.message) + return h + .response(error.message) .code(error.statusCode) .type('application/json'); } - const genericError = Boom.create(error.statusCode, error.message); + const genericError = new Boom(error.message, { statusCode: error.statusCode }); if (error.headers) { Object.keys(error.headers).forEach(header => { @@ -78,15 +77,8 @@ export const graphqlHapi: IRegister = Object.assign( path: options.path || '/graphql', vhost: options.vhost || undefined, }); - - return next(); }, - { - attributes: { - name: 'graphql', - }, - } -); +}; export type HapiGraphiQLOptionsFunction = ( req?: Request @@ -100,30 +92,26 @@ export interface HapiGraphiQLPluginOptions { graphiqlOptions: GraphiQL.GraphiQLData | HapiGraphiQLOptionsFunction; } -export const graphiqlHapi: IRegister = Object.assign( - (server: Server, options: HapiGraphiQLPluginOptions) => { +export const graphiqlHapi: Plugin = { + name: 'graphiql', + register: (server: Server, options: HapiGraphiQLPluginOptions) => { if (!options || !options.graphiqlOptions) { throw new Error('Apollo Server GraphiQL requires options.'); } server.route({ - config: options.route || {}, - handler: async (request: Request, reply: IReply) => { + options: options.route || {}, + handler: async (request: Request, h: ResponseToolkit) => { const graphiqlString = await GraphiQL.resolveGraphiQLString( request.query, options.graphiqlOptions, request ); - return reply(graphiqlString).type('text/html'); + return h.response(graphiqlString).type('text/html'); }, method: 'GET', path: options.path || '/graphiql', }); }, - { - attributes: { - name: 'graphiql', - }, - } -); +}; diff --git a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts index c8e97c89911c8c..034ce7f66a7686 100644 --- a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts @@ -5,7 +5,7 @@ */ import { GraphQLSchema } from 'graphql'; -import { IStrictReply, Request, Server } from 'hapi'; +import { Request, ResponseToolkit, Server } from 'hapi'; import { InfraMetricModel } from '../metrics/adapter_types'; import { @@ -13,11 +13,24 @@ import { InfraFrameworkIndexPatternsService, InfraFrameworkRequest, InfraFrameworkRouteOptions, + InfraResponse, InfraTSVBResponse, InfraWrappableRequest, internalInfraFrameworkRequest, } from './adapter_types'; -import { graphiqlHapi, graphqlHapi } from './apollo_server_hapi'; +import { + graphiqlHapi, + graphqlHapi, + HapiGraphiQLPluginOptions, + HapiGraphQLPluginOptions, +} from './apollo_server_hapi'; + +declare module 'hapi' { + interface PluginProperties { + elasticsearch: any; + kibana: any; + } +} export class InfraKibanaBackendFrameworkAdapter implements InfraBackendFrameworkAdapter { public version: string; @@ -41,7 +54,7 @@ export class InfraKibanaBackendFrameworkAdapter implements InfraBackendFramework } public registerGraphQLEndpoint(routePath: string, schema: GraphQLSchema): void { - this.server.register({ + this.server.register({ options: { graphqlOptions: (req: Request) => ({ context: { req: wrapRequest(req) }, @@ -49,10 +62,10 @@ export class InfraKibanaBackendFrameworkAdapter implements InfraBackendFramework }), path: routePath, }, - register: graphqlHapi, + plugin: graphqlHapi, }); - this.server.register({ + this.server.register({ options: { graphiqlOptions: { endpointURL: routePath, @@ -60,15 +73,16 @@ export class InfraKibanaBackendFrameworkAdapter implements InfraBackendFramework }, path: `${routePath}/graphiql`, }, - register: graphiqlHapi, + plugin: graphiqlHapi, }); } - public registerRoute( - route: InfraFrameworkRouteOptions - ) { - const wrappedHandler = (request: any, reply: IStrictReply) => - route.handler(wrapRequest(request), reply); + public registerRoute< + RouteRequest extends InfraWrappableRequest, + RouteResponse extends InfraResponse + >(route: InfraFrameworkRouteOptions) { + const wrappedHandler = (request: any, h: ResponseToolkit) => + route.handler(wrapRequest(request), h); this.server.route({ handler: wrappedHandler, @@ -112,24 +126,23 @@ export class InfraKibanaBackendFrameworkAdapter implements InfraBackendFramework ) { const internalRequest = req[internalInfraFrameworkRequest]; const server = internalRequest.server; - return new Promise((resolve, reject) => { - const request = { - url: '/api/metrics/vis/data', - method: 'POST', - headers: internalRequest.headers, - payload: { - timerange, - panels: [model], - filters, - }, - }; - server.inject(request, res => { - if (res.statusCode !== 200) { - return reject(res); - } - resolve(res.result); - }); - }); + const request = { + url: '/api/metrics/vis/data', + method: 'POST', + headers: internalRequest.headers, + payload: { + timerange, + panels: [model], + filters, + }, + }; + + const res = await server.inject(request); + if (res.statusCode !== 200) { + throw res; + } + + return res.result as InfraTSVBResponse; } } diff --git a/x-pack/plugins/infra/server/logging_legacy/adjacent_search_results.ts b/x-pack/plugins/infra/server/logging_legacy/adjacent_search_results.ts index 58ad2743fa5ddf..7d757329b7ca79 100644 --- a/x-pack/plugins/infra/server/logging_legacy/adjacent_search_results.ts +++ b/x-pack/plugins/infra/server/logging_legacy/adjacent_search_results.ts @@ -32,9 +32,9 @@ export const initAdjacentSearchResultsRoutes = (framework: InfraBackendFramework framework.registerRoute< InfraWrappableRequest, - AdjacentSearchResultsApiPostResponse + Promise >({ - config: { + options: { validate: { payload: Joi.object().keys({ after: Joi.number() @@ -50,7 +50,7 @@ export const initAdjacentSearchResultsRoutes = (framework: InfraBackendFramework }), }, }, - handler: async (request, reply) => { + handler: async (request, h) => { const timings = { esRequestSent: Date.now(), esResponseProcessed: 0, @@ -92,15 +92,15 @@ export const initAdjacentSearchResultsRoutes = (framework: InfraBackendFramework timings.esResponseProcessed = Date.now(); - return reply({ + return { results: { after: searchResultsAfterTarget, before: searchResultsBeforeTarget, }, timings, - }); + }; } catch (requestError) { - return reply(Boom.wrap(requestError)); + throw Boom.boomify(requestError); } }, method: 'POST', diff --git a/x-pack/plugins/infra/server/logging_legacy/contained_search_results.ts b/x-pack/plugins/infra/server/logging_legacy/contained_search_results.ts index d53d731cd293ff..dbd8b1f4202dd4 100644 --- a/x-pack/plugins/infra/server/logging_legacy/contained_search_results.ts +++ b/x-pack/plugins/infra/server/logging_legacy/contained_search_results.ts @@ -28,9 +28,9 @@ export const initContainedSearchResultsRoutes = (framework: InfraBackendFramewor framework.registerRoute< InfraWrappableRequest, - ContainedSearchResultsApiPostResponse + Promise >({ - config: { + options: { validate: { payload: Joi.object().keys({ end: logEntryTimeSchema.required(), @@ -41,7 +41,7 @@ export const initContainedSearchResultsRoutes = (framework: InfraBackendFramewor }), }, }, - handler: async (request, reply) => { + handler: async request => { const timings = { esRequestSent: Date.now(), esResponseProcessed: 0, @@ -62,12 +62,12 @@ export const initContainedSearchResultsRoutes = (framework: InfraBackendFramewor timings.esResponseProcessed = Date.now(); - return reply({ + return { results: searchResults, timings, - }); + }; } catch (requestError) { - return reply(Boom.wrap(requestError)); + throw Boom.boomify(requestError); } }, method: 'POST', diff --git a/x-pack/plugins/infra/server/logging_legacy/search_summary.ts b/x-pack/plugins/infra/server/logging_legacy/search_summary.ts index 161dc7ea90a75f..b51d4d4cabbb04 100644 --- a/x-pack/plugins/infra/server/logging_legacy/search_summary.ts +++ b/x-pack/plugins/infra/server/logging_legacy/search_summary.ts @@ -31,9 +31,9 @@ export const initSearchSummaryRoutes = (framework: InfraBackendFrameworkAdapter) framework.registerRoute< InfraWrappableRequest, - SearchSummaryApiPostResponse + Promise >({ - config: { + options: { validate: { payload: Joi.object().keys({ bucketSize: summaryBucketSizeSchema.required(), @@ -45,7 +45,7 @@ export const initSearchSummaryRoutes = (framework: InfraBackendFrameworkAdapter) }), }, }, - handler: async (request, reply) => { + handler: async request => { const timings = { esRequestSent: Date.now(), esResponseProcessed: 0, @@ -66,12 +66,12 @@ export const initSearchSummaryRoutes = (framework: InfraBackendFrameworkAdapter) timings.esResponseProcessed = Date.now(); - return reply({ + return { buckets: summaryBuckets, timings, - }); + }; } catch (requestError) { - return reply(Boom.wrap(requestError)); + throw Boom.boomify(requestError); } }, method: 'POST', diff --git a/x-pack/plugins/infra/yarn.lock b/x-pack/plugins/infra/yarn.lock index b054aeb5441b41..389330fd046776 100644 --- a/x-pack/plugins/infra/yarn.lock +++ b/x-pack/plugins/infra/yarn.lock @@ -2,12 +2,10 @@ # yarn lockfile v1 -"@types/boom@3.2.2": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@types/boom/-/boom-3.2.2.tgz#6773bb1bbfec111f5ea683874b8d932157d58885" - integrity sha512-Wbgg2JXCnlEMWB2faZgT8x1MPPgzqqLBWx1zXXWGPDQDo9CcvQkIW89QqY+yekoXIKI+qW/eZsg/gv6+WNFwEg== - dependencies: - "@types/node" "*" +"@types/boom@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/boom/-/boom-7.2.0.tgz#19c36cbb5811a7493f0f2e37f31d42b28df1abc1" + integrity sha512-HonbGsHFbskh9zRAzA6tabcw18mCOsSEOL2ibGAuVqk6e7nElcRmWO5L4UfIHpDbWBWw+eZYFdsQ1+MEGgpcVA== "@types/color-convert@*": version "1.9.0" @@ -33,11 +31,6 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.116.tgz#5ccf215653e3e8c786a58390751033a9adca0eb9" integrity sha512-lRnAtKnxMXcYYXqOiotTmJd74uawNWuPnsnPrrO7HiFuE3npE2iQhfABatbYDyxTNqZNuXzcKGhw37R7RjBFLg== -"@types/node@*": - version "10.11.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.11.4.tgz#e8bd933c3f78795d580ae41d86590bfc1f4f389d" - integrity sha512-ojnbBiKkZFYRfQpmtnnWTMw+rzGp/JiystjluW9jgN3VzRwilXddJ6aGQ9V/7iuDG06SBgn7ozW9k3zcAnYjYQ== - boom@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/boom/-/boom-3.1.1.tgz#b6424f01ed8d492b2b12ae86047c24e8b6a7c937" diff --git a/x-pack/plugins/license_management/server/lib/wrap_es_error.js b/x-pack/plugins/license_management/server/lib/wrap_es_error.js index 5dfe29fcdad11c..2e639f9912b6d5 100644 --- a/x-pack/plugins/license_management/server/lib/wrap_es_error.js +++ b/x-pack/plugins/license_management/server/lib/wrap_es_error.js @@ -16,7 +16,7 @@ import Boom from 'boom'; export function wrapEsError(err) { const statusCode = err.statusCode; if (statusCode === 403) { - return Boom.forbidden('Insufficient user permissions for adding a license.'); + throw Boom.forbidden('Insufficient user permissions for adding a license.'); } - return Boom.boomify(err, err.statusCode); + throw Boom.boomify(err, err.statusCode); } diff --git a/x-pack/plugins/license_management/server/routes/api/license/register_license_route.js b/x-pack/plugins/license_management/server/routes/api/license/register_license_route.js index f311d72ed10e85..e70e61ab07e6be 100644 --- a/x-pack/plugins/license_management/server/routes/api/license/register_license_route.js +++ b/x-pack/plugins/license_management/server/routes/api/license/register_license_route.js @@ -12,9 +12,9 @@ export function registerLicenseRoute(server) { server.route({ path: '/api/license', method: 'PUT', - handler: (request, reply) => { + handler: (request) => { return putLicense(request, xpackInfo) - .then(reply, e => reply(wrapEsError(e))); + .catch(e => wrapEsError(e)); } }); } diff --git a/x-pack/plugins/license_management/server/routes/api/license/register_start_basic_route.js b/x-pack/plugins/license_management/server/routes/api/license/register_start_basic_route.js index 2f4400a4155e4b..0dbe46ca106f2b 100644 --- a/x-pack/plugins/license_management/server/routes/api/license/register_start_basic_route.js +++ b/x-pack/plugins/license_management/server/routes/api/license/register_start_basic_route.js @@ -12,9 +12,9 @@ export function registerStartBasicRoute(server) { server.route({ path: '/api/license/start_basic', method: 'POST', - handler: (request, reply) => { + handler: (request) => { return startBasic(request, xpackInfo) - .then(reply, e => reply(wrapEsError(e))); + .catch(e => wrapEsError(e)); } }); } diff --git a/x-pack/plugins/license_management/server/routes/api/license/register_start_trial_routes.js b/x-pack/plugins/license_management/server/routes/api/license/register_start_trial_routes.js index ef20cfdf5b9f07..43b3ffef9c301c 100644 --- a/x-pack/plugins/license_management/server/routes/api/license/register_start_trial_routes.js +++ b/x-pack/plugins/license_management/server/routes/api/license/register_start_trial_routes.js @@ -12,17 +12,17 @@ export function registerStartTrialRoutes(server) { server.route({ path: '/api/license/start_trial', method: 'GET', - handler: (request, reply) => { + handler: (request) => { return canStartTrial(request) - .then(reply, e => reply(wrapEsError(e))); + .catch(e => wrapEsError(e)); } }); server.route({ path: '/api/license/start_trial', method: 'POST', - handler: (request, reply) => { + handler: (request) => { return startTrial(request, xpackInfo) - .then(reply, e => reply(wrapEsError(e))); + .catch(e => wrapEsError(e)); } }); } diff --git a/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js b/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js index 890a366ac65c1e..3295113d38ee5a 100755 --- a/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js +++ b/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js @@ -14,5 +14,5 @@ import Boom from 'boom'; * @return Object Boom error response */ export function wrapCustomError(err, statusCode) { - return Boom.wrap(err, statusCode); + return Boom.boomify(err, { statusCode }); } diff --git a/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js b/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js index 3673de6470bb99..112efc6749ae1a 100755 --- a/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js +++ b/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js @@ -18,5 +18,5 @@ export function wrapEsError(err) { if (statusCode === 403) { return Boom.forbidden('Insufficient user permissions for managing Logstash pipelines'); } - return Boom.wrap(err, err.statusCode); + return Boom.boomify(err, { statusCode: err.statusCode }); } diff --git a/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js b/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js index b0cdced7adbefe..ffd915c5133626 100755 --- a/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js +++ b/x-pack/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js @@ -13,5 +13,5 @@ import Boom from 'boom'; * @return Object Boom error response */ export function wrapUnknownError(err) { - return Boom.wrap(err); + return Boom.boomify(err); } diff --git a/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index c543d79814dd3d..c63eef750bee9f 100755 --- a/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -40,14 +40,13 @@ describe('license_pre_routing_factory', () => { }; }); - it ('replies with 403', (done) => { + it ('replies with 403', () => { const licensePreRouting = licensePreRoutingFactory(mockServer); const stubRequest = {}; - licensePreRouting(stubRequest, (response) => { + expect(() => licensePreRouting(stubRequest)).to.throwException((response) => { expect(response).to.be.an(Error); expect(response.isBoom).to.be(true); expect(response.output.statusCode).to.be(403); - done(); }); }); }); @@ -59,13 +58,11 @@ describe('license_pre_routing_factory', () => { }; }); - it ('replies with nothing', (done) => { + it ('replies with nothing', () => { const licensePreRouting = licensePreRoutingFactory(mockServer); const stubRequest = {}; - licensePreRouting(stubRequest, (response) => { - expect(response).to.be(undefined); - done(); - }); + const response = licensePreRouting(stubRequest); + expect(response).to.be(null); }); }); }); diff --git a/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js b/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js index 4ae31f692bfd79..862ed8a575ba5b 100755 --- a/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js +++ b/x-pack/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js @@ -12,16 +12,15 @@ export const licensePreRoutingFactory = once((server) => { const xpackMainPlugin = server.plugins.xpack_main; // License checking and enable/disable logic - function licensePreRouting(request, reply) { + function licensePreRouting() { const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults(); if (!licenseCheckResults.isAvailable) { const error = new Error(licenseCheckResults.message); const statusCode = 403; - const wrappedError = wrapCustomError(error, statusCode); - reply(wrappedError); - } else { - reply(); + throw wrapCustomError(error, statusCode); } + + return null; } return licensePreRouting; diff --git a/x-pack/plugins/logstash/server/routes/api/cluster/register_load_route.js b/x-pack/plugins/logstash/server/routes/api/cluster/register_load_route.js index 0d565f80299c51..3f6a363f424d71 100755 --- a/x-pack/plugins/logstash/server/routes/api/cluster/register_load_route.js +++ b/x-pack/plugins/logstash/server/routes/api/cluster/register_load_route.js @@ -19,16 +19,18 @@ export function registerLoadRoute(server) { server.route({ path: '/api/logstash/cluster', method: 'GET', - handler: (request, reply) => { + handler: (request, h) => { const callWithRequest = callWithRequestFactory(server, request); return fetchCluster(callWithRequest) - .then(responseFromES => reply({ cluster: Cluster.fromUpstreamJSON(responseFromES).downstreamJSON })) + .then(responseFromES => ({ + cluster: Cluster.fromUpstreamJSON(responseFromES).downstreamJSON + })) .catch((e) => { if (e.status === 403) { - return reply(); + return h.response(); } - reply(Boom.internal(e)); + throw Boom.internal(e); }); }, config: { diff --git a/x-pack/plugins/logstash/server/routes/api/pipeline/register_delete_route.js b/x-pack/plugins/logstash/server/routes/api/pipeline/register_delete_route.js index 179504d753add2..9702e35ac5152b 100755 --- a/x-pack/plugins/logstash/server/routes/api/pipeline/register_delete_route.js +++ b/x-pack/plugins/logstash/server/routes/api/pipeline/register_delete_route.js @@ -24,13 +24,13 @@ export function registerDeleteRoute(server) { server.route({ path: '/api/logstash/pipeline/{id}', method: 'DELETE', - handler: (request, reply) => { + handler: (request, h) => { const callWithRequest = callWithRequestFactory(server, request); const pipelineId = request.params.id; return deletePipeline(callWithRequest, pipelineId) - .then(() => reply().code(204)) - .catch(e => reply(wrapEsError(e))); + .then(() => h.response().code(204)) + .catch(e => wrapEsError(e)); }, config: { pre: [ licensePreRouting ] diff --git a/x-pack/plugins/logstash/server/routes/api/pipeline/register_load_route.js b/x-pack/plugins/logstash/server/routes/api/pipeline/register_load_route.js index 789ea81b193951..90e897a18eb863 100755 --- a/x-pack/plugins/logstash/server/routes/api/pipeline/register_load_route.js +++ b/x-pack/plugins/logstash/server/routes/api/pipeline/register_load_route.js @@ -31,20 +31,20 @@ export function registerLoadRoute(server) { server.route({ path: '/api/logstash/pipeline/{id}', method: 'GET', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const pipelineId = request.params.id; return fetchPipeline(callWithRequest, pipelineId) .then((pipelineResponseFromES) => { if (!pipelineResponseFromES.found) { - return reply(Boom.notFound()); + throw Boom.notFound(); } const pipeline = Pipeline.fromUpstreamJSON(pipelineResponseFromES); - reply(pipeline.downstreamJSON); + return pipeline.downstreamJSON; }) - .catch((e) => reply(Boom.internal(e))); + .catch((e) => Boom.boomify(e)); }, config: { pre: [ licensePreRouting ] diff --git a/x-pack/plugins/logstash/server/routes/api/pipeline/register_save_route.js b/x-pack/plugins/logstash/server/routes/api/pipeline/register_save_route.js index 7af9baaa122da1..235392e42620b5 100755 --- a/x-pack/plugins/logstash/server/routes/api/pipeline/register_save_route.js +++ b/x-pack/plugins/logstash/server/routes/api/pipeline/register_save_route.js @@ -27,7 +27,7 @@ export function registerSaveRoute(server) { server.route({ path: '/api/logstash/pipeline/{id}', method: 'PUT', - handler: async (request, reply) => { + handler: async (request, h) => { let username; if (server.plugins.security) { const user = await server.plugins.security.getUser(request); @@ -39,8 +39,8 @@ export function registerSaveRoute(server) { const pipeline = Pipeline.fromDownstreamJSON(request.payload, pipelineId, username); return savePipeline(callWithRequest, pipeline.id, pipeline.upstreamJSON) - .then(() => reply().code(204)) - .catch(e => reply(wrapEsError(e))); + .then(() => h.response().code(204)) + .catch(e => wrapEsError(e)); }, config: { pre: [ licensePreRouting ] diff --git a/x-pack/plugins/logstash/server/routes/api/pipelines/register_delete_route.js b/x-pack/plugins/logstash/server/routes/api/pipelines/register_delete_route.js index e0d754563ea59e..e733ae46e20f9e 100755 --- a/x-pack/plugins/logstash/server/routes/api/pipelines/register_delete_route.js +++ b/x-pack/plugins/logstash/server/routes/api/pipelines/register_delete_route.js @@ -39,16 +39,12 @@ export function registerDeleteRoute(server) { server.route({ path: '/api/logstash/pipelines', method: 'DELETE', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); return deletePipelines(callWithRequest, request.payload.pipelineIds) - .then(results => { - reply({ results }); - }) - .catch(err => { - reply(wrapUnknownError(err)); - }); + .then(results => ({ results })) + .catch(err => wrapUnknownError(err)); }, config: { pre: [ licensePreRouting ] diff --git a/x-pack/plugins/logstash/server/routes/api/pipelines/register_list_route.js b/x-pack/plugins/logstash/server/routes/api/pipelines/register_list_route.js index f942e2080be6ed..6d9eab891276c0 100755 --- a/x-pack/plugins/logstash/server/routes/api/pipelines/register_list_route.js +++ b/x-pack/plugins/logstash/server/routes/api/pipelines/register_list_route.js @@ -31,7 +31,7 @@ export function registerListRoute(server) { server.route({ path: '/api/logstash/pipelines', method: 'GET', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); return fetchPipelines(callWithRequest) @@ -41,10 +41,9 @@ export function registerListRoute(server) { return PipelineListItem.fromUpstreamJSON(pipeline).downstreamJSON; }); - reply({ pipelines }); - + return { pipelines }; }) - .catch(e => reply(wrapEsError(e))); + .catch(e => wrapEsError(e)); }, config: { pre: [ licensePreRouting ] diff --git a/x-pack/plugins/logstash/server/routes/api/upgrade/register_execute_route.js b/x-pack/plugins/logstash/server/routes/api/upgrade/register_execute_route.js index 843525e28375c9..7bdeb136576cb3 100755 --- a/x-pack/plugins/logstash/server/routes/api/upgrade/register_execute_route.js +++ b/x-pack/plugins/logstash/server/routes/api/upgrade/register_execute_route.js @@ -42,13 +42,13 @@ export function registerExecuteRoute(server) { server.route({ path: '/api/logstash/upgrade', method: 'POST', - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); try { await executeUpgrade(callWithRequest); - reply({ is_upgraded: true }); + return { is_upgraded: true }; } catch(err) { - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); } }, config: { diff --git a/x-pack/plugins/ml/index.js b/x-pack/plugins/ml/index.js index 1ed1a591b93476..c84bf9d56eb5bd 100644 --- a/x-pack/plugins/ml/index.js +++ b/x-pack/plugins/ml/index.js @@ -66,12 +66,12 @@ export const ml = (kibana) => { // Add server routes and initialize the plugin here const commonRouteConfig = { pre: [ - function forbidApiAccess(request, reply) { + function forbidApiAccess() { const licenseCheckResults = xpackMainPlugin.info.feature(thisPlugin.id).getLicenseCheckResults(); if (licenseCheckResults.isAvailable) { - reply(); + return null; } else { - reply(Boom.forbidden(licenseCheckResults.message)); + throw Boom.forbidden(licenseCheckResults.message); } } ] diff --git a/x-pack/plugins/ml/public/file_datavisualizer/components/import_view/importer/sst_importer.js b/x-pack/plugins/ml/public/file_datavisualizer/components/import_view/importer/sst_importer.js index d2132715e47957..43acb19a387a85 100644 --- a/x-pack/plugins/ml/public/file_datavisualizer/components/import_view/importer/sst_importer.js +++ b/x-pack/plugins/ml/public/file_datavisualizer/components/import_view/importer/sst_importer.js @@ -32,16 +32,11 @@ export class SstImporter extends Importer { const char = text[i]; if (char === '\n') { if (line.match(this.multilineStartPattern) !== null) { - // the line buffer matches the start of a new message. - // so push the last message to the list and clear the variable. data.push({ message }); message = ''; } else { - // looks like this \n char is in the middle of a field. - // so add the \n to end of the last message and keep going. message += char; } - // move the line buffer to the message variable and clear the buffer message += line; line = ''; } else { @@ -49,29 +44,11 @@ export class SstImporter extends Importer { } } - // add the last message to the list + // add the last line of the file to the list if (message !== '') { data.push({ message }); } - // add any left over line buffer to the data - // needed in case the last line does not end with a \n character. - // note, this could be a partial message - if (line !== '') { - if (line.match(this.multilineStartPattern) !== null) { - // line starts with the multilineStartPattern, it looks like a complete line - data.push({ message: line }); - } - else { - // line looks like the end of the last message - // add it with a \n to preserve the one that - // would have been lost when the loop ended - if (data.length) { - data[data.length - 1].message += `\n${line}`; - } - } - } - // remove first line if it is blank if (data[0] && data[0].message === '') { data.shift(); diff --git a/x-pack/plugins/ml/server/client/errors.js b/x-pack/plugins/ml/server/client/errors.js index 38f3ff56bebb8a..98da148192a898 100644 --- a/x-pack/plugins/ml/server/client/errors.js +++ b/x-pack/plugins/ml/server/client/errors.js @@ -6,8 +6,8 @@ -import { wrap as wrapBoom } from 'boom'; +import { boomify } from 'boom'; export function wrapError(error) { - return wrapBoom(error, error.status); + return boomify(error, { statusCode: error.status }); } diff --git a/x-pack/plugins/ml/server/models/calendar/calendar_manager.js b/x-pack/plugins/ml/server/models/calendar/calendar_manager.js index db12e61d69f226..8b5cbf5b716f29 100644 --- a/x-pack/plugins/ml/server/models/calendar/calendar_manager.js +++ b/x-pack/plugins/ml/server/models/calendar/calendar_manager.js @@ -26,7 +26,7 @@ export class CalendarManager { calendar.events = await this.eventManager.getCalendarEvents(calendarId); return calendar; } else { - return Boom.notFound(`Calendar with the id "${calendarId}" not found`); + throw Boom.notFound(`Calendar with the id "${calendarId}" not found`); } } catch (error) { throw Boom.badRequest(error); @@ -67,7 +67,7 @@ export class CalendarManager { // return the newly created calendar return await this.getCalendar(calendarId); } catch (error) { - return Boom.badRequest(error); + throw Boom.badRequest(error); } } @@ -115,7 +115,7 @@ export class CalendarManager { })); } catch (error) { - return Boom.badRequest(error); + throw Boom.badRequest(error); } // return the updated calendar diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js index 7843ca4f0a6d8b..06d5f808165935 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js @@ -132,7 +132,7 @@ export class DataRecognizer { dirName = manifestFile.dirName; } else { - return Boom.notFound(`Module with the id "${id}" not found`); + throw Boom.notFound(`Module with the id "${id}" not found`); } const jobs = []; @@ -213,7 +213,7 @@ export class DataRecognizer { manifestFile && manifestFile.json && manifestFile.json.defaultIndexPattern === undefined) { - return Boom.badRequest(`No index pattern configured in "${moduleId}" configuration file and no index pattern passed to the endpoint`); + throw Boom.badRequest(`No index pattern configured in "${moduleId}" configuration file and no index pattern passed to the endpoint`); } this.indexPatternName = (indexPatternName === undefined) ? manifestFile.json.defaultIndexPattern : indexPatternName; this.indexPatternId = this.getIndexPatternId(this.indexPatternName); diff --git a/x-pack/plugins/ml/server/models/filter/filter_manager.js b/x-pack/plugins/ml/server/models/filter/filter_manager.js index 9912191d4acb92..82e37d53e80bfa 100644 --- a/x-pack/plugins/ml/server/models/filter/filter_manager.js +++ b/x-pack/plugins/ml/server/models/filter/filter_manager.js @@ -31,7 +31,7 @@ export class FilterManager { filter.used_by = filtersInUse[filter.filter_id]; return filter; } else { - return Boom.notFound(`Filter with the id "${filterId}" not found`); + throw Boom.notFound(`Filter with the id "${filterId}" not found`); } } catch (error) { throw Boom.badRequest(error); @@ -92,7 +92,7 @@ export class FilterManager { // Returns the newly created filter. return await this.callWithRequest('ml.addFilter', { filterId, body: filter }); } catch (error) { - return Boom.badRequest(error); + throw Boom.badRequest(error); } } @@ -118,7 +118,7 @@ export class FilterManager { body }); } catch (error) { - return Boom.badRequest(error); + throw Boom.badRequest(error); } } diff --git a/x-pack/plugins/ml/server/routes/anomaly_detectors.js b/x-pack/plugins/ml/server/routes/anomaly_detectors.js index ca112dd1c80d22..6627471a6d0b16 100644 --- a/x-pack/plugins/ml/server/routes/anomaly_detectors.js +++ b/x-pack/plugins/ml/server/routes/anomaly_detectors.js @@ -14,11 +14,10 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/anomaly_detectors', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return callWithRequest('ml.jobs') - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -28,12 +27,11 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/anomaly_detectors/{jobId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const jobId = request.params.jobId; return callWithRequest('ml.jobs', { jobId }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -43,11 +41,10 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/anomaly_detectors/_stats', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return callWithRequest('ml.jobStats') - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -57,12 +54,11 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/anomaly_detectors/{jobId}/_stats', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const jobId = request.params.jobId; return callWithRequest('ml.jobStats', { jobId }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -72,13 +68,12 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'PUT', path: '/api/ml/anomaly_detectors/{jobId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const jobId = request.params.jobId; const body = request.payload; return callWithRequest('ml.addJob', { jobId, body }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -88,13 +83,12 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/anomaly_detectors/{jobId}/_update', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const jobId = request.params.jobId; const body = request.payload; return callWithRequest('ml.updateJob', { jobId, body }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -104,12 +98,11 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/anomaly_detectors/{jobId}/_open', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const jobId = request.params.jobId; return callWithRequest('ml.openJob', { jobId }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -119,7 +112,7 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/anomaly_detectors/{jobId}/_close', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const options = { jobId: request.params.jobId @@ -129,8 +122,7 @@ export function jobRoutes(server, commonRouteConfig) { options.force = force; } return callWithRequest('ml.closeJob', options) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -140,7 +132,7 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'DELETE', path: '/api/ml/anomaly_detectors/{jobId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const options = { jobId: request.params.jobId @@ -150,8 +142,7 @@ export function jobRoutes(server, commonRouteConfig) { options.force = force; } return callWithRequest('ml.deleteJob', options) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -161,12 +152,11 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/anomaly_detectors/_validate/detector', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const body = request.payload; return callWithRequest('ml.validateDetector', { body }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -176,13 +166,12 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/anomaly_detectors/{jobId}/_forecast', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const jobId = request.params.jobId; const duration = request.payload.duration; return callWithRequest('ml.forecast', { jobId, duration }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -192,7 +181,7 @@ export function jobRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/anomaly_detectors/{jobId}/results/overall_buckets', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return callWithRequest('ml.overallBuckets', { jobId: request.params.jobId, @@ -201,8 +190,7 @@ export function jobRoutes(server, commonRouteConfig) { start: request.payload.start, end: request.payload.end }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/calendars.js b/x-pack/plugins/ml/server/routes/calendars.js index ffd4b88a27a28e..f389b528730d60 100644 --- a/x-pack/plugins/ml/server/routes/calendars.js +++ b/x-pack/plugins/ml/server/routes/calendars.js @@ -41,11 +41,10 @@ export function calendars(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/calendars', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return getAllCalendars(callWithRequest) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -55,12 +54,11 @@ export function calendars(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/calendars/{calendarId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const calendarId = request.params.calendarId; return getCalendar(callWithRequest, calendarId) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -70,12 +68,11 @@ export function calendars(server, commonRouteConfig) { server.route({ method: 'PUT', path: '/api/ml/calendars', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const body = request.payload; return newCalendar(callWithRequest, body) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -85,13 +82,12 @@ export function calendars(server, commonRouteConfig) { server.route({ method: 'PUT', path: '/api/ml/calendars/{calendarId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const calendarId = request.params.calendarId; const body = request.payload; return updateCalendar(callWithRequest, calendarId, body) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -101,12 +97,11 @@ export function calendars(server, commonRouteConfig) { server.route({ method: 'DELETE', path: '/api/ml/calendars/{calendarId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const calendarId = request.params.calendarId; return deleteCalendar(callWithRequest, calendarId) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/data_visualizer.js b/x-pack/plugins/ml/server/routes/data_visualizer.js index 7168cac43492bf..a8c3e026f6e779 100644 --- a/x-pack/plugins/ml/server/routes/data_visualizer.js +++ b/x-pack/plugins/ml/server/routes/data_visualizer.js @@ -65,7 +65,7 @@ export function dataVisualizerRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/data_visualizer/get_field_stats/{indexPatternTitle}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const indexPatternTitle = request.params.indexPatternTitle; const payload = request.payload; @@ -80,8 +80,7 @@ export function dataVisualizerRoutes(server, commonRouteConfig) { payload.latest, payload.interval, payload.maxExamples) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -91,7 +90,7 @@ export function dataVisualizerRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/data_visualizer/get_overall_stats/{indexPatternTitle}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const indexPatternTitle = request.params.indexPatternTitle; const payload = request.payload; @@ -105,8 +104,7 @@ export function dataVisualizerRoutes(server, commonRouteConfig) { payload.timeFieldName, payload.earliest, payload.latest) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/datafeeds.js b/x-pack/plugins/ml/server/routes/datafeeds.js index 171b87ef209b7a..1923bf65c67633 100644 --- a/x-pack/plugins/ml/server/routes/datafeeds.js +++ b/x-pack/plugins/ml/server/routes/datafeeds.js @@ -14,11 +14,10 @@ export function dataFeedRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/datafeeds', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return callWithRequest('ml.datafeeds') - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -28,12 +27,11 @@ export function dataFeedRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/datafeeds/{datafeedId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const datafeedId = request.params.datafeedId; return callWithRequest('ml.datafeeds', { datafeedId }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -43,11 +41,10 @@ export function dataFeedRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/datafeeds/_stats', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return callWithRequest('ml.datafeedStats') - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -57,12 +54,11 @@ export function dataFeedRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/datafeeds/{datafeedId}/_stats', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const datafeedId = request.params.datafeedId; return callWithRequest('ml.datafeedStats', { datafeedId }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -72,13 +68,12 @@ export function dataFeedRoutes(server, commonRouteConfig) { server.route({ method: 'PUT', path: '/api/ml/datafeeds/{datafeedId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const datafeedId = request.params.datafeedId; const body = request.payload; return callWithRequest('ml.addDatafeed', { datafeedId, body }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -88,13 +83,12 @@ export function dataFeedRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/datafeeds/{datafeedId}/_update', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const datafeedId = request.params.datafeedId; const body = request.payload; return callWithRequest('ml.updateDatafeed', { datafeedId, body }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -104,7 +98,7 @@ export function dataFeedRoutes(server, commonRouteConfig) { server.route({ method: 'DELETE', path: '/api/ml/datafeeds/{datafeedId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const options = { datafeedId: request.params.datafeedId @@ -114,8 +108,7 @@ export function dataFeedRoutes(server, commonRouteConfig) { options.force = force; } return callWithRequest('ml.deleteDatafeed', options) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -125,14 +118,13 @@ export function dataFeedRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/datafeeds/{datafeedId}/_start', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const datafeedId = request.params.datafeedId; const start = request.payload.start; const end = request.payload.end; return callWithRequest('ml.startDatafeed', { datafeedId, start, end }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -142,12 +134,11 @@ export function dataFeedRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/datafeeds/{datafeedId}/_stop', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const datafeedId = request.params.datafeedId; return callWithRequest('ml.stopDatafeed', { datafeedId }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -157,12 +148,11 @@ export function dataFeedRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/datafeeds/{datafeedId}/_preview', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const datafeedId = request.params.datafeedId; return callWithRequest('ml.datafeedPreview', { datafeedId }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/fields_service.js b/x-pack/plugins/ml/server/routes/fields_service.js index 5218bd48897625..4d130041ccc57e 100644 --- a/x-pack/plugins/ml/server/routes/fields_service.js +++ b/x-pack/plugins/ml/server/routes/fields_service.js @@ -48,11 +48,10 @@ export function fieldsService(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/fields_service/field_cardinality', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return getCardinalityOfFields(callWithRequest, request.payload) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -62,11 +61,10 @@ export function fieldsService(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/fields_service/time_field_range', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return getTimeFieldRange(callWithRequest, request.payload) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/file_data_visualizer.js b/x-pack/plugins/ml/server/routes/file_data_visualizer.js index 550dd88651e360..eb843d18712213 100644 --- a/x-pack/plugins/ml/server/routes/file_data_visualizer.js +++ b/x-pack/plugins/ml/server/routes/file_data_visualizer.js @@ -24,13 +24,12 @@ export function fileDataVisualizerRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/file_data_visualizer/analyze_file', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const data = request.payload; return analyzeFiles(callWithRequest, data, request.query) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(wrapError); }, config: { ...commonRouteConfig, @@ -41,14 +40,13 @@ export function fileDataVisualizerRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/file_data_visualizer/import', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { id } = request.query; const { index, data, settings, mappings, ingestPipeline } = request.payload; return importData(callWithRequest, id, index, settings, mappings, ingestPipeline, data) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(wrapError); }, config: { ...commonRouteConfig, diff --git a/x-pack/plugins/ml/server/routes/filters.js b/x-pack/plugins/ml/server/routes/filters.js index 5aedaf334d8498..517b498353d099 100644 --- a/x-pack/plugins/ml/server/routes/filters.js +++ b/x-pack/plugins/ml/server/routes/filters.js @@ -53,11 +53,10 @@ export function filtersRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/filters', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return getAllFilters(callWithRequest) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -67,11 +66,10 @@ export function filtersRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/filters/_stats', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return getAllFilterStats(callWithRequest) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -81,12 +79,11 @@ export function filtersRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/filters/{filterId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const filterId = request.params.filterId; return getFilter(callWithRequest, filterId) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -96,12 +93,11 @@ export function filtersRoutes(server, commonRouteConfig) { server.route({ method: 'PUT', path: '/api/ml/filters', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const body = request.payload; return newFilter(callWithRequest, body) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -111,7 +107,7 @@ export function filtersRoutes(server, commonRouteConfig) { server.route({ method: 'PUT', path: '/api/ml/filters/{filterId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const filterId = request.params.filterId; const payload = request.payload; @@ -121,8 +117,7 @@ export function filtersRoutes(server, commonRouteConfig) { payload.description, payload.addItems, payload.removeItems) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -132,12 +127,11 @@ export function filtersRoutes(server, commonRouteConfig) { server.route({ method: 'DELETE', path: '/api/ml/filters/{filterId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const filterId = request.params.filterId; return deleteFilter(callWithRequest, filterId) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/indices.js b/x-pack/plugins/ml/server/routes/indices.js index 2b697a3dc729c4..899713d42a15ee 100644 --- a/x-pack/plugins/ml/server/routes/indices.js +++ b/x-pack/plugins/ml/server/routes/indices.js @@ -14,7 +14,7 @@ export function indicesRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/indices/field_caps', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const index = request.payload.index; let fields = '*'; @@ -23,8 +23,7 @@ export function indicesRoutes(server, commonRouteConfig) { } return callWithRequest('fieldCaps', { index, fields }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/job_audit_messages.js b/x-pack/plugins/ml/server/routes/job_audit_messages.js index b420d707f34f08..c0573fdf893b45 100644 --- a/x-pack/plugins/ml/server/routes/job_audit_messages.js +++ b/x-pack/plugins/ml/server/routes/job_audit_messages.js @@ -14,14 +14,13 @@ export function jobAuditMessagesRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/job_audit_messages/messages/{jobId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { getJobAuditMessages } = jobAuditMessagesProvider(callWithRequest); const { jobId } = request.params; const from = request.query.from; return getJobAuditMessages(jobId, from) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -31,13 +30,12 @@ export function jobAuditMessagesRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/job_audit_messages/messages', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { getJobAuditMessages } = jobAuditMessagesProvider(callWithRequest); const from = request.query.from; return getJobAuditMessages(undefined, from) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -47,12 +45,11 @@ export function jobAuditMessagesRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/job_audit_messages/summary', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { getAuditMessagesSummary } = jobAuditMessagesProvider(callWithRequest); return getAuditMessagesSummary() - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/job_service.js b/x-pack/plugins/ml/server/routes/job_service.js index 1d1319f5c96271..024bd03999a190 100644 --- a/x-pack/plugins/ml/server/routes/job_service.js +++ b/x-pack/plugins/ml/server/routes/job_service.js @@ -14,7 +14,7 @@ export function jobServiceRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/jobs/force_start_datafeeds', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { forceStartDatafeeds } = jobServiceProvider(callWithRequest); const { @@ -23,8 +23,7 @@ export function jobServiceRoutes(server, commonRouteConfig) { end } = request.payload; return forceStartDatafeeds(datafeedIds, start, end) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -34,13 +33,12 @@ export function jobServiceRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/jobs/stop_datafeeds', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { stopDatafeeds } = jobServiceProvider(callWithRequest); const { datafeedIds } = request.payload; return stopDatafeeds(datafeedIds) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -50,13 +48,12 @@ export function jobServiceRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/jobs/delete_jobs', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { deleteJobs } = jobServiceProvider(callWithRequest); const { jobIds } = request.payload; return deleteJobs(jobIds) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -66,13 +63,12 @@ export function jobServiceRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/jobs/close_jobs', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { closeJobs } = jobServiceProvider(callWithRequest); const { jobIds } = request.payload; return closeJobs(jobIds) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -82,13 +78,12 @@ export function jobServiceRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/jobs/jobs_summary', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { jobsSummary } = jobServiceProvider(callWithRequest); const { jobIds } = request.payload; return jobsSummary(jobIds) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -98,13 +93,12 @@ export function jobServiceRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/jobs/jobs', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { createFullJobsList } = jobServiceProvider(callWithRequest); const { jobIds } = request.payload; return createFullJobsList(jobIds) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -114,12 +108,11 @@ export function jobServiceRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/jobs/groups', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { getAllGroups } = jobServiceProvider(callWithRequest); return getAllGroups() - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -129,13 +122,12 @@ export function jobServiceRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/jobs/update_groups', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const { updateGroups } = jobServiceProvider(callWithRequest); const { jobs } = request.payload; return updateGroups(jobs) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/job_validation.js b/x-pack/plugins/ml/server/routes/job_validation.js index 3b0b335539efdd..dd25f7a39dacbc 100644 --- a/x-pack/plugins/ml/server/routes/job_validation.js +++ b/x-pack/plugins/ml/server/routes/job_validation.js @@ -41,22 +41,19 @@ export function jobValidationRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/validate/estimate_bucket_span', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); try { return estimateBucketSpanFactory(callWithRequest, server)(request.payload) - .then(reply) // this catch gets triggered when the estimation code runs without error // but isn't able to come up with a bucket span estimation. // this doesn't return a HTTP error but an object with an error message // which the client is then handling. triggering a HTTP error would be // too severe for this case. - .catch((resp) => { - reply({ - error: true, - message: resp - }); - }); + .catch((resp) => ({ + error: true, + message: resp + })); // this catch gets triggered when an actual error gets thrown when running // the estimation code, for example when the request payload is malformed } catch(error) { @@ -71,13 +68,10 @@ export function jobValidationRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/validate/calculate_model_memory_limit', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return calculateModelMemoryLimit(callWithRequest, request.payload) - .then(reply) - .catch((resp) => { - reply(wrapError(resp)); - }); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -87,15 +81,12 @@ export function jobValidationRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/validate/job', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); // pkg.branch corresponds to the version used in documentation links. const version = server.config().get('pkg.branch'); return validateJob(callWithRequest, request.payload, version, server) - .then(reply) - .catch((resp) => { - reply(wrapError(resp)); - }); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/modules.js b/x-pack/plugins/ml/server/routes/modules.js index bae0e4b6fcbcbe..94c6e5919e4d9e 100644 --- a/x-pack/plugins/ml/server/routes/modules.js +++ b/x-pack/plugins/ml/server/routes/modules.js @@ -51,12 +51,11 @@ export function dataRecognizer(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/modules/recognize/{indexPatternTitle}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const indexPatternTitle = request.params.indexPatternTitle; return recognize(callWithRequest, indexPatternTitle) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -66,12 +65,11 @@ export function dataRecognizer(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/modules/get_module/{moduleId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const moduleId = request.params.moduleId; return getModule(callWithRequest, moduleId) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -81,7 +79,7 @@ export function dataRecognizer(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/modules/setup/{moduleId}', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const moduleId = request.params.moduleId; @@ -107,8 +105,7 @@ export function dataRecognizer(server, commonRouteConfig) { end, request ) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/notification_settings.js b/x-pack/plugins/ml/server/routes/notification_settings.js index c772bc67842d9e..5ebf08b2055d97 100644 --- a/x-pack/plugins/ml/server/routes/notification_settings.js +++ b/x-pack/plugins/ml/server/routes/notification_settings.js @@ -14,15 +14,14 @@ export function notificationRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/notification_settings', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); const params = { includeDefaults: true, filterPath: '**.xpack.notification' }; return callWithRequest('cluster.getSettings', params) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/results_service.js b/x-pack/plugins/ml/server/routes/results_service.js index 07f261a07e0f1e..145563d85f89b2 100644 --- a/x-pack/plugins/ml/server/routes/results_service.js +++ b/x-pack/plugins/ml/server/routes/results_service.js @@ -59,11 +59,10 @@ export function resultsServiceRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/results/anomalies_table_data', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return getAnomaliesTableData(callWithRequest, request.payload) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -73,11 +72,10 @@ export function resultsServiceRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/results/category_definition', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return getCategoryDefinition(callWithRequest, request.payload) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -87,11 +85,10 @@ export function resultsServiceRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/results/category_examples', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return getCategoryExamples(callWithRequest, request.payload) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/ml/server/routes/system.js b/x-pack/plugins/ml/server/routes/system.js index 02abc8e08e7d94..e723defdabf01c 100644 --- a/x-pack/plugins/ml/server/routes/system.js +++ b/x-pack/plugins/ml/server/routes/system.js @@ -39,7 +39,7 @@ export function systemRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/_has_privileges', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); // isSecurityDisabled will return true if it is a basic license // this will cause the subsequent ml.privilegeCheck to fail. @@ -48,12 +48,11 @@ export function systemRoutes(server, commonRouteConfig) { if (isBasicLicense(server) || isSecurityDisabled(server)) { // if xpack.security.enabled has been explicitly set to false // return that security is disabled and don't call the privilegeCheck endpoint - reply({ securityDisabled: true }); + return { securityDisabled: true }; } else { const body = request.payload; return callWithRequest('ml.privilegeCheck', { body }) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); } }, config: { @@ -64,7 +63,7 @@ export function systemRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/ml_node_count', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return new Promise((resolve, reject) => { // check for basic license first for consistency with other @@ -105,8 +104,7 @@ export function systemRoutes(server, commonRouteConfig) { .catch(reject); } }) - .then(resp => reply(resp)) - .catch(error => reply(wrapError(error))); + .catch(error => wrapError(error)); }, config: { ...commonRouteConfig @@ -116,11 +114,10 @@ export function systemRoutes(server, commonRouteConfig) { server.route({ method: 'GET', path: '/api/ml/info', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return callWithRequest('ml.info') - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig @@ -130,11 +127,10 @@ export function systemRoutes(server, commonRouteConfig) { server.route({ method: 'POST', path: '/api/ml/es_search', - handler(request, reply) { + handler(request) { const callWithRequest = callWithRequestFactory(server, request); return callWithRequest('search', request.payload) - .then(resp => reply(resp)) - .catch(resp => reply(wrapError(resp))); + .catch(resp => wrapError(resp)); }, config: { ...commonRouteConfig diff --git a/x-pack/plugins/monitoring/config.js b/x-pack/plugins/monitoring/config.js index 3341805910356d..7c9c52c0df1ac6 100644 --- a/x-pack/plugins/monitoring/config.js +++ b/x-pack/plugins/monitoring/config.js @@ -12,74 +12,73 @@ import { XPACK_INFO_API_DEFAULT_POLL_FREQUENCY_IN_MILLIS } from '../../server/li * @return {Object} config schema */ export const config = (Joi) => { - const { array, boolean, number, object, string } = Joi; - const DEFAULT_REQUEST_HEADERS = ['authorization']; + const DEFAULT_REQUEST_HEADERS = [ 'authorization' ]; - return object({ - ccs: object({ - enabled: boolean().default(true) + return Joi.object({ + ccs: Joi.object({ + enabled: Joi.boolean().default(true) }).default(), - enabled: boolean().default(true), - ui: object({ - enabled: boolean().default(true), - container: object({ - elasticsearch: object({ - enabled: boolean().default(false) + enabled: Joi.boolean().default(true), + ui: Joi.object({ + enabled: Joi.boolean().default(true), + container: Joi.object({ + elasticsearch: Joi.object({ + enabled: Joi.boolean().default(false) }).default(), - logstash: object({ - enabled: boolean().default(false) + logstash: Joi.object({ + enabled: Joi.boolean().default(false) }).default() }).default() }).default(), - index_pattern: string().default('.monitoring-*-2-*,.monitoring-*-6-*'), - kibana: object({ - index_pattern: string().default('.monitoring-kibana-2-*,.monitoring-kibana-6-*'), - collection: object({ - enabled: boolean().default(true), - interval: number().default(10000) // op status metrics get buffered at `ops.interval` and flushed to the bulk endpoint at this interval + index_pattern: Joi.string().default('.monitoring-*-2-*,.monitoring-*-6-*'), + kibana: Joi.object({ + index_pattern: Joi.string().default('.monitoring-kibana-2-*,.monitoring-kibana-6-*'), + collection: Joi.object({ + enabled: Joi.boolean().default(true), + interval: Joi.number().default(10000) // op status metrics get buffered at `ops.interval` and flushed to the bulk endpoint at this interval }).default() }).default(), - logstash: object({ - index_pattern: string().default('.monitoring-logstash-2-*,.monitoring-logstash-6-*') + logstash: Joi.object({ + index_pattern: Joi.string().default('.monitoring-logstash-2-*,.monitoring-logstash-6-*') }).default(), - beats: object({ - index_pattern: string().default('.monitoring-beats-6-*') + beats: Joi.object({ + index_pattern: Joi.string().default('.monitoring-beats-6-*') }).default(), - cluster_alerts: object({ - enabled: boolean().default(true), - index: string().default('.monitoring-alerts-6'), - email_notifications: object({ - enabled: boolean().default(true), - email_address: string().email(), + cluster_alerts: Joi.object({ + enabled: Joi.boolean().default(true), + index: Joi.string().default('.monitoring-alerts-6'), + email_notifications: Joi.object({ + enabled: Joi.boolean().default(true), + email_address: Joi.string().email(), }).default() }).default(), - xpack_api_polling_frequency_millis: number().default(XPACK_INFO_API_DEFAULT_POLL_FREQUENCY_IN_MILLIS), - max_bucket_size: number().default(10000), - min_interval_seconds: number().default(10), - show_license_expiration: boolean().default(true), - report_stats: boolean().default(true), - agent: object({ - interval: string().regex(/[\d\.]+[yMwdhms]/).default('10s') + xpack_api_polling_frequency_millis: Joi.number().default(XPACK_INFO_API_DEFAULT_POLL_FREQUENCY_IN_MILLIS), + max_bucket_size: Joi.number().default(10000), + min_interval_seconds: Joi.number().default(10), + show_license_expiration: Joi.boolean().default(true), + report_stats: Joi.boolean().default(true), + agent: Joi.object({ + interval: Joi.string().regex(/[\d\.]+[yMwdhms]/).default('10s') }).default(), - elasticsearch: object({ - customHeaders: object().default({}), - index_pattern: string().default('.monitoring-es-2-*,.monitoring-es-6-*'), - logQueries: boolean().default(false), - requestHeadersWhitelist: array().items().single().default(DEFAULT_REQUEST_HEADERS), - url: string().uri({ scheme: ['http', 'https'] }), // if empty, use Kibana's connection config - username: string(), - password: string(), - requestTimeout: number().default(30000), - pingTimeout: number().default(30000), - ssl: object({ - verificationMode: string().valid('none', 'certificate', 'full').default('full'), - certificateAuthorities: array().single().items(string()), - certificate: string(), - key: string(), - keyPassphrase: string(), - alwaysPresentCertificate: boolean().default(false), + elasticsearch: Joi.object({ + customHeaders: Joi.object().default({}), + index_pattern: Joi.string().default('.monitoring-es-2-*,.monitoring-es-6-*'), + logQueries: Joi.boolean().default(false), + requestHeadersWhitelist: Joi.array().items().single().default(DEFAULT_REQUEST_HEADERS), + url: Joi.string().uri({ scheme: ['http', 'https'] }), // if empty, use Kibana's connection config + username: Joi.string(), + password: Joi.string(), + requestTimeout: Joi.number().default(30000), + pingTimeout: Joi.number().default(30000), + ssl: Joi.object({ + verificationMode: Joi.string().valid('none', 'certificate', 'full').default('full'), + certificateAuthorities: Joi.array().single().items(Joi.string()), + certificate: Joi.string(), + key: Joi.string(), + keyPassphrase: Joi.string(), + alwaysPresentCertificate: Joi.boolean().default(false), }).default(), - apiVersion: string().default('master') + apiVersion: Joi.string().default('master') }).default() }).default(); }; diff --git a/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/checker_errors.test.js.snap b/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/checker_errors.test.js.snap index 249203ccc03156..5018bad3177089 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/checker_errors.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/checker_errors.test.js.snap @@ -36,7 +36,7 @@ Array [
- Error: no access for you + no access for you
{ test('should render typical boom errors from api response', () => { const err1 = forbidden(new Error('no access for you')); - const err2 = wrap(new Error('bad thing happened')); + const err2 = boomify(new Error('bad thing happened')); const errors = [err1, err2].map(err => err.output.payload); const component = render(); expect(component).toMatchSnapshot(); diff --git a/x-pack/plugins/monitoring/public/lib/elasticsearch_settings/__tests__/enabler.test.js b/x-pack/plugins/monitoring/public/lib/elasticsearch_settings/__tests__/enabler.test.js index 1874426138eb26..91db0349a27798 100644 --- a/x-pack/plugins/monitoring/public/lib/elasticsearch_settings/__tests__/enabler.test.js +++ b/x-pack/plugins/monitoring/public/lib/elasticsearch_settings/__tests__/enabler.test.js @@ -11,6 +11,7 @@ import { forbidden } from 'boom'; const updateModel = properties => properties; const updateModelSpy = sinon.spy(updateModel); + describe('Settings Enabler Class for calling API to update Elasticsearch Settings', () => { test('should return status from successfully calling API', async () => { const get$http = () => ({ @@ -54,7 +55,7 @@ describe('Settings Enabler Class for calling API to update Elasticsearch Setting expect(updateModelSpy.lastCall.args[0]).toEqual({ errors: { error: 'Forbidden', - message: 'Error: this is not available', + message: 'this is not available', statusCode: 403 }, isCollectionIntervalUpdated: false, diff --git a/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js b/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js index dd189f1a47dda2..0eadb8c176eef7 100644 --- a/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js +++ b/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js @@ -53,7 +53,9 @@ function getMockServerFromConnectionUrl(monitoringClusterUrl) { ElasticsearchClientLogging: noop } }, - on: noop, + events: { + on: noop, + }, expose: sinon.stub(), log: sinon.stub() }; diff --git a/x-pack/plugins/monitoring/server/es_client/instantiate_client.js b/x-pack/plugins/monitoring/server/es_client/instantiate_client.js index c48837b8279e5d..93aca32d74a756 100644 --- a/x-pack/plugins/monitoring/server/es_client/instantiate_client.js +++ b/x-pack/plugins/monitoring/server/es_client/instantiate_client.js @@ -42,7 +42,7 @@ export function exposeClient(server) { const esPlugin = server.plugins.elasticsearch; const cluster = esPlugin.createCluster('monitoring', config); - server.on('close', bindKey(cluster, 'close')); + server.events.on('stop', bindKey(cluster, 'close')); server.log([LOGGING_TAG, 'es-client'], `config sourced from: ${configSource} cluster (${config.url})`); } diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.js index 334164fdfd634d..0c202b1c9e3657 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.js @@ -10,31 +10,55 @@ import { KIBANA_STATS_TYPE_MONITORING, } from '../../../common/constants'; import { opsBuffer } from './ops_buffer'; +import Oppsy from 'oppsy'; +import { cloneDeep } from 'lodash'; + + +class OpsMonitor { + constructor(server, buffer, interval) { + this._buffer = buffer; + this._interval = interval; + this._oppsy = new Oppsy(server); + this._server = server; + } + + start = () => { + this._oppsy.on('ops', (event) => { + // Oppsy has a bad race condition that will modify this data before + // we ship it off to the buffer. Let's create our copy first. + event = cloneDeep(event); + // Oppsy used to provide this, but doesn't anymore. Grab it ourselves. + this._server.listener.getConnections((_, count) => { + event.concurrent_connections = count; + this._buffer.push(event); + }); + }); + + this._oppsy.on('error', console.log); + this._oppsy.start(this._interval); + }; + + stop = () => { + this._oppsy.stop(); + this._oppsy.removeAllListeners(); + }; +} + /* * Initialize a collector for Kibana Ops Stats */ -export function getOpsStatsCollector(server) { - let monitor; +export function getOpsStatsCollector(server, kbnServer) { const buffer = opsBuffer(server); - const onOps = event => buffer.push(event); - - const start = () => { - monitor = server.plugins['even-better'].monitor; - monitor.on('ops', onOps); - }; - const stop = () => { - if (monitor) { - monitor.removeListener('ops', onOps); - } - }; + const interval = kbnServer.config.get('ops.interval'); + const opsMonitor = new OpsMonitor(server, buffer, interval); /* Handle stopping / restarting the event listener if Elasticsearch stops and restarts * NOTE it is possible for the plugin status to go from red to red and * trigger handlers twice */ - server.plugins.elasticsearch.status.on('red', stop); - server.plugins.elasticsearch.status.on('green', start); + server.plugins.elasticsearch.status.on('red', opsMonitor.stop); + server.plugins.elasticsearch.status.on('green', opsMonitor.start); // `process` is a NodeJS global, and is always available without using require/import process.on('SIGHUP', () => { @@ -43,11 +67,11 @@ export function getOpsStatsCollector(server) { 'Re-initializing Kibana Monitoring due to SIGHUP' ); setTimeout(() => { - stop(); - start(); + opsMonitor.stop(); + opsMonitor.start(); server.log( ['info', LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG], - 'Re-initialized Kibana Monitoring due to SIGHUP' + 'Re-initializing Kibana Monitoring due to SIGHUP' ); }, 5 * 1000); // wait 5 seconds to avoid race condition with reloading logging configuration }); @@ -55,7 +79,7 @@ export function getOpsStatsCollector(server) { const { collectorSet } = server.usage; return collectorSet.makeStatsCollector({ type: KIBANA_STATS_TYPE_MONITORING, - init: start, + init: opsMonitor.start, fetch: async () => { return await buffer.flush(); } diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js index 7c3f381af9bf71..61b1e6a673d93a 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js @@ -27,7 +27,7 @@ const events = [ heapUsed: 318428400, external: 5172252 }, - concurrents: { '5601': 6 }, + concurrent_connections: 6, psdelay: 0.4091129992157221 }, { @@ -53,7 +53,7 @@ const events = [ heapUsed: 315669840, external: 5083177 }, - concurrents: { '5601': 6 }, + concurrent_connections: 6, psdelay: 0.6715770000591874 } ]; diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_concurrent_connections.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_concurrent_connections.js deleted file mode 100644 index a1d27e710fd5fe..00000000000000 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_concurrent_connections.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 { mapConcurrentConnections } from '../map_concurrent_connections'; -import expect from 'expect.js'; - -describe('Map concurrent connections', () => { - it('flatten ports', () => { - expect(mapConcurrentConnections({ '5600': 5 })).to.be(5); - }); - - it('combine results', () => { - expect(mapConcurrentConnections({ - '5600': 5, - '5602': 3 - })).to.be(8); - }); -}); diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/event_roller.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/event_roller.js index d03e49e829f76f..4f88bd0b75093a 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/event_roller.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/event_roller.js @@ -9,7 +9,6 @@ import moment from 'moment'; import v8 from 'v8'; import { mapRequests } from './map_requests'; import { mapResponseTimes } from './map_response_times'; -import { mapConcurrentConnections } from './map_concurrent_connections'; // rollup functions are for objects with unpredictable keys (e.g., {'200': 1, '201': 2} + {'200':2} = {'200': 3, '201': 2}) const maxRollup = partialRight(assign, (latest, prev) => max([latest, prev])); @@ -29,7 +28,7 @@ export class EventRoller { return { concurrent_connections: sum([ - mapConcurrentConnections(event.concurrents), // NOTE: incoming property is called `concurrents` and we map it to `concurrent_connections` + event.concurrent_connections, this.getFromRollup('concurrent_connections') ]), // memory/os stats use the latest event's details diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/map_concurrent_connections.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/map_concurrent_connections.js deleted file mode 100644 index f7c725e77361a1..00000000000000 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/map_concurrent_connections.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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 _ from 'lodash'; - -export function mapConcurrentConnections(concurrents) { - return _.reduce(_.values(concurrents), (result, value) => { - return result + value; - }, 0); -} diff --git a/x-pack/plugins/monitoring/server/lib/errors/handle_error.js b/x-pack/plugins/monitoring/server/lib/errors/handle_error.js index 15ac202bce6a1e..319f93d4cd1903 100644 --- a/x-pack/plugins/monitoring/server/lib/errors/handle_error.js +++ b/x-pack/plugins/monitoring/server/lib/errors/handle_error.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { wrap } from 'boom'; +import { boomify } from 'boom'; import { isKnownError, handleKnownError } from './known_errors'; import { isAuthError, handleAuthError } from './auth_errors'; import { LOGGING_TAG } from '../../../common/constants'; @@ -34,5 +34,5 @@ export function handleError(err, req) { const statusCode = err.isBoom ? err.output.statusCode : err.statusCode; // wrap the error; defaults to statusCode = 500 if statusCode is undefined - return wrap(err, statusCode, err.message); + return boomify(err, { statusCode, message: err.message }); } diff --git a/x-pack/plugins/monitoring/server/lib/errors/handle_settings_error.js b/x-pack/plugins/monitoring/server/lib/errors/handle_settings_error.js index cb6e24c03711f1..54c0c39d0b3966 100644 --- a/x-pack/plugins/monitoring/server/lib/errors/handle_settings_error.js +++ b/x-pack/plugins/monitoring/server/lib/errors/handle_settings_error.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { wrap } from 'boom'; +import { boomify } from 'boom'; export function handleSettingsError(err) { - return wrap(err, err.statusCode); + return boomify(err, { statusCode: err.statusCode }); } diff --git a/x-pack/plugins/monitoring/server/lib/errors/known_errors.js b/x-pack/plugins/monitoring/server/lib/errors/known_errors.js index 82cee95b4f4c4e..0f59a0af3f108a 100644 --- a/x-pack/plugins/monitoring/server/lib/errors/known_errors.js +++ b/x-pack/plugins/monitoring/server/lib/errors/known_errors.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { wrap } from 'boom'; +import { boomify } from 'boom'; /* * Check if the given error message is a known "safe" type of error @@ -29,5 +29,5 @@ export function isKnownError(err) { export function handleKnownError(err) { err.message = err.message + ': ' + mapTypeMessage[err.constructor.name]; - return wrap(err, KNOWN_ERROR_STATUS_CODE); + return boomify(err, { statusCode: KNOWN_ERROR_STATUS_CODE }); } diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/index.js b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/index.js index 0f402fa2e02111..d9cea7f88b322c 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/index.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/index.js @@ -31,7 +31,7 @@ export function clusterAlertsRoute(server) { }) } }, - handler(req, reply) { + handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -43,8 +43,7 @@ export function clusterAlertsRoute(server) { }; return getClusterLicense(req, esIndexPattern, clusterUuid) - .then(license => alertsClusterSearch(req, alertsIndex, { cluster_uuid: clusterUuid, license }, checkLicense, options)) - .then(reply); + .then(license => alertsClusterSearch(req, alertsIndex, { cluster_uuid: clusterUuid, license }, checkLicense, options)); } }); } diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/apm/instance.js b/x-pack/plugins/monitoring/server/routes/api/v1/apm/instance.js index ff009a3b7fb76e..7f9a79046d994a 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/apm/instance.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/apm/instance.js @@ -30,7 +30,7 @@ export function apmInstanceRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const apmUuid = req.params.apmUuid; const config = server.config(); const clusterUuid = req.params.clusterUuid; @@ -43,12 +43,12 @@ export function apmInstanceRoute(server) { getApmInfo(req, apmIndexPattern, { clusterUuid, apmUuid }), ]); - reply({ + return { metrics, apmSummary, - }); + }; } catch (err) { - reply(handleError(err, req)); + return handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/apm/instances.js b/x-pack/plugins/monitoring/server/routes/api/v1/apm/instances.js index 241d535721ec3d..ec8c3cdd8d8612 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/apm/instances.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/apm/instances.js @@ -27,7 +27,7 @@ export function apmInstancesRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -40,13 +40,12 @@ export function apmInstancesRoute(server) { getApms(req, apmIndexPattern, clusterUuid), ]); - reply({ + return { stats, apms - }); - + }; } catch (err) { - reply(handleError(err, req)); + return handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/apm/overview.js b/x-pack/plugins/monitoring/server/routes/api/v1/apm/overview.js index 098c68d9a6de33..ecad1a444f7b01 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/apm/overview.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/apm/overview.js @@ -29,7 +29,7 @@ export function apmOverviewRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -44,12 +44,12 @@ export function apmOverviewRoute(server) { getMetrics(req, apmIndexPattern, metricSet), ]); - reply({ + return { stats, metrics - }); + }; } catch (err) { - reply(handleError(err, req)); + return handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/beats/beat_detail.js b/x-pack/plugins/monitoring/server/routes/api/v1/beats/beat_detail.js index 1fb0cb6f27ec1b..7bce52319c7e98 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/beats/beat_detail.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/beats/beat_detail.js @@ -30,7 +30,7 @@ export function beatsDetailRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const clusterUuid = req.params.clusterUuid; const beatUuid = req.params.beatUuid; @@ -51,12 +51,12 @@ export function beatsDetailRoute(server) { getMetrics(req, beatsIndexPattern, metricSet, [{ term: { 'beats_stats.beat.uuid': beatUuid } }]), ]); - reply({ + return { summary, metrics, - }); + }; } catch (err) { - reply(handleError(err, req)); + throw handleError(err, req); } } diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/beats/beats.js b/x-pack/plugins/monitoring/server/routes/api/v1/beats/beats.js index 23ecfb34ec231e..f2e7a46f0278a2 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/beats/beats.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/beats/beats.js @@ -27,7 +27,7 @@ export function beatsListingRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; @@ -41,13 +41,13 @@ export function beatsListingRoute(server) { getBeats(req, beatsIndexPattern, clusterUuid), ]); - reply({ + return { stats, listing - }); + }; } catch (err) { - reply(handleError(err, req)); + throw handleError(err, req); } } diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/beats/overview.js b/x-pack/plugins/monitoring/server/routes/api/v1/beats/overview.js index ce7e5176ee2e8f..b2f0267265538a 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/beats/overview.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/beats/overview.js @@ -29,7 +29,7 @@ export function beatsOverviewRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; @@ -47,13 +47,13 @@ export function beatsOverviewRoute(server) { getMetrics(req, beatsIndexPattern, metricSet), ]); - reply({ + return { ...latest, stats, metrics - }); + }; } catch (err) { - reply(handleError(err, req)); + throw handleError(err, req); } } diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/check_access/check_access.js b/x-pack/plugins/monitoring/server/routes/api/v1/check_access/check_access.js index 69a6cff8818b25..9561b074db3ea0 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/check_access/check_access.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/check_access/check_access.js @@ -15,15 +15,15 @@ export function checkAccessRoute(server) { server.route({ method: 'GET', path: '/api/monitoring/v1/check_access', - handler: async (req, reply) => { + handler: async (req) => { const response = {}; try { await verifyMonitoringAuth(req); response.has_access = true; // response data is ignored } catch (err) { - return reply(handleError(err, req)); + throw handleError(err, req); } - return reply(response); + return response; } }); } diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/cluster/cluster.js b/x-pack/plugins/monitoring/server/routes/api/v1/cluster/cluster.js index 329dc16e5bab4e..1b0d3d83f13168 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/cluster/cluster.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/cluster/cluster.js @@ -30,7 +30,7 @@ export function clusterRoute(server) { }) } }, - handler: (req, reply) => { + handler: (req) => { const config = server.config(); const ccs = req.payload.ccs; const esIndexPattern = prefixIndexPattern(config, 'xpack.monitoring.elasticsearch.index_pattern', ccs); @@ -47,8 +47,7 @@ export function clusterRoute(server) { }; return getClustersFromRequest(req, indexPatterns, options) - .then(reply) - .catch(err => reply(handleError(err, req))); + .catch(err => handleError(err, req)); } }); } diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.js b/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.js index 315947f0344396..5d3a903ab38d71 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/cluster/clusters.js @@ -28,7 +28,7 @@ export function clustersRoute(server) { }) } }, - handler: async (req, reply) => { + handler: async (req) => { let clusters = []; // NOTE using try/catch because checkMonitoringAuth is expected to throw @@ -50,10 +50,10 @@ export function clustersRoute(server) { clusters = await getClustersFromRequest(req, indexPatterns); } catch (err) { - return reply(handleError(err, req)); + throw handleError(err, req); } - return reply(clusters); + return clusters; } }); } diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr.js index 304423c50c3f63..bd711c65ac4f01 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr.js @@ -173,7 +173,7 @@ export function ccrRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const esIndexPattern = prefixIndexPattern(config, 'xpack.monitoring.elasticsearch.index_pattern', ccs); @@ -183,8 +183,7 @@ export function ccrRoute(server) { const response = await callWithRequest(req, 'search', buildRequest(req, config, esIndexPattern)); if (!response || Object.keys(response).length === 0) { - reply({ data: [] }); - return; + return { data: [] }; } const fullStats = get(response, 'hits.hits').reduce((accum, hit) => { @@ -237,9 +236,9 @@ export function ccrRoute(server) { return accum; }, []); - reply({ data }); + return { data }; } catch(err) { - reply(handleError(err, req)); + return handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr_shard.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr_shard.js index ac07b826731126..cc8268a3599114 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr_shard.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ccr_shard.js @@ -87,7 +87,7 @@ export function ccrShardRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const index = req.params.index; const shardId = req.params.shardId; @@ -134,15 +134,15 @@ export function ccrShardRoute(server) { const stat = get(ccrResponse, 'hits.hits[0]._source.ccr_stats', {}); const oldestStat = get(ccrResponse, 'hits.hits[0].inner_hits.oldest.hits.hits[0]._source.ccr_stats', {}); - reply({ + return { metrics, stat, formattedLeader: getFormattedLeaderIndex(stat.leader_index), timestamp: get(ccrResponse, 'hits.hits[0]._source.timestamp'), oldestStat, - }); + }; } catch(err) { - reply(handleError(err, req)); + return handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/index_detail.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/index_detail.js index 8c03aadfe52116..e27ec33db86ab1 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/index_detail.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/index_detail.js @@ -37,7 +37,7 @@ export function esIndexRoute(server) { }) } }, - handler: async (req, reply) => { + handler: async (req) => { try { const config = server.config(); const ccs = req.payload.ccs; @@ -76,14 +76,14 @@ export function esIndexRoute(server) { }; } - reply({ + return { indexSummary, metrics, ...shardAllocation, - }); + }; } catch (err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/indices.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/indices.js index caaacc0470dd82..4e9d434372bae0 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/indices.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/indices.js @@ -33,7 +33,7 @@ export function esIndicesRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const { clusterUuid } = req.params; const { show_system_indices: showSystemIndices } = req.query; @@ -45,12 +45,12 @@ export function esIndicesRoute(server) { const shardStats = await getShardStats(req, esIndexPattern, clusterStats, { includeIndices: true }); const indices = await getIndices(req, esIndexPattern, showSystemIndices, shardStats); - reply({ + return { clusterStatus: getClusterStatus(clusterStats, shardStats), indices - }); + }; } catch(err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ml_jobs.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ml_jobs.js index 1272de71d5ed4d..f6387bd1fa25e5 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ml_jobs.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/ml_jobs.js @@ -30,7 +30,7 @@ export function mlJobRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -41,12 +41,12 @@ export function mlJobRoute(server) { const shardStats = await getShardStats(req, esIndexPattern, clusterStats); const rows = await getMlJobs(req, esIndexPattern); - reply({ + return { clusterStatus: getClusterStatus(clusterStats, shardStats), rows - }); + }; } catch(err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/node_detail.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/node_detail.js index c847e749613777..6f5d37930e7c19 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/node_detail.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/node_detail.js @@ -37,7 +37,7 @@ export function esNodeRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const showSystemIndices = req.payload.showSystemIndices; @@ -91,13 +91,13 @@ export function esNodeRoute(server) { }; } - reply({ + return { nodeSummary, metrics, ...shardAllocation - }); + }; } catch (err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/nodes.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/nodes.js index 56704b478b1480..7fe93e1394b219 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/nodes.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/nodes.js @@ -30,7 +30,7 @@ export function esNodesRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -42,9 +42,9 @@ export function esNodesRoute(server) { const clusterStatus = getClusterStatus(clusterStats, shardStats); const nodes = await getNodes(req, esIndexPattern, clusterStats, shardStats); - reply({ clusterStatus, nodes, }); + return { clusterStatus, nodes, }; } catch(err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/overview.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/overview.js index b4f8518fc14b74..ad1d65c67b6b09 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/overview.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/overview.js @@ -32,7 +32,7 @@ export function esOverviewRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -46,13 +46,13 @@ export function esOverviewRoute(server) { ]); const shardStats = await getShardStats(req, esIndexPattern, clusterStats); - reply({ + return { clusterStatus: getClusterStatus(clusterStats, shardStats), metrics, shardActivity - }); + }; } catch (err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/cluster.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/cluster.js index 1a59687bd0b320..e44aaba8339886 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/cluster.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/cluster.js @@ -17,12 +17,12 @@ export function clusterSettingsCheckRoute(server) { config: { validate: {} }, - async handler(req, reply) { + async handler(req) { try { const response = await checkClusterSettings(req); // needs to be try/catch to handle privilege error - reply(response); + return response; } catch (err) { - reply(handleSettingsError(err)); + throw handleSettingsError(err); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/nodes.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/nodes.js index 8ac38ed34672f0..0905423f9f7dc5 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/nodes.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/nodes.js @@ -17,12 +17,12 @@ export function nodesSettingsCheckRoute(server) { config: { validate: {} }, - async handler(req, reply) { + async handler(req) { try { const response = await checkNodesSettings(req); // needs to be try/catch to handle privilege error - reply(response); + return response; } catch (err) { - reply(handleSettingsError(err)); + throw handleSettingsError(err); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/set/collection_enabled.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/set/collection_enabled.js index d9252e68fd5bcc..bb5c617c7fe8b5 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/set/collection_enabled.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/set/collection_enabled.js @@ -17,12 +17,12 @@ export function setCollectionEnabledRoute(server) { config: { validate: {} }, - async handler(req, reply) { + async handler(req) { try { const response = await setCollectionEnabled(req); - reply(response); + return response; } catch (err) { - reply(handleSettingsError(err)); + throw handleSettingsError(err); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/set/collection_interval.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/set/collection_interval.js index 3b14af86dffc94..17279deee7eedf 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/set/collection_interval.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/set/collection_interval.js @@ -17,12 +17,12 @@ export function setCollectionIntervalRoute(server) { config: { validate: {} }, - async handler(req, reply) { + async handler(req) { try { const response = await setCollectionInterval(req); - reply(response); + return response; } catch (err) { - reply(handleSettingsError(err)); + throw handleSettingsError(err); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/kibana/instance.js b/x-pack/plugins/monitoring/server/routes/api/v1/kibana/instance.js index 83a0de0c041142..6486ea530d53f6 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/kibana/instance.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/kibana/instance.js @@ -36,7 +36,7 @@ export function kibanaInstanceRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -49,12 +49,12 @@ export function kibanaInstanceRoute(server) { getKibanaInfo(req, kbnIndexPattern, { clusterUuid, kibanaUuid }), ]); - reply({ + return { metrics, kibanaSummary, - }); + }; } catch (err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/kibana/instances.js b/x-pack/plugins/monitoring/server/routes/api/v1/kibana/instances.js index 416f6dc62a8110..580172ecd7ecea 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/kibana/instances.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/kibana/instances.js @@ -31,7 +31,7 @@ export function kibanaInstancesRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -43,12 +43,12 @@ export function kibanaInstancesRoute(server) { getKibanas(req, kbnIndexPattern, { clusterUuid }), ]); - reply({ + return { clusterStatus, kibanas, - }); + }; } catch(err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/kibana/overview.js b/x-pack/plugins/monitoring/server/routes/api/v1/kibana/overview.js index d0b43a733bde7e..b7f396eef138fb 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/kibana/overview.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/kibana/overview.js @@ -32,7 +32,7 @@ export function kibanaOverviewRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -44,12 +44,12 @@ export function kibanaOverviewRoute(server) { getMetrics(req, kbnIndexPattern, metricSet), ]); - reply({ + return { clusterStatus, metrics, - }); + }; } catch(err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/node.js b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/node.js index 2879693360f6ba..6916fa871e810b 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/node.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/node.js @@ -46,7 +46,7 @@ export function logstashNodeRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -74,12 +74,12 @@ export function logstashNodeRoute(server) { getNodeInfo(req, lsIndexPattern, { clusterUuid, logstashUuid }), ]); - reply({ + return { metrics, nodeSummary, - }); + }; } catch(err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/nodes.js b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/nodes.js index 29ce593f8e0793..109094f4a475fb 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/nodes.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/nodes.js @@ -42,7 +42,7 @@ export function logstashNodesRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -54,13 +54,13 @@ export function logstashNodesRoute(server) { getNodes(req, lsIndexPattern, { clusterUuid }), ]); - reply({ + return { clusterStatus, nodes, - }); + }; } catch (err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/overview.js b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/overview.js index 09ed653631aec0..35fe0271a1885e 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/overview.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/overview.js @@ -42,7 +42,7 @@ export function logstashOverviewRoute(server) { }) } }, - async handler(req, reply) { + async handler(req) { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; @@ -54,12 +54,12 @@ export function logstashOverviewRoute(server) { getClusterStatus(req, lsIndexPattern, { clusterUuid }) ]); - reply({ + return { metrics, clusterStatus, - }); + }; } catch(err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js index 49b968323da104..3a93dd57a98182 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js @@ -37,18 +37,18 @@ export function logstashPipelineRoute(server) { }) } }, - handler: (req, reply) => { + handler: (req) => { const config = server.config(); const ccs = req.payload.ccs; const clusterUuid = req.params.clusterUuid; const lsIndexPattern = prefixIndexPattern(config, 'xpack.monitoring.logstash.index_pattern', ccs); const pipelineId = req.params.pipelineId; - const pipelineHash = req.params.pipelineHash; + // Optional params default to empty string, set to null to be more explicit. + const pipelineHash = req.params.pipelineHash || null; return getPipeline(req, config, lsIndexPattern, clusterUuid, pipelineId, pipelineHash) - .then(reply) - .catch(err => reply(handleError(err, req))); + .catch(err => handleError(err, req)); } }); } diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipelines/cluster_pipelines.js b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipelines/cluster_pipelines.js index a0d6c7c416878a..5a90e4ec9e9dc3 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipelines/cluster_pipelines.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipelines/cluster_pipelines.js @@ -31,7 +31,7 @@ export function logstashClusterPipelinesRoute(server) { }) } }, - handler: async (req, reply) => { + handler: async (req) => { const config = server.config(); const { ccs } = req.payload; const clusterUuid = req.params.clusterUuid; @@ -54,9 +54,9 @@ export function logstashClusterPipelinesRoute(server) { throughputMetric, nodesCountMetric ); - reply(response); + return response; } catch (err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipelines/node_pipelines.js b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipelines/node_pipelines.js index c4d1baf1d82870..8aace30bb61f31 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipelines/node_pipelines.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipelines/node_pipelines.js @@ -32,7 +32,7 @@ export function logstashNodePipelinesRoute(server) { }) } }, - handler: async (req, reply) => { + handler: async (req) => { const config = server.config(); const { ccs } = req.payload; const { clusterUuid, logstashUuid } = req.params; @@ -53,9 +53,9 @@ export function logstashNodePipelinesRoute(server) { throughputMetric, nodesCountMetric ); - reply(response); + return response; } catch (err) { - reply(handleError(err, req)); + throw handleError(err, req); } } }); diff --git a/x-pack/plugins/notifications/config.js b/x-pack/plugins/notifications/config.js index 9234e6ee5f2259..996db49542646c 100644 --- a/x-pack/plugins/notifications/config.js +++ b/x-pack/plugins/notifications/config.js @@ -11,42 +11,40 @@ * @return {Object} config schema */ export const config = (Joi) => { - const { array, boolean, number, object, string } = Joi; - - return object({ - enabled: boolean().default(true), - email: object({ - enabled: boolean().default(false), - smtp: object({ - host: string().default('localhost'), - port: number().default(25), - require_tls: boolean().default(false), - pool: boolean().default(false), - auth: object({ - username: string(), - password: string() + return Joi.object({ + enabled: Joi.boolean().default(true), + email: Joi.object({ + enabled: Joi.boolean().default(false), + smtp: Joi.object({ + host: Joi.string().default('localhost'), + port: Joi.number().default(25), + require_tls: Joi.boolean().default(false), + pool: Joi.boolean().default(false), + auth: Joi.object({ + username: Joi.string(), + password: Joi.string() }).default(), }).default(), - defaults: object({ - from: string(), - to: array().single().items(string()), - cc: array().single().items(string()), - bcc: array().single().items(string()), + defaults: Joi.object({ + from: Joi.string(), + to: Joi.array().single().items(Joi.string()), + cc: Joi.array().single().items(Joi.string()), + bcc: Joi.array().single().items(Joi.string()), }).default(), }).default(), - slack: object({ - enabled: boolean().default(false), - token: string().required(), - defaults: object({ - channel: string(), - as_user: boolean().default(false), - icon_emoji: string(), - icon_url: string(), - link_names: boolean().default(true), - mrkdwn: boolean().default(true), - unfurl_links: boolean().default(true), - unfurl_media: boolean().default(true), - username: string(), + slack: Joi.object({ + enabled: Joi.boolean().default(false), + token: Joi.string().required(), + defaults: Joi.object({ + channel: Joi.string(), + as_user: Joi.boolean().default(false), + icon_emoji: Joi.string(), + icon_url: Joi.string(), + link_names: Joi.boolean().default(true), + mrkdwn: Joi.boolean().default(true), + unfurl_links: Joi.boolean().default(true), + unfurl_media: Joi.boolean().default(true), + username: Joi.string(), }).default(), }) }).default(); diff --git a/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.js b/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.js index ad11190729ef3f..88934583d500e2 100644 --- a/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.js +++ b/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.js @@ -5,7 +5,7 @@ */ import Joi from 'joi'; -import { wrap } from 'boom'; +import { boomify } from 'boom'; /** * Check the incoming request parameters to see if the action should be allowed to fire. @@ -55,27 +55,26 @@ export function checkForErrors(action, actionId, data) { * @param {NotificationService} notificationService The notification service singleton. * @param {String} actionId The specified action's ID. * @param {Function} data The notification data to send via the specified action. - * @param {Function} reply The response function from the server route. * @param {Function} _checkForErrors Exposed for testing. */ -export async function sendNotification(server, notificationService, actionId, data, reply, { _checkForErrors = checkForErrors } = { }) { +export async function sendNotification(server, notificationService, actionId, data, { _checkForErrors = checkForErrors } = { }) { const action = notificationService.getActionForId(actionId); const error = _checkForErrors(action, actionId, data); if (error === null) { return action.performAction(data) - .then(result => reply(result.toJson())) - .catch(err => reply(wrap(err))); // by API definition, this should never happen as performAction isn't allow to throw errrors + .then(result => result.toJson()) + .catch(err => boomify(err)); // by API definition, this should never happen as performAction isn't allow to throw errrors } server.log(['actions', 'error'], error.message); - reply({ + return { status_code: 400, ok: false, message: `Error: ${error.message}`, error, - }); + }; } /** @@ -98,11 +97,11 @@ export function notificationServiceSendRoute(server, notificationService) { }) } }, - handler: (req, reply) => { + handler: (req) => { const actionId = req.payload.action; const data = req.payload.data; - sendNotification(server, notificationService, actionId, data, reply); + sendNotification(server, notificationService, actionId, data); }, }); } diff --git a/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.test.js b/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.test.js index 55e272b38ce4a8..0a50ef9cc1ba4b 100644 --- a/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.test.js +++ b/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.test.js @@ -5,7 +5,7 @@ */ import { checkForErrors, sendNotification } from './notify'; -import { wrap } from 'boom'; +import { boomify } from 'boom'; describe('notifications/routes/send', () => { @@ -96,9 +96,8 @@ describe('notifications/routes/send', () => { getActionForId: jest.fn().mockReturnValue(action), }; const checkForErrors = jest.fn().mockReturnValue(error); - const reply = jest.fn(); - await sendNotification(server, notificationService, id, notification, reply, { _checkForErrors: checkForErrors }); + const sendResponse = await sendNotification(server, notificationService, id, notification, { _checkForErrors: checkForErrors }); expect(notificationService.getActionForId).toHaveBeenCalledTimes(1); expect(notificationService.getActionForId).toHaveBeenCalledWith(id); @@ -107,8 +106,7 @@ describe('notifications/routes/send', () => { expect(server.log).toHaveBeenCalledTimes(1); expect(server.log).toHaveBeenCalledWith(['actions', 'error'], error.message); - expect(reply).toHaveBeenCalledTimes(1); - expect(reply).toHaveBeenCalledWith({ + expect(sendResponse).toEqual({ status_code: 400, ok: false, message: `Error: ${error.message}`, @@ -129,17 +127,15 @@ describe('notifications/routes/send', () => { getActionForId: jest.fn().mockReturnValue(action), }; const checkForErrors = jest.fn().mockReturnValue(null); - const reply = jest.fn(); - await sendNotification(server, notificationService, id, notification, reply, { _checkForErrors: checkForErrors }); + const sendResponse = await sendNotification(server, notificationService, id, notification, { _checkForErrors: checkForErrors }); expect(notificationService.getActionForId).toHaveBeenCalledTimes(1); expect(notificationService.getActionForId).toHaveBeenCalledWith(id); expect(checkForErrors).toHaveBeenCalledTimes(1); expect(checkForErrors).toHaveBeenCalledWith(action, id, notification); - expect(reply).toHaveBeenCalledTimes(1); - expect(reply).toHaveBeenCalledWith(response); + expect(sendResponse).toEqual(response); }); it('replies with unexpected result error', async () => { @@ -152,17 +148,15 @@ describe('notifications/routes/send', () => { getActionForId: jest.fn().mockReturnValue(action), }; const checkForErrors = jest.fn().mockReturnValue(null); - const reply = jest.fn(); - await sendNotification(server, notificationService, id, notification, reply, { _checkForErrors: checkForErrors }); + const sendResponse = await sendNotification(server, notificationService, id, notification, { _checkForErrors: checkForErrors }); expect(notificationService.getActionForId).toHaveBeenCalledTimes(1); expect(notificationService.getActionForId).toHaveBeenCalledWith(id); expect(checkForErrors).toHaveBeenCalledTimes(1); expect(checkForErrors).toHaveBeenCalledWith(action, id, notification); - expect(reply).toHaveBeenCalledTimes(1); - expect(reply).toHaveBeenCalledWith(wrap(error)); + expect(sendResponse).toEqual(boomify(error)); }); }); diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/hit_iterator.js b/x-pack/plugins/reporting/export_types/csv/server/lib/hit_iterator.js index a16173b61a4319..364f161bc778a2 100644 --- a/x-pack/plugins/reporting/export_types/csv/server/lib/hit_iterator.js +++ b/x-pack/plugins/reporting/export_types/csv/server/lib/hit_iterator.js @@ -61,5 +61,3 @@ export function createHitIterator(logger) { } }; } - - diff --git a/x-pack/plugins/reporting/server/lib/__tests__/authorized_user_pre_routing.js b/x-pack/plugins/reporting/server/lib/__tests__/authorized_user_pre_routing.js index 665de2068a4916..3c5d044212d1ff 100644 --- a/x-pack/plugins/reporting/server/lib/__tests__/authorized_user_pre_routing.js +++ b/x-pack/plugins/reporting/server/lib/__tests__/authorized_user_pre_routing.js @@ -64,94 +64,74 @@ describe('authorized_user_pre_routing', function () { }()); - it('should reply with boom notFound when xpackInfo is undefined', async function () { + it('should return with boom notFound when xpackInfo is undefined', async function () { const mockServer = createMockServer({ xpackInfoUndefined: true }); const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); - const reply = sinon.spy(); - await authorizedUserPreRouting({}, reply); - expect(reply.calledOnce).to.be(true); - const replyValue = reply.firstCall.args[0]; - expect(replyValue.isBoom).to.be(true); - expect(replyValue.output.statusCode).to.be(404); + const response = await authorizedUserPreRouting(); + expect(response.isBoom).to.be(true); + expect(response.output.statusCode).to.be(404); }); - it(`should reply with boom notFound when xpackInfo isn't available`, async function () { + it(`should return with boom notFound when xpackInfo isn't available`, async function () { const mockServer = createMockServer({ xpackInfoAvailable: false }); - const reply = sinon.spy(); const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); - await authorizedUserPreRouting({}, reply); - expect(reply.calledOnce).to.be(true); - const replyValue = reply.firstCall.args[0]; - expect(replyValue.isBoom).to.be(true); - expect(replyValue.output.statusCode).to.be(404); + const response = await authorizedUserPreRouting(); + expect(response.isBoom).to.be(true); + expect(response.output.statusCode).to.be(404); }); - it('should reply with null user when security is disabled in Elasticsearch', async function () { + it('should return with null user when security is disabled in Elasticsearch', async function () { const mockServer = createMockServer({ securityEnabled: false }); - const reply = sinon.spy(); const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); - await authorizedUserPreRouting({}, reply); - expect(reply.calledOnce).to.be(true); - expect(reply.firstCall.args[0]).to.be(null); + const response = await authorizedUserPreRouting(); + expect(response).to.be(null); }); - it('should reply with boom unauthenticated when security is enabled but no authenticated user', async function () { + it('should return with boom unauthenticated when security is enabled but no authenticated user', async function () { const mockServer = createMockServer({ user: null }); - const reply = sinon.spy(); const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); - await authorizedUserPreRouting({}, reply); - expect(reply.calledOnce).to.be(true); - const replyValue = reply.firstCall.args[0]; - expect(replyValue.isBoom).to.be(true); - expect(replyValue.output.statusCode).to.be(401); + const response = await authorizedUserPreRouting(); + expect(response.isBoom).to.be(true); + expect(response.output.statusCode).to.be(401); }); - it(`should reply with boom forbidden when security is enabled but user doesn't have allowed role`, async function () { + it(`should return with boom forbidden when security is enabled but user doesn't have allowed role`, async function () { const mockServer = createMockServer({ user: { roles: [] }, config: { 'xpack.reporting.roles.allow': ['.reporting_user'] } }); - const reply = sinon.spy(); const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); - await authorizedUserPreRouting({}, reply); - expect(reply.calledOnce).to.be(true); - const replyValue = reply.firstCall.args[0]; - expect(replyValue.isBoom).to.be(true); - expect(replyValue.output.statusCode).to.be(403); + const response = await authorizedUserPreRouting(); + expect(response.isBoom).to.be(true); + expect(response.output.statusCode).to.be(403); }); - it('should reply with user when security is enabled and user has explicitly allowed role', async function () { + it('should return with user when security is enabled and user has explicitly allowed role', async function () { const user = { roles: ['.reporting_user', 'something_else'] }; const mockServer = createMockServer({ user, config: { 'xpack.reporting.roles.allow': ['.reporting_user'] } }); - const reply = sinon.spy(); const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); - await authorizedUserPreRouting({}, reply); - expect(reply.calledOnce).to.be(true); - const replyValue = reply.firstCall.args[0]; - expect(replyValue).to.be(user); + const response = await authorizedUserPreRouting(); + expect(response).to.be(user); }); - it('should reply with user when security is enabled and user has superuser role', async function () { + it('should return with user when security is enabled and user has superuser role', async function () { const user = { roles: ['superuser', 'something_else'] }; const mockServer = createMockServer({ user, config: { 'xpack.reporting.roles.allow': [] } }); - const reply = sinon.spy(); const authorizedUserPreRouting = authorizedUserPreRoutingFactory(mockServer); - await authorizedUserPreRouting({}, reply); - expect(reply.calledOnce).to.be(true); - const replyValue = reply.firstCall.args[0]; - expect(replyValue).to.be(user); + const response = await authorizedUserPreRouting(); + expect(response).to.be(user); }); }); diff --git a/x-pack/plugins/reporting/server/lib/authorized_user_pre_routing.js b/x-pack/plugins/reporting/server/lib/authorized_user_pre_routing.js index 9755cf92b87c94..bace2e39105aab 100644 --- a/x-pack/plugins/reporting/server/lib/authorized_user_pre_routing.js +++ b/x-pack/plugins/reporting/server/lib/authorized_user_pre_routing.js @@ -14,31 +14,31 @@ function authorizedUserPreRoutingFn(server) { const getUser = getUserFactory(server); const config = server.config(); - return async function authorizedUserPreRouting(request, reply) { + return async function authorizedUserPreRouting(request) { const xpackInfo = server.plugins.xpack_main.info; if (!xpackInfo || !xpackInfo.isAvailable()) { server.log(['reporting', 'authorizedUserPreRouting', 'debug'], 'Unable to authorize user before xpack info is available.'); - return reply(boom.notFound()); + return boom.notFound(); } const security = xpackInfo.feature('security'); if (!security.isEnabled() || !security.isAvailable()) { - return reply(null); + return null; } const user = await getUser(request); if (!user) { - return reply(boom.unauthorized(`Sorry, you aren't authenticated`)); + return boom.unauthorized(`Sorry, you aren't authenticated`); } const authorizedRoles = [ superuserRole, ...config.get('xpack.reporting.roles.allow') ]; if(!user.roles.find(role => authorizedRoles.includes(role))) { - return reply(boom.forbidden(`Sorry, you don't have access to Reporting`)); + return boom.forbidden(`Sorry, you don't have access to Reporting`); } - reply(user); + return user; }; } diff --git a/x-pack/plugins/reporting/server/lib/job_response_handler.js b/x-pack/plugins/reporting/server/lib/job_response_handler.js index 1357e9ff3a295e..05f9313583a35e 100644 --- a/x-pack/plugins/reporting/server/lib/job_response_handler.js +++ b/x-pack/plugins/reporting/server/lib/job_response_handler.js @@ -14,26 +14,26 @@ function jobResponseHandlerFn(server) { const jobsQuery = jobsQueryFactory(server); const getDocumentPayload = getDocumentPayloadFactory(server); - return function jobResponseHandler(validJobTypes, user, reply, params, opts = {}) { + return function jobResponseHandler(validJobTypes, user, h, params, opts = {}) { const { docId } = params; return jobsQuery.get(user, docId, { includeContent: !opts.excludeContent }) .then((doc) => { - if (!doc) return reply(boom.notFound()); + if (!doc) return boom.notFound(); const { jobtype: jobType } = doc._source; if (!validJobTypes.includes(jobType)) { - return reply(boom.unauthorized(`Sorry, you are not authorized to download ${jobType} reports`)); + return boom.unauthorized(`Sorry, you are not authorized to download ${jobType} reports`); } const output = getDocumentPayload(doc); if (!WHITELISTED_JOB_CONTENT_TYPES.includes(output.contentType)) { - return reply(boom.badImplementation(`Unsupported content-type of ${output.contentType} specified by job output`)); + return boom.badImplementation(`Unsupported content-type of ${output.contentType} specified by job output`); } - const response = reply(output.content); - response.type(output.contentType); - response.code(output.statusCode); + const response = h.response(output.content) + .type(output.contentType) + .code(output.statusCode); if (output.headers) { Object.keys(output.headers).forEach(key => { diff --git a/x-pack/plugins/reporting/server/lib/reporting_feature_pre_routing.js b/x-pack/plugins/reporting/server/lib/reporting_feature_pre_routing.js index bc534e10e5764f..5a2d2a6213ef9a 100644 --- a/x-pack/plugins/reporting/server/lib/reporting_feature_pre_routing.js +++ b/x-pack/plugins/reporting/server/lib/reporting_feature_pre_routing.js @@ -13,14 +13,14 @@ function reportingFeaturePreRoutingFn(server) { // License checking and enable/disable logic return function reportingFeaturePreRouting(getReportingFeatureId) { - return function licensePreRouting(request, reply) { + return function licensePreRouting(request) { const licenseCheckResults = xpackMainPlugin.info.feature(pluginId).getLicenseCheckResults(); const reportingFeatureId = getReportingFeatureId(request); const reportingFeature = licenseCheckResults[reportingFeatureId]; if (!reportingFeature.showLinks || !reportingFeature.enableLinks) { - reply(Boom.forbidden(reportingFeature.message)); + throw Boom.forbidden(reportingFeature.message); } else { - reply(reportingFeature); + return reportingFeature; } }; }; diff --git a/x-pack/plugins/reporting/server/routes/jobs.js b/x-pack/plugins/reporting/server/routes/jobs.js index acc529b017c9a8..49bbb80e111829 100644 --- a/x-pack/plugins/reporting/server/routes/jobs.js +++ b/x-pack/plugins/reporting/server/routes/jobs.js @@ -35,13 +35,13 @@ export function jobs(server) { server.route({ path: `${mainEntry}/list`, method: 'GET', - handler: (request, reply) => { + handler: (request) => { const page = parseInt(request.query.page) || 0; const size = Math.min(100, parseInt(request.query.size) || 10); const jobIds = request.query.ids ? request.query.ids.split(',') : null; const results = jobsQuery.list(request.pre.management.jobTypes, request.pre.user, page, size, jobIds); - reply(results); + return results; }, config: getRouteConfig(), }); @@ -50,9 +50,9 @@ export function jobs(server) { server.route({ path: `${mainEntry}/count`, method: 'GET', - handler: (request, reply) => { + handler: (request) => { const results = jobsQuery.count(request.pre.management.jobTypes, request.pre.user); - reply(results); + return results; }, config: getRouteConfig(), }); @@ -61,21 +61,21 @@ export function jobs(server) { server.route({ path: `${mainEntry}/output/{docId}`, method: 'GET', - handler: (request, reply) => { + handler: (request) => { const { docId } = request.params; jobsQuery.get(request.pre.user, docId, { includeContent: true }) .then((doc) => { if (!doc) { - return reply(boom.notFound()); + return boom.notFound(); } const { jobtype: jobType } = doc._source; if (!request.pre.management.jobTypes.includes(jobType)) { - return reply(boom.unauthorized(`Sorry, you are not authorized to download ${jobType} reports`)); + return boom.unauthorized(`Sorry, you are not authorized to download ${jobType} reports`); } - reply(doc._source.output); + return doc._source.output; }); }, config: getRouteConfig(), @@ -90,13 +90,15 @@ export function jobs(server) { server.route({ path: `${mainEntry}/download/{docId}`, method: 'GET', - handler: async (request, reply) => { + handler: async (request, h) => { const { docId } = request.params; - const response = await jobResponseHandler(request.pre.management.jobTypes, request.pre.user, reply, { docId }); + let response = await jobResponseHandler(request.pre.management.jobTypes, request.pre.user, h, { docId }); if (!response.isBoom) { - response.header('accept-ranges', 'none'); + response = response.header('accept-ranges', 'none'); } + + return response; }, config: { ...getRouteConfig(), diff --git a/x-pack/plugins/reporting/server/routes/jobs.test.js b/x-pack/plugins/reporting/server/routes/jobs.test.js index 1b2bbefae1541c..1ffa7b670d836b 100644 --- a/x-pack/plugins/reporting/server/routes/jobs.test.js +++ b/x-pack/plugins/reporting/server/routes/jobs.test.js @@ -10,12 +10,12 @@ import { jobs } from './jobs'; import { ExportTypesRegistry } from '../../common/export_types_registry'; jest.mock('../lib/authorized_user_pre_routing', () => { return { - authorizedUserPreRoutingFactory: () => (request, reply) => reply({}) + authorizedUserPreRoutingFactory: () => () => ({}) }; }); jest.mock('../lib/reporting_feature_pre_routing', () => { return { - reportingFeaturePreRoutingFactory: () => () => (request, reply) => reply({ jobTypes: ['unencodedJobType', 'base64EncodedJobType'] }) + reportingFeaturePreRoutingFactory: () => () => () => ({ jobTypes: ['unencodedJobType', 'base64EncodedJobType'] }) }; }); @@ -23,8 +23,7 @@ jest.mock('../lib/reporting_feature_pre_routing', () => { let mockServer; beforeEach(() => { - mockServer = new Hapi.Server({ debug: false }); - mockServer.connection({ port: 8080 }); + mockServer = new Hapi.Server({ debug: false, port: 8080, routes: { log: { collect: true } } }); mockServer.config = memoize(() => ({ get: jest.fn() })); const exportTypesRegistry = new ExportTypesRegistry(); exportTypesRegistry.register({ @@ -71,7 +70,8 @@ test(`returns 404 if job not found`, async () => { url: '/api/reporting/jobs/download/1' }; - const { statusCode } = await mockServer.inject(request); + const response = await mockServer.inject(request); + const { statusCode } = response; expect(statusCode).toBe(404); }); @@ -240,12 +240,11 @@ describe(`when job is completed`, () => { }); test(`logs error message about invalid content type`, async () => { - const { request } = await getCompletedResponse({ outputContentType: 'application/html' }); - const logs = request.getLog(); + const { request: { logs } } = await getCompletedResponse({ outputContentType: 'application/html' }); const errorLogs = logs.filter(log => difference(['internal', 'implementation', 'error'], log.tags).length === 0); expect(errorLogs).toHaveLength(1); - expect(errorLogs[0].data).toBeInstanceOf(Error); - expect(errorLogs[0].data.message).toMatch(/Unsupported content-type of application\/html/); + expect(errorLogs[0].error).toBeInstanceOf(Error); + expect(errorLogs[0].error.message).toMatch(/Unsupported content-type of application\/html/); }); }); }); diff --git a/x-pack/plugins/reporting/server/routes/main.js b/x-pack/plugins/reporting/server/routes/main.js index 553d505d315713..05364d834af2c6 100644 --- a/x-pack/plugins/reporting/server/routes/main.js +++ b/x-pack/plugins/reporting/server/routes/main.js @@ -44,10 +44,10 @@ export function main(server) { server.route({ path: `${mainEntry}/{p*}`, method: 'GET', - handler: (request, reply) => { + handler: () => { const err = boom.methodNotAllowed('GET is not allowed'); err.output.headers.allow = 'POST'; - reply(err); + return err; }, config: getRouteConfig(), }); @@ -57,7 +57,7 @@ export function main(server) { server.route({ path: path, method: 'POST', - handler: async (request, reply) => { + handler: async (request, h) => { const message = `The following URL is deprecated and will stop working in the next major version: ${request.url.path}`; server.log(['warning', 'reporting', 'deprecation'], message); @@ -65,13 +65,13 @@ export function main(server) { const savedObjectId = request.params.savedId; const queryString = querystring.stringify(request.query); - await handler(exportTypeId, { + return await handler(exportTypeId, { objectType, savedObjectId, queryString - }, request, reply); + }, request, h); } catch (err) { - handleError(exportTypeId, reply, err); + throw handleError(exportTypeId, err); } }, config: getStaticFeatureConfig(exportTypeId), @@ -96,19 +96,19 @@ export function main(server) { server.route({ path: `${mainEntry}/{exportType}`, method: 'POST', - handler: async (request, reply) => { + handler: async (request, h) => { const exportType = request.params.exportType; try { const jobParams = rison.decode(request.query.jobParams); - await handler(exportType, jobParams, request, reply); + return await handler(exportType, jobParams, request, h); } catch (err) { - handleError(exportType, reply, err); + throw handleError(exportType, err); } }, config: getRouteConfig(request => request.params.exportType), }); - async function handler(exportTypeId, jobParams, request, reply) { + async function handler(exportTypeId, jobParams, request, h) { const user = request.pre.user; const headers = { authorization: request.headers.authorization, @@ -120,17 +120,17 @@ export function main(server) { // return the queue's job information const jobJson = job.toJSON(); - const response = reply({ + return h.response({ path: `${DOWNLOAD_BASE_URL}/${jobJson.id}`, job: jobJson, - }); - response.type('application/json'); + }) + .type('application/json'); } - function handleError(exportType, reply, err) { - if (err instanceof esErrors['401']) return reply(boom.unauthorized(`Sorry, you aren't authenticated`)); - if (err instanceof esErrors['403']) return reply(boom.forbidden(`Sorry, you are not authorized to create ${exportType} reports`)); - if (err instanceof esErrors['404']) return reply(boom.wrap(err, 404)); - reply(err); + function handleError(exportType, err) { + if (err instanceof esErrors['401']) return boom.unauthorized(`Sorry, you aren't authenticated`); + if (err instanceof esErrors['403']) return boom.forbidden(`Sorry, you are not authorized to create ${exportType} reports`); + if (err instanceof esErrors['404']) return boom.boomify(err, { statusCode: 404 }); + return err; } } diff --git a/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_custom_error.js b/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_custom_error.js index 5a0fac8873a9a5..f6d20614062030 100644 --- a/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_custom_error.js +++ b/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_custom_error.js @@ -14,5 +14,5 @@ import Boom from 'boom'; * @return Object Boom error response */ export function wrapCustomError(err, statusCode) { - return Boom.wrap(err, statusCode); + return Boom.boomify(err, { statusCode }); } diff --git a/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_es_error.js b/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_es_error.js index 1ab865e952d108..f87de8a48d8d84 100644 --- a/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_es_error.js +++ b/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_es_error.js @@ -43,7 +43,7 @@ export function wrapEsError(err, statusCodeToMessageMap = {}) { // If no custom message if specified for the error's status code, just // wrap the error as a Boom error response and return it if (!statusCodeToMessageMap[statusCode]) { - const boomError = Boom.wrap(err, statusCode); + const boomError = Boom.boomify(err, { statusCode }); // The caused_by chain has the most information so use that if it's available. If not then // settle for the root_cause. @@ -57,5 +57,5 @@ export function wrapEsError(err, statusCodeToMessageMap = {}) { // Otherwise, use the custom message to create a Boom error response and // return it const message = statusCodeToMessageMap[statusCode]; - return Boom.create(statusCode, message); + return new Boom(message, { statusCode }); } diff --git a/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_unknown_error.js b/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_unknown_error.js index 7e6a7dd1e075c7..8527a4587d3979 100644 --- a/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_unknown_error.js +++ b/x-pack/plugins/rollup/server/lib/error_wrappers/wrap_unknown_error.js @@ -13,5 +13,5 @@ import Boom from 'boom'; * @return Object Boom error response */ export function wrapUnknownError(err) { - return Boom.wrap(err); + return Boom.boomify(err); } diff --git a/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index b72f8cc7697310..ffbbd1395a4183 100644 --- a/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -40,15 +40,12 @@ describe('license_pre_routing_factory', () => { }; }); - it ('replies with 403', (done) => { + it ('replies with 403', () => { const licensePreRouting = licensePreRoutingFactory(mockServer); - const stubRequest = {}; - licensePreRouting(stubRequest, (response) => { - expect(response).to.be.an(Error); - expect(response.isBoom).to.be(true); - expect(response.output.statusCode).to.be(403); - done(); - }); + const response = licensePreRouting(); + expect(response).to.be.an(Error); + expect(response.isBoom).to.be(true); + expect(response.output.statusCode).to.be(403); }); }); @@ -59,13 +56,10 @@ describe('license_pre_routing_factory', () => { }; }); - it ('replies with nothing', (done) => { + it ('replies with nothing', () => { const licensePreRouting = licensePreRoutingFactory(mockServer); - const stubRequest = {}; - licensePreRouting(stubRequest, (response) => { - expect(response).to.be(undefined); - done(); - }); + const response = licensePreRouting(); + expect(response).to.be(null); }); }); }); diff --git a/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/license_pre_routing_factory.js b/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/license_pre_routing_factory.js index b06e571dbe3250..35053c1ae73b47 100644 --- a/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/license_pre_routing_factory.js +++ b/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/license_pre_routing_factory.js @@ -12,15 +12,15 @@ export const licensePreRoutingFactory = once((server) => { const xpackMainPlugin = server.plugins.xpack_main; // License checking and enable/disable logic - function licensePreRouting(request, reply) { + function licensePreRouting() { const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults(); if (!licenseCheckResults.isAvailable) { const error = new Error(licenseCheckResults.message); const statusCode = 403; const wrappedError = wrapCustomError(error, statusCode); - reply(wrappedError); + return wrappedError; } else { - reply(); + return null; } } diff --git a/x-pack/plugins/rollup/server/routes/api/index_patterns.js b/x-pack/plugins/rollup/server/routes/api/index_patterns.js index c453c173b758fc..9cd64126280756 100644 --- a/x-pack/plugins/rollup/server/routes/api/index_patterns.js +++ b/x-pack/plugins/rollup/server/routes/api/index_patterns.js @@ -34,7 +34,7 @@ export function registerFieldsForWildcardRoute(server) { }).default() } }, - handler: async (request, reply) => { + handler: async (request) => { const { meta_fields: metaFields, fields, @@ -87,15 +87,15 @@ export function registerFieldsForWildcardRoute(server) { }) ); }); - return reply({ - fields: rollupFields - }); + return { + fields: rollupFields + }; } catch(err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + return wrapEsError(err); } - reply(wrapUnknownError(err)); + return wrapUnknownError(err); } } }); diff --git a/x-pack/plugins/rollup/server/routes/api/indices.js b/x-pack/plugins/rollup/server/routes/api/indices.js index 7487026da02123..8ef1a0eff114db 100644 --- a/x-pack/plugins/rollup/server/routes/api/indices.js +++ b/x-pack/plugins/rollup/server/routes/api/indices.js @@ -27,18 +27,18 @@ export function registerIndicesRoute(server) { config: { pre: [ licensePreRouting ] }, - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); try { const data = await callWithRequest('rollup.rollupIndexCapabilities', { indexPattern: '_all' }); - reply(getCapabilitiesForRollupIndices(data)); + return getCapabilitiesForRollupIndices(data); } catch(err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + return wrapEsError(err); } - reply(wrapUnknownError(err)); + return wrapUnknownError(err); } } }); @@ -55,7 +55,7 @@ export function registerIndicesRoute(server) { config: { pre: [ licensePreRouting ] }, - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); try { @@ -89,30 +89,30 @@ export function registerIndicesRoute(server) { } }); - reply({ + return { doesMatchIndices, doesMatchRollupIndices, dateFields, numericFields, keywordFields, - }); + }; } catch(err) { // 404s are still valid results. if (err.statusCode === 404) { - return reply({ + return { doesMatchIndices: false, doesMatchRollupIndices: false, dateFields: [], numericFields: [], keywordFields: [], - }); + }; } if (isEsError(err)) { - return reply(wrapEsError(err)); + return wrapEsError(err); } - reply(wrapUnknownError(err)); + wrapUnknownError(err); } } }); diff --git a/x-pack/plugins/rollup/server/routes/api/jobs.js b/x-pack/plugins/rollup/server/routes/api/jobs.js index 6233610d44fa20..8ce1e7738be743 100644 --- a/x-pack/plugins/rollup/server/routes/api/jobs.js +++ b/x-pack/plugins/rollup/server/routes/api/jobs.js @@ -18,17 +18,16 @@ export function registerJobsRoute(server) { config: { pre: [ licensePreRouting ] }, - handler: async (request, reply) => { + handler: async (request) => { try { const callWithRequest = callWithRequestFactory(server, request); - const results = await callWithRequest('rollup.jobs'); - reply(results); + return await callWithRequest('rollup.jobs'); } catch(err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + return wrapEsError(err); } - reply(wrapUnknownError(err)); + wrapUnknownError(err); } }, }); @@ -39,7 +38,7 @@ export function registerJobsRoute(server) { config: { pre: [ licensePreRouting ] }, - handler: async (request, reply) => { + handler: async (request) => { try { const { id, @@ -56,14 +55,13 @@ export function registerJobsRoute(server) { // Then request the newly created job. const results = await callWithRequest('rollup.job', { id }); - reply(results.jobs[0]); + return results.jobs[0]; } catch(err) { if (isEsError(err)) { - const boomError = wrapEsError(err); - return reply(boomError); + return wrapEsError(err); } - reply(wrapUnknownError(err)); + return wrapUnknownError(err); } }, }); @@ -74,19 +72,17 @@ export function registerJobsRoute(server) { config: { pre: [ licensePreRouting ] }, - handler: async (request, reply) => { + handler: async (request) => { try { const { jobIds } = request.payload; const callWithRequest = callWithRequestFactory(server, request); - const results = await Promise.all(jobIds.map(id => callWithRequest('rollup.startJob', { id }))); - - reply(results); + return await Promise.all(jobIds.map(id => callWithRequest('rollup.startJob', { id }))); } catch(err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + return wrapEsError(err); } - reply(wrapUnknownError(err)); + return wrapUnknownError(err); } }, }); @@ -97,19 +93,17 @@ export function registerJobsRoute(server) { config: { pre: [ licensePreRouting ] }, - handler: async (request, reply) => { + handler: async (request) => { try { const { jobIds } = request.payload; const callWithRequest = callWithRequestFactory(server, request); - const results = await Promise.all(jobIds.map(id => callWithRequest('rollup.stopJob', { id }))); - - reply(results); + return await Promise.all(jobIds.map(id => callWithRequest('rollup.stopJob', { id }))); } catch(err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + return wrapEsError(err); } - reply(wrapUnknownError(err)); + return wrapUnknownError(err); } }, }); @@ -120,19 +114,17 @@ export function registerJobsRoute(server) { config: { pre: [ licensePreRouting ] }, - handler: async (request, reply) => { + handler: async (request) => { try { const { jobIds } = request.payload; const callWithRequest = callWithRequestFactory(server, request); - const results = await Promise.all(jobIds.map(id => callWithRequest('rollup.deleteJob', { id }))); - - reply(results); + return await Promise.all(jobIds.map(id => callWithRequest('rollup.deleteJob', { id }))); } catch(err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + return wrapEsError(err); } - reply(wrapUnknownError(err)); + return wrapUnknownError(err); } }, }); diff --git a/x-pack/plugins/rollup/server/routes/api/search.js b/x-pack/plugins/rollup/server/routes/api/search.js index aa0427ddbc93d0..45cf0af0b6017a 100644 --- a/x-pack/plugins/rollup/server/routes/api/search.js +++ b/x-pack/plugins/rollup/server/routes/api/search.js @@ -19,7 +19,7 @@ export function registerSearchRoute(server) { config: { pre: [ licensePreRouting ] }, - handler: async (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); try { @@ -30,14 +30,13 @@ export function registerSearchRoute(server) { }) )); - const results = await Promise.all(requests); - reply(results); + return await Promise.all(requests); } catch(err) { if (isEsError(err)) { - return reply(wrapEsError(err)); + return wrapEsError(err); } - reply(wrapUnknownError(err)); + wrapUnknownError(err); } }, }); diff --git a/x-pack/plugins/searchprofiler/index.js b/x-pack/plugins/searchprofiler/index.js index efbe02dbc33d2d..aff28431b58ef9 100644 --- a/x-pack/plugins/searchprofiler/index.js +++ b/x-pack/plugins/searchprofiler/index.js @@ -39,12 +39,12 @@ export const searchprofiler = (kibana) => { // Add server routes and initialize the plugin here const commonRouteConfig = { pre: [ - function forbidApiAccess(request, reply) { + function forbidApiAccess() { const licenseCheckResults = xpackMainPlugin.info.feature(thisPlugin.id).getLicenseCheckResults(); if (licenseCheckResults.showAppLink && licenseCheckResults.enableAppLink) { - reply(); + return null; } else { - reply(Boom.forbidden(licenseCheckResults.message)); + throw Boom.forbidden(licenseCheckResults.message); } } ] diff --git a/x-pack/plugins/searchprofiler/server/routes/profile.js b/x-pack/plugins/searchprofiler/server/routes/profile.js index 5f5fe7f6a8220e..4da247a00697d2 100644 --- a/x-pack/plugins/searchprofiler/server/routes/profile.js +++ b/x-pack/plugins/searchprofiler/server/routes/profile.js @@ -21,7 +21,7 @@ export function profileRoute(server, commonRouteConfig) { }).required() //Joi validation } }, - handler: (request, reply) => { + handler: (request) => { const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); let parsed = request.payload.query; @@ -35,15 +35,15 @@ export function profileRoute(server, commonRouteConfig) { }; callWithRequest(request, 'search', body).then((resp) => { - reply({ + return { ok: true, resp: resp - }); + }; }).catch((err) => { - reply({ + return { ok: false, err: err - }); + }; }); } }); diff --git a/x-pack/plugins/security/index.js b/x-pack/plugins/security/index.js index 4e611e1eedaec5..eddc390f8ad302 100644 --- a/x-pack/plugins/security/index.js +++ b/x-pack/plugins/security/index.js @@ -102,9 +102,11 @@ export const security = (kibana) => new kibana.Plugin({ // Create a Hapi auth scheme that should be applied to each request. server.auth.scheme('login', () => ({ authenticate: authenticateFactory(server) })); - // The `required` means that the `session` strategy that is based on `login` schema defined above will be + server.auth.strategy('session', 'login'); + + // The default means that the `session` strategy that is based on `login` schema defined above will be // automatically assigned to all routes that don't contain an auth config. - server.auth.strategy('session', 'login', 'required'); + server.auth.default('session'); // exposes server.plugins.security.authorization const authorization = createAuthorizationService(server, xpackInfoFeature); diff --git a/x-pack/plugins/security/server/lib/__tests__/__fixtures__/h.js b/x-pack/plugins/security/server/lib/__tests__/__fixtures__/h.js new file mode 100644 index 00000000000000..31355b87957549 --- /dev/null +++ b/x-pack/plugins/security/server/lib/__tests__/__fixtures__/h.js @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { stub } from 'sinon'; + +export function hFixture() { + const h = {}; + + Object.assign(h, { + authenticated: stub().returns(h), + continue: 'continue value', + redirect: stub().returns(h), + unstate: stub().returns(h), + takeover: stub().returns(h) + }); + + return h; +} diff --git a/x-pack/plugins/security/server/lib/__tests__/__fixtures__/reply.js b/x-pack/plugins/security/server/lib/__tests__/__fixtures__/reply.js deleted file mode 100644 index 19f339bf14c542..00000000000000 --- a/x-pack/plugins/security/server/lib/__tests__/__fixtures__/reply.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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 { spy } from 'sinon'; - -export function replyFixture() { - const reply = spy(); - reply.redirect = spy(); - reply.continue = spy(); - reply.unstate = spy(); - return reply; -} \ No newline at end of file diff --git a/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js b/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js index 61955452c03d7d..c511eca58ac4da 100644 --- a/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js +++ b/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js @@ -5,9 +5,10 @@ */ import Boom from 'boom'; +import expect from 'expect.js'; import sinon from 'sinon'; -import { replyFixture } from './__fixtures__/reply'; +import { hFixture } from './__fixtures__/h'; import { requestFixture } from './__fixtures__/request'; import { serverFixture } from './__fixtures__/server'; @@ -17,14 +18,14 @@ import { authenticateFactory } from '../auth_redirect'; describe('lib/auth_redirect', function () { let authenticate; let request; - let reply; + let h; let err; let credentials; let server; beforeEach(() => { request = requestFixture(); - reply = replyFixture(); + h = hFixture(); err = new Error(); credentials = {}; server = serverFixture(); @@ -44,7 +45,7 @@ describe('lib/auth_redirect', function () { Promise.resolve(AuthenticationResult.succeeded(credentials)) ); - await authenticate(request, reply); + await authenticate(request, h); sinon.assert.calledWithExactly(server.plugins.security.authenticate, request); }); @@ -54,11 +55,10 @@ describe('lib/auth_redirect', function () { Promise.resolve(AuthenticationResult.succeeded(credentials)) ); - await authenticate(request, reply); + await authenticate(request, h); - sinon.assert.calledWith(reply.continue, { credentials }); - sinon.assert.notCalled(reply.redirect); - sinon.assert.notCalled(reply); + sinon.assert.calledWith(h.authenticated, { credentials }); + sinon.assert.notCalled(h.redirect); }); it('redirects user if redirection is requested by the authenticator', async () => { @@ -66,11 +66,11 @@ describe('lib/auth_redirect', function () { Promise.resolve(AuthenticationResult.redirectTo('/some/url')) ); - await authenticate(request, reply); + await authenticate(request, h); - sinon.assert.calledWithExactly(reply.redirect, '/some/url'); - sinon.assert.notCalled(reply.continue); - sinon.assert.notCalled(reply); + sinon.assert.calledWithExactly(h.redirect, '/some/url'); + sinon.assert.called(h.takeover); + sinon.assert.notCalled(h.authenticated); }); it('returns `Internal Server Error` when `authenticate` throws unhandled exception', async () => { @@ -78,12 +78,13 @@ describe('lib/auth_redirect', function () { .withArgs(request) .returns(Promise.reject(err)); - await authenticate(request, reply); + const response = await authenticate(request, h); sinon.assert.calledWithExactly(server.log, ['error', 'authentication'], sinon.match.same(err)); - sinon.assert.calledWithExactly(reply, sinon.match((error) => error.isBoom && error.output.statusCode === 500)); - sinon.assert.notCalled(reply.redirect); - sinon.assert.notCalled(reply.continue); + expect(response.isBoom).to.be(true); + expect(response.output.statusCode).to.be(500); + sinon.assert.notCalled(h.redirect); + sinon.assert.notCalled(h.authenticated); }); it('returns wrapped original error when `authenticate` fails to authenticate user', async () => { @@ -92,16 +93,16 @@ describe('lib/auth_redirect', function () { Promise.resolve(AuthenticationResult.failed(esError)) ); - await authenticate(request, reply); + const response = await authenticate(request, h); sinon.assert.calledWithExactly( server.log, ['info', 'authentication'], 'Authentication attempt failed: some message' ); - sinon.assert.calledWithExactly(reply, esError); - sinon.assert.notCalled(reply.redirect); - sinon.assert.notCalled(reply.continue); + expect(response).to.eql(esError); + sinon.assert.notCalled(h.redirect); + sinon.assert.notCalled(h.authenticated); }); it('returns `unauthorized` when authentication can not be handled', async () => { @@ -109,37 +110,30 @@ describe('lib/auth_redirect', function () { Promise.resolve(AuthenticationResult.notHandled()) ); - await authenticate(request, reply); + const response = await authenticate(request, h); - sinon.assert.calledWithExactly( - reply, - sinon.match({ - isBoom: true, - message: 'Unauthorized', - output: { statusCode: 401 }, - }) - ); - sinon.assert.notCalled(reply.redirect); - sinon.assert.notCalled(reply.continue); + expect(response.isBoom).to.be(true); + expect(response.message).to.be('Unauthorized'); + expect(response.output.statusCode).to.be(401); + sinon.assert.notCalled(h.redirect); + sinon.assert.notCalled(h.authenticated); }); it('replies with no credentials when security is disabled in elasticsearch', async () => { server.plugins.xpack_main.info.feature.returns({ isEnabled: sinon.stub().returns(false) }); - await authenticate(request, reply); + await authenticate(request, h); - sinon.assert.calledWith(reply.continue, { credentials: {} }); - sinon.assert.notCalled(reply.redirect); - sinon.assert.notCalled(reply); + sinon.assert.calledWith(h.authenticated, { credentials: {} }); + sinon.assert.notCalled(h.redirect); }); it('replies with no credentials when license is basic', async () => { server.plugins.xpack_main.info.license.isOneOf.returns(true); - await authenticate(request, reply); + await authenticate(request, h); - sinon.assert.calledWith(reply.continue, { credentials: {} }); - sinon.assert.notCalled(reply.redirect); - sinon.assert.notCalled(reply); + sinon.assert.calledWith(h.authenticated, { credentials: {} }); + sinon.assert.notCalled(h.redirect); }); }); diff --git a/x-pack/plugins/security/server/lib/auth_redirect.js b/x-pack/plugins/security/server/lib/auth_redirect.js index 6f1896744fa484..2bb87357ec27a5 100644 --- a/x-pack/plugins/security/server/lib/auth_redirect.js +++ b/x-pack/plugins/security/server/lib/auth_redirect.js @@ -15,14 +15,13 @@ import { wrapError } from './errors'; * request that needs to be authenticated. */ export function authenticateFactory(server) { - return async function authenticate(request, reply) { + return async function authenticate(request, h) { // If security is disabled or license is basic, continue with no user credentials // and delete the client cookie as well. const xpackInfo = server.plugins.xpack_main.info; if (xpackInfo.isAvailable() && (!xpackInfo.feature('security').isEnabled() || xpackInfo.license.isOneOf('basic'))) { - reply.continue({ credentials: {} }); - return; + return h.authenticated({ credentials: {} }); } let authenticationResult; @@ -30,24 +29,23 @@ export function authenticateFactory(server) { authenticationResult = await server.plugins.security.authenticate(request); } catch(err) { server.log(['error', 'authentication'], err); - reply(wrapError(err)); - return; + return wrapError(err); } if (authenticationResult.succeeded()) { - reply.continue({ credentials: authenticationResult.user }); + return h.authenticated({ credentials: authenticationResult.user }); } else if (authenticationResult.redirected()) { // Some authentication mechanisms may require user to be redirected to another location to // initiate or complete authentication flow. It can be Kibana own login page for basic // authentication (username and password) or arbitrary external page managed by 3rd party // Identity Provider for SSO authentication mechanisms. Authentication provider is the one who // decides what location user should be redirected to. - reply.redirect(authenticationResult.redirectURL); + return h.redirect(authenticationResult.redirectURL).takeover(); } else if (authenticationResult.failed()) { server.log(['info', 'authentication'], `Authentication attempt failed: ${authenticationResult.error.message}`); - reply(wrapError(authenticationResult.error)); + return wrapError(authenticationResult.error); } else { - reply(Boom.unauthorized()); + return Boom.unauthorized(); } }; } diff --git a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js index 557a3743e75c57..d3b6f5aa15cb85 100644 --- a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js +++ b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js @@ -529,7 +529,7 @@ describe('Authenticator', () => { it('throw non-401 boom errors.', async () => { const request = requestFixture(); - const non401Error = Boom.wrap(new TypeError()); + const non401Error = Boom.boomify(new TypeError()); server.plugins.security.getUser .withArgs(request) .returns(Promise.reject(non401Error)); diff --git a/x-pack/plugins/security/server/lib/authentication/__tests__/session.js b/x-pack/plugins/security/server/lib/authentication/__tests__/session.js index 1b759bf2af2504..a03ba0ec0a4fa6 100644 --- a/x-pack/plugins/security/server/lib/authentication/__tests__/session.js +++ b/x-pack/plugins/security/server/lib/authentication/__tests__/session.js @@ -22,7 +22,6 @@ describe('Session', () => { config = { get: sinon.stub() }; server.config.returns(config); - server.register.yields(); sandbox.useFakeTimers(); }); @@ -41,13 +40,14 @@ describe('Session', () => { await Session.create(server); sinon.assert.calledOnce(server.auth.strategy); - sinon.assert.calledWithExactly(server.auth.strategy, 'security-cookie', 'cookie', false, { + sinon.assert.calledWithExactly(server.auth.strategy, 'security-cookie', 'cookie', { cookie: 'cookie-name', password: 'encryption-key', clearInvalid: true, validateFunc: sinon.match.func, isHttpOnly: true, isSecure: 'secure-cookies', + isSameSite: false, path: 'base/path/' }); }); @@ -72,9 +72,7 @@ describe('Session', () => { it('logs the reason of validation function failure.', async () => { const request = {}; const failureReason = new Error('Invalid cookie.'); - server.auth.test.withArgs('security-cookie', request, sinon.match.func).yields( - failureReason - ); + server.auth.test.withArgs('security-cookie', request).rejects(failureReason); expect(await session.get(request)).to.be(null); sinon.assert.calledOnce(server.log); @@ -84,7 +82,7 @@ describe('Session', () => { it('returns null if multiple session cookies are detected.', async () => { const request = {}; const sessions = [{ value: { token: 'token' } }, { value: { token: 'token' } }]; - server.auth.test.withArgs('security-cookie', request, sinon.match.func).yields(null, sessions); + server.auth.test.withArgs('security-cookie', request).resolves(sessions); expect(await session.get(request)).to.be(null); }); @@ -92,39 +90,31 @@ describe('Session', () => { it('returns what validation function returns', async () => { const request = {}; const rawSessionValue = { value: { token: 'token' } }; - server.auth.test.withArgs('security-cookie', request, sinon.match.func).yields( - null, rawSessionValue - ); + server.auth.test.withArgs('security-cookie', request).resolves(rawSessionValue); expect(await session.get(request)).to.be.eql(rawSessionValue.value); }); it('correctly process session expiration date', async () => { - const { validateFunc } = server.auth.strategy.firstCall.args[3]; + const { validateFunc } = server.auth.strategy.firstCall.args[2]; const currentTime = 100; sandbox.clock.tick(currentTime); - const callback = sinon.stub(); const sessionWithoutExpires = { token: 'token' }; - validateFunc({}, sessionWithoutExpires, callback); + let result = validateFunc({}, sessionWithoutExpires); - sinon.assert.calledOnce(callback); - sinon.assert.calledWithExactly(callback, null, true, sessionWithoutExpires); + expect(result.valid).to.be(true); - callback.resetHistory(); const notExpiredSession = { token: 'token', expires: currentTime + 1 }; - validateFunc({}, notExpiredSession, callback); + result = validateFunc({}, notExpiredSession); - sinon.assert.calledOnce(callback); - sinon.assert.calledWithExactly(callback, null, true, notExpiredSession); + expect(result.valid).to.be(true); - callback.resetHistory(); const expiredSession = { token: 'token', expires: currentTime - 1 }; - validateFunc({}, expiredSession, callback); + result = validateFunc({}, expiredSession); - sinon.assert.calledOnce(callback); - sinon.assert.calledWithExactly(callback, sinon.match.instanceOf(Error), false); + expect(result.valid).to.be(false); }); }); diff --git a/x-pack/plugins/security/server/lib/authentication/session.js b/x-pack/plugins/security/server/lib/authentication/session.js index 129e92ca4c98d1..e838445c4286fd 100644 --- a/x-pack/plugins/security/server/lib/authentication/session.js +++ b/x-pack/plugins/security/server/lib/authentication/session.js @@ -64,21 +64,20 @@ export class Session { async get(request) { assertRequest(request); - return new Promise((resolve) => { - this._server.auth.test(HAPI_STRATEGY_NAME, request, (err, session) => { - if (Array.isArray(session)) { - const warning = `Found ${session.length} auth sessions when we were only expecting 1.`; - this._server.log(['warning', 'security', 'auth', 'session'], warning); - return resolve(null); - } - - if (err) { - this._server.log(['debug', 'security', 'auth', 'session'], err); - } - - resolve(err ? null : session.value); - }); - }); + try { + const session = await this._server.auth.test(HAPI_STRATEGY_NAME, request); + + if (Array.isArray(session)) { + const warning = `Found ${session.length} auth sessions when we were only expecting 1.`; + this._server.log(['warning', 'security', 'auth', 'session'], warning); + return null; + } + + return session.value; + } catch (err) { + this._server.log(['debug', 'security', 'auth', 'session'], err); + return null; + } } /** @@ -151,14 +150,8 @@ export class Session { */ static async create(server) { // Register HAPI plugin that manages session cookie and delegate parsing of the session cookie to it. - await new Promise((resolve, reject) => { - server.register(hapiAuthCookie, (error) => { - if (error) { - reject(error); - } else { - resolve(); - } - }); + await server.register({ + plugin: hapiAuthCookie }); const config = server.config(); @@ -169,16 +162,24 @@ export class Session { const secure = config.get('xpack.security.secureCookies'); const ttl = config.get(`xpack.security.sessionTimeout`); - server.auth.strategy(HAPI_STRATEGY_NAME, 'cookie', HAPI_STRATEGY_MODE, { + server.auth.strategy(HAPI_STRATEGY_NAME, 'cookie', { cookie: name, password, clearInvalid: true, validateFunc: Session._validateCookie, isHttpOnly: httpOnly, isSecure: secure, + isSameSite: false, path: path, }); + if (HAPI_STRATEGY_MODE) { + server.auth.default({ + strategy: HAPI_STRATEGY_NAME, + mode: 'required' + }); + } + return new Session(server, { httpOnly, name, @@ -197,12 +198,11 @@ export class Session { * @param {function} callback Callback to be called once validation is completed. * @private */ - static _validateCookie(request, session, callback) { + static _validateCookie(request, session) { if (session.expires && session.expires < Date.now()) { - callback(new Error('Session has expired'), false /* isValid */); - return; + return { valid: false }; } - callback(null /* error */, true /* isValid */, session); + return { valid: true }; } } diff --git a/x-pack/plugins/security/server/lib/authorization/__snapshots__/check_privileges.test.js.snap b/x-pack/plugins/security/server/lib/authorization/__snapshots__/check_privileges.test.js.snap index 634600a2549d62..6a03134dc32ac3 100644 --- a/x-pack/plugins/security/server/lib/authorization/__snapshots__/check_privileges.test.js.snap +++ b/x-pack/plugins/security/server/lib/authorization/__snapshots__/check_privileges.test.js.snap @@ -2,9 +2,9 @@ exports[`#checkPrivilegesAtSpace throws error when checking for login and user has login but doesn't have version 1`] = `[Error: Multiple versions of Kibana are running against the same Elasticsearch cluster, unable to authorize user.]`; -exports[`#checkPrivilegesAtSpace with a malformed Elasticsearch response throws a validation error when an extra privilege is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because ["action:saved_objects/bar-type/get" is not allowed]]]]`; +exports[`#checkPrivilegesAtSpace with a malformed Elasticsearch response throws a validation error when an extra privilege is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because ["action:saved_objects/bar-type/get" is not allowed]]]]`; -exports[`#checkPrivilegesAtSpace with a malformed Elasticsearch response throws a validation error when privileges are missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because [child "action:saved_objects/foo-type/get" fails because ["action:saved_objects/foo-type/get" is required]]]]]`; +exports[`#checkPrivilegesAtSpace with a malformed Elasticsearch response throws a validation error when privileges are missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because [child "action:saved_objects/foo-type/get" fails because ["action:saved_objects/foo-type/get" is required]]]]]`; exports[`#checkPrivilegesAtSpaces throws error when Elasticsearch returns malformed response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because [child "mock-action:version" fails because ["mock-action:version" is required]]]]]`; @@ -18,10 +18,10 @@ exports[`#checkPrivilegesAtSpaces with a malformed Elasticsearch response throws exports[`#checkPrivilegesAtSpaces with a malformed Elasticsearch response throws a validation error when privileges are missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_2" fails because ["space:space_2" is required]]]]`; -exports[`#checkPrivilegesGlobally throws error when Elasticsearch returns malformed response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because [child "mock-action:version" fails because ["mock-action:version" is required]]]]]`; +exports[`#checkPrivilegesGlobally throws error when Elasticsearch returns malformed response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because [child "mock-action:version" fails because ["mock-action:version" is required]]]]]`; exports[`#checkPrivilegesGlobally throws error when checking for login and user has login but doesn't have version 1`] = `[Error: Multiple versions of Kibana are running against the same Elasticsearch cluster, unable to authorize user.]`; -exports[`#checkPrivilegesGlobally with a malformed Elasticsearch response throws a validation error when an extra privilege is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because ["action:saved_objects/bar-type/get" is not allowed]]]]`; +exports[`#checkPrivilegesGlobally with a malformed Elasticsearch response throws a validation error when an extra privilege is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because ["action:saved_objects/bar-type/get" is not allowed]]]]`; -exports[`#checkPrivilegesGlobally with a malformed Elasticsearch response throws a validation error when privileges are missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because [child "action:saved_objects/foo-type/get" fails because ["action:saved_objects/foo-type/get" is required]]]]]`; +exports[`#checkPrivilegesGlobally with a malformed Elasticsearch response throws a validation error when privileges are missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because [child "action:saved_objects/foo-type/get" fails because ["action:saved_objects/foo-type/get" is required]]]]]`; diff --git a/x-pack/plugins/security/server/lib/errors.js b/x-pack/plugins/security/server/lib/errors.js index 6996faeaac8de6..0f8a0f0d8c0a9b 100644 --- a/x-pack/plugins/security/server/lib/errors.js +++ b/x-pack/plugins/security/server/lib/errors.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { wrap as wrapBoom } from 'boom'; +import { boomify } from 'boom'; export function wrapError(error) { - return wrapBoom(error, error.status); + return boomify(error, { statusCode: error.status }); } diff --git a/x-pack/plugins/security/server/lib/route_pre_check_license.js b/x-pack/plugins/security/server/lib/route_pre_check_license.js index b7017033ccafeb..41db792b33d943 100644 --- a/x-pack/plugins/security/server/lib/route_pre_check_license.js +++ b/x-pack/plugins/security/server/lib/route_pre_check_license.js @@ -9,12 +9,12 @@ const Boom = require('boom'); export function routePreCheckLicense(server) { const xpackMainPlugin = server.plugins.xpack_main; const pluginId = 'security'; - return function forbidApiAccess(request, reply) { + return function forbidApiAccess() { const licenseCheckResults = xpackMainPlugin.info.feature(pluginId).getLicenseCheckResults(); if (!licenseCheckResults.showLinks) { - reply(Boom.forbidden(licenseCheckResults.linksMessage)); + throw Boom.forbidden(licenseCheckResults.linksMessage); } else { - reply(); + return null; } }; } diff --git a/x-pack/plugins/security/server/routes/api/public/roles/delete.js b/x-pack/plugins/security/server/routes/api/public/roles/delete.js index 697a9bd32df1b9..ecba6c3f97e6a2 100644 --- a/x-pack/plugins/security/server/routes/api/public/roles/delete.js +++ b/x-pack/plugins/security/server/routes/api/public/roles/delete.js @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; import Joi from 'joi'; import { wrapError } from '../../../../lib/errors'; @@ -12,11 +11,12 @@ export function initDeleteRolesApi(server, callWithRequest, routePreCheckLicense server.route({ method: 'DELETE', path: '/api/security/role/{name}', - handler(request, reply) { - const name = request.params.name; + handler(request, h) { + const { name } = request.params; return callWithRequest(request, 'shield.deleteRole', { name }).then( - () => reply().code(204), - _.flow(wrapError, reply)); + () => h.response().code(204), + wrapError + ); }, config: { validate: { diff --git a/x-pack/plugins/security/server/routes/api/public/roles/delete.test.js b/x-pack/plugins/security/server/routes/api/public/roles/delete.test.js index 0337b8e8b9f661..638edf577da3a6 100644 --- a/x-pack/plugins/security/server/routes/api/public/roles/delete.test.js +++ b/x-pack/plugins/security/server/routes/api/public/roles/delete.test.js @@ -9,12 +9,11 @@ import Boom from 'boom'; import { initDeleteRolesApi } from './delete'; const createMockServer = () => { - const mockServer = new Hapi.Server({ debug: false }); - mockServer.connection({ port: 8080 }); + const mockServer = new Hapi.Server({ debug: false, port: 8080 }); return mockServer; }; -const defaultPreCheckLicenseImpl = (request, reply) => reply(); +const defaultPreCheckLicenseImpl = () => null; describe('DELETE role', () => { const deleteRoleTest = ( @@ -76,14 +75,14 @@ describe('DELETE role', () => { statusCode: 404, result: { error: 'Not Found', + message: 'Not Found', statusCode: 404, }, }, }); deleteRoleTest(`returns result of routePreCheckLicense`, { - preCheckLicenseImpl: (request, reply) => - reply(Boom.forbidden('test forbidden message')), + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), asserts: { statusCode: 403, result: { diff --git a/x-pack/plugins/security/server/routes/api/public/roles/get.js b/x-pack/plugins/security/server/routes/api/public/roles/get.js index 797a76110d21af..145d06f74fb400 100644 --- a/x-pack/plugins/security/server/routes/api/public/roles/get.js +++ b/x-pack/plugins/security/server/routes/api/public/roles/get.js @@ -65,12 +65,12 @@ export function initGetRolesApi(server, callWithRequest, routePreCheckLicenseFn, server.route({ method: 'GET', path: '/api/security/role', - async handler(request, reply) { + async handler(request) { try { const response = await callWithRequest(request, 'shield.getRole'); - return reply(transformRolesFromEs(response)); + return transformRolesFromEs(response); } catch (error) { - reply(wrapError(error)); + return wrapError(error); } }, config: { @@ -81,17 +81,17 @@ export function initGetRolesApi(server, callWithRequest, routePreCheckLicenseFn, server.route({ method: 'GET', path: '/api/security/role/{name}', - async handler(request, reply) { + async handler(request) { const name = request.params.name; try { const response = await callWithRequest(request, 'shield.getRole', { name }); if (response[name]) { - return reply(transformRoleFromEs(response[name], name)); + return transformRoleFromEs(response[name], name); } - return reply(Boom.notFound()); + return Boom.notFound(); } catch (error) { - reply(wrapError(error)); + return wrapError(error); } }, config: { diff --git a/x-pack/plugins/security/server/routes/api/public/roles/get.test.js b/x-pack/plugins/security/server/routes/api/public/roles/get.test.js index 28f754248d829e..26d6288aa8eb4c 100644 --- a/x-pack/plugins/security/server/routes/api/public/roles/get.test.js +++ b/x-pack/plugins/security/server/routes/api/public/roles/get.test.js @@ -10,8 +10,7 @@ import { initGetRolesApi } from './get'; const application = 'kibana-.kibana'; const createMockServer = () => { - const mockServer = new Hapi.Server({ debug: false }); - mockServer.connection({ port: 8080 }); + const mockServer = new Hapi.Server({ debug: false, port: 8080 }); return mockServer; }; @@ -19,7 +18,7 @@ describe('GET roles', () => { const getRolesTest = ( description, { - preCheckLicenseImpl = (request, reply) => reply(), + preCheckLicenseImpl = () => null, callWithRequestImpl, asserts, } @@ -63,8 +62,7 @@ describe('GET roles', () => { describe('failure', () => { getRolesTest(`returns result of routePreCheckLicense`, { - preCheckLicenseImpl: (request, reply) => - reply(Boom.forbidden('test forbidden message')), + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), asserts: { statusCode: 403, result: { @@ -386,7 +384,7 @@ describe('GET role', () => { description, { name, - preCheckLicenseImpl = (request, reply) => reply(), + preCheckLicenseImpl = () => null, callWithRequestImpl, asserts, } @@ -431,8 +429,7 @@ describe('GET role', () => { describe('failure', () => { getRoleTest(`returns result of routePreCheckLicense`, { - preCheckLicenseImpl: (request, reply) => - reply(Boom.forbidden('test forbidden message')), + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), asserts: { statusCode: 403, result: { diff --git a/x-pack/plugins/security/server/routes/api/public/roles/put.js b/x-pack/plugins/security/server/routes/api/public/roles/put.js index 0152453a10a26d..65dd78ed2d4b1c 100644 --- a/x-pack/plugins/security/server/routes/api/public/roles/put.js +++ b/x-pack/plugins/security/server/routes/api/public/roles/put.js @@ -86,8 +86,8 @@ export function initPutRolesApi( server.route({ method: 'PUT', path: '/api/security/role/{name}', - async handler(request, reply) { - const name = request.params.name; + async handler(request, h) { + const { name } = request.params; try { const existingRoleResponse = await callWithRequest(request, 'shield.getRole', { name, @@ -100,12 +100,12 @@ export function initPutRolesApi( ); await callWithRequest(request, 'shield.putRole', { name, body }); - reply().code(204); + return h.response().code(204); } catch (err) { - reply(wrapError(err)); + throw wrapError(err); } }, - config: { + options: { validate: { params: Joi.object() .keys({ diff --git a/x-pack/plugins/security/server/routes/api/public/roles/put.test.js b/x-pack/plugins/security/server/routes/api/public/roles/put.test.js index ffa7b247f99d2b..26d6eb1966ead1 100644 --- a/x-pack/plugins/security/server/routes/api/public/roles/put.test.js +++ b/x-pack/plugins/security/server/routes/api/public/roles/put.test.js @@ -7,17 +7,25 @@ import Hapi from 'hapi'; import Boom from 'boom'; import { initPutRolesApi } from './put'; +import { defaultValidationErrorHandler } from '../../../../../../../../src/core/server/http/http_tools'; import { GLOBAL_RESOURCE } from '../../../../../common/constants'; const application = 'kibana-.kibana'; const createMockServer = () => { - const mockServer = new Hapi.Server({ debug: false }); - mockServer.connection({ port: 8080 }); + const mockServer = new Hapi.Server({ + debug: false, + port: 8080, + routes: { + validate: { + failAction: defaultValidationErrorHandler + } + } + }); return mockServer; }; -const defaultPreCheckLicenseImpl = (request, reply) => reply(); +const defaultPreCheckLicenseImpl = () => null; const privilegeMap = { global: { @@ -62,7 +70,8 @@ const putRoleTest = ( headers, payload, }; - const { result, statusCode } = await mockServer.inject(request); + const response = await mockServer.inject(request); + const { result, statusCode } = response; expect(result).toEqual(asserts.result); expect(statusCode).toBe(asserts.statusCode); @@ -97,6 +106,7 @@ describe('PUT role', () => { statusCode: 404, result: { error: 'Not Found', + message: 'Not Found', statusCode: 404, }, }, @@ -178,7 +188,7 @@ describe('PUT role', () => { statusCode: 400, result: { error: 'Bad Request', - message: `child \"kibana\" fails because [child \"space\" fails because [\"*\" is not allowed]]`, + message: `child \"kibana\" fails because [child \"space\" fails because [\"*\" is not allowed]]`, statusCode: 400, validation: { keys: ['kibana.space.*'], @@ -201,7 +211,7 @@ describe('PUT role', () => { statusCode: 400, result: { error: 'Bad Request', - message: `child \"kibana\" fails because [child \"space\" fails because [\"foo-*\" is not allowed]]`, + message: `child \"kibana\" fails because [child \"space\" fails because [\"foo-*\" is not allowed]]`, statusCode: 400, validation: { keys: ['kibana.space.foo-*'], @@ -214,8 +224,7 @@ describe('PUT role', () => { putRoleTest(`returns result of routePreCheckLicense`, { name: 'foo-role', payload: {}, - preCheckLicenseImpl: (request, reply) => - reply(Boom.forbidden('test forbidden message')), + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), asserts: { statusCode: 403, result: { diff --git a/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js b/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js index 155fc041f24a55..9302055928ab44 100644 --- a/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js +++ b/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js @@ -18,13 +18,16 @@ import { DeauthenticationResult } from '../../../../lib/authentication/deauthent describe('Authentication routes', () => { let serverStub; - let replyStub; + let hStub; beforeEach(() => { serverStub = serverFixture(); - replyStub = sinon.stub(); - replyStub.continue = sinon.stub(); - replyStub.redirect = sinon.stub(); + hStub = { + authenticated: sinon.stub(), + continue: 'blah', + redirect: sinon.stub(), + response: sinon.stub() + }; initAuthenticateApi(serverStub); }); @@ -74,39 +77,29 @@ describe('Authentication routes', () => { const unhandledException = new Error('Something went wrong.'); authenticateStub.throws(unhandledException); - await loginRoute.handler(request, replyStub); - - sinon.assert.notCalled(replyStub.continue); - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, sinon.match({ - isBoom: true, - output: { - payload: { + return loginRoute + .handler(request, hStub) + .catch((response) => { + expect(response.isBoom).to.be(true); + expect(response.output.payload).to.eql({ statusCode: 500, error: 'Internal Server Error', message: 'An internal server error occurred' - } - } - })); + }); + }); }); it('returns 401 if authentication fails.', async () => { const failureReason = new Error('Something went wrong.'); authenticateStub.returns(Promise.resolve(AuthenticationResult.failed(failureReason))); - await loginRoute.handler(request, replyStub); - - sinon.assert.notCalled(replyStub.continue); - sinon.assert.calledOnce(replyStub); - - sinon.assert.calledWithExactly( - replyStub, - sinon.match({ - isBoom: true, - message: failureReason.toString(), - output: { statusCode: 401 }, - }) - ); + return loginRoute + .handler(request, hStub) + .catch((response) => { + expect(response.isBoom).to.be(true); + expect(response.message).to.be(failureReason.message); + expect(response.output.statusCode).to.be(401); + }); }); it('returns 401 if authentication is not handled.', async () => { @@ -114,19 +107,13 @@ describe('Authentication routes', () => { Promise.resolve(AuthenticationResult.notHandled()) ); - await loginRoute.handler(request, replyStub); - - sinon.assert.notCalled(replyStub.continue); - sinon.assert.calledOnce(replyStub); - - sinon.assert.calledWithExactly( - replyStub, - sinon.match({ - isBoom: true, - message: 'Unauthorized', - output: { statusCode: 401 }, - }) - ); + return loginRoute + .handler(request, hStub) + .catch((response) => { + expect(response.isBoom).to.be(true); + expect(response.message).to.be('Unauthorized'); + expect(response.output.statusCode).to.be(401); + }); }); describe('authentication succeeds', () => { @@ -140,13 +127,11 @@ describe('Authentication routes', () => { ); authorizationModeStub.useRbacForRequest.returns(true); - await loginRoute.handler(request, replyStub); + await loginRoute.handler(request, hStub); sinon.assert.calledWithExactly(authorizationModeStub.useRbacForRequest, request); sinon.assert.neverCalledWith(serverStub.log, ['warning', 'deprecated', 'security'], getDeprecationMessage(user.username)); - sinon.assert.notCalled(replyStub); - sinon.assert.calledOnce(replyStub.continue); - sinon.assert.calledWithExactly(replyStub.continue, { credentials: user }); + sinon.assert.calledOnce(hStub.response); }); it(`returns user data and logs deprecation warning if authorization.mode.useRbacForRequest returns false.`, async () => { @@ -156,13 +141,11 @@ describe('Authentication routes', () => { ); authorizationModeStub.useRbacForRequest.returns(false); - await loginRoute.handler(request, replyStub); + await loginRoute.handler(request, hStub); sinon.assert.calledWithExactly(authorizationModeStub.useRbacForRequest, request); sinon.assert.calledWith(serverStub.log, ['warning', 'deprecated', 'security'], getDeprecationMessage(user.username)); - sinon.assert.notCalled(replyStub); - sinon.assert.calledOnce(replyStub.continue); - sinon.assert.calledWithExactly(replyStub.continue, { credentials: user }); + sinon.assert.calledOnce(hStub.response); }); }); @@ -197,12 +180,12 @@ describe('Authentication routes', () => { .withArgs(request) .returns(Promise.reject(unhandledException)); - await logoutRoute.handler(request, replyStub); - - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, Boom.wrap(unhandledException)); - sinon.assert.notCalled(replyStub.continue); - sinon.assert.notCalled(replyStub.redirect); + return logoutRoute + .handler(request, hStub) + .catch((response) => { + expect(response).to.be(Boom.boomify(unhandledException)); + sinon.assert.notCalled(hStub.redirect); + }); }); it('returns 500 if authenticator fails to deauthenticate.', async () => { @@ -213,30 +196,25 @@ describe('Authentication routes', () => { .withArgs(request) .returns(Promise.resolve(DeauthenticationResult.failed(failureReason))); - await logoutRoute.handler(request, replyStub); - - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, Boom.wrap(failureReason)); - sinon.assert.notCalled(replyStub.continue); - sinon.assert.notCalled(replyStub.redirect); + return logoutRoute + .handler(request, hStub) + .catch((response) => { + expect(response).to.be(Boom.boomify(failureReason)); + sinon.assert.notCalled(hStub.redirect); + }); }); it('returns 400 for AJAX requests that can not handle redirect.', async () => { const request = requestFixture({ headers: { 'kbn-xsrf': 'xsrf' } }); - await logoutRoute.handler(request, replyStub); - - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly( - replyStub, - sinon.match({ - isBoom: true, - message: 'Client should be able to process redirect response.', - output: { statusCode: 400 } - }) - ); - sinon.assert.notCalled(replyStub.continue); - sinon.assert.notCalled(replyStub.redirect); + return logoutRoute + .handler(request, hStub) + .catch((response) => { + expect(response.isBoom).to.be(true); + expect(response.message).to.be('Client should be able to process redirect response.'); + expect(response.output.statusCode).to.be(400); + sinon.assert.notCalled(hStub.redirect); + }); }); it('redirects user to the URL returned by authenticator.', async () => { @@ -248,12 +226,10 @@ describe('Authentication routes', () => { Promise.resolve(DeauthenticationResult.redirectTo('https://custom.logout')) ); - await logoutRoute.handler(request, replyStub); + await logoutRoute.handler(request, hStub); - sinon.assert.calledOnce(replyStub.redirect); - sinon.assert.calledWithExactly(replyStub.redirect, 'https://custom.logout'); - sinon.assert.notCalled(replyStub); - sinon.assert.notCalled(replyStub.continue); + sinon.assert.calledOnce(hStub.redirect); + sinon.assert.calledWithExactly(hStub.redirect, 'https://custom.logout'); }); it('redirects user to the base path if deauthentication succeeds.', async () => { @@ -263,12 +239,10 @@ describe('Authentication routes', () => { .withArgs(request) .returns(Promise.resolve(DeauthenticationResult.succeeded())); - await logoutRoute.handler(request, replyStub); + await logoutRoute.handler(request, hStub); - sinon.assert.calledOnce(replyStub.redirect); - sinon.assert.calledWithExactly(replyStub.redirect, '/test-base-path/'); - sinon.assert.notCalled(replyStub); - sinon.assert.notCalled(replyStub.continue); + sinon.assert.calledOnce(hStub.redirect); + sinon.assert.calledWithExactly(hStub.redirect, '/test-base-path/'); }); it('redirects user to the base path if deauthentication is not handled.', async () => { @@ -278,12 +252,10 @@ describe('Authentication routes', () => { .withArgs(request) .returns(Promise.resolve(DeauthenticationResult.notHandled())); - await logoutRoute.handler(request, replyStub); + await logoutRoute.handler(request, hStub); - sinon.assert.calledOnce(replyStub.redirect); - sinon.assert.calledWithExactly(replyStub.redirect, '/test-base-path/'); - sinon.assert.notCalled(replyStub); - sinon.assert.notCalled(replyStub.continue); + sinon.assert.calledOnce(hStub.redirect); + sinon.assert.calledWithExactly(hStub.redirect, '/test-base-path/'); }); }); @@ -306,10 +278,9 @@ describe('Authentication routes', () => { it('returns user from the authenticated request property.', async () => { const request = { auth: { credentials: { username: 'user' } } }; - await meRoute.handler(request, replyStub); + const response = await meRoute.handler(request, hStub); - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, { username: 'user' }); + expect(response).to.eql({ username: 'user' }); }); }); @@ -345,21 +316,17 @@ describe('Authentication routes', () => { const unhandledException = new Error('Something went wrong.'); serverStub.plugins.security.authenticate.throws(unhandledException); - await samlAcsRoute.handler(request, replyStub); - - sinon.assert.notCalled(replyStub.continue); - sinon.assert.notCalled(replyStub.redirect); - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, sinon.match({ - isBoom: true, - output: { - payload: { + return samlAcsRoute + .handler(request, hStub) + .catch((response) => { + sinon.assert.notCalled(hStub.redirect); + expect(response.isBoom).to.be(true); + expect(response.output.payload).to.eql({ statusCode: 500, error: 'Internal Server Error', message: 'An internal server error occurred' - } - } - })); + }); + }); }); it('returns 401 if authentication fails.', async () => { @@ -368,19 +335,14 @@ describe('Authentication routes', () => { Promise.resolve(AuthenticationResult.failed(failureReason)) ); - await samlAcsRoute.handler(request, replyStub); - - sinon.assert.notCalled(replyStub.continue); - sinon.assert.notCalled(replyStub.redirect); - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly( - replyStub, - sinon.match({ - isBoom: true, - message: failureReason.toString(), - output: { statusCode: 401 } - }) - ); + return samlAcsRoute + .handler(request, hStub) + .catch((response) => { + sinon.assert.notCalled(hStub.redirect); + expect(response.isBoom).to.be(true); + expect(response.message).to.be(failureReason.message); + expect(response.output.statusCode).to.be(401); + }); }); it('returns 401 if authentication is not handled.', async () => { @@ -388,19 +350,14 @@ describe('Authentication routes', () => { Promise.resolve(AuthenticationResult.notHandled()) ); - await samlAcsRoute.handler(request, replyStub); - - sinon.assert.notCalled(replyStub.continue); - sinon.assert.notCalled(replyStub.redirect); - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly( - replyStub, - sinon.match({ - isBoom: true, - message: 'Unauthorized', - output: { statusCode: 401 } - }) - ); + return samlAcsRoute + .handler(request, hStub) + .catch((response) => { + sinon.assert.notCalled(hStub.redirect); + expect(response.isBoom).to.be(true); + expect(response.message).to.be('Unauthorized'); + expect(response.output.statusCode).to.be(401); + }); }); it('returns 403 if there an active session exists.', async () => { @@ -408,20 +365,15 @@ describe('Authentication routes', () => { Promise.resolve(AuthenticationResult.succeeded({})) ); - await samlAcsRoute.handler(request, replyStub); - - sinon.assert.notCalled(replyStub.continue); - sinon.assert.notCalled(replyStub.redirect); - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly( - replyStub, - sinon.match({ - isBoom: true, - message: 'Sorry, you already have an active Kibana session. ' + - 'If you want to start a new one, please logout from the existing session first.', - output: { statusCode: 403 } - }) - ); + return samlAcsRoute + .handler(request, hStub) + .catch((response) => { + sinon.assert.notCalled(hStub.redirect); + expect(response.isBoom).to.be(true); + expect(response.message).to.be('Sorry, you already have an active Kibana session. ' + + 'If you want to start a new one, please logout from the existing session first.'); + expect(response.output.statusCode).to.be(403); + }); }); it('redirects if required by the authentication process.', async () => { @@ -429,11 +381,9 @@ describe('Authentication routes', () => { Promise.resolve(AuthenticationResult.redirectTo('http://redirect-to/path')) ); - await samlAcsRoute.handler(request, replyStub); + await samlAcsRoute.handler(request, hStub); - sinon.assert.calledWithExactly(replyStub.redirect, 'http://redirect-to/path'); - sinon.assert.notCalled(replyStub); - sinon.assert.notCalled(replyStub.continue); + sinon.assert.calledWithExactly(hStub.redirect, 'http://redirect-to/path'); }); }); }); diff --git a/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js b/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js index 204b703bf0f15b..bdd66e0c578f85 100644 --- a/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js +++ b/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js @@ -81,21 +81,17 @@ describe('User routes', () => { it('returns 401 if old password is wrong.', async () => { getUserStub.returns(Promise.reject(new Error('Something went wrong.'))); - const replyStub = sinon.stub(); - await changePasswordRoute.handler(request, replyStub); - - sinon.assert.notCalled(clusterStub.callWithRequest); - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, sinon.match({ - isBoom: true, - output: { - payload: { + return changePasswordRoute + .handler(request) + .catch((response) => { + sinon.assert.notCalled(clusterStub.callWithRequest); + expect(response.isBoom).to.be(true); + expect(response.output.payload).to.eql({ statusCode: 401, error: 'Unauthorized', - message: 'Error: Something went wrong.' - } - } - })); + message: 'Something went wrong.' + }); + }); }); it('returns 401 if user can authenticate with new password.', async () => { @@ -109,28 +105,24 @@ describe('User routes', () => { Promise.resolve(AuthenticationResult.failed(new Error('Something went wrong.'))) ); - const replyStub = sinon.stub(); - await changePasswordRoute.handler(request, replyStub); - - sinon.assert.calledOnce(clusterStub.callWithRequest); - sinon.assert.calledWithExactly( - clusterStub.callWithRequest, - sinon.match.same(request), - 'shield.changePassword', - { username: 'user', body: { password: 'new-password' } } - ); - - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, sinon.match({ - isBoom: true, - output: { - payload: { + return changePasswordRoute + .handler(request) + .catch((response) => { + sinon.assert.calledOnce(clusterStub.callWithRequest); + sinon.assert.calledWithExactly( + clusterStub.callWithRequest, + sinon.match.same(request), + 'shield.changePassword', + { username: 'user', body: { password: 'new-password' } } + ); + + expect(response.isBoom).to.be(true); + expect(response.output.payload).to.eql({ statusCode: 401, error: 'Unauthorized', - message: 'Error: Something went wrong.' - } - } - })); + message: 'Something went wrong.' + }); + }); }); it('returns 500 if password update request fails.', async () => { @@ -142,20 +134,16 @@ describe('User routes', () => { ) .returns(Promise.reject(new Error('Request failed.'))); - const replyStub = sinon.stub(); - await changePasswordRoute.handler(request, replyStub); - - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, sinon.match({ - isBoom: true, - output: { - payload: { + return changePasswordRoute + .handler(request) + .catch((response) => { + expect(response.isBoom).to.be(true); + expect(response.output.payload).to.eql({ statusCode: 500, error: 'Internal Server Error', message: 'An internal server error occurred' - } - } - })); + }); + }); }); it('successfully changes own password if provided old password is correct.', async () => { @@ -169,10 +157,10 @@ describe('User routes', () => { Promise.resolve(AuthenticationResult.succeeded({})) ); - const replyResultStub = { code: sinon.stub() }; - const replyStub = sinon.stub().returns(replyResultStub); + const hResponseStub = { code: sinon.stub() }; + const hStub = { response: sinon.stub().returns(hResponseStub) }; - await changePasswordRoute.handler(request, replyStub); + await changePasswordRoute.handler(request, hStub); sinon.assert.calledOnce(clusterStub.callWithRequest); sinon.assert.calledWithExactly( @@ -182,9 +170,8 @@ describe('User routes', () => { { username: 'user', body: { password: 'new-password' } } ); - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub); - sinon.assert.calledWithExactly(replyResultStub.code, 204); + sinon.assert.calledWithExactly(hStub.response); + sinon.assert.calledWithExactly(hResponseStub.code, 204); }); }); @@ -198,30 +185,26 @@ describe('User routes', () => { ) .returns(Promise.reject(new Error('Request failed.'))); - const replyStub = sinon.stub(); - await changePasswordRoute.handler(request, replyStub); - - sinon.assert.notCalled(serverStub.plugins.security.getUser); - sinon.assert.notCalled(serverStub.plugins.security.authenticate); + return changePasswordRoute + .handler(request) + .catch((response) => { + sinon.assert.notCalled(serverStub.plugins.security.getUser); + sinon.assert.notCalled(serverStub.plugins.security.authenticate); - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, sinon.match({ - isBoom: true, - output: { - payload: { + expect(response.isBoom).to.be(true); + expect(response.output.payload).to.eql({ statusCode: 500, error: 'Internal Server Error', message: 'An internal server error occurred' - } - } - })); + }); + }); }); it('successfully changes user password.', async () => { - const replyResultStub = { code: sinon.stub() }; - const replyStub = sinon.stub().returns(replyResultStub); + const hResponseStub = { code: sinon.stub() }; + const hStub = { response: sinon.stub().returns(hResponseStub) }; - await changePasswordRoute.handler(request, replyStub); + await changePasswordRoute.handler(request, hStub); sinon.assert.notCalled(serverStub.plugins.security.getUser); sinon.assert.notCalled(serverStub.plugins.security.authenticate); @@ -234,9 +217,8 @@ describe('User routes', () => { { username: 'target-user', body: { password: 'new-password' } } ); - sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub); - sinon.assert.calledWithExactly(replyResultStub.code, 204); + sinon.assert.calledWithExactly(hStub.response); + sinon.assert.calledWithExactly(hResponseStub.code, 204); }); }); }); diff --git a/x-pack/plugins/security/server/routes/api/v1/authenticate.js b/x-pack/plugins/security/server/routes/api/v1/authenticate.js index c791def49e9d25..fc905b58b9d0e0 100644 --- a/x-pack/plugins/security/server/routes/api/v1/authenticate.js +++ b/x-pack/plugins/security/server/routes/api/v1/authenticate.js @@ -27,7 +27,7 @@ export function initAuthenticateApi(server) { emptyStatusCode: 204, } }, - async handler(request, reply) { + async handler(request, h) { const { username, password } = request.payload; try { @@ -36,7 +36,7 @@ export function initAuthenticateApi(server) { ); if (!authenticationResult.succeeded()) { - return reply(Boom.unauthorized(authenticationResult.error)); + throw Boom.unauthorized(authenticationResult.error); } const { authorization } = server.plugins.security; @@ -45,9 +45,9 @@ export function initAuthenticateApi(server) { server.log(['warning', 'deprecated', 'security'], msg); } - return reply.continue({ credentials: authenticationResult.user }); + return h.response(); } catch(err) { - return reply(wrapError(err)); + throw wrapError(err); } } }); @@ -64,7 +64,7 @@ export function initAuthenticateApi(server) { } } }, - async handler(request, reply) { + async handler(request, h) { try { // When authenticating using SAML we _expect_ to redirect to the SAML provider. // However, it may happen that Identity Provider sends a new SAML Response @@ -91,21 +91,19 @@ export function initAuthenticateApi(server) { // although it might not be the ideal UX in the long term. const authenticationResult = await server.plugins.security.authenticate(request); if (authenticationResult.succeeded()) { - return reply( - Boom.forbidden( - 'Sorry, you already have an active Kibana session. ' + - 'If you want to start a new one, please logout from the existing session first.' - ) + throw Boom.forbidden( + 'Sorry, you already have an active Kibana session. ' + + 'If you want to start a new one, please logout from the existing session first.' ); } if (authenticationResult.redirected()) { - return reply.redirect(authenticationResult.redirectURL); + return h.redirect(authenticationResult.redirectURL); } - return reply(Boom.unauthorized(authenticationResult.error)); + throw Boom.unauthorized(authenticationResult.error); } catch (err) { - return reply(wrapError(err)); + throw wrapError(err); } } }); @@ -116,24 +114,22 @@ export function initAuthenticateApi(server) { config: { auth: false }, - async handler(request, reply) { + async handler(request, h) { if (!canRedirectRequest(request)) { - return reply( - Boom.badRequest('Client should be able to process redirect response.') - ); + throw Boom.badRequest('Client should be able to process redirect response.'); } try { const deauthenticationResult = await server.plugins.security.deauthenticate(request); if (deauthenticationResult.failed()) { - return reply(wrapError(deauthenticationResult.error)); + throw wrapError(deauthenticationResult.error); } - return reply.redirect( + return h.redirect( deauthenticationResult.redirectURL || `${server.config().get('server.basePath')}/` ); } catch (err) { - return reply(wrapError(err)); + throw wrapError(err); } } }); @@ -141,8 +137,8 @@ export function initAuthenticateApi(server) { server.route({ method: 'GET', path: '/api/security/v1/me', - handler(request, reply) { - reply(request.auth.credentials); + handler(request) { + return request.auth.credentials; } }); } diff --git a/x-pack/plugins/security/server/routes/api/v1/indices.js b/x-pack/plugins/security/server/routes/api/v1/indices.js index 68d171d6a2dbbb..eb1f02c15e1ac9 100644 --- a/x-pack/plugins/security/server/routes/api/v1/indices.js +++ b/x-pack/plugins/security/server/routes/api/v1/indices.js @@ -14,14 +14,14 @@ export function initIndicesApi(server) { server.route({ method: 'GET', path: '/api/security/v1/fields/{query}', - handler(request, reply) { + handler(request) { return callWithRequest(request, 'indices.getFieldMapping', { index: request.params.query, fields: '*', allowNoIndices: false, includeDefaults: true }) - .then((mappings) => reply( + .then((mappings) => _(mappings) .map('mappings') .map(_.values) @@ -30,8 +30,8 @@ export function initIndicesApi(server) { .flatten() .uniq() .value() - )) - .catch(_.flow(wrapError, reply)); + ) + .catch(wrapError); } }); } diff --git a/x-pack/plugins/security/server/routes/api/v1/users.js b/x-pack/plugins/security/server/routes/api/v1/users.js index babe6bef569d45..7490039442de0d 100644 --- a/x-pack/plugins/security/server/routes/api/v1/users.js +++ b/x-pack/plugins/security/server/routes/api/v1/users.js @@ -20,10 +20,10 @@ export function initUsersApi(server) { server.route({ method: 'GET', path: '/api/security/v1/users', - handler(request, reply) { + handler(request) { return callWithRequest(request, 'shield.getUser').then( - (response) => reply(_.values(response)), - _.flow(wrapError, reply) + _.values, + wrapError ); }, config: { @@ -34,14 +34,14 @@ export function initUsersApi(server) { server.route({ method: 'GET', path: '/api/security/v1/users/{username}', - handler(request, reply) { + handler(request) { const username = request.params.username; return callWithRequest(request, 'shield.getUser', { username }).then( (response) => { - if (response[username]) return reply(response[username]); - return reply(Boom.notFound()); + if (response[username]) return response[username]; + throw Boom.notFound(); }, - _.flow(wrapError, reply)); + wrapError); }, config: { pre: [routePreCheckLicenseFn] @@ -51,12 +51,12 @@ export function initUsersApi(server) { server.route({ method: 'POST', path: '/api/security/v1/users/{username}', - handler(request, reply) { + handler(request) { const username = request.params.username; const body = _(request.payload).omit(['username', 'enabled']).omit(_.isNull); return callWithRequest(request, 'shield.putUser', { username, body }).then( - () => reply(request.payload), - _.flow(wrapError, reply)); + () => request.payload, + wrapError); }, config: { validate: { @@ -69,11 +69,11 @@ export function initUsersApi(server) { server.route({ method: 'DELETE', path: '/api/security/v1/users/{username}', - handler(request, reply) { + handler(request, h) { const username = request.params.username; return callWithRequest(request, 'shield.deleteUser', { username }).then( - () => reply().code(204), - _.flow(wrapError, reply)); + () => h.response().code(204), + wrapError); }, config: { pre: [routePreCheckLicenseFn] @@ -83,7 +83,7 @@ export function initUsersApi(server) { server.route({ method: 'POST', path: '/api/security/v1/users/{username}/password', - async handler(request, reply) { + async handler(request, h) { const username = request.params.username; const { password, newPassword } = request.payload; const isCurrentUser = username === request.auth.credentials.username; @@ -95,7 +95,7 @@ export function initUsersApi(server) { BasicCredentials.decorateRequest(request, username, password) ); } catch(err) { - return reply(Boom.unauthorized(err)); + throw Boom.unauthorized(err); } } @@ -110,14 +110,14 @@ export function initUsersApi(server) { ); if (!authenticationResult.succeeded()) { - return reply(Boom.unauthorized((authenticationResult.error))); + throw Boom.unauthorized((authenticationResult.error)); } } } catch(err) { - return reply(wrapError(err)); + throw wrapError(err); } - return reply().code(204); + return h.response().code(204); }, config: { validate: { diff --git a/x-pack/plugins/security/server/routes/views/login.js b/x-pack/plugins/security/server/routes/views/login.js index 87e0c86c618b98..95c0c56ed6ad56 100644 --- a/x-pack/plugins/security/server/routes/views/login.js +++ b/x-pack/plugins/security/server/routes/views/login.js @@ -29,15 +29,15 @@ export function initLoginView(server, xpackMainPlugin) { server.route({ method: 'GET', path: '/login', - handler(request, reply) { + handler(request, h) { const isUserAlreadyLoggedIn = !!request.state[cookieName]; if (isUserAlreadyLoggedIn || !shouldShowLogin()) { const basePath = config.get('server.basePath'); const url = get(request, 'raw.req.url'); const next = parseNext(url, basePath); - return reply.redirect(next); + return h.redirect(next); } - return reply.renderAppWithDefaultConfig(login); + return h.renderAppWithDefaultConfig(login); }, config: { auth: false diff --git a/x-pack/plugins/security/server/routes/views/logout.js b/x-pack/plugins/security/server/routes/views/logout.js index 3334dff35b7198..aa407f0cf3c857 100644 --- a/x-pack/plugins/security/server/routes/views/logout.js +++ b/x-pack/plugins/security/server/routes/views/logout.js @@ -10,8 +10,8 @@ export function initLogoutView(server) { server.route({ method: 'GET', path: '/logout', - handler(request, reply) { - return reply.renderAppWithDefaultConfig(logout); + handler(request, h) { + return h.renderAppWithDefaultConfig(logout); }, config: { auth: false diff --git a/x-pack/plugins/spaces/server/lib/errors.ts b/x-pack/plugins/spaces/server/lib/errors.ts index 4f95c175b0f159..de4b09206d3ee6 100644 --- a/x-pack/plugins/spaces/server/lib/errors.ts +++ b/x-pack/plugins/spaces/server/lib/errors.ts @@ -4,8 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ // @ts-ignore -import { wrap as wrapBoom } from 'boom'; +import { boomify } from 'boom'; export function wrapError(error: any) { - return wrapBoom(error, error.status); + if (error.isBoom) { + return error; + } + + return boomify(error, { statusCode: error.status }); } diff --git a/x-pack/plugins/spaces/server/lib/route_pre_check_license.ts b/x-pack/plugins/spaces/server/lib/route_pre_check_license.ts index 449836633993c4..f7f12ffa36fbc9 100644 --- a/x-pack/plugins/spaces/server/lib/route_pre_check_license.ts +++ b/x-pack/plugins/spaces/server/lib/route_pre_check_license.ts @@ -9,12 +9,12 @@ import Boom from 'boom'; export function routePreCheckLicense(server: any) { const xpackMainPlugin = server.plugins.xpack_main; const pluginId = 'spaces'; - return function forbidApiAccess(request: any, reply: any) { + return function forbidApiAccess(request: any) { const licenseCheckResults = xpackMainPlugin.info.feature(pluginId).getLicenseCheckResults(); if (!licenseCheckResults.showSpaces) { - reply(Boom.forbidden(licenseCheckResults.linksMessage)); + return Boom.forbidden(licenseCheckResults.linksMessage); } else { - reply(); + return ''; } }; } diff --git a/x-pack/plugins/spaces/server/lib/space_request_interceptors.test.ts b/x-pack/plugins/spaces/server/lib/space_request_interceptors.test.ts index 5b8792c45de372..5fbe98a8a2f14c 100644 --- a/x-pack/plugins/spaces/server/lib/space_request_interceptors.test.ts +++ b/x-pack/plugins/spaces/server/lib/space_request_interceptors.test.ts @@ -29,8 +29,6 @@ describe('interceptors', () => { ) => { server = new Server(); - server.connection({ port: 0 }); - interface Config { [key: string]: any; } @@ -89,22 +87,22 @@ describe('interceptors', () => { { method: 'GET', path: '/', - handler: (req: any, reply: any) => { - return reply({ path: req.path, url: req.url, basePath: req.getBasePath() }); + handler: (req: any) => { + return { path: req.path, url: req.url, basePath: req.getBasePath() }; }, }, { method: 'GET', path: '/app/kibana', - handler: (req: any, reply: any) => { - return reply({ path: req.path, url: req.url, basePath: req.getBasePath() }); + handler: (req: any) => { + return { path: req.path, url: req.url, basePath: req.getBasePath() }; }, }, { method: 'GET', path: '/api/foo', - handler: (req: any, reply: any) => { - return reply({ path: req.path, url: req.url, basePath: req.getBasePath() }); + handler: (req: any) => { + return { path: req.path, url: req.url, basePath: req.getBasePath() }; }, }, ]); @@ -133,9 +131,9 @@ describe('interceptors', () => { describe('onRequest', () => { test('handles paths without a space identifier', async () => { - const testHandler = jest.fn((req, reply) => { + const testHandler = jest.fn((req, h) => { expect(req.path).toBe('/'); - return reply.continue(); + return h.continue; }); await request('/', (hapiServer: any) => { @@ -146,9 +144,9 @@ describe('interceptors', () => { }); test('strips the Space URL Context from the request', async () => { - const testHandler = jest.fn((req, reply) => { + const testHandler = jest.fn((req, h) => { expect(req.path).toBe('/'); - return reply.continue(); + return h.continue; }); await request('/s/foo', (hapiServer: any) => { @@ -159,9 +157,9 @@ describe('interceptors', () => { }); test('ignores space identifiers in the middle of the path', async () => { - const testHandler = jest.fn((req, reply) => { + const testHandler = jest.fn((req, h) => { expect(req.path).toBe('/some/path/s/foo/bar'); - return reply.continue(); + return h.continue; }); await request('/some/path/s/foo/bar', (hapiServer: any) => { @@ -172,12 +170,12 @@ describe('interceptors', () => { }); test('strips the Space URL Context from the request, maintaining the rest of the path', async () => { - const testHandler = jest.fn((req, reply) => { + const testHandler = jest.fn((req, h) => { expect(req.path).toBe('/i/love/spaces.html'); expect(req.query).toEqual({ queryParam: 'queryValue', }); - return reply.continue(); + return h.continue; }); await request('/s/foo/i/love/spaces.html?queryParam=queryValue', (hapiServer: any) => { @@ -210,7 +208,7 @@ describe('interceptors', () => { describe('when accessing an app within a non-existent space', () => { it('redirects to the space selector screen', async () => { - const testHandler = jest.fn((req, reply) => { + const testHandler = jest.fn((req, h) => { const { response } = req; if (response && response.isBoom) { @@ -220,7 +218,7 @@ describe('interceptors', () => { expect(response.statusCode).toEqual(302); expect(response.headers.location).toEqual(serverBasePath); - return reply.continue(); + return h.continue; }); const spaces = [ @@ -247,7 +245,7 @@ describe('interceptors', () => { describe('when accessing an API endpoint within a non-existent space', () => { it('allows the request to continue', async () => { - const testHandler = jest.fn((req, reply) => { + const testHandler = jest.fn((req, h) => { const { response } = req; if (response && response.isBoom) { @@ -256,7 +254,7 @@ describe('interceptors', () => { expect(response.statusCode).toEqual(200); - return reply.continue(); + return h.continue; }); const spaces = [ @@ -283,7 +281,7 @@ describe('interceptors', () => { describe('with a single available space', () => { test('it redirects to the defaultRoute within the context of the single Space when navigating to Kibana root', async () => { - const testHandler = jest.fn((req, reply) => { + const testHandler = jest.fn((req, h) => { const { response } = req; if (response && response.isBoom) { @@ -293,7 +291,7 @@ describe('interceptors', () => { expect(response.statusCode).toEqual(302); expect(response.headers.location).toEqual(`${serverBasePath}/s/a-space${defaultRoute}`); - return reply.continue(); + return h.continue; }); const spaces = [ @@ -329,7 +327,7 @@ describe('interceptors', () => { // which does not have a URL Context. In this scenario, the end result is the same as the other test, but the final URL the user // is redirected to does not contain a space identifier (e.g., /s/foo) - const testHandler = jest.fn((req, reply) => { + const testHandler = jest.fn((req, h) => { const { response } = req; if (response && response.isBoom) { @@ -339,7 +337,7 @@ describe('interceptors', () => { expect(response.statusCode).toEqual(302); expect(response.headers.location).toEqual(`${serverBasePath}${defaultRoute}`); - return reply.continue(); + return h.continue; }); const spaces = [ @@ -392,7 +390,7 @@ describe('interceptors', () => { const getHiddenUiAppHandler = jest.fn(() => '
space selector
'); - const testHandler = jest.fn((req, reply) => { + const testHandler = jest.fn((req, h) => { const { response } = req; if (response && response.isBoom) { @@ -402,14 +400,14 @@ describe('interceptors', () => { expect(response.statusCode).toEqual(200); expect(response.source).toEqual({ app: '
space selector
', renderApp: true }); - return reply.continue(); + return h.continue; }); await request( '/', (hapiServer: any) => { server.decorate('server', 'getHiddenUiAppById', getHiddenUiAppHandler); - server.decorate('reply', 'renderApp', function renderAppHandler(app: any) { + server.decorate('toolkit', 'renderApp', function renderAppHandler(app: any) { // @ts-ignore this({ renderApp: true, app }); }); diff --git a/x-pack/plugins/spaces/server/lib/space_request_interceptors.ts b/x-pack/plugins/spaces/server/lib/space_request_interceptors.ts index dd5b865d5fd8e2..baf1bdc061c164 100644 --- a/x-pack/plugins/spaces/server/lib/space_request_interceptors.ts +++ b/x-pack/plugins/spaces/server/lib/space_request_interceptors.ts @@ -12,7 +12,7 @@ import { addSpaceIdToPath, getSpaceIdFromPath } from './spaces_url_parser'; export function initSpacesRequestInterceptors(server: any) { const serverBasePath = server.config().get('server.basePath'); - server.ext('onRequest', async function spacesOnRequestHandler(request: any, reply: any) { + server.ext('onRequest', async function spacesOnRequestHandler(request: any, h: any) { const path = request.path; // If navigating within the context of a space, then we store the Space's URL Context on the request, @@ -35,10 +35,10 @@ export function initSpacesRequestInterceptors(server: any) { request.setUrl(newUrl); } - return reply.continue(); + return h.continue; }); - server.ext('onPostAuth', async function spacesOnRequestHandler(request: any, reply: any) { + server.ext('onPostAuth', async function spacesOnRequestHandler(request: any, h: any) { const path = request.path; const isRequestingKibanaRoot = path === '/'; @@ -62,18 +62,16 @@ export function initSpacesRequestInterceptors(server: any) { const space = spaces[0]; const destination = addSpaceIdToPath(basePath, space.id, defaultRoute); - return reply.redirect(destination); + return h.redirect(destination).takeover(); } if (spaces.length > 0) { // render spaces selector instead of home page const app = server.getHiddenUiAppById('space_selector'); - return reply.renderApp(app, { - spaces, - }); + return (await h.renderApp(app, { spaces })).takeover(); } } catch (error) { - return reply(wrapError(error)); + return wrapError(error); } } @@ -94,9 +92,9 @@ export function initSpacesRequestInterceptors(server: any) { `Unable to navigate to space "${spaceId}", redirecting to Space Selector. ${error}` ); // Space doesn't exist, or user not authorized for space, or some other issue retrieving the active space. - return reply.redirect(getSpaceSelectorUrl(server.config())); + return h.redirect(getSpaceSelectorUrl(server.config())).takeover(); } } - return reply.continue(); + return h.continue; }); } diff --git a/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_test_handler.ts b/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_test_handler.ts index db30e9fd111ca4..74f80ba2ff3b72 100644 --- a/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_test_handler.ts +++ b/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_test_handler.ts @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Server } from 'hapi'; +// @ts-ignore +import { PluginProperties, Server } from 'hapi'; import { SpacesClient } from '../../../lib/spaces_client'; import { createSpaces } from './create_spaces'; @@ -20,7 +21,7 @@ export interface TestOptions { setupFn?: (server: any) => void; testConfig?: TestConfig; payload?: any; - preCheckLicenseImpl?: (req: any, reply: any) => any; + preCheckLicenseImpl?: (req: any, h: any) => any; expectSpacesClientCall?: boolean; } @@ -38,13 +39,24 @@ export type RequestRunner = ( options?: TestOptions ) => Promise; -export const defaultPreCheckLicenseImpl = (request: any, reply: any) => reply(); +export const defaultPreCheckLicenseImpl = (request: any) => ''; const baseConfig: TestConfig = { 'server.basePath': '', 'xpack.spaces.maxSpaces': 1000, }; +// Merge / extend default interfaces for hapi. This is all faked out below. +declare module 'hapi' { + interface Server { + savedObjects: any; + } + + interface PluginProperties { + spaces: any; + } +} + export function createTestHandler(initApiFn: (server: any, preCheckLicenseImpl: any) => void) { const teardowns: TeardownFn[] = []; @@ -77,8 +89,6 @@ export function createTestHandler(initApiFn: (server: any, preCheckLicenseImpl: ...testConfig, }; - server.connection({ port: 0 }); - await setupFn(server); const mockConfig = { diff --git a/x-pack/plugins/spaces/server/routes/api/public/delete.test.ts b/x-pack/plugins/spaces/server/routes/api/public/delete.test.ts index 21948e28c56d6a..a1a23604f159ab 100644 --- a/x-pack/plugins/spaces/server/routes/api/public/delete.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/public/delete.test.ts @@ -6,7 +6,7 @@ jest.mock('../../../lib/route_pre_check_license', () => { return { - routePreCheckLicense: () => (request: any, reply: any) => reply.continue(), + routePreCheckLicense: () => (request: any, h: any) => h.continue, }; }); @@ -50,8 +50,7 @@ describe('Spaces Public API', () => { test(`returns result of routePreCheckLicense`, async () => { const { response } = await request('DELETE', '/api/spaces/space/a-space', { - preCheckLicenseImpl: (req: any, reply: any) => - reply(Boom.forbidden('test forbidden message')), + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), expectSpacesClientCall: false, }); diff --git a/x-pack/plugins/spaces/server/routes/api/public/delete.ts b/x-pack/plugins/spaces/server/routes/api/public/delete.ts index 080c765dd4a44d..c9536ab2c9782b 100644 --- a/x-pack/plugins/spaces/server/routes/api/public/delete.ts +++ b/x-pack/plugins/spaces/server/routes/api/public/delete.ts @@ -12,7 +12,7 @@ export function initDeleteSpacesApi(server: any, routePreCheckLicenseFn: any) { server.route({ method: 'DELETE', path: '/api/spaces/space/{id}', - async handler(request: any, reply: any) { + async handler(request: any, h: any) { const { SavedObjectsClient } = server.savedObjects; const spacesClient: SpacesClient = server.plugins.spaces.spacesClient.getScopedClient( request @@ -26,12 +26,12 @@ export function initDeleteSpacesApi(server: any, routePreCheckLicenseFn: any) { result = await spacesClient.delete(id); } catch (error) { if (SavedObjectsClient.errors.isNotFoundError(error)) { - return reply(Boom.notFound()); + return Boom.notFound(); } - return reply(wrapError(error)); + return wrapError(error); } - return reply(result).code(204); + return h.response(result).code(204); }, config: { pre: [routePreCheckLicenseFn], diff --git a/x-pack/plugins/spaces/server/routes/api/public/get.test.ts b/x-pack/plugins/spaces/server/routes/api/public/get.test.ts index ad3e758853e01d..daef9c54633c5d 100644 --- a/x-pack/plugins/spaces/server/routes/api/public/get.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/public/get.test.ts @@ -6,7 +6,7 @@ jest.mock('../../../lib/route_pre_check_license', () => { return { - routePreCheckLicense: () => (request: any, reply: any) => reply.continue(), + routePreCheckLicense: () => (request: any, h: any) => h.continue, }; }); @@ -54,8 +54,7 @@ describe('GET spaces', () => { test(`returns result of routePreCheckLicense`, async () => { const { response } = await request('GET', '/api/spaces/space', { - preCheckLicenseImpl: (req: any, reply: any) => - reply(Boom.forbidden('test forbidden message')), + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), expectSpacesClientCall: false, }); diff --git a/x-pack/plugins/spaces/server/routes/api/public/get.ts b/x-pack/plugins/spaces/server/routes/api/public/get.ts index ae3a083c50123a..4702ff9136415d 100644 --- a/x-pack/plugins/spaces/server/routes/api/public/get.ts +++ b/x-pack/plugins/spaces/server/routes/api/public/get.ts @@ -13,7 +13,7 @@ export function initGetSpacesApi(server: any, routePreCheckLicenseFn: any) { server.route({ method: 'GET', path: '/api/spaces/space', - async handler(request: any, reply: any) { + async handler(request: any) { const spacesClient: SpacesClient = server.plugins.spaces.spacesClient.getScopedClient( request ); @@ -23,10 +23,10 @@ export function initGetSpacesApi(server: any, routePreCheckLicenseFn: any) { try { spaces = await spacesClient.getAll(); } catch (error) { - return reply(wrapError(error)); + return wrapError(error); } - return reply(spaces); + return spaces; }, config: { pre: [routePreCheckLicenseFn], @@ -36,7 +36,7 @@ export function initGetSpacesApi(server: any, routePreCheckLicenseFn: any) { server.route({ method: 'GET', path: '/api/spaces/space/{id}', - async handler(request: any, reply: any) { + async handler(request: any) { const spaceId = request.params.id; const { SavedObjectsClient } = server.savedObjects; @@ -45,12 +45,12 @@ export function initGetSpacesApi(server: any, routePreCheckLicenseFn: any) { ); try { - return reply(await spacesClient.get(spaceId)); + return await spacesClient.get(spaceId); } catch (error) { if (SavedObjectsClient.errors.isNotFoundError(error)) { - return reply(Boom.notFound()); + return Boom.notFound(); } - return reply(wrapError(error)); + return wrapError(error); } }, config: { diff --git a/x-pack/plugins/spaces/server/routes/api/public/post.test.ts b/x-pack/plugins/spaces/server/routes/api/public/post.test.ts index b554d5fc67354a..cf69882f9857d6 100644 --- a/x-pack/plugins/spaces/server/routes/api/public/post.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/public/post.test.ts @@ -6,7 +6,7 @@ jest.mock('../../../lib/route_pre_check_license', () => { return { - routePreCheckLicense: () => (request: any, reply: any) => reply.continue(), + routePreCheckLicense: () => (request: any, h: any) => h.continue, }; }); @@ -71,8 +71,7 @@ describe('Spaces Public API', () => { }; const { response } = await request('POST', '/api/spaces/space', { - preCheckLicenseImpl: (req: any, reply: any) => - reply(Boom.forbidden('test forbidden message')), + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), expectSpacesClientCall: false, payload, }); diff --git a/x-pack/plugins/spaces/server/routes/api/public/post.ts b/x-pack/plugins/spaces/server/routes/api/public/post.ts index a4c1e04a73831b..a4aa1219925384 100644 --- a/x-pack/plugins/spaces/server/routes/api/public/post.ts +++ b/x-pack/plugins/spaces/server/routes/api/public/post.ts @@ -13,7 +13,7 @@ export function initPostSpacesApi(server: any, routePreCheckLicenseFn: any) { server.route({ method: 'POST', path: '/api/spaces/space', - async handler(request: any, reply: any) { + async handler(request: any) { const { SavedObjectsClient } = server.savedObjects; const spacesClient: SpacesClient = server.plugins.spaces.spacesClient.getScopedClient( request @@ -22,12 +22,12 @@ export function initPostSpacesApi(server: any, routePreCheckLicenseFn: any) { const space = request.payload; try { - return reply(await spacesClient.create(space)); + return await spacesClient.create(space); } catch (error) { if (SavedObjectsClient.errors.isConflictError(error)) { - return reply(Boom.conflict(`A space with the identifier ${space.id} already exists.`)); + return Boom.conflict(`A space with the identifier ${space.id} already exists.`); } - return reply(wrapError(error)); + return wrapError(error); } }, config: { diff --git a/x-pack/plugins/spaces/server/routes/api/public/put.test.ts b/x-pack/plugins/spaces/server/routes/api/public/put.test.ts index c44cabd72bf428..35c5779a236ae1 100644 --- a/x-pack/plugins/spaces/server/routes/api/public/put.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/public/put.test.ts @@ -5,7 +5,7 @@ */ jest.mock('../../../lib/route_pre_check_license', () => { return { - routePreCheckLicense: () => (request: any, reply: any) => reply.continue(), + routePreCheckLicense: () => (request: any, h: any) => h.continue, }; }); @@ -97,8 +97,7 @@ describe('Spaces Public API', () => { }; const { response } = await request('PUT', '/api/spaces/space/a-space', { - preCheckLicenseImpl: (req: any, reply: any) => - reply(Boom.forbidden('test forbidden message')), + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), expectSpacesClientCall: false, payload, }); diff --git a/x-pack/plugins/spaces/server/routes/api/public/put.ts b/x-pack/plugins/spaces/server/routes/api/public/put.ts index dea7e3a79d5c0b..08d6646db90f68 100644 --- a/x-pack/plugins/spaces/server/routes/api/public/put.ts +++ b/x-pack/plugins/spaces/server/routes/api/public/put.ts @@ -14,7 +14,7 @@ export function initPutSpacesApi(server: any, routePreCheckLicenseFn: any) { server.route({ method: 'PUT', path: '/api/spaces/space/{id}', - async handler(request: any, reply: any) { + async handler(request: any) { const { SavedObjectsClient } = server.savedObjects; const spacesClient: SpacesClient = server.plugins.spaces.spacesClient.getScopedClient( request @@ -28,12 +28,12 @@ export function initPutSpacesApi(server: any, routePreCheckLicenseFn: any) { result = await spacesClient.update(id, { ...space }); } catch (error) { if (SavedObjectsClient.errors.isNotFoundError(error)) { - return reply(Boom.notFound()); + return Boom.notFound(); } - return reply(wrapError(error)); + return wrapError(error); } - return reply(result); + return result; }, config: { validate: { diff --git a/x-pack/plugins/spaces/server/routes/api/v1/spaces.test.ts b/x-pack/plugins/spaces/server/routes/api/v1/spaces.test.ts index 0758ceb32746ca..4ad464d3ea119d 100644 --- a/x-pack/plugins/spaces/server/routes/api/v1/spaces.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/v1/spaces.test.ts @@ -6,7 +6,7 @@ jest.mock('../../../lib/route_pre_check_license', () => { return { - routePreCheckLicense: () => (request: any, reply: any) => reply.continue(), + routePreCheckLicense: () => (request: any, h: any) => h.continue, }; }); @@ -54,8 +54,7 @@ describe('Spaces API', () => { test(`returns result of routePreCheckLicense`, async () => { const { response } = await request('POST', '/api/spaces/v1/space/a-space/select', { - preCheckLicenseImpl: (req: any, reply: any) => - reply(Boom.forbidden('test forbidden message')), + preCheckLicenseImpl: () => Boom.forbidden('test forbidden message'), expectSpacesClientCall: false, }); diff --git a/x-pack/plugins/spaces/server/routes/api/v1/spaces.ts b/x-pack/plugins/spaces/server/routes/api/v1/spaces.ts index 6f09d1831bff9a..427878e2caf2ff 100644 --- a/x-pack/plugins/spaces/server/routes/api/v1/spaces.ts +++ b/x-pack/plugins/spaces/server/routes/api/v1/spaces.ts @@ -15,7 +15,7 @@ export function initPrivateSpacesApi(server: any, routePreCheckLicenseFn: any) { server.route({ method: 'POST', path: '/api/spaces/v1/space/{id}/select', - async handler(request: any, reply: any) { + async handler(request: any) { const { SavedObjectsClient } = server.savedObjects; const spacesClient: SpacesClient = server.plugins.spaces.spacesClient.getScopedClient( request @@ -30,20 +30,20 @@ export function initPrivateSpacesApi(server: any, routePreCheckLicenseFn: any) { SavedObjectsClient.errors ); if (!existingSpace) { - return reply(Boom.notFound()); + return Boom.notFound(); } const config = server.config(); - return reply({ + return { location: addSpaceIdToPath( config.get('server.basePath'), existingSpace.id, config.get('server.defaultRoute') ), - }); + }; } catch (error) { - return reply(wrapError(error)); + return wrapError(error); } }, config: { diff --git a/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_custom_error.js b/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_custom_error.js index 890a366ac65c1e..3295113d38ee5a 100644 --- a/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_custom_error.js +++ b/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_custom_error.js @@ -14,5 +14,5 @@ import Boom from 'boom'; * @return Object Boom error response */ export function wrapCustomError(err, statusCode) { - return Boom.wrap(err, statusCode); + return Boom.boomify(err, { statusCode }); } diff --git a/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_es_error.js b/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_es_error.js index 3d69ff19a6c848..2df2e4b802e1a1 100644 --- a/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_es_error.js +++ b/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_es_error.js @@ -20,11 +20,11 @@ export function wrapEsError(err, statusCodeToMessageMap = {}) { // If no custom message if specified for the error's status code, just // wrap the error as a Boom error response and return it if (!statusCodeToMessageMap[statusCode]) { - return Boom.wrap(err, err.statusCode); + return Boom.boomify(err, { statusCode }); } // Otherwise, use the custom message to create a Boom error response and // return it const message = statusCodeToMessageMap[statusCode]; - return Boom.create(statusCode, message); -} \ No newline at end of file + return new Boom(message, { statusCode }); +} diff --git a/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_unknown_error.js b/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_unknown_error.js index ca72fa00309221..4b865880ae20de 100644 --- a/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_unknown_error.js +++ b/x-pack/plugins/watcher/server/lib/error_wrappers/wrap_unknown_error.js @@ -13,5 +13,5 @@ import Boom from 'boom'; * @return Object Boom error response */ export function wrapUnknownError(err) { - return Boom.wrap(err); + return Boom.boomify(err); } \ No newline at end of file diff --git a/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js index b72f8cc7697310..359b3fb2ce6f4f 100644 --- a/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ b/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js @@ -40,14 +40,13 @@ describe('license_pre_routing_factory', () => { }; }); - it ('replies with 403', (done) => { + it ('replies with 403', () => { const licensePreRouting = licensePreRoutingFactory(mockServer); const stubRequest = {}; - licensePreRouting(stubRequest, (response) => { + expect(() => licensePreRouting(stubRequest)).to.throwException((response) => { expect(response).to.be.an(Error); expect(response.isBoom).to.be(true); expect(response.output.statusCode).to.be(403); - done(); }); }); }); @@ -59,13 +58,11 @@ describe('license_pre_routing_factory', () => { }; }); - it ('replies with nothing', (done) => { + it ('replies with nothing', () => { const licensePreRouting = licensePreRoutingFactory(mockServer); const stubRequest = {}; - licensePreRouting(stubRequest, (response) => { - expect(response).to.be(undefined); - done(); - }); + const response = licensePreRouting(stubRequest); + expect(response).to.be(null); }); }); }); diff --git a/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/license_pre_routing_factory.js b/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/license_pre_routing_factory.js index b3720ab265393b..11e01304b6e5cf 100644 --- a/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/license_pre_routing_factory.js +++ b/x-pack/plugins/watcher/server/lib/license_pre_routing_factory/license_pre_routing_factory.js @@ -12,16 +12,15 @@ export const licensePreRoutingFactory = once((server) => { const xpackMainPlugin = server.plugins.xpack_main; // License checking and enable/disable logic - function licensePreRouting(request, reply) { + function licensePreRouting() { const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults(); if (!licenseCheckResults.isAvailable) { const error = new Error(licenseCheckResults.message); const statusCode = 403; - const wrappedError = wrapCustomError(error, statusCode); - reply(wrappedError); - } else { - reply(); + throw wrapCustomError(error, statusCode); } + + return null; } return licensePreRouting; diff --git a/x-pack/plugins/watcher/server/routes/api/fields/register_list_route.js b/x-pack/plugins/watcher/server/routes/api/fields/register_list_route.js index fac63494db64f0..7d45d3a2aa60b4 100644 --- a/x-pack/plugins/watcher/server/routes/api/fields/register_list_route.js +++ b/x-pack/plugins/watcher/server/routes/api/fields/register_list_route.js @@ -29,7 +29,7 @@ export function registerListRoute(server) { server.route({ path: '/api/watcher/fields', method: 'POST', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const { indexes } = request.payload; @@ -41,16 +41,16 @@ export function registerListRoute(server) { const fields = Fields.fromUpstreamJson(json); - reply(fields.downstreamJson); + return fields.downstreamJson; }) .catch(err => { // Case: Error from Elasticsearch JS client if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/history/register_load_route.js b/x-pack/plugins/watcher/server/routes/api/history/register_load_route.js index fd1953b5e1fc36..5011e7df313ab3 100644 --- a/x-pack/plugins/watcher/server/routes/api/history/register_load_route.js +++ b/x-pack/plugins/watcher/server/routes/api/history/register_load_route.js @@ -34,7 +34,7 @@ export function registerLoadRoute(server) { server.route({ path: '/api/watcher/history/{id}', method: 'GET', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const id = request.params.id; @@ -42,10 +42,8 @@ export function registerLoadRoute(server) { .then((responseFromES) => { const hit = get(responseFromES, 'hits.hits[0]'); if (!hit) { - return reply( - wrapCustomError( - new Error(`Watch History Item with id = ${id} not found`), 404 - ) + throw wrapCustomError( + new Error(`Watch History Item with id = ${id} not found`), 404 ); } @@ -59,16 +57,18 @@ export function registerLoadRoute(server) { }; const watchHistoryItem = WatchHistoryItem.fromUpstreamJson(json); - reply({ watchHistoryItem: watchHistoryItem.downstreamJson }); + ({ + watchHistoryItem: watchHistoryItem.downstreamJson + }); }) .catch(err => { // Case: Error from Elasticsearch JS client if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } // Case: default - reply(wrapUnknownError(err)); + wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/indices/register_get_route.js b/x-pack/plugins/watcher/server/routes/api/indices/register_get_route.js index 31007b1653056b..86de6f3da7ad52 100644 --- a/x-pack/plugins/watcher/server/routes/api/indices/register_get_route.js +++ b/x-pack/plugins/watcher/server/routes/api/indices/register_get_route.js @@ -64,22 +64,22 @@ export function registerGetRoute(server) { server.route({ path: '/api/watcher/indices', method: 'POST', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const { pattern } = request.payload; return getIndices(callWithRequest, pattern) .then(indices => { - reply({ indices }); + return { indices }; }) .catch(err => { - // Case: Error from Elasticsearch JS client + // Case: Error from Elasticsearch JS client if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/license/register_refresh_route.js b/x-pack/plugins/watcher/server/routes/api/license/register_refresh_route.js index 20394e8f624200..cbd5dc7f6631f4 100644 --- a/x-pack/plugins/watcher/server/routes/api/license/register_refresh_route.js +++ b/x-pack/plugins/watcher/server/routes/api/license/register_refresh_route.js @@ -18,8 +18,8 @@ export function registerRefreshRoute(server) { server.route({ path: '/api/watcher/license/refresh', method: 'GET', - handler: (request, reply) => { - reply({ success: true }); + handler: () => { + return { success: true }; }, config: { pre: [ licensePreRouting ] diff --git a/x-pack/plugins/watcher/server/routes/api/settings/register_load_route.js b/x-pack/plugins/watcher/server/routes/api/settings/register_load_route.js index 9180a7b28f30d9..65c961c8c82f2c 100644 --- a/x-pack/plugins/watcher/server/routes/api/settings/register_load_route.js +++ b/x-pack/plugins/watcher/server/routes/api/settings/register_load_route.js @@ -25,20 +25,19 @@ export function registerLoadRoute(server) { server.route({ path: '/api/watcher/settings', method: 'GET', - handler: (request, reply) => { + handler: () => { return fetchClusterSettings(callWithInternalUser) .then((settings) => { - reply(Settings.fromUpstreamJson(settings).downstreamJson); + return Settings.fromUpstreamJson(settings).downstreamJson; }) .catch(err => { - // Case: Error from Elasticsearch JS client if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/watch/action/register_acknowledge_route.js b/x-pack/plugins/watcher/server/routes/api/watch/action/register_acknowledge_route.js index 94689ea2d4f76c..ffecebf805cf6b 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/action/register_acknowledge_route.js +++ b/x-pack/plugins/watcher/server/routes/api/watch/action/register_acknowledge_route.js @@ -19,7 +19,7 @@ export function registerAcknowledgeRoute(server) { server.route({ path: '/api/watcher/watch/{watchId}/action/{actionId}/acknowledge', method: 'PUT', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const { watchId, actionId } = request.params; @@ -32,20 +32,21 @@ export function registerAcknowledgeRoute(server) { }; const watchStatus = WatchStatus.fromUpstreamJson(json); - reply({ watchStatus: watchStatus.downstreamJson }); + return { + watchStatus: watchStatus.downstreamJson + }; }) .catch(err => { - // Case: Error from Elasticsearch JS client if (isEsError(err)) { const statusCodeToMessageMap = { 404: `Watch with id = ${watchId} not found` }; - return reply(wrapEsError(err, statusCodeToMessageMap)); + throw wrapEsError(err, statusCodeToMessageMap); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_activate_route.js b/x-pack/plugins/watcher/server/routes/api/watch/register_activate_route.js index 8858650e6c2861..ea669a16a01722 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_activate_route.js +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_activate_route.js @@ -25,7 +25,7 @@ export function registerActivateRoute(server) { server.route({ path: '/api/watcher/watch/{watchId}/activate', method: 'PUT', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const { watchId } = request.params; @@ -39,20 +39,21 @@ export function registerActivateRoute(server) { }; const watchStatus = WatchStatus.fromUpstreamJson(json); - reply({ watchStatus: watchStatus.downstreamJson }); + return { + watchStatus: watchStatus.downstreamJson + }; }) .catch(err => { - // Case: Error from Elasticsearch JS client if (isEsError(err)) { const statusCodeToMessageMap = { 404: `Watch with id = ${watchId} not found` }; - return reply(wrapEsError(err, statusCodeToMessageMap)); + throw wrapEsError(err, statusCodeToMessageMap); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_deactivate_route.js b/x-pack/plugins/watcher/server/routes/api/watch/register_deactivate_route.js index e08dae47005280..2411290e2034a9 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_deactivate_route.js +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_deactivate_route.js @@ -25,7 +25,7 @@ export function registerDeactivateRoute(server) { server.route({ path: '/api/watcher/watch/{watchId}/deactivate', method: 'PUT', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const { watchId } = request.params; @@ -39,20 +39,21 @@ export function registerDeactivateRoute(server) { }; const watchStatus = WatchStatus.fromUpstreamJson(json); - reply({ watchStatus: watchStatus.downstreamJson }); + return { + watchStatus: watchStatus.downstreamJson + }; }) .catch(err => { - // Case: Error from Elasticsearch JS client if (isEsError(err)) { const statusCodeToMessageMap = { 404: `Watch with id = ${watchId} not found` }; - return reply(wrapEsError(err, statusCodeToMessageMap)); + throw wrapEsError(err, statusCodeToMessageMap); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_delete_route.js b/x-pack/plugins/watcher/server/routes/api/watch/register_delete_route.js index 7c823e24dbcfe6..3312dc88893827 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_delete_route.js +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_delete_route.js @@ -23,25 +23,24 @@ export function registerDeleteRoute(server) { server.route({ path: '/api/watcher/watch/{watchId}', method: 'DELETE', - handler: (request, reply) => { + handler: (request, h) => { const callWithRequest = callWithRequestFactory(server, request); const { watchId } = request.params; return deleteWatch(callWithRequest, watchId) - .then(() => reply().code(204)) + .then(() => h.response().code(204)) .catch(err => { - // Case: Error from Elasticsearch JS client if (isEsError(err)) { const statusCodeToMessageMap = { 404: `Watch with id = ${watchId} not found` }; - return reply(wrapEsError(err, statusCodeToMessageMap)); + throw wrapEsError(err, statusCodeToMessageMap); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_execute_route.js b/x-pack/plugins/watcher/server/routes/api/watch/register_execute_route.js index 765ca7ec05c4d2..c3af87172072da 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_execute_route.js +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_execute_route.js @@ -29,7 +29,7 @@ export function registerExecuteRoute(server) { server.route({ path: '/api/watcher/watch/execute', method: 'PUT', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const executeDetails = ExecuteDetails.fromDownstreamJson(request.payload.executeDetails); const watch = Watch.fromDownstreamJson(request.payload.watch); @@ -47,17 +47,19 @@ export function registerExecuteRoute(server) { }; const watchHistoryItem = WatchHistoryItem.fromUpstreamJson(json); - reply({ watchHistoryItem: watchHistoryItem.downstreamJson }); + ({ + watchHistoryItem: watchHistoryItem.downstreamJson + }); }) .catch(err => { // Case: Error from Elasticsearch JS client if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } // Case: default - reply(wrapUnknownError(err)); + wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_history_route.js b/x-pack/plugins/watcher/server/routes/api/watch/register_history_route.js index 6d801ade25a5e9..702cf8a2b64e27 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_history_route.js +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_history_route.js @@ -49,7 +49,7 @@ export function registerHistoryRoute(server) { server.route({ path: '/api/watcher/watch/{watchId}/history', method: 'GET', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const { watchId } = request.params; const { startTime } = request.query; @@ -68,18 +68,18 @@ export function registerHistoryRoute(server) { }, opts); }); - reply({ + return { watchHistoryItems: watchHistoryItems.map(watchHistoryItem => watchHistoryItem.downstreamJson) - }); + }; }) .catch(err => { - // Case: Error from Elasticsearch JS client + // Case: Error from Elasticsearch JS client if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_load_route.js b/x-pack/plugins/watcher/server/routes/api/watch/register_load_route.js index f225169ac25a7d..96cfccba7a16d8 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_load_route.js +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_load_route.js @@ -24,7 +24,7 @@ export function registerLoadRoute(server) { server.route({ path: '/api/watcher/watch/{id}', method: 'GET', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const id = request.params.id; @@ -40,20 +40,21 @@ export function registerLoadRoute(server) { }; const watch = Watch.fromUpstreamJson(json); - reply({ watch: watch.downstreamJson }); + return { + watch: watch.downstreamJson + }; }) .catch(err => { - // Case: Error from Elasticsearch JS client if (isEsError(err)) { const statusCodeToMessageMap = { 404: `Watch with id = ${id} not found` }; - return reply(wrapEsError(err, statusCodeToMessageMap)); + throw wrapEsError(err, statusCodeToMessageMap); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_save_route.js b/x-pack/plugins/watcher/server/routes/api/watch/register_save_route.js index 6a2247408b529f..3434a0ab559f28 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_save_route.js +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_save_route.js @@ -25,22 +25,20 @@ export function registerSaveRoute(server) { server.route({ path: '/api/watcher/watch/{id}', method: 'PUT', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const watch = Watch.fromDownstreamJson(request.payload); return saveWatch(callWithRequest, watch.upstreamJson) - .then(reply) .catch(err => { - // Case: Error from Elasticsearch JS client if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.js b/x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.js index 782f72f7ab4510..ff9d8f9775d5ed 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.js +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.js @@ -30,7 +30,7 @@ export function registerVisualizeRoute(server) { server.route({ path: '/api/watcher/watch/visualize', method: 'POST', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); const watch = Watch.fromDownstreamJson(request.payload.watch); const options = VisualizeOptions.fromDownstreamJson(request.payload.options); @@ -40,17 +40,19 @@ export function registerVisualizeRoute(server) { .then(hits => { const visualizeData = watch.formatVisualizeData(hits); - reply({ visualizeData }); + return { + visualizeData + }; }) .catch(err => { // Case: Error from Elasticsearch JS client if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.js b/x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.js index ae0ca5c24e13bd..0112aefbe77e47 100644 --- a/x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.js +++ b/x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.js @@ -36,16 +36,15 @@ export function registerDeleteRoute(server) { server.route({ path: '/api/watcher/watches', method: 'DELETE', - handler: (request, reply) => { + handler: async (request) => { const callWithRequest = callWithRequestFactory(server, request); - return deleteWatches(callWithRequest, request.payload.watchIds) - .then(results => { - reply({ results }); - }) - .catch(err => { - reply(wrapUnknownError(err)); - }); + try { + const results = await deleteWatches(callWithRequest, request.payload.watchIds); + return { results }; + } catch (err) { + throw wrapUnknownError(err); + } }, config: { pre: [ licensePreRouting ] diff --git a/x-pack/plugins/watcher/server/routes/api/watches/register_list_route.js b/x-pack/plugins/watcher/server/routes/api/watches/register_list_route.js index a1a29cca4cd8d4..e3424386dc705c 100644 --- a/x-pack/plugins/watcher/server/routes/api/watches/register_list_route.js +++ b/x-pack/plugins/watcher/server/routes/api/watches/register_list_route.js @@ -34,7 +34,7 @@ export function registerListRoute(server) { server.route({ path: '/api/watcher/watches', method: 'GET', - handler: (request, reply) => { + handler: (request) => { const callWithRequest = callWithRequestFactory(server, request); return fetchWatches(callWithRequest) @@ -51,19 +51,18 @@ export function registerListRoute(server) { }); }); - reply({ + return { watches: watches.map(watch => watch.downstreamJson) - }); + }; }) .catch(err => { - // Case: Error from Elasticsearch JS client if (isEsError(err)) { - return reply(wrapEsError(err)); + throw wrapEsError(err); } // Case: default - reply(wrapUnknownError(err)); + throw wrapUnknownError(err); }); }, config: { diff --git a/x-pack/plugins/xpack_main/server/lib/__tests__/inject_xpack_info_signature.js b/x-pack/plugins/xpack_main/server/lib/__tests__/inject_xpack_info_signature.js index ba62b338be4077..c044636a2c93a6 100644 --- a/x-pack/plugins/xpack_main/server/lib/__tests__/inject_xpack_info_signature.js +++ b/x-pack/plugins/xpack_main/server/lib/__tests__/inject_xpack_info_signature.js @@ -20,7 +20,8 @@ describe('injectXPackInfoSignature()', () => { } } - let mockReply; + const fakeH = { continue: 'blah' }; + let mockXPackInfo; beforeEach(() => { mockXPackInfo = sinon.stub({ @@ -28,10 +29,6 @@ describe('injectXPackInfoSignature()', () => { getSignature() {}, refreshNow() {} }); - - mockReply = sinon.stub({ - continue() {} - }); }); describe('error response', () => { @@ -49,11 +46,11 @@ describe('injectXPackInfoSignature()', () => { }; const mockResponse = new MockErrorResponse(); - await injectXPackInfoSignature(mockXPackInfo, { response: mockResponse }, mockReply); + const response = await injectXPackInfoSignature(mockXPackInfo, { response: mockResponse }, fakeH); expect(mockResponse.headers).to.eql({}); expect(mockResponse.output.headers).to.eql({}); - sinon.assert.calledOnce(mockReply.continue); + expect(response).to.be(fakeH.continue); }); it('refreshes `xpackInfo` and injects its updated signature.', async () => { @@ -70,13 +67,13 @@ describe('injectXPackInfoSignature()', () => { }; const mockResponse = new MockErrorResponse(); - await injectXPackInfoSignature(mockXPackInfo, { response: mockResponse }, mockReply); + const response = await injectXPackInfoSignature(mockXPackInfo, { response: mockResponse }, fakeH); expect(mockResponse.headers).to.eql({}); expect(mockResponse.output.headers).to.eql({ 'kbn-xpack-sig': 'new-signature' }); - sinon.assert.calledOnce(mockReply.continue); + expect(response).to.be(fakeH.continue); }); }); @@ -86,12 +83,12 @@ describe('injectXPackInfoSignature()', () => { mockXPackInfo.getSignature.returns('this-should-never-be-set'); const mockResponse = { headers: {}, output: { headers: {} } }; - await injectXPackInfoSignature(mockXPackInfo, { response: mockResponse }, mockReply); + const response = await injectXPackInfoSignature(mockXPackInfo, { response: mockResponse }, fakeH); expect(mockResponse.headers).to.eql({}); expect(mockResponse.output.headers).to.eql({}); sinon.assert.notCalled(mockXPackInfo.refreshNow); - sinon.assert.calledOnce(mockReply.continue); + expect(response).to.be(fakeH.continue); }); it('injects signature if `xpackInfo` is available.', async () => { @@ -99,14 +96,14 @@ describe('injectXPackInfoSignature()', () => { mockXPackInfo.getSignature.returns('available-signature'); const mockResponse = { headers: {}, output: { headers: {} } }; - await injectXPackInfoSignature(mockXPackInfo, { response: mockResponse }, mockReply); + const response = await injectXPackInfoSignature(mockXPackInfo, { response: mockResponse }, fakeH); expect(mockResponse.headers).to.eql({ 'kbn-xpack-sig': 'available-signature' }); expect(mockResponse.output.headers).to.eql({}); sinon.assert.notCalled(mockXPackInfo.refreshNow); - sinon.assert.calledOnce(mockReply.continue); + expect(response).to.be(fakeH.continue); }); }); }); diff --git a/x-pack/plugins/xpack_main/server/lib/inject_xpack_info_signature.js b/x-pack/plugins/xpack_main/server/lib/inject_xpack_info_signature.js index b9522d132bfbdc..166bd2b4755f05 100644 --- a/x-pack/plugins/xpack_main/server/lib/inject_xpack_info_signature.js +++ b/x-pack/plugins/xpack_main/server/lib/inject_xpack_info_signature.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export async function injectXPackInfoSignature(info, request, reply) { +export async function injectXPackInfoSignature(info, request, h) { // If we're returning an error response, refresh xpack info from // Elasticsearch in case the error is due to a change in license information // in Elasticsearch. @@ -21,5 +21,5 @@ export async function injectXPackInfoSignature(info, request, reply) { response.headers['kbn-xpack-sig'] = info.getSignature(); } - return reply.continue(); + return h.continue; } diff --git a/x-pack/plugins/xpack_main/server/lib/setup_xpack_main.js b/x-pack/plugins/xpack_main/server/lib/setup_xpack_main.js index 3718fdb5e8ff7d..125e481c384a16 100644 --- a/x-pack/plugins/xpack_main/server/lib/setup_xpack_main.js +++ b/x-pack/plugins/xpack_main/server/lib/setup_xpack_main.js @@ -22,7 +22,7 @@ export function setupXPackMain(server) { server.expose('info', info); server.expose('createXPackInfo', (options) => new XPackInfo(server, options)); - server.ext('onPreResponse', (request, reply) => injectXPackInfoSignature(info, request, reply)); + server.ext('onPreResponse', (request, h) => injectXPackInfoSignature(info, request, h)); const setPluginStatus = () => { if (info.isAvailable()) { diff --git a/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js b/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js index 06f5b8885f7dd5..9e095a12dad78e 100644 --- a/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js +++ b/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ +import expect from 'expect.js'; import sinon from 'sinon'; import { xpackInfoRoute } from '../xpack_info'; describe('XPackInfo routes', () => { let serverStub; - let replyStub; beforeEach(() => { serverStub = { route: sinon.stub(), @@ -21,8 +21,6 @@ describe('XPackInfo routes', () => { } }; - replyStub = sinon.stub(); - xpackInfoRoute(serverStub); }); @@ -38,16 +36,11 @@ describe('XPackInfo routes', () => { serverStub.plugins.xpack_main.info.isAvailable.returns(false); const onRouteHandler = serverStub.route.firstCall.args[0].handler; - onRouteHandler({}, replyStub); + const response = onRouteHandler(); - sinon.assert.calledWithExactly( - replyStub, - sinon.match({ - isBoom: true, - message: 'Not Found', - output: { statusCode: 404 }, - }) - ); + expect(response.isBoom).to.be(true); + expect(response.message).to.be('Not Found'); + expect(response.output.statusCode).to.be(404); }); it('replies with pre-processed `xpackInfo` if it is available.', () => { @@ -71,27 +64,24 @@ describe('XPackInfo routes', () => { }); const onRouteHandler = serverStub.route.firstCall.args[0].handler; - onRouteHandler({}, replyStub); + const response = onRouteHandler(); - sinon.assert.calledWithExactly( - replyStub, - { - license: { - type: 'gold', - is_active: true, - expiry_date_in_millis: 1509368280381 - }, - features: { - security: { - show_login: true, - allow_login: true, - show_links: false, - allow_role_document_level_security: false, - allow_role_field_level_security: false, - links_message: 'Message' - } + expect(response).to.eql({ + license: { + type: 'gold', + is_active: true, + expiry_date_in_millis: 1509368280381 + }, + features: { + security: { + show_login: true, + allow_login: true, + show_links: false, + allow_role_document_level_security: false, + allow_role_field_level_security: false, + links_message: 'Message' } } - ); + }); }); }); diff --git a/x-pack/plugins/xpack_main/server/routes/api/v1/settings.js b/x-pack/plugins/xpack_main/server/routes/api/v1/settings.js index b546054bfe7f17..599be67e93d9a1 100644 --- a/x-pack/plugins/xpack_main/server/routes/api/v1/settings.js +++ b/x-pack/plugins/xpack_main/server/routes/api/v1/settings.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { wrap as wrapError } from 'boom'; +import { boomify } from 'boom'; import { KIBANA_SETTINGS_TYPE } from '../../../../../monitoring/common/constants'; import { getKibanaInfoForStats } from '../../../../../monitoring/server/kibana_monitoring/lib'; @@ -17,7 +17,7 @@ export function settingsRoute(server, kbnServer) { server.route({ path: '/api/settings', method: 'GET', - async handler(req, reply) { + async handler(req) { const { server } = req; const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); const callCluster = (...args) => callWithRequest(req, ...args); // All queries from HTTP API must use authentication headers from the request @@ -33,19 +33,19 @@ export function settingsRoute(server, kbnServer) { const uuid = await getClusterUuid(callCluster); const kibana = getKibanaInfoForStats(server, kbnServer); - reply({ + return { cluster_uuid: uuid, settings: { ...settings, kibana, } - }); + }; } catch(err) { req.log(['error'], err); // FIXME doesn't seem to log anything useful if ES times out if (err.isBoom) { - reply(err); + return err; } else { - reply(wrapError(err, err.statusCode, err.message)); + return boomify(err, { statusCode: err.statusCode, message: err.message }); } } } diff --git a/x-pack/plugins/xpack_main/server/routes/api/v1/telemetry/telemetry.js b/x-pack/plugins/xpack_main/server/routes/api/v1/telemetry/telemetry.js index 9700b527698f3a..5457602638d8c1 100644 --- a/x-pack/plugins/xpack_main/server/routes/api/v1/telemetry/telemetry.js +++ b/x-pack/plugins/xpack_main/server/routes/api/v1/telemetry/telemetry.js @@ -5,7 +5,7 @@ */ import Joi from 'joi'; -import { wrap } from 'boom'; +import { boomify } from 'boom'; import { getAllStats, getLocalStats } from '../../../../lib/telemetry'; /** @@ -46,7 +46,7 @@ export function telemetryRoute(server) { }) } }, - handler: async (req, reply) => { + handler: async (req, h) => { const savedObjectsClient = req.getSavedObjectsClient(); try { await savedObjectsClient.create('telemetry', { @@ -56,9 +56,9 @@ export function telemetryRoute(server) { overwrite: true, }); } catch (err) { - return reply(wrap(err)); + return boomify(err); } - reply({}).code(200); + return h.response({}).code(200); } }); @@ -82,20 +82,20 @@ export function telemetryRoute(server) { }) } }, - handler: async (req, reply) => { + handler: async (req, h) => { const config = req.server.config(); const start = req.payload.timeRange.min; const end = req.payload.timeRange.max; try { - reply(await getTelemetry(req, config, start, end)); + return await getTelemetry(req, config, start, end); } catch (err) { if (config.get('env.dev')) { - // don't ignore errors when running in dev mode - reply(wrap(err)); + // don't ignore errors when running in dev mode + return boomify(err); } else { - // ignore errors, return empty set and a 200 - reply([]).code(200); + // ignore errors, return empty set and a 200 + return h.response([]).code(200); } } } diff --git a/x-pack/plugins/xpack_main/server/routes/api/v1/xpack_info.js b/x-pack/plugins/xpack_main/server/routes/api/v1/xpack_info.js index 0564e9bb0512ec..13daa649f850d0 100644 --- a/x-pack/plugins/xpack_main/server/routes/api/v1/xpack_info.js +++ b/x-pack/plugins/xpack_main/server/routes/api/v1/xpack_info.js @@ -14,14 +14,12 @@ export function xpackInfoRoute(server) { server.route({ method: 'GET', path: '/api/xpack/v1/info', - handler(req, reply) { + handler() { const xPackInfo = server.plugins.xpack_main.info; - return reply( - xPackInfo.isAvailable() - ? convertKeysToSnakeCaseDeep(xPackInfo.toJSON()) - : Boom.notFound() - ); + return xPackInfo.isAvailable() + ? convertKeysToSnakeCaseDeep(xPackInfo.toJSON()) + : Boom.notFound(); } }); } diff --git a/x-pack/test/spaces_api_integration/common/suites/delete.ts b/x-pack/test/spaces_api_integration/common/suites/delete.ts index ee1018658a3211..627ff1e17c9c1b 100644 --- a/x-pack/test/spaces_api_integration/common/suites/delete.ts +++ b/x-pack/test/spaces_api_integration/common/suites/delete.ts @@ -123,6 +123,7 @@ export function deleteTestSuiteFactory(es: any, esArchiver: any, supertest: Supe expect(resp.body).to.eql({ error: 'Not Found', statusCode: 404, + message: 'Not Found', }); }; diff --git a/x-pack/test/spaces_api_integration/common/suites/get.ts b/x-pack/test/spaces_api_integration/common/suites/get.ts index 50cddc4a7dac35..2083aaa588e806 100644 --- a/x-pack/test/spaces_api_integration/common/suites/get.ts +++ b/x-pack/test/spaces_api_integration/common/suites/get.ts @@ -42,6 +42,7 @@ export function getTestSuiteFactory(esArchiver: any, supertest: SuperAgent) const createExpectNotFoundResult = () => (resp: { [key: string]: any }) => { expect(resp.body).to.eql({ error: 'Not Found', + message: 'Not Found', statusCode: 404, }); }; diff --git a/x-pack/test/spaces_api_integration/common/suites/select.ts b/x-pack/test/spaces_api_integration/common/suites/select.ts index ca4d3556a04cba..3bbea4f1a0bdcb 100644 --- a/x-pack/test/spaces_api_integration/common/suites/select.ts +++ b/x-pack/test/spaces_api_integration/common/suites/select.ts @@ -44,6 +44,7 @@ export function selectTestSuiteFactory(esArchiver: any, supertest: SuperTest (resp: { [key: string]: any }) => { expect(resp.body).to.eql({ error: 'Not Found', + message: 'Not Found', statusCode: 404, }); }; diff --git a/x-pack/test/spaces_api_integration/common/suites/update.ts b/x-pack/test/spaces_api_integration/common/suites/update.ts index cfd1123e2b72c8..f6828987bd8f00 100644 --- a/x-pack/test/spaces_api_integration/common/suites/update.ts +++ b/x-pack/test/spaces_api_integration/common/suites/update.ts @@ -45,6 +45,7 @@ export function updateTestSuiteFactory(esArchiver: any, supertest: SuperTest { expect(resp.body).to.eql({ error: 'Not Found', + message: 'Not Found', statusCode: 404, }); }; diff --git a/x-pack/yarn.lock b/x-pack/yarn.lock index ccfdd6c6481355..621514e0d69cc6 100644 --- a/x-pack/yarn.lock +++ b/x-pack/yarn.lock @@ -177,6 +177,16 @@ dependencies: "@types/babel-types" "*" +"@types/boom@*": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/boom/-/boom-7.2.0.tgz#19c36cbb5811a7493f0f2e37f31d42b28df1abc1" + integrity sha512-HonbGsHFbskh9zRAzA6tabcw18mCOsSEOL2ibGAuVqk6e7nElcRmWO5L4UfIHpDbWBWw+eZYFdsQ1+MEGgpcVA== + +"@types/catbox@*": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@types/catbox/-/catbox-10.0.1.tgz#266679017749041fe9873fee1131dd2aaa04a07e" + integrity sha512-ECuJ+f5gGHiLeiE4RlE/xdqv/0JVDToegPV1aTb10tQStYa0Ycq2OJfQukDv3IFaw3B+CMV46jHc5bXe6QXEQg== + "@types/cookie@^0.3.1": version "0.3.1" resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.1.tgz#720a756ea8e760a258708b52441bd341f1ef4296" @@ -270,12 +280,19 @@ resolved "https://registry.yarnpkg.com/@types/handlebars/-/handlebars-4.0.38.tgz#d0ebec1934c0bba97f99a0cb703fe2ef8c4a662f" integrity sha512-oMzU0D7jDp+H2go/i0XqBHfr+HEhYD/e1TvkhHi3yrhQm/7JFR8FJMdvoH76X8G1FBpgc6Pwi+QslCJBeJ1N9g== -"@types/hapi@15.0.1": - version "15.0.1" - resolved "https://registry.yarnpkg.com/@types/hapi/-/hapi-15.0.1.tgz#919e1d3a9160a080c9fdefaccc892239772e1258" - integrity sha512-5nxjmOY+irp5h0S7T87jtJqp2/cJAKWczC4fQ85Xt1SEQmeBYgzHn+LKrHOEY7pcZkg2+rJLFUDw4ohuorTbRg== +"@types/hapi@^17.0.18": + version "17.0.18" + resolved "https://registry.yarnpkg.com/@types/hapi/-/hapi-17.0.18.tgz#f855fe18766aa2592a3a689c3e6eabe72989ff1a" + integrity sha512-sRoDjz1iVOCxTqq+EepzDQI773k2PjboHpvMpp524278grosStxZ5+oooVjNLJZj1iZIbiLeeR5/ZeIRgVXsCg== dependencies: + "@types/boom" "*" + "@types/catbox" "*" + "@types/iron" "*" + "@types/joi" "*" + "@types/mimos" "*" "@types/node" "*" + "@types/podium" "*" + "@types/shot" "*" "@types/history@*": version "4.7.2" @@ -287,6 +304,13 @@ resolved "https://registry.yarnpkg.com/@types/history/-/history-4.6.2.tgz#12cfaba693ba20f114ed5765467ff25fdf67ddb0" integrity sha512-eVAb52MJ4lfPLiO9VvTgv8KaZDEIqCwhv+lXOMLlt4C1YHTShgmMULEg0RrCbnqfYd6QKfHsMp0MiX0vWISpSw== +"@types/iron@*": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@types/iron/-/iron-5.0.1.tgz#5420bbda8623c48ee51b9a78ebad05d7305b4b24" + integrity sha512-Ng5BkVGPt7Tw9k1OJ6qYwuD9+dmnWgActmsnnrdvs4075N8V2go1f6Pz8omG3q5rbHjXN6yzzZDYo3JOgAE/Ug== + dependencies: + "@types/node" "*" + "@types/is-stream@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@types/is-stream/-/is-stream-1.1.0.tgz#b84d7bb207a210f2af9bed431dc0fbe9c4143be1" @@ -299,10 +323,10 @@ resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.3.1.tgz#a4319aedb071d478e6f407d1c4578ec8156829cf" integrity sha512-/UMY+2GkOZ27Vrc51pqC5J8SPd39FKt7kkoGAtWJ8s4msj0b15KehDWIiJpWY3/7tLxBQLLzJhIBhnEsXdzpgw== -"@types/joi@^10.4.4": - version "10.6.4" - resolved "https://registry.yarnpkg.com/@types/joi/-/joi-10.6.4.tgz#0989d69e792a7db13e951852e6949df6787f113f" - integrity sha512-eS6EeSGueXvS16CsHa7OKkRK1xBb6L+rXuXlzbWSWvb4v7zgNFPmY8l6aWWgEkHFeITVBadeQHQhVUpx0sd1tw== +"@types/joi@*", "@types/joi@^13.4.2": + version "13.6.1" + resolved "https://registry.yarnpkg.com/@types/joi/-/joi-13.6.1.tgz#325486a397504f8e22c8c551dc8b0e1d41d5d5ae" + integrity sha512-JxZ0NP8NuB0BJOXi1KvAA6rySLTPmhOy4n2gzSFq/IFM3LNFm0h+2Vn/bPPgEYlWqzS2NPeLgKqfm75baX+Hog== "@types/jsonwebtoken@^7.2.7": version "7.2.8" @@ -321,6 +345,18 @@ resolved "https://registry.yarnpkg.com/@types/loglevel/-/loglevel-1.5.3.tgz#adfce55383edc5998a2170ad581b3e23d6adb5b8" integrity sha512-TzzIZihV+y9kxSg5xJMkyIkaoGkXi50isZTtGHObNHRqAAwjGNjSCNPI7AUAv0tZUKTq9f2cdkCUd/2JVZUTrA== +"@types/mime-db@*": + version "1.27.0" + resolved "https://registry.yarnpkg.com/@types/mime-db/-/mime-db-1.27.0.tgz#9bc014a1fd1fdf47649c1a54c6dd7966b8284792" + integrity sha1-m8AUof0f30dknBpUxt15ZrgoR5I= + +"@types/mimos@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mimos/-/mimos-3.0.1.tgz#59d96abe1c9e487e7463fe41e8d86d76b57a441a" + integrity sha512-MATIRH4VMIJki8lcYUZdNQEHuAG7iQ1FWwoLgxV+4fUOly2xZYdhHtGgvQyWiTeJqq2tZbE0nOOgZD6pR0FpNQ== + dependencies: + "@types/mime-db" "*" + "@types/mocha@^5.2.5": version "5.2.5" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.5.tgz#8a4accfc403c124a0bafe8a9fc61a05ec1032073" @@ -355,6 +391,11 @@ dependencies: "@types/node" "*" +"@types/podium@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/podium/-/podium-1.0.0.tgz#bfaa2151be2b1d6109cc69f7faa9dac2cba3bb20" + integrity sha1-v6ohUb4rHWEJzGn3+qnawsujuyA= + "@types/prettier@1.13.1": version "1.13.1" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.13.1.tgz#5dd359398de96863a0629156f382913a06ebe013" @@ -426,6 +467,13 @@ resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.10.2.tgz#bd1740c4ad51966609b058803ee6874577848b37" integrity sha512-LqJkY4VQ7S09XhI7kA3ON71AxauROhSv74639VsNXC9ish4IWHnIi98if+nP1MxQV3RMPqXSCYgpPsDHjlg9UQ== +"@types/shot@*": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/shot/-/shot-4.0.0.tgz#7545500c489b65c69b5bc5446ba4fef3bd26af92" + integrity sha512-Xv+n8yfccuicMlwBY58K5PVVNtXRm7uDzcwwmCarBxMP+XxGfnh1BI06YiVAsPbTAzcnYsrzpoS5QHeyV7LS8A== + dependencies: + "@types/node" "*" + "@types/sinon@^5.0.1": version "5.0.3" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-5.0.3.tgz#2b1840122f372350c563e3ceda2f447b55f3a927" @@ -491,13 +539,13 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accept@2.x.x: - version "2.1.4" - resolved "https://registry.yarnpkg.com/accept/-/accept-2.1.4.tgz#887af54ceee5c7f4430461971ec400c61d09acbb" - integrity sha1-iHr1TO7lx/RDBGGXHsQAxh0JrLs= +accept@3.x.x: + version "3.0.2" + resolved "https://registry.yarnpkg.com/accept/-/accept-3.0.2.tgz#83e41cec7e1149f3fd474880423873db6c6cc9ac" + integrity sha512-bghLXFkCOsC1Y2TZ51etWfKDs6q249SAoHTZVfzWWdlZxoij+mgkj9AmUJWQpDY48TfnrTDIe43Xem4zdMe7mQ== dependencies: - boom "5.x.x" - hoek "4.x.x" + boom "7.x.x" + hoek "5.x.x" accepts@1.3.3: version "1.3.3" @@ -608,13 +656,12 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= -ammo@2.x.x: - version "2.0.4" - resolved "https://registry.yarnpkg.com/ammo/-/ammo-2.0.4.tgz#bf80aab211698ea78f63ef5e7f113dd5d9e8917f" - integrity sha1-v4CqshFpjqePY+9efxE91dnokX8= +ammo@3.x.x: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ammo/-/ammo-3.0.1.tgz#c79ceeac36fb4e55085ea3fe0c2f42bfa5f7c914" + integrity sha512-4UqoM8xQjwkQ78oiU4NbBK0UgYqeKMAKmwE4ec7Rz3rGU8ZEBFxzgF2sUYKOAlqIXExBDYLN6y1ShF5yQ4hwLQ== dependencies: - boom "5.x.x" - hoek "4.x.x" + hoek "5.x.x" angular-resource@1.4.9: version "1.4.9" @@ -1161,10 +1208,10 @@ atob@^2.0.0: resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" integrity sha1-GcenYEc3dEaPILLS0DNyrX1Mv10= -atob@~1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773" - integrity sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M= +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== attr-accept@^1.1.3: version "1.1.3" @@ -1215,10 +1262,10 @@ axios@^0.18.0: follow-redirects "^1.3.0" is-buffer "^1.1.5" -b64@3.x.x: - version "3.0.3" - resolved "https://registry.yarnpkg.com/b64/-/b64-3.0.3.tgz#36afeee0d9345f046387ce6de8a6702afe5bb56e" - integrity sha512-Pbeh0i6OLubPJdIdCepn8ZQHwN2MWznZHbHABSTEfQ706ie+yuxNSaPdqX1xRatT6WanaS1EazMiSg0NUW2XxQ== +b64@4.x.x: + version "4.0.0" + resolved "https://registry.yarnpkg.com/b64/-/b64-4.0.0.tgz#c37f587f0a383c7019e821120e8c3f58f0d22772" + integrity sha512-EhmUQodKB0sdzPPrbIWbGqA5cQeTWxYrAgNeeT1rLZWtD3tbNTnphz8J4vkXI3cPgBNlXBjzEbzDzq0Nwi4f9A== babel-code-frame@^6.26.0: version "6.26.0" @@ -1360,6 +1407,14 @@ babel-jest@^23.4.2: babel-plugin-istanbul "^4.1.6" babel-preset-jest "^23.2.0" +babel-jest@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1" + integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew== + dependencies: + babel-plugin-istanbul "^4.1.6" + babel-preset-jest "^23.2.0" + babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" @@ -1810,6 +1865,11 @@ better-assert@~1.0.0: dependencies: callsite "1.0.0" +big-time@2.x.x: + version "2.0.1" + resolved "https://registry.yarnpkg.com/big-time/-/big-time-2.0.1.tgz#68c7df8dc30f97e953f25a67a76ac9713c16c9de" + integrity sha1-aMffjcMPl+lT8lpnp2rJcTwWyd4= + big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" @@ -1861,20 +1921,6 @@ boom@2.x.x: dependencies: hoek "2.x.x" -boom@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-3.1.1.tgz#b6424f01ed8d492b2b12ae86047c24e8b6a7c937" - integrity sha1-tkJPAe2NSSsrEq6GBHwk6LanyTc= - dependencies: - hoek "3.x.x" - -boom@3.x.x: - version "3.2.2" - resolved "https://registry.yarnpkg.com/boom/-/boom-3.2.2.tgz#0f0cc5d04adc5003b8c7d71f42cca7271fef0e78" - integrity sha1-DwzF0ErcUAO4x9cfQsynJx/vDng= - dependencies: - hoek "4.x.x" - boom@4.x.x: version "4.3.1" resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" @@ -1889,13 +1935,21 @@ boom@5.x.x: dependencies: hoek "4.x.x" -boom@^7.1.0: +boom@7.x.x, boom@^7.1.0, boom@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/boom/-/boom-7.2.0.tgz#2bff24a55565767fde869ec808317eb10c48e966" integrity sha1-K/8kpVVldn/ehp7ICDF+sQxI6WY= dependencies: hoek "5.x.x" +bounce@1.x.x: + version "1.2.0" + resolved "https://registry.yarnpkg.com/bounce/-/bounce-1.2.0.tgz#e3bac68c73fd256e38096551efc09f504873c8c8" + integrity sha512-8syCGe8B2/WC53118/F/tFy5aW00j+eaGPXmAUP7iBhxc+EBZZxS1vKelWyBCH6IqojgS2t1gF0glH30qAJKEw== + dependencies: + boom "7.x.x" + hoek "5.x.x" + brace-expansion@^1.0.0, brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" @@ -2086,13 +2140,13 @@ cacheable-request@^2.1.1: normalize-url "2.0.1" responselike "1.0.2" -call@3.x.x: - version "3.0.4" - resolved "https://registry.yarnpkg.com/call/-/call-3.0.4.tgz#e380f2f2a491330aa79085355f8be080877d559e" - integrity sha1-44Dy8qSRMwqnkIU1X4vggId9VZ4= +call@5.x.x: + version "5.0.1" + resolved "https://registry.yarnpkg.com/call/-/call-5.0.1.tgz#ac1b5c106d9edc2a17af2a4a4f74dd4f0c06e910" + integrity sha512-ollfFPSshiuYLp7AsrmpkQJ/PxCi6AzV81rCjBwWhyF2QGyUY/vPDMzoh4aUcWyucheRglG2LaS5qkIEfLRh6A== dependencies: - boom "4.x.x" - hoek "4.x.x" + boom "7.x.x" + hoek "5.x.x" callsite@1.0.0: version "1.0.0" @@ -2150,21 +2204,23 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -catbox-memory@2.x.x: - version "2.0.4" - resolved "https://registry.yarnpkg.com/catbox-memory/-/catbox-memory-2.0.4.tgz#433e255902caf54233d1286429c8f4df14e822d5" - integrity sha1-Qz4lWQLK9UIz0ShkKcj03xToItU= +catbox-memory@3.x.x: + version "3.1.2" + resolved "https://registry.yarnpkg.com/catbox-memory/-/catbox-memory-3.1.2.tgz#4aeec1bc994419c0f7e60087f172aaedd9b4911c" + integrity sha512-lhWtutLVhsq3Mucxk2McxBPPibJ34WcHuWFz3xqub9u9Ve/IQYpZv3ijLhQXfQped9DXozURiaq9O3aZpP91eg== dependencies: - hoek "4.x.x" + big-time "2.x.x" + boom "7.x.x" + hoek "5.x.x" -catbox@7.x.x: - version "7.1.5" - resolved "https://registry.yarnpkg.com/catbox/-/catbox-7.1.5.tgz#c56f7e8e9555d27c0dc038a96ef73e57d186bb1f" - integrity sha512-4fui5lELzqZ+9cnaAP/BcqXTH6LvWLBRtFhJ0I4FfgfXiSaZcf6k9m9dqOyChiTxNYtvLk7ZMYSf7ahMq3bf5A== +catbox@10.x.x: + version "10.0.3" + resolved "https://registry.yarnpkg.com/catbox/-/catbox-10.0.3.tgz#1f6f6436dfab30cdd23f753877bcb4afe980414b" + integrity sha512-qwus6RnVctHXYwfxvvDwvlMWHwCjQdIpQQbtyHnRF0JpwmxbQJ/UIZi9y8O6DpphKCdfO9gpxgb2ne9ZDx39BQ== dependencies: - boom "5.x.x" - hoek "4.x.x" - joi "10.x.x" + boom "7.x.x" + hoek "5.x.x" + joi "13.x.x" center-align@^0.1.1: version "0.1.3" @@ -2486,7 +2542,7 @@ commander@2.12.2, commander@^2.9.0: commander@2.15.1: version "2.15.1" - resolved "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== commander@2.16.0: @@ -2589,12 +2645,12 @@ content-type-parser@^1.0.1: resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7" integrity sha512-lM4l4CnMEwOLHAHr/P6MEZwZFPJFtAAKgL6pogbXmVZggIqXhdB6RbBtPOTsw2FcXwYhehRGERJmRrjOiIB8pQ== -content@3.x.x: - version "3.0.6" - resolved "https://registry.yarnpkg.com/content/-/content-3.0.6.tgz#9c2e301e9ae515ed65a4b877d78aa5659bb1b809" - integrity sha512-tyl3fRp8jOHsQR0X9vrIy0mKQccv0tA9/RlvLl514eA7vHOJr/TnmMTpgQjInwbeW9IOQVy0OECGAuQNUa0nnQ== +content@4.x.x: + version "4.0.5" + resolved "https://registry.yarnpkg.com/content/-/content-4.0.5.tgz#bc547deabc889ab69bce17faf3585c29f4c41bf2" + integrity sha512-wDP6CTWDpwCf791fNxlCCkZGRkrNzSEU/8ju9Hnr3Uc5mF/gFR5W+fcoGm6zUSlVPdSXYn5pCbySADKj7YM4Cg== dependencies: - boom "5.x.x" + boom "7.x.x" convert-source-map@^1.4.0, convert-source-map@^1.5.0: version "1.5.1" @@ -2725,6 +2781,13 @@ cryptiles@3.x.x: dependencies: boom "5.x.x" +cryptiles@4.x.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-4.1.2.tgz#363c9ab5c859da9d2d6fb901b64d980966181184" + integrity sha512-U2ALcoAHvA1oO2xOreyHvtkQ+IELqDG2WVWRI1GH/XEmmfGIOalnM5MU5Dd2ITyWfr3m6kNqXiy8XuYyd4wKJw== + dependencies: + boom "7.x.x" + css-box-model@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.0.0.tgz#60142814f2b25be00c4aac65ea1a55a531b18922" @@ -2760,13 +2823,13 @@ css-what@2.1: integrity sha1-lGfQMsOM+u+58teVASUwYvh/ob0= css@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc" - integrity sha1-c6TIHehdtmTU7mdPfUcIXjstVdw= + version "2.2.4" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" + integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== dependencies: - inherits "^2.0.1" - source-map "^0.1.38" - source-map-resolve "^0.3.0" + inherits "^2.0.3" + source-map "^0.6.1" + source-map-resolve "^0.5.2" urix "^0.1.0" csso@~2.3.1: @@ -3685,15 +3748,15 @@ expect.js@0.3.1: resolved "https://registry.yarnpkg.com/expect.js/-/expect.js-0.3.1.tgz#b0a59a0d2eff5437544ebf0ceaa6015841d09b5b" integrity sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s= -expect@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-23.5.0.tgz#18999a0eef8f8acf99023fde766d9c323c2562ed" - integrity sha512-aG083W63tBloy8YgafWuC44EakjYe0Q6Mg35aujBPvyNU38DvLat9BVzOihNP2NZDLaCJiFNe0vejbtO6knnlA== +expect@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98" + integrity sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w== dependencies: ansi-styles "^3.2.0" - jest-diff "^23.5.0" + jest-diff "^23.6.0" jest-get-type "^22.1.0" - jest-matcher-utils "^23.5.0" + jest-matcher-utils "^23.6.0" jest-message-util "^23.4.0" jest-regex-util "^23.3.0" @@ -4797,39 +4860,38 @@ handlebars@^4.0.10: optionalDependencies: uglify-js "^3.1.4" -hapi-auth-cookie@6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/hapi-auth-cookie/-/hapi-auth-cookie-6.1.1.tgz#927db39e434916d81ab870d4181d70d53e745572" - integrity sha1-kn2znkNJFtgauHDUGB1w1T50VXI= - dependencies: - boom "3.x.x" - hoek "3.x.x" - joi "7.x.x" - -hapi@14.2.0: - version "14.2.0" - resolved "https://registry.yarnpkg.com/hapi/-/hapi-14.2.0.tgz#e4fe2fc182598a0f81e87b41b6be0fbd31c75409" - integrity sha1-5P4vwYJZig+B6HtBtr4PvTHHVAk= - dependencies: - accept "2.x.x" - ammo "2.x.x" - boom "3.x.x" - call "3.x.x" - catbox "7.x.x" - catbox-memory "2.x.x" - cryptiles "3.x.x" - heavy "4.x.x" - hoek "4.x.x" - iron "4.x.x" - items "2.x.x" - joi "9.x.x" - kilt "2.x.x" - mimos "3.x.x" - peekaboo "2.x.x" - shot "3.x.x" - statehood "4.x.x" - subtext "4.x.x" - topo "2.x.x" +hapi-auth-cookie@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/hapi-auth-cookie/-/hapi-auth-cookie-9.0.0.tgz#3b0af443334e2bd92490ddb17bed16e3e9edfd01" + integrity sha512-N71Mt7Jk0+7WLnuvfSv0DoGzgpn7TqOd+/AB73RfHpLvzYoskJ9AlFV3Op60DB01RJNaABZtdcH1l4HM3DMbog== + dependencies: + boom "7.x.x" + bounce "1.x.x" + hoek "5.x.x" + joi "13.x.x" + +hapi@^17.5.3: + version "17.6.0" + resolved "https://registry.yarnpkg.com/hapi/-/hapi-17.6.0.tgz#158a2276253a8de727be678c4daeb1f73929e588" + integrity sha512-GSHjE1hJExluAukrT/QuYSk96irmbYBDd3wOgywiHsPoR2QeKgDnIttD+dB6NbADEmSdb9MS5gTUIVq0uHTdkA== + dependencies: + accept "3.x.x" + ammo "3.x.x" + boom "7.x.x" + bounce "1.x.x" + call "5.x.x" + catbox "10.x.x" + catbox-memory "3.x.x" + heavy "6.x.x" + hoek "5.x.x" + joi "13.x.x" + mimos "4.x.x" + podium "3.x.x" + shot "4.x.x" + statehood "6.x.x" + subtext "6.x.x" + teamwork "3.x.x" + topo "3.x.x" har-schema@^1.0.5: version "1.0.5" @@ -5016,14 +5078,14 @@ header-case@^1.0.0: no-case "^2.2.0" upper-case "^1.1.3" -heavy@4.x.x: - version "4.0.4" - resolved "https://registry.yarnpkg.com/heavy/-/heavy-4.0.4.tgz#36c91336c00ccfe852caa4d153086335cd2f00e9" - integrity sha1-NskTNsAMz+hSyqTRUwhjNc0vAOk= +heavy@6.x.x: + version "6.1.0" + resolved "https://registry.yarnpkg.com/heavy/-/heavy-6.1.0.tgz#1bbfa43dc61dd4b543ede3ff87db8306b7967274" + integrity sha512-TKS9DC9NOTGulHQI31Lx+bmeWmNOstbJbGMiN3pX6bF+Zc2GKSpbbym4oasNnB6yPGkqJ9TQXXYDGohqNSJRxA== dependencies: - boom "5.x.x" - hoek "4.x.x" - joi "10.x.x" + boom "7.x.x" + hoek "5.x.x" + joi "13.x.x" highlight.js@^9.12.0, highlight.js@~9.12.0: version "9.12.0" @@ -5046,11 +5108,6 @@ hoek@2.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= -hoek@3.x.x: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-3.0.4.tgz#268adff66bb6695c69b4789a88b1e0847c3f3123" - integrity sha1-Jorf9mu2aVxptHiaiLHghHw/MSM= - hoek@4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" @@ -5342,7 +5399,7 @@ invert-kv@^1.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= -iron@4, iron@4.x.x: +iron@4: version "4.0.5" resolved "https://registry.yarnpkg.com/iron/-/iron-4.0.5.tgz#4f042cceb8b9738f346b59aa734c83a89bc31428" integrity sha1-TwQszri5c480a1mqc0yDqJvDFCg= @@ -5351,6 +5408,15 @@ iron@4, iron@4.x.x: cryptiles "3.x.x" hoek "4.x.x" +iron@5.x.x: + version "5.0.4" + resolved "https://registry.yarnpkg.com/iron/-/iron-5.0.4.tgz#003ed822f656f07c2b62762815f5de3947326867" + integrity sha512-7iQ5/xFMIYaNt9g2oiNiWdhrOTdRUMFaWENUd0KghxwPUhrIH8DUY8FEyLNTTzf75jaII+jMexLdY/2HfV61RQ== + dependencies: + boom "7.x.x" + cryptiles "4.x.x" + hoek "5.x.x" + is-absolute@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" @@ -5701,15 +5767,12 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isemail@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a" - integrity sha1-vgPfjMPineTSxd9lASY/H6RZXpo= - -isemail@2.x.x: - version "2.2.1" - resolved "https://registry.yarnpkg.com/isemail/-/isemail-2.2.1.tgz#0353d3d9a62951080c262c2aa0a42b8ea8e9e2a6" - integrity sha1-A1PT2aYpUQgMJiwqoKQrjqjp4qY= +isemail@3.x.x: + version "3.1.4" + resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.1.4.tgz#76e2187ff7bee59d57522c6fd1c3f09a331933cf" + integrity sha512-yE/W5osEWuAGSLVixV9pAexhkbZzglmuhO2CxdHu7IBh7uzuZogQ4bk0lE26HoZ6HD4ZYfKRKilkNuCnuJIBJw== + dependencies: + punycode "2.x.x" isexe@^2.0.0: version "2.0.0" @@ -5819,11 +5882,6 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" -items@2.x.x: - version "2.1.1" - resolved "https://registry.yarnpkg.com/items/-/items-2.1.1.tgz#8bd16d9c83b19529de5aea321acaada78364a198" - integrity sha1-i9FtnIOxlSneWuoyGsqtp4NkoZg= - iterall@^1.1.3, iterall@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" @@ -5883,35 +5941,35 @@ jest-cli@^23.5.0: which "^1.2.12" yargs "^11.0.0" -jest-config@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.5.0.tgz#3770fba03f7507ee15f3b8867c742e48f31a9773" - integrity sha512-JENhQpLaVwXWPLUkhPYgIfecHKsU8GR1vj79rS4n0LSRsHx/U2wItZKoKAd5vtt2J58JPxRq4XheG79jd4fI7Q== +jest-config@^23.5.0, jest-config@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d" + integrity sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ== dependencies: babel-core "^6.0.0" - babel-jest "^23.4.2" + babel-jest "^23.6.0" chalk "^2.0.1" glob "^7.1.1" jest-environment-jsdom "^23.4.0" jest-environment-node "^23.4.0" jest-get-type "^22.1.0" - jest-jasmine2 "^23.5.0" + jest-jasmine2 "^23.6.0" jest-regex-util "^23.3.0" - jest-resolve "^23.5.0" + jest-resolve "^23.6.0" jest-util "^23.4.0" - jest-validate "^23.5.0" + jest-validate "^23.6.0" micromatch "^2.3.11" - pretty-format "^23.5.0" + pretty-format "^23.6.0" -jest-diff@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.5.0.tgz#250651a433dd0050290a07642946cc9baaf06fba" - integrity sha512-Miz8GakJIz443HkGpVOAyHQgSYqcgs2zQmDJl4oV7DYrFotchdoQvxceF6LhfpRBV1LOUGcFk5Dd/ffSXVwMsA== +jest-diff@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d" + integrity sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g== dependencies: chalk "^2.0.1" diff "^3.2.0" jest-get-type "^22.1.0" - pretty-format "^23.5.0" + pretty-format "^23.6.0" jest-docblock@^23.2.0: version "23.2.0" @@ -5920,13 +5978,13 @@ jest-docblock@^23.2.0: dependencies: detect-newline "^2.1.0" -jest-each@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.5.0.tgz#77f7e2afe6132a80954b920006e78239862b10ba" - integrity sha512-8BgebQgAJmWXpYp4Qt9l3cn1Xei0kZ7JL4cs/NXh7750ATlPGzRRYbutFVJTk5B/Lt3mjHP3G3tLQLyBOCSHGA== +jest-each@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575" + integrity sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg== dependencies: chalk "^2.0.1" - pretty-format "^23.5.0" + pretty-format "^23.6.0" jest-environment-jsdom@^23.4.0: version "23.4.0" @@ -5950,10 +6008,10 @@ jest-get-type@^22.1.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w== -jest-haste-map@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.5.0.tgz#d4ca618188bd38caa6cb20349ce6610e194a8065" - integrity sha512-bt9Swigb6KZ6ZQq/fQDUwdUeHenVvZ6G/lKwJjwRGp+Fap8D4B3bND3FaeJg7vXVsLX8hXshRArbVxLop/5wLw== +jest-haste-map@^23.5.0, jest-haste-map@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16" + integrity sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg== dependencies: fb-watchman "^2.0.0" graceful-fs "^4.1.11" @@ -5964,39 +6022,39 @@ jest-haste-map@^23.5.0: micromatch "^2.3.11" sane "^2.0.0" -jest-jasmine2@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.5.0.tgz#05fe7f1788e650eeb5a03929e6461ea2e9f3db53" - integrity sha512-xMgvDUvgqKpilsGnneC9Qr+uIlROxKI3UoJcHZeUlu6AKpQyEkGh0hKbfM0NaEjX5sy7WeFQEhcp/AiWlHcc0A== +jest-jasmine2@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0" + integrity sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ== dependencies: babel-traverse "^6.0.0" chalk "^2.0.1" co "^4.6.0" - expect "^23.5.0" + expect "^23.6.0" is-generator-fn "^1.0.0" - jest-diff "^23.5.0" - jest-each "^23.5.0" - jest-matcher-utils "^23.5.0" + jest-diff "^23.6.0" + jest-each "^23.6.0" + jest-matcher-utils "^23.6.0" jest-message-util "^23.4.0" - jest-snapshot "^23.5.0" + jest-snapshot "^23.6.0" jest-util "^23.4.0" - pretty-format "^23.5.0" + pretty-format "^23.6.0" -jest-leak-detector@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.5.0.tgz#14ac2a785bd625160a2ea968fd5d98b7dcea3e64" - integrity sha512-40VsHQCIEslxg91Zg5NiZGtPeWSBLXiD6Ww+lhHlIF6u8uSQ+xgiD6NbWHFOYs1VBRI+V/ym7Q1aOtVg9tqMzQ== +jest-leak-detector@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de" + integrity sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg== dependencies: - pretty-format "^23.5.0" + pretty-format "^23.6.0" -jest-matcher-utils@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.5.0.tgz#0e2ea67744cab78c9ab15011c4d888bdd3e49e2a" - integrity sha512-hmQUKUKYOExp3T8dNYK9A9copCFYKoRLcY4WDJJ0Z2u3oF6rmAhHuZtmpHBuGpASazobBxm3TXAfAXDvz2T7+Q== +jest-matcher-utils@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80" + integrity sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog== dependencies: chalk "^2.0.1" jest-get-type "^22.1.0" - pretty-format "^23.5.0" + pretty-format "^23.6.0" jest-message-util@^23.4.0: version "23.4.0" @@ -6020,45 +6078,45 @@ jest-regex-util@^23.3.0: integrity sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U= jest-resolve-dependencies@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.5.0.tgz#10c4d135beb9d2256de1fedc7094916c3ad74af7" - integrity sha512-APZc/CjfzL8rH/wr+Gh7XJJygYaDjMQsWaJy4ZR1WaHWKude4WcfdU8xjqaNbx5NsVF2P2tVvsLbumlPXCdJOw== + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d" + integrity sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA== dependencies: jest-regex-util "^23.3.0" - jest-snapshot "^23.5.0" + jest-snapshot "^23.6.0" -jest-resolve@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.5.0.tgz#3b8e7f67e84598f0caf63d1530bd8534a189d0e6" - integrity sha512-CRPc0ebG3baNKz/QicIy5rGfzYpMNm8AjEl/tDQhehq/QC4ttyauZdvAXel3qo+4Gri9ljajnxW+hWyxZbbcnQ== +jest-resolve@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae" + integrity sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA== dependencies: browser-resolve "^1.11.3" chalk "^2.0.1" realpath-native "^1.0.0" jest-runner@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.5.0.tgz#570f7a044da91648b5bb9b6baacdd511076c71d7" - integrity sha512-cpBvkBTVmW1ab1thbtoh2m6VnnM0BYKhj3MEzbOTZjPfzoIjUVIxLUTDobVNOvEK7aTEb/2oiPlNoOTSNJx8mw== + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38" + integrity sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA== dependencies: exit "^0.1.2" graceful-fs "^4.1.11" - jest-config "^23.5.0" + jest-config "^23.6.0" jest-docblock "^23.2.0" - jest-haste-map "^23.5.0" - jest-jasmine2 "^23.5.0" - jest-leak-detector "^23.5.0" + jest-haste-map "^23.6.0" + jest-jasmine2 "^23.6.0" + jest-leak-detector "^23.6.0" jest-message-util "^23.4.0" - jest-runtime "^23.5.0" + jest-runtime "^23.6.0" jest-util "^23.4.0" jest-worker "^23.2.0" source-map-support "^0.5.6" throat "^4.0.0" -jest-runtime@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.5.0.tgz#eb503525a196dc32f2f9974e3482d26bdf7b63ce" - integrity sha512-WzzYxYtoU8S1MJns0G4E3BsuFUTFBiu1qsk3iC9OTugzNQcQKt0BoOGsT7wXCKqkw/09QdV77vvaeJXST2Efgg== +jest-runtime@^23.5.0, jest-runtime@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082" + integrity sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw== dependencies: babel-core "^6.0.0" babel-plugin-istanbul "^4.1.6" @@ -6067,14 +6125,14 @@ jest-runtime@^23.5.0: exit "^0.1.2" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.1.11" - jest-config "^23.5.0" - jest-haste-map "^23.5.0" + jest-config "^23.6.0" + jest-haste-map "^23.6.0" jest-message-util "^23.4.0" jest-regex-util "^23.3.0" - jest-resolve "^23.5.0" - jest-snapshot "^23.5.0" + jest-resolve "^23.6.0" + jest-snapshot "^23.6.0" jest-util "^23.4.0" - jest-validate "^23.5.0" + jest-validate "^23.6.0" micromatch "^2.3.11" realpath-native "^1.0.0" slash "^1.0.0" @@ -6087,20 +6145,20 @@ jest-serializer@^23.0.1: resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165" integrity sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU= -jest-snapshot@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.5.0.tgz#cc368ebd8513e1175e2a7277f37a801b7358ae79" - integrity sha512-NYg8MFNVyPXmnnihiltasr4t1FJEXFbZFaw1vZCowcnezIQ9P1w+yxTwjWT564QP24Zbn5L9cjxLs8d6K+pNlw== +jest-snapshot@^23.5.0, jest-snapshot@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a" + integrity sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg== dependencies: babel-types "^6.0.0" chalk "^2.0.1" - jest-diff "^23.5.0" - jest-matcher-utils "^23.5.0" + jest-diff "^23.6.0" + jest-matcher-utils "^23.6.0" jest-message-util "^23.4.0" - jest-resolve "^23.5.0" + jest-resolve "^23.6.0" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^23.5.0" + pretty-format "^23.6.0" semver "^5.5.0" jest-styled-components@^6.1.1: @@ -6124,15 +6182,15 @@ jest-util@^23.4.0: slash "^1.0.0" source-map "^0.6.0" -jest-validate@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.5.0.tgz#f5df8f761cf43155e1b2e21d6e9de8a2852d0231" - integrity sha512-XmStdYhfdiDKacXX5sNqEE61Zz4/yXaPcDsKvVA0429RBu2pkQyIltCVG7UitJIEAzSs3ociQTdyseAW8VGPiA== +jest-validate@^23.5.0, jest-validate@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474" + integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A== dependencies: chalk "^2.0.1" jest-get-type "^22.1.0" leven "^2.1.0" - pretty-format "^23.5.0" + pretty-format "^23.6.0" jest-watcher@^23.4.0: version "23.4.0" @@ -6158,46 +6216,14 @@ jest@^23.5.0: import-local "^1.0.0" jest-cli "^23.5.0" -joi@10.x.x: - version "10.6.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-10.6.0.tgz#52587f02d52b8b75cdb0c74f0b164a191a0e1fc2" - integrity sha512-hBF3LcqyAid+9X/pwg+eXjD2QBZI5eXnBFJYaAkH4SK3mp9QSRiiQnDYlmlz5pccMvnLcJRS4whhDOTCkmsAdQ== +joi@13.x.x, joi@^13.5.2: + version "13.7.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-13.7.0.tgz#cfd85ebfe67e8a1900432400b4d03bbd93fb879f" + integrity sha512-xuY5VkHfeOYK3Hdi91ulocfuFopwgbSORmIwzcwHKESQhC7w1kD5jaVSPnqDxS2I8t3RZ9omCKAxNwXN5zG1/Q== dependencies: - hoek "4.x.x" - isemail "2.x.x" - items "2.x.x" - topo "2.x.x" - -joi@6.10.1: - version "6.10.1" - resolved "https://registry.yarnpkg.com/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06" - integrity sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY= - dependencies: - hoek "2.x.x" - isemail "1.x.x" - moment "2.x.x" - topo "1.x.x" - -joi@7.x.x: - version "7.3.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-7.3.0.tgz#4d9c9f181830444083665b5b6cd5b8ca6779a5e9" - integrity sha1-TZyfGBgwRECDZltbbNW4ymd5pek= - dependencies: - hoek "3.x.x" - isemail "2.x.x" - moment "2.x.x" - topo "2.x.x" - -joi@9.x.x: - version "9.2.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-9.2.0.tgz#3385ac790192130cbe230e802ec02c9215bbfeda" - integrity sha1-M4WseQGSEwy+Iw6ALsAskhW7/to= - dependencies: - hoek "4.x.x" - isemail "2.x.x" - items "2.x.x" - moment "2.x.x" - topo "2.x.x" + hoek "5.x.x" + isemail "3.x.x" + topo "3.x.x" jquery@^3.3.1: version "3.3.1" @@ -6439,13 +6465,6 @@ keyv@3.0.0: dependencies: json-buffer "3.0.0" -kilt@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/kilt/-/kilt-2.0.2.tgz#04d7183c298a1232efddf7ddca5959a8f6301e20" - integrity sha1-BNcYPCmKEjLv3ffdyllZqPYwHiA= - dependencies: - hoek "4.x.x" - kind-of@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" @@ -7233,12 +7252,12 @@ mimic-response@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e" integrity sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4= -mimos@3.x.x: - version "3.0.3" - resolved "https://registry.yarnpkg.com/mimos/-/mimos-3.0.3.tgz#b9109072ad378c2b72f6a0101c43ddfb2b36641f" - integrity sha1-uRCQcq03jCty9qAQHEPd+ys2ZB8= +mimos@4.x.x: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimos/-/mimos-4.0.0.tgz#76e3d27128431cb6482fd15b20475719ad626a5a" + integrity sha512-JvlvRLqGIlk+AYypWrbrDmhsM+6JVx/xBM5S3AMwTBz1trPCEoPN/swO2L4Wu653fL7oJdgk8DMQyG/Gq3JkZg== dependencies: - hoek "4.x.x" + hoek "5.x.x" mime-db "1.x.x" min-document@^2.19.0: @@ -7375,7 +7394,7 @@ moment@2.22.2, moment@>=2.14.0: resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y= -moment@2.x.x, "moment@>= 2.9.0", moment@^2.13.0, moment@^2.20.1: +"moment@>= 2.9.0", moment@^2.13.0, moment@^2.20.1: version "2.20.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd" integrity sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg== @@ -7500,13 +7519,13 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" integrity sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA== -nigel@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/nigel/-/nigel-2.0.2.tgz#93a1866fb0c52d87390aa75e2b161f4b5c75e5b1" - integrity sha1-k6GGb7DFLYc5CqdeKxYfS1x15bE= +nigel@3.x.x: + version "3.0.1" + resolved "https://registry.yarnpkg.com/nigel/-/nigel-3.0.1.tgz#48a08859d65177312f1c25af7252c1e07bb07c2a" + integrity sha512-kCVtUG9JyD//tsYrZY+/Y+2gUrANVSba8y23QkM5Znx0FOxlnl9Z4OVPBODmstKWTOvigfTO+Va1VPOu3eWSOQ== dependencies: - hoek "4.x.x" - vise "2.x.x" + hoek "5.x.x" + vise "3.x.x" nise@^1.2.0: version "1.3.3" @@ -7885,6 +7904,13 @@ onetime@^1.0.0: resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= +oppsy@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/oppsy/-/oppsy-2.0.0.tgz#3a194517adc24c3c61cdc56f35f4537e93a35e34" + integrity sha1-OhlFF63CTDxhzcVvNfRTfpOjXjQ= + dependencies: + hoek "5.x.x" + optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -8276,11 +8302,6 @@ pdfmake@0.1.33: lodash "^4.17.4" pdfkit "^0.8.3" -peekaboo@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/peekaboo/-/peekaboo-2.0.2.tgz#fc42e139efd698c6ff2870a6b20c047cd9aa29ff" - integrity sha1-/ELhOe/WmMb/KHCmsgwEfNmqKf8= - pegjs@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" @@ -8301,16 +8322,16 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -pez@2.x.x: - version "2.1.5" - resolved "https://registry.yarnpkg.com/pez/-/pez-2.1.5.tgz#5ec2cc62500cc3eb4236d4a414cf5a17b5eb5007" - integrity sha1-XsLMYlAMw+tCNtSkFM9aF7XrUAc= +pez@4.x.x: + version "4.0.2" + resolved "https://registry.yarnpkg.com/pez/-/pez-4.0.2.tgz#0a7c81b64968e90b0e9562b398f390939e9c4b53" + integrity sha512-HuPxmGxHsEFPWhdkwBs2gIrHhFqktIxMtudISTFN95RQ85ZZAOl8Ki6u3nnN/X8OUaGlIGldk/l8p2IR4/i76w== dependencies: - b64 "3.x.x" - boom "5.x.x" - content "3.x.x" - hoek "4.x.x" - nigel "2.x.x" + b64 "4.x.x" + boom "7.x.x" + content "4.x.x" + hoek "5.x.x" + nigel "3.x.x" pify@^2.0.0: version "2.3.0" @@ -8426,6 +8447,14 @@ pngjs@3.3.1, pngjs@^3.0.0: resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.1.tgz#8e14e6679ee7424b544334c3b2d21cea6d8c209a" integrity sha512-ggXCTsqHRIsGMkHlCEhbHhUmNTA2r1lpkE0NL4Q9S8spkXbm4vE9TVmPso2AGYn90Gltdz8W5CyzhcIGg2Gejg== +podium@3.x.x: + version "3.1.2" + resolved "https://registry.yarnpkg.com/podium/-/podium-3.1.2.tgz#b701429739cf6bdde6b3015ae6b48d400817ce9e" + integrity sha512-18VrjJAduIdPv7d9zWsfmKxTj3cQTYC5Pv5gtKxcWujYBpGbV+mhNSPYhlHW5xeWoazYyKfB9FEsPT12r5rY1A== + dependencies: + hoek "5.x.x" + joi "13.x.x" + polished@^1.9.2: version "1.9.2" resolved "https://registry.yarnpkg.com/polished/-/polished-1.9.2.tgz#d705cac66f3a3ed1bd38aad863e2c1e269baf6b6" @@ -8466,10 +8495,10 @@ prettier@1.13.7: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281" integrity sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w== -pretty-format@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.5.0.tgz#0f9601ad9da70fe690a269cd3efca732c210687c" - integrity sha512-iFLvYTXOn+C/s7eV+pr4E8DD7lYa2/klXMEz+lvH14qSDWAJ7S+kFmMe1SIWesATHQxopHTxRcB2nrpExhzaBA== +pretty-format@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760" + integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw== dependencies: ansi-regex "^3.0.0" ansi-styles "^3.2.0" @@ -8647,6 +8676,11 @@ pumpify@^1.3.5: inherits "^2.0.3" pump "^2.0.0" +punycode@2.x.x: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -9661,7 +9695,7 @@ resolve-pathname@^2.2.0: resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879" integrity sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg== -resolve-url@^0.2.1, resolve-url@~0.2.1: +resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= @@ -10003,13 +10037,13 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -shot@3.x.x: - version "3.4.2" - resolved "https://registry.yarnpkg.com/shot/-/shot-3.4.2.tgz#1e5c3f6f2b26649adc42f7eb350214a5a0291d67" - integrity sha1-Hlw/bysmZJrcQvfrNQIUpaApHWc= +shot@4.x.x: + version "4.0.5" + resolved "https://registry.yarnpkg.com/shot/-/shot-4.0.5.tgz#c7e7455d11d60f6b6cd3c43e15a3b431c17e5566" + integrity sha1-x+dFXRHWD2ts08Q+FaO0McF+VWY= dependencies: - hoek "4.x.x" - joi "10.x.x" + hoek "5.x.x" + joi "13.x.x" sigmund@~1.0.0: version "1.0.1" @@ -10162,16 +10196,6 @@ sort-keys@^2.0.0: dependencies: is-plain-obj "^1.0.0" -source-map-resolve@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761" - integrity sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E= - dependencies: - atob "~1.1.0" - resolve-url "~0.2.1" - source-map-url "~0.3.0" - urix "~0.1.0" - source-map-resolve@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.1.tgz#7ad0f593f2281598e854df80f19aae4b92d7a11a" @@ -10183,6 +10207,17 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-resolve@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" @@ -10211,23 +10246,11 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map-url@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" - integrity sha1-fsrxO1e80J2opAxdJp2zN5nUqvk= - "source-map@>= 0.1.2", source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.1.38, source-map@~0.1.30, source-map@~0.1.33: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - integrity sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y= - dependencies: - amdefine ">=0.0.4" - source-map@^0.4.2, source-map@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" @@ -10240,6 +10263,13 @@ source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= +source-map@~0.1.30, source-map@~0.1.33: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + integrity sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y= + dependencies: + amdefine ">=0.0.4" + sparkles@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" @@ -10319,17 +10349,17 @@ stack-utils@^1.0.1: resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" integrity sha1-1PM6tU6OOHeLDKXP07OvsS22hiA= -statehood@4.x.x: - version "4.1.0" - resolved "https://registry.yarnpkg.com/statehood/-/statehood-4.1.0.tgz#8a2877d13d9850aab6ce877a54b778df0f43acdb" - integrity sha1-iih30T2YUKq2zod6VLd43w9DrNs= +statehood@6.x.x: + version "6.0.6" + resolved "https://registry.yarnpkg.com/statehood/-/statehood-6.0.6.tgz#0dbd7c50774d3f61a24e42b0673093bbc81fa5f0" + integrity sha512-jR45n5ZMAkasw0xoE9j9TuLmJv4Sa3AkXe+6yIFT6a07kXYHgSbuD2OVGECdZGFxTmvNqLwL1iRIgvq6O6rq+A== dependencies: - boom "3.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - iron "4.x.x" - items "2.x.x" - joi "9.x.x" + boom "7.x.x" + bounce "1.x.x" + cryptiles "4.x.x" + hoek "5.x.x" + iron "5.x.x" + joi "13.x.x" static-eval@~0.2.0: version "0.2.4" @@ -10529,16 +10559,16 @@ stylis@^3.5.0: resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.1.tgz#fd341d59f57f9aeb412bc14c9d8a8670b438e03b" integrity sha512-yM4PyeHuwhIOUHNJxi1/Mbq8kVLv4AkyE7IYLP/LK0lIFcr3tRa2H1iZlBYKIxOlf+/jruBTe8DdKSyQX9w4OA== -subtext@4.x.x: - version "4.4.1" - resolved "https://registry.yarnpkg.com/subtext/-/subtext-4.4.1.tgz#2fcec945de429283c3d18b151ff0fa1f1b87aec9" - integrity sha1-L87JRd5CkoPD0YsVH/D6HxuHrsk= +subtext@6.x.x: + version "6.0.7" + resolved "https://registry.yarnpkg.com/subtext/-/subtext-6.0.7.tgz#8e40a67901a734d598142665c90e398369b885f9" + integrity sha512-IcJUvRjeR+NB437Iq+LORFNJW4L6Knqkj3oQrBrkdhIaS2VKJvx/9aYEq7vi+PEx5/OuehOL/40SkSZotLi/MA== dependencies: - boom "5.x.x" - content "3.x.x" - hoek "4.x.x" - pez "2.x.x" - wreck "12.x.x" + boom "7.x.x" + content "4.x.x" + hoek "5.x.x" + pez "4.x.x" + wreck "14.x.x" superagent@3.8.2: version "3.8.2" @@ -10725,6 +10755,11 @@ tar@^2.0.0, tar@^2.2.1: fstream "^1.0.2" inherits "2" +teamwork@3.x.x: + version "3.0.1" + resolved "https://registry.yarnpkg.com/teamwork/-/teamwork-3.0.1.tgz#ff38c7161f41f8070b7813716eb6154036ece196" + integrity sha512-hEkJIpDOfOYe9NYaLFk00zQbzZeKNCY8T2pRH3I13Y1mJwxaSQ6NEsjY5rCp+11ezCiZpWGoGFTbOuhg4qKevQ== + test-exclude@^4.2.1: version "4.2.3" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20" @@ -10936,19 +10971,12 @@ toggle-selection@^1.0.3: resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= -topo@1.x.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/topo/-/topo-1.1.0.tgz#e9d751615d1bb87dc865db182fa1ca0a5ef536d5" - integrity sha1-6ddRYV0buH3IZdsYL6HKCl71NtU= - dependencies: - hoek "2.x.x" - -topo@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/topo/-/topo-2.0.2.tgz#cd5615752539057c0dc0491a621c3bc6fbe1d182" - integrity sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI= +topo@3.x.x: + version "3.0.0" + resolved "https://registry.yarnpkg.com/topo/-/topo-3.0.0.tgz#37e48c330efeac784538e0acd3e62ca5e231fe7a" + integrity sha512-Tlu1fGlR90iCdIPURqPiufqAlCZYzLjHYVVbcFWDMcX7+tK8hdZWAfsMrD/pBul9jqHHwFjNdf1WaxA9vTRRhw== dependencies: - hoek "4.x.x" + hoek "5.x.x" tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.3.0, tough-cookie@~2.3.3: version "2.3.3" @@ -11001,7 +11029,12 @@ trim-right@^1.0.1: dependencies: glob "^6.0.4" -tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" + integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ== + +tslib@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== @@ -11213,7 +11246,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urix@^0.1.0, urix@~0.1.0: +urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= @@ -11428,12 +11461,12 @@ vinyl@^2.0.0, vinyl@^2.1.0: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" -vise@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vise/-/vise-2.0.2.tgz#6b08e8fb4cb76e3a50cd6dd0ec37338e811a0d39" - integrity sha1-awjo+0y3bjpQzW3Q7DczjoEaDTk= +vise@3.x.x: + version "3.0.0" + resolved "https://registry.yarnpkg.com/vise/-/vise-3.0.0.tgz#76ad14ab31669c50fbb0817bc0e72fedcbb3bf4c" + integrity sha512-kBFZLmiL1Vm3rHXphkhvvAcsjgeQXRrOFCbJb0I50YZZP4HGRNH+xGzK3matIMcpbsfr3I02u9odj4oCD0TWgA== dependencies: - hoek "4.x.x" + hoek "5.x.x" w3c-hr-time@^1.0.1: version "1.0.1" @@ -11619,13 +11652,13 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -wreck@12.x.x: - version "12.5.1" - resolved "https://registry.yarnpkg.com/wreck/-/wreck-12.5.1.tgz#cd2ffce167449e1f0242ed9cf80552e20fb6902a" - integrity sha512-l5DUGrc+yDyIflpty1x9XuMj1ehVjC/dTbF3/BasOO77xk0EdEa4M/DuOY8W88MQDAD0fEDqyjc8bkIMHd2E9A== +wreck@14.x.x: + version "14.1.0" + resolved "https://registry.yarnpkg.com/wreck/-/wreck-14.1.0.tgz#b13e526b6a8318e5ebc6969c0b21075c06337067" + integrity sha512-y/iwFhwdGoM8Hk1t1I4LbuLhM3curVD8STd5NcFI0c/4b4cQAMLcnCRxXX9sLQAggDC8dXYSaQNsT64hga6lvA== dependencies: - boom "5.x.x" - hoek "4.x.x" + boom "7.x.x" + hoek "5.x.x" write-file-atomic@^2.1.0: version "2.3.0" diff --git a/yarn.lock b/yarn.lock index 382e8e31224928..7d79736eb28131 100644 --- a/yarn.lock +++ b/yarn.lock @@ -158,6 +158,16 @@ resolved "https://registry.yarnpkg.com/@elastic/filesaver/-/filesaver-1.1.2.tgz#1998ffb3cd89c9da4ec12a7793bfcae10e30c77a" integrity sha512-YZbSufYFBhAj+S2cJgiKALoxIJevqXN2MSr6Yqr42rJdaPuM31cj6pUDwflkql1oDjupqD9la+MfxPFjXI1JFQ== +"@elastic/good@8.1.1-kibana1": + version "8.1.1-kibana1" + resolved "https://registry.yarnpkg.com/@elastic/good/-/good-8.1.1-kibana1.tgz#d8e444fdac8cc7dad36d4e29acc566cbf93298b9" + integrity sha512-RLeMEkeglz4EpvlHyI/6I3C1V3+8AzT/BdzFL1h2MDUoaJlFHGoF7U6T5vkTO1BuAY7EgUeG8zIoftb1fweRQg== + dependencies: + hoek "5.x.x" + joi "13.x.x" + oppsy "2.x.x" + pumpify "1.3.x" + "@elastic/node-crypto@0.1.2": version "0.1.2" resolved "https://registry.yarnpkg.com/@elastic/node-crypto/-/node-crypto-0.1.2.tgz#c18ac282f635e88f041cc1555d806e492ca8f3b1" @@ -727,10 +737,10 @@ resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.12.6.tgz#3d619198585fcabe5f4e1adfb5cf5f3388c66c13" integrity sha512-wXAVyLfkG1UMkKOdMijVWFky39+OD/41KftzqfX1Oejd0Gm6dOIKjCihSVECg6X7PHjftxXmfOKA/d1H79ZfvQ== -"@types/hapi-latest@npm:@types/hapi@17.0.12": - version "17.0.12" - resolved "https://registry.yarnpkg.com/@types/hapi/-/hapi-17.0.12.tgz#5751f4d8db4decb4eae6671a4efbeae671278ceb" - integrity sha512-OdCd3r7IVLM894EGA6jrrxJpbY7r3EG+jJBGveGshMxwxQE58mL7NdRcr4hmdCzsgUl3aVtZkSK4GpAf8C9kMw== +"@types/hapi@^17.0.18": + version "17.6.1" + resolved "https://registry.yarnpkg.com/@types/hapi/-/hapi-17.6.1.tgz#006590e92d82bb5b1e20af6d4bc46898a8d43db2" + integrity sha512-Fk8j8INn131ws5kmqaMxYSlyg38iMjsQ2TbY2XMvWhPDfErFWBqTDJcB4jP8Hv68A5PaG9M1+nNWM3mHxTFg4Q== dependencies: "@types/boom" "*" "@types/catbox" "*" @@ -751,6 +761,11 @@ resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.0.tgz#2fac51050c68f7d6f96c5aafc631132522f4aa3f" integrity sha512-1A/RUAX4VtmGzNTGLSfmiPxQ3XwUSe/1YN4lW9GRa+j307oFK6MPjhlvw6jEHDodUBIvSvrA7/iHDchr5LS+0Q== +"@types/hoek@^4.1.3": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@types/hoek/-/hoek-4.1.3.tgz#d1982d48fb0d2a0e5d7e9d91838264d8e428d337" + integrity sha1-0ZgtSPsNKg5dfp2Rg4Jk2OQo0zc= + "@types/iron@*": version "5.0.1" resolved "https://registry.yarnpkg.com/@types/iron/-/iron-5.0.1.tgz#5420bbda8623c48ee51b9a78ebad05d7305b4b24" @@ -775,10 +790,10 @@ resolved "https://registry.yarnpkg.com/@types/joi/-/joi-13.3.0.tgz#bdfa2e49d8d258ba79f23304228d0c4d5cfc848c" integrity sha512-nOnsbHvoo5DsQEh8VGlbQlfg9+/iFSxE5RQKLNkAODIqyupdEkBCZf6RCNxR+9X0egMIkJ43NnwkEJKxLogsIA== -"@types/joi@^10.4.4": - version "10.6.2" - resolved "https://registry.yarnpkg.com/@types/joi/-/joi-10.6.2.tgz#0e7d632fe918c337784e87b16c7cc0098876179a" - integrity sha512-Fvw5Sj9XL3Fzjky9T3N/gKtChamphIKg80wfy9h+LSUFYAKmCPc/so0nJd7xYk46qEw3D81X51qk38INx3sDew== +"@types/joi@^13.4.2": + version "13.6.1" + resolved "https://registry.yarnpkg.com/@types/joi/-/joi-13.6.1.tgz#325486a397504f8e22c8c551dc8b0e1d41d5d5ae" + integrity sha512-JxZ0NP8NuB0BJOXi1KvAA6rySLTPmhOy4n2gzSFq/IFM3LNFm0h+2Vn/bPPgEYlWqzS2NPeLgKqfm75baX+Hog== "@types/jquery@^3.3.6": version "3.3.6" @@ -1064,14 +1079,6 @@ abortcontroller-polyfill@^1.1.9: resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.1.9.tgz#9fefe359fda2e9e0932dc85e6106453ac393b2da" integrity sha512-omvG7zOHIs3BphdH62Kh3xy8nlftAsTyp7PDa9EmC3Jz9pa6sZFYk7UhNgu9Y4sIBhj6jF0RgeFZYvPnsP5sBw== -accept@2.x.x: - version "2.1.4" - resolved "https://registry.yarnpkg.com/accept/-/accept-2.1.4.tgz#887af54ceee5c7f4430461971ec400c61d09acbb" - integrity sha1-iHr1TO7lx/RDBGGXHsQAxh0JrLs= - dependencies: - boom "5.x.x" - hoek "4.x.x" - accept@3.x.x: version "3.0.2" resolved "https://registry.yarnpkg.com/accept/-/accept-3.0.2.tgz#83e41cec7e1149f3fd474880423873db6c6cc9ac" @@ -1241,14 +1248,6 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= -ammo@2.x.x: - version "2.0.4" - resolved "https://registry.yarnpkg.com/ammo/-/ammo-2.0.4.tgz#bf80aab211698ea78f63ef5e7f113dd5d9e8917f" - integrity sha1-v4CqshFpjqePY+9efxE91dnokX8= - dependencies: - boom "5.x.x" - hoek "4.x.x" - ammo@3.x.x: version "3.0.1" resolved "https://registry.yarnpkg.com/ammo/-/ammo-3.0.1.tgz#c79ceeac36fb4e55085ea3fe0c2f42bfa5f7c914" @@ -1881,11 +1880,6 @@ axios@^0.18.0: follow-redirects "^1.3.0" is-buffer "^1.1.5" -b64@3.x.x: - version "3.0.3" - resolved "https://registry.yarnpkg.com/b64/-/b64-3.0.3.tgz#36afeee0d9345f046387ce6de8a6702afe5bb56e" - integrity sha512-Pbeh0i6OLubPJdIdCepn8ZQHwN2MWznZHbHABSTEfQ706ie+yuxNSaPdqX1xRatT6WanaS1EazMiSg0NUW2XxQ== - b64@4.x.x: version "4.0.0" resolved "https://registry.yarnpkg.com/b64/-/b64-4.0.0.tgz#c37f587f0a383c7019e821120e8c3f58f0d22772" @@ -2106,6 +2100,14 @@ babel-jest@^23.4.2: babel-plugin-istanbul "^4.1.6" babel-preset-jest "^23.2.0" +babel-jest@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1" + integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew== + dependencies: + babel-plugin-istanbul "^4.1.6" + babel-preset-jest "^23.2.0" + babel-loader@7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.2.tgz#f6cbe122710f1aa2af4d881c6d5b54358ca24126" @@ -2883,20 +2885,6 @@ boom@2.x.x: dependencies: hoek "2.x.x" -boom@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-3.1.1.tgz#b6424f01ed8d492b2b12ae86047c24e8b6a7c937" - integrity sha1-tkJPAe2NSSsrEq6GBHwk6LanyTc= - dependencies: - hoek "3.x.x" - -boom@3.X.X, boom@3.x.x: - version "3.2.2" - resolved "https://registry.yarnpkg.com/boom/-/boom-3.2.2.tgz#0f0cc5d04adc5003b8c7d71f42cca7271fef0e78" - integrity sha1-DwzF0ErcUAO4x9cfQsynJx/vDng= - dependencies: - hoek "4.x.x" - boom@4.x.x: version "4.3.1" resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" @@ -2904,14 +2892,14 @@ boom@4.x.x: dependencies: hoek "4.x.x" -boom@5.2.0, boom@5.x.x: +boom@5.x.x: version "5.2.0" resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" integrity sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw== dependencies: hoek "4.x.x" -boom@7.x.x, boom@^7.1.0: +boom@7.x.x, boom@^7.1.0, boom@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/boom/-/boom-7.2.0.tgz#2bff24a55565767fde869ec808317eb10c48e966" integrity sha1-K/8kpVVldn/ehp7ICDF+sQxI6WY= @@ -3314,14 +3302,6 @@ call-me-maybe@^1.0.1: resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= -call@3.x.x: - version "3.0.4" - resolved "https://registry.yarnpkg.com/call/-/call-3.0.4.tgz#e380f2f2a491330aa79085355f8be080877d559e" - integrity sha1-44Dy8qSRMwqnkIU1X4vggId9VZ4= - dependencies: - boom "4.x.x" - hoek "4.x.x" - call@5.x.x: version "5.0.1" resolved "https://registry.yarnpkg.com/call/-/call-5.0.1.tgz#ac1b5c106d9edc2a17af2a4a4f74dd4f0c06e910" @@ -3428,13 +3408,6 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -catbox-memory@2.x.x: - version "2.0.4" - resolved "https://registry.yarnpkg.com/catbox-memory/-/catbox-memory-2.0.4.tgz#433e255902caf54233d1286429c8f4df14e822d5" - integrity sha1-Qz4lWQLK9UIz0ShkKcj03xToItU= - dependencies: - hoek "4.x.x" - catbox-memory@3.x.x: version "3.1.2" resolved "https://registry.yarnpkg.com/catbox-memory/-/catbox-memory-3.1.2.tgz#4aeec1bc994419c0f7e60087f172aaedd9b4911c" @@ -3454,15 +3427,6 @@ catbox@10.x.x: hoek "5.x.x" joi "13.x.x" -catbox@7.x.x: - version "7.1.5" - resolved "https://registry.yarnpkg.com/catbox/-/catbox-7.1.5.tgz#c56f7e8e9555d27c0dc038a96ef73e57d186bb1f" - integrity sha512-4fui5lELzqZ+9cnaAP/BcqXTH6LvWLBRtFhJ0I4FfgfXiSaZcf6k9m9dqOyChiTxNYtvLk7ZMYSf7ahMq3bf5A== - dependencies: - boom "5.x.x" - hoek "4.x.x" - joi "10.x.x" - caw@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" @@ -4189,13 +4153,6 @@ content-type@~1.0.1, content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== -content@3.x.x: - version "3.0.7" - resolved "https://registry.yarnpkg.com/content/-/content-3.0.7.tgz#0cbb88e82702d35ccf59800b8add609bb5c1dfc2" - integrity sha512-LXtnSnvE+Z1Cjpa3P9gh9kb396qV4MqpfwKy777BOSF8n6nw2vAi03tHNl0/XRqZUyzVzY/+nMXOZVnEapWzdg== - dependencies: - boom "5.x.x" - content@4.x.x: version "4.0.5" resolved "https://registry.yarnpkg.com/content/-/content-4.0.5.tgz#bc547deabc889ab69bce17faf3585c29f4c41bf2" @@ -6075,17 +6032,6 @@ esutils@~1.0.0: resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" integrity sha1-gVHTWOIMisx/t0XnRywAJf5JZXA= -even-better@7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/even-better/-/even-better-7.0.2.tgz#d056f429c90ecc20ee9494aca0a751f743504d2e" - integrity sha1-0Fb0KckOzCDulJSsoKdR90NQTS4= - dependencies: - hoek "2.x.x" - items "1.x.x" - joi "6.x.x" - traverse "0.6.6" - wreck "6.x.x" - event-emitter@~0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" @@ -6245,15 +6191,15 @@ expect.js@0.3.1: resolved "https://registry.yarnpkg.com/expect.js/-/expect.js-0.3.1.tgz#b0a59a0d2eff5437544ebf0ceaa6015841d09b5b" integrity sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s= -expect@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-23.5.0.tgz#18999a0eef8f8acf99023fde766d9c323c2562ed" - integrity sha512-aG083W63tBloy8YgafWuC44EakjYe0Q6Mg35aujBPvyNU38DvLat9BVzOihNP2NZDLaCJiFNe0vejbtO6knnlA== +expect@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98" + integrity sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w== dependencies: ansi-styles "^3.2.0" - jest-diff "^23.5.0" + jest-diff "^23.6.0" jest-get-type "^22.1.0" - jest-matcher-utils "^23.5.0" + jest-matcher-utils "^23.6.0" jest-message-util "^23.4.0" jest-regex-util "^23.3.0" @@ -7530,7 +7476,7 @@ gulp-sourcemaps@1.7.3: through2 "2.X" vinyl "1.X" -"h2o2-latest@npm:h2o2@8.1.2": +h2o2@^8.1.2: version "8.1.2" resolved "https://registry.yarnpkg.com/h2o2/-/h2o2-8.1.2.tgz#25e6f69f453175c9ca1e3618741c5ebe1b5000c1" integrity sha1-Jeb2n0UxdcnKHjYYdBxevhtQAME= @@ -7540,16 +7486,6 @@ gulp-sourcemaps@1.7.3: joi "13.x.x" wreck "14.x.x" -h2o2@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/h2o2/-/h2o2-5.1.1.tgz#dc09d59e8771d0ffc9f3bdba2e6b72ef6151c1e3" - integrity sha1-3AnVnodx0P/J8726Lmty72FRweM= - dependencies: - boom "3.X.X" - hoek "4.X.X" - joi "9.X.X" - wreck "9.X.X" - handlebars@4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.5.tgz#92c6ed6bb164110c50d4d8d0fbddc70806c6f8e7" @@ -7583,19 +7519,20 @@ handlebars@^4.0.10: optionalDependencies: uglify-js "^3.1.4" -hapi-auth-cookie@6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/hapi-auth-cookie/-/hapi-auth-cookie-6.1.1.tgz#927db39e434916d81ab870d4181d70d53e745572" - integrity sha1-kn2znkNJFtgauHDUGB1w1T50VXI= +hapi-auth-cookie@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/hapi-auth-cookie/-/hapi-auth-cookie-9.0.0.tgz#3b0af443334e2bd92490ddb17bed16e3e9edfd01" + integrity sha512-N71Mt7Jk0+7WLnuvfSv0DoGzgpn7TqOd+/AB73RfHpLvzYoskJ9AlFV3Op60DB01RJNaABZtdcH1l4HM3DMbog== dependencies: - boom "3.x.x" - hoek "3.x.x" - joi "7.x.x" + boom "7.x.x" + bounce "1.x.x" + hoek "5.x.x" + joi "13.x.x" -"hapi-latest@npm:hapi@17.5.0": - version "17.5.0" - resolved "https://registry.yarnpkg.com/hapi/-/hapi-17.5.0.tgz#9fc33f10d6f563d0203853937b60dd13a59b51ce" - integrity sha512-/btV0jpXb8ldoywsAt+FZg3qUVCx2ZjeA29Mluo3w/gcCJtzUnZfGALS8xR3d2ssVySm7JXVqeepy37Z02gJLQ== +hapi@^17.5.3: + version "17.6.0" + resolved "https://registry.yarnpkg.com/hapi/-/hapi-17.6.0.tgz#158a2276253a8de727be678c4daeb1f73929e588" + integrity sha512-GSHjE1hJExluAukrT/QuYSk96irmbYBDd3wOgywiHsPoR2QeKgDnIttD+dB6NbADEmSdb9MS5gTUIVq0uHTdkA== dependencies: accept "3.x.x" ammo "3.x.x" @@ -7615,31 +7552,6 @@ hapi-auth-cookie@6.1.1: teamwork "3.x.x" topo "3.x.x" -hapi@14.2.0: - version "14.2.0" - resolved "https://registry.yarnpkg.com/hapi/-/hapi-14.2.0.tgz#e4fe2fc182598a0f81e87b41b6be0fbd31c75409" - integrity sha1-5P4vwYJZig+B6HtBtr4PvTHHVAk= - dependencies: - accept "2.x.x" - ammo "2.x.x" - boom "3.x.x" - call "3.x.x" - catbox "7.x.x" - catbox-memory "2.x.x" - cryptiles "3.x.x" - heavy "4.x.x" - hoek "4.x.x" - iron "4.x.x" - items "2.x.x" - joi "9.x.x" - kilt "2.x.x" - mimos "3.x.x" - peekaboo "2.x.x" - shot "3.x.x" - statehood "4.x.x" - subtext "4.x.x" - topo "2.x.x" - har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" @@ -7851,15 +7763,6 @@ he@^0.5.0: resolved "https://registry.yarnpkg.com/he/-/he-0.5.0.tgz#2c05ffaef90b68e860f3fd2b54ef580989277ee2" integrity sha1-LAX/rvkLaOhg8/0rVO9YCYknfuI= -heavy@4.x.x: - version "4.0.4" - resolved "https://registry.yarnpkg.com/heavy/-/heavy-4.0.4.tgz#36c91336c00ccfe852caa4d153086335cd2f00e9" - integrity sha1-NskTNsAMz+hSyqTRUwhjNc0vAOk= - dependencies: - boom "5.x.x" - hoek "4.x.x" - joi "10.x.x" - heavy@6.x.x: version "6.1.0" resolved "https://registry.yarnpkg.com/heavy/-/heavy-6.1.0.tgz#1bbfa43dc61dd4b543ede3ff87db8306b7967274" @@ -7904,12 +7807,7 @@ hoek@2.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= -hoek@3.x.x: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-3.0.4.tgz#268adff66bb6695c69b4789a88b1e0847c3f3123" - integrity sha1-Jorf9mu2aVxptHiaiLHghHw/MSM= - -hoek@4.2.1, hoek@4.X.X, hoek@4.x.x: +hoek@4.2.1, hoek@4.x.x: version "4.2.1" resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA== @@ -7919,6 +7817,11 @@ hoek@5.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-5.0.3.tgz#b71d40d943d0a95da01956b547f83c4a5b4a34ac" integrity sha512-Bmr56pxML1c9kU+NS51SMFkiVQAb+9uFfXwyqR2tn4w2FPvmPt65eZ9aCcEfRXd9G74HkZnILC6p967pED4aiw== +hoek@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-5.0.4.tgz#0f7fa270a1cafeb364a4b2ddfaa33f864e4157da" + integrity sha512-Alr4ZQgoMlnere5FZJsIyfIjORBqZll5POhDsF4q64dPuJR6rNxXdDxtHSQq8OXRurhmx+PWYEE8bXRROY8h0w== + hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.5: version "2.5.5" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" @@ -8204,17 +8107,17 @@ indexof@0.0.1: resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= -inert@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/inert/-/inert-4.0.2.tgz#f26094988e653f81c84a690664781546f8d75928" - integrity sha1-8mCUmI5lP4HISmkGZHgVRvjXWSg= +inert@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/inert/-/inert-5.1.0.tgz#e9f130dc3047ccd9ffaa64b157b4c1114611035d" + integrity sha512-5rJZbezGEkBN4QrP/HEEwsQ0N+7YzqDZrvBZrE7B0CrNY6I4XKI434aL3UNLCmbI4HzPGQs7Ae/4h1tiTMJ6Wg== dependencies: - ammo "2.x.x" - boom "3.x.x" - hoek "4.x.x" - items "2.x.x" - joi "9.x.x" - lru-cache "4.0.x" + ammo "3.x.x" + boom "7.x.x" + bounce "1.x.x" + hoek "5.x.x" + joi "13.x.x" + lru-cache "4.1.x" infinity-agent@^2.0.0: version "2.0.3" @@ -8395,7 +8298,7 @@ ip-regex@^1.0.1: resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd" integrity sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0= -iron@4, iron@4.x.x: +iron@4: version "4.0.5" resolved "https://registry.yarnpkg.com/iron/-/iron-4.0.5.tgz#4f042cceb8b9738f346b59aa734c83a89bc31428" integrity sha1-TwQszri5c480a1mqc0yDqJvDFCg= @@ -8886,16 +8789,6 @@ isbinaryfile@^3.0.0: resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621" integrity sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE= -isemail@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a" - integrity sha1-vgPfjMPineTSxd9lASY/H6RZXpo= - -isemail@2.x.x: - version "2.2.1" - resolved "https://registry.yarnpkg.com/isemail/-/isemail-2.2.1.tgz#0353d3d9a62951080c262c2aa0a42b8ea8e9e2a6" - integrity sha1-A1PT2aYpUQgMJiwqoKQrjqjp4qY= - isemail@3.x.x: version "3.1.1" resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.1.1.tgz#e8450fe78ff1b48347db599122adcd0668bd92b5" @@ -9070,11 +8963,6 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" -items@1.x.x: - version "1.1.1" - resolved "https://registry.yarnpkg.com/items/-/items-1.1.1.tgz#435b5dd21bca28b3cfd25bb5c6b278b715010fd9" - integrity sha1-Q1td0hvKKLPP0lu1xrJ4txUBD9k= - items@2.x.x: version "2.1.1" resolved "https://registry.yarnpkg.com/items/-/items-2.1.1.tgz#8bd16d9c83b19529de5aea321acaada78364a198" @@ -9139,35 +9027,35 @@ jest-cli@^23.5.0: which "^1.2.12" yargs "^11.0.0" -jest-config@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.5.0.tgz#3770fba03f7507ee15f3b8867c742e48f31a9773" - integrity sha512-JENhQpLaVwXWPLUkhPYgIfecHKsU8GR1vj79rS4n0LSRsHx/U2wItZKoKAd5vtt2J58JPxRq4XheG79jd4fI7Q== +jest-config@^23.5.0, jest-config@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d" + integrity sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ== dependencies: babel-core "^6.0.0" - babel-jest "^23.4.2" + babel-jest "^23.6.0" chalk "^2.0.1" glob "^7.1.1" jest-environment-jsdom "^23.4.0" jest-environment-node "^23.4.0" jest-get-type "^22.1.0" - jest-jasmine2 "^23.5.0" + jest-jasmine2 "^23.6.0" jest-regex-util "^23.3.0" - jest-resolve "^23.5.0" + jest-resolve "^23.6.0" jest-util "^23.4.0" - jest-validate "^23.5.0" + jest-validate "^23.6.0" micromatch "^2.3.11" - pretty-format "^23.5.0" + pretty-format "^23.6.0" -jest-diff@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.5.0.tgz#250651a433dd0050290a07642946cc9baaf06fba" - integrity sha512-Miz8GakJIz443HkGpVOAyHQgSYqcgs2zQmDJl4oV7DYrFotchdoQvxceF6LhfpRBV1LOUGcFk5Dd/ffSXVwMsA== +jest-diff@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d" + integrity sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g== dependencies: chalk "^2.0.1" diff "^3.2.0" jest-get-type "^22.1.0" - pretty-format "^23.5.0" + pretty-format "^23.6.0" jest-docblock@^21.0.0: version "21.2.0" @@ -9181,13 +9069,13 @@ jest-docblock@^23.2.0: dependencies: detect-newline "^2.1.0" -jest-each@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.5.0.tgz#77f7e2afe6132a80954b920006e78239862b10ba" - integrity sha512-8BgebQgAJmWXpYp4Qt9l3cn1Xei0kZ7JL4cs/NXh7750ATlPGzRRYbutFVJTk5B/Lt3mjHP3G3tLQLyBOCSHGA== +jest-each@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575" + integrity sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg== dependencies: chalk "^2.0.1" - pretty-format "^23.5.0" + pretty-format "^23.6.0" jest-environment-jsdom@^23.4.0: version "23.4.0" @@ -9211,10 +9099,10 @@ jest-get-type@^22.1.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w== -jest-haste-map@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.5.0.tgz#d4ca618188bd38caa6cb20349ce6610e194a8065" - integrity sha512-bt9Swigb6KZ6ZQq/fQDUwdUeHenVvZ6G/lKwJjwRGp+Fap8D4B3bND3FaeJg7vXVsLX8hXshRArbVxLop/5wLw== +jest-haste-map@^23.5.0, jest-haste-map@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16" + integrity sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg== dependencies: fb-watchman "^2.0.0" graceful-fs "^4.1.11" @@ -9225,39 +9113,39 @@ jest-haste-map@^23.5.0: micromatch "^2.3.11" sane "^2.0.0" -jest-jasmine2@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.5.0.tgz#05fe7f1788e650eeb5a03929e6461ea2e9f3db53" - integrity sha512-xMgvDUvgqKpilsGnneC9Qr+uIlROxKI3UoJcHZeUlu6AKpQyEkGh0hKbfM0NaEjX5sy7WeFQEhcp/AiWlHcc0A== +jest-jasmine2@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0" + integrity sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ== dependencies: babel-traverse "^6.0.0" chalk "^2.0.1" co "^4.6.0" - expect "^23.5.0" + expect "^23.6.0" is-generator-fn "^1.0.0" - jest-diff "^23.5.0" - jest-each "^23.5.0" - jest-matcher-utils "^23.5.0" + jest-diff "^23.6.0" + jest-each "^23.6.0" + jest-matcher-utils "^23.6.0" jest-message-util "^23.4.0" - jest-snapshot "^23.5.0" + jest-snapshot "^23.6.0" jest-util "^23.4.0" - pretty-format "^23.5.0" + pretty-format "^23.6.0" -jest-leak-detector@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.5.0.tgz#14ac2a785bd625160a2ea968fd5d98b7dcea3e64" - integrity sha512-40VsHQCIEslxg91Zg5NiZGtPeWSBLXiD6Ww+lhHlIF6u8uSQ+xgiD6NbWHFOYs1VBRI+V/ym7Q1aOtVg9tqMzQ== +jest-leak-detector@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de" + integrity sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg== dependencies: - pretty-format "^23.5.0" + pretty-format "^23.6.0" -jest-matcher-utils@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.5.0.tgz#0e2ea67744cab78c9ab15011c4d888bdd3e49e2a" - integrity sha512-hmQUKUKYOExp3T8dNYK9A9copCFYKoRLcY4WDJJ0Z2u3oF6rmAhHuZtmpHBuGpASazobBxm3TXAfAXDvz2T7+Q== +jest-matcher-utils@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80" + integrity sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog== dependencies: chalk "^2.0.1" jest-get-type "^22.1.0" - pretty-format "^23.5.0" + pretty-format "^23.6.0" jest-message-util@^23.4.0: version "23.4.0" @@ -9286,45 +9174,45 @@ jest-regex-util@^23.3.0: integrity sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U= jest-resolve-dependencies@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.5.0.tgz#10c4d135beb9d2256de1fedc7094916c3ad74af7" - integrity sha512-APZc/CjfzL8rH/wr+Gh7XJJygYaDjMQsWaJy4ZR1WaHWKude4WcfdU8xjqaNbx5NsVF2P2tVvsLbumlPXCdJOw== + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d" + integrity sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA== dependencies: jest-regex-util "^23.3.0" - jest-snapshot "^23.5.0" + jest-snapshot "^23.6.0" -jest-resolve@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.5.0.tgz#3b8e7f67e84598f0caf63d1530bd8534a189d0e6" - integrity sha512-CRPc0ebG3baNKz/QicIy5rGfzYpMNm8AjEl/tDQhehq/QC4ttyauZdvAXel3qo+4Gri9ljajnxW+hWyxZbbcnQ== +jest-resolve@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae" + integrity sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA== dependencies: browser-resolve "^1.11.3" chalk "^2.0.1" realpath-native "^1.0.0" jest-runner@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.5.0.tgz#570f7a044da91648b5bb9b6baacdd511076c71d7" - integrity sha512-cpBvkBTVmW1ab1thbtoh2m6VnnM0BYKhj3MEzbOTZjPfzoIjUVIxLUTDobVNOvEK7aTEb/2oiPlNoOTSNJx8mw== + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38" + integrity sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA== dependencies: exit "^0.1.2" graceful-fs "^4.1.11" - jest-config "^23.5.0" + jest-config "^23.6.0" jest-docblock "^23.2.0" - jest-haste-map "^23.5.0" - jest-jasmine2 "^23.5.0" - jest-leak-detector "^23.5.0" + jest-haste-map "^23.6.0" + jest-jasmine2 "^23.6.0" + jest-leak-detector "^23.6.0" jest-message-util "^23.4.0" - jest-runtime "^23.5.0" + jest-runtime "^23.6.0" jest-util "^23.4.0" jest-worker "^23.2.0" source-map-support "^0.5.6" throat "^4.0.0" -jest-runtime@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.5.0.tgz#eb503525a196dc32f2f9974e3482d26bdf7b63ce" - integrity sha512-WzzYxYtoU8S1MJns0G4E3BsuFUTFBiu1qsk3iC9OTugzNQcQKt0BoOGsT7wXCKqkw/09QdV77vvaeJXST2Efgg== +jest-runtime@^23.5.0, jest-runtime@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082" + integrity sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw== dependencies: babel-core "^6.0.0" babel-plugin-istanbul "^4.1.6" @@ -9333,14 +9221,14 @@ jest-runtime@^23.5.0: exit "^0.1.2" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.1.11" - jest-config "^23.5.0" - jest-haste-map "^23.5.0" + jest-config "^23.6.0" + jest-haste-map "^23.6.0" jest-message-util "^23.4.0" jest-regex-util "^23.3.0" - jest-resolve "^23.5.0" - jest-snapshot "^23.5.0" + jest-resolve "^23.6.0" + jest-snapshot "^23.6.0" jest-util "^23.4.0" - jest-validate "^23.5.0" + jest-validate "^23.6.0" micromatch "^2.3.11" realpath-native "^1.0.0" slash "^1.0.0" @@ -9353,20 +9241,20 @@ jest-serializer@^23.0.1: resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165" integrity sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU= -jest-snapshot@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.5.0.tgz#cc368ebd8513e1175e2a7277f37a801b7358ae79" - integrity sha512-NYg8MFNVyPXmnnihiltasr4t1FJEXFbZFaw1vZCowcnezIQ9P1w+yxTwjWT564QP24Zbn5L9cjxLs8d6K+pNlw== +jest-snapshot@^23.5.0, jest-snapshot@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a" + integrity sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg== dependencies: babel-types "^6.0.0" chalk "^2.0.1" - jest-diff "^23.5.0" - jest-matcher-utils "^23.5.0" + jest-diff "^23.6.0" + jest-matcher-utils "^23.6.0" jest-message-util "^23.4.0" - jest-resolve "^23.5.0" + jest-resolve "^23.6.0" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^23.5.0" + pretty-format "^23.6.0" semver "^5.5.0" jest-util@^23.4.0: @@ -9383,15 +9271,15 @@ jest-util@^23.4.0: slash "^1.0.0" source-map "^0.6.0" -jest-validate@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.5.0.tgz#f5df8f761cf43155e1b2e21d6e9de8a2852d0231" - integrity sha512-XmStdYhfdiDKacXX5sNqEE61Zz4/yXaPcDsKvVA0429RBu2pkQyIltCVG7UitJIEAzSs3ociQTdyseAW8VGPiA== +jest-validate@^23.5.0, jest-validate@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474" + integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A== dependencies: chalk "^2.0.1" jest-get-type "^22.1.0" leven "^2.1.0" - pretty-format "^23.5.0" + pretty-format "^23.6.0" jest-watcher@^23.4.0: version "23.4.0" @@ -9444,26 +9332,6 @@ jit-grunt@~0.10.0: resolved "https://registry.yarnpkg.com/jit-grunt/-/jit-grunt-0.10.0.tgz#008c3a7fe1e96bd0d84e260ea1fa1783457f79c2" integrity sha1-AIw6f+Hpa9DYTiYOofoXg0V/ecI= -joi@10.4.1: - version "10.4.1" - resolved "https://registry.yarnpkg.com/joi/-/joi-10.4.1.tgz#a2fca1f0d603d1b843f2c1e086b52461f6be1f36" - integrity sha1-ovyh8NYD0bhD8sHghrUkYfa+HzY= - dependencies: - hoek "4.x.x" - isemail "2.x.x" - items "2.x.x" - topo "2.x.x" - -joi@10.x.x: - version "10.6.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-10.6.0.tgz#52587f02d52b8b75cdb0c74f0b164a191a0e1fc2" - integrity sha512-hBF3LcqyAid+9X/pwg+eXjD2QBZI5eXnBFJYaAkH4SK3mp9QSRiiQnDYlmlz5pccMvnLcJRS4whhDOTCkmsAdQ== - dependencies: - hoek "4.x.x" - isemail "2.x.x" - items "2.x.x" - topo "2.x.x" - joi@13.x.x, joi@^13.4.0: version "13.4.0" resolved "https://registry.yarnpkg.com/joi/-/joi-13.4.0.tgz#afc359ee3d8bc5f9b9ba6cdc31b46d44af14cecc" @@ -9473,46 +9341,14 @@ joi@13.x.x, joi@^13.4.0: isemail "3.x.x" topo "3.x.x" -joi@6.10.1, joi@6.x.x: - version "6.10.1" - resolved "https://registry.yarnpkg.com/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06" - integrity sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY= +joi@^13.5.2: + version "13.7.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-13.7.0.tgz#cfd85ebfe67e8a1900432400b4d03bbd93fb879f" + integrity sha512-xuY5VkHfeOYK3Hdi91ulocfuFopwgbSORmIwzcwHKESQhC7w1kD5jaVSPnqDxS2I8t3RZ9omCKAxNwXN5zG1/Q== dependencies: - hoek "2.x.x" - isemail "1.x.x" - moment "2.x.x" - topo "1.x.x" - -joi@7.x.x: - version "7.3.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-7.3.0.tgz#4d9c9f181830444083665b5b6cd5b8ca6779a5e9" - integrity sha1-TZyfGBgwRECDZltbbNW4ymd5pek= - dependencies: - hoek "3.x.x" - isemail "2.x.x" - moment "2.x.x" - topo "2.x.x" - -joi@8.x.x: - version "8.4.2" - resolved "https://registry.yarnpkg.com/joi/-/joi-8.4.2.tgz#bd7774658fe99058d8994ed1d4b9962484ebb859" - integrity sha1-vXd0ZY/pkFjYmU7R1LmWJITruFk= - dependencies: - hoek "4.x.x" - isemail "2.x.x" - moment "2.x.x" - topo "2.x.x" - -joi@9.X.X, joi@9.x.x: - version "9.2.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-9.2.0.tgz#3385ac790192130cbe230e802ec02c9215bbfeda" - integrity sha1-M4WseQGSEwy+Iw6ALsAskhW7/to= - dependencies: - hoek "4.x.x" - isemail "2.x.x" - items "2.x.x" - moment "2.x.x" - topo "2.x.x" + hoek "5.x.x" + isemail "3.x.x" + topo "3.x.x" jpeg-js@^0.2.0: version "0.2.0" @@ -9949,13 +9785,6 @@ keyv@3.0.0: dependencies: json-buffer "3.0.0" -kilt@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/kilt/-/kilt-2.0.2.tgz#04d7183c298a1232efddf7ddca5959a8f6301e20" - integrity sha1-BNcYPCmKEjLv3ffdyllZqPYwHiA= - dependencies: - hoek "4.x.x" - kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -10750,14 +10579,6 @@ lowlight@~1.9.1: dependencies: highlight.js "~9.12.0" -lru-cache@4.0.x: - version "4.0.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" - integrity sha1-HRdnnAac2l0ECZGgnbwsDbN35V4= - dependencies: - pseudomap "^1.0.1" - yallist "^2.0.0" - lru-cache@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" @@ -11072,14 +10893,6 @@ mimic-response@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e" integrity sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4= -mimos@3.x.x: - version "3.0.3" - resolved "https://registry.yarnpkg.com/mimos/-/mimos-3.0.3.tgz#b9109072ad378c2b72f6a0101c43ddfb2b36641f" - integrity sha1-uRCQcq03jCty9qAQHEPd+ys2ZB8= - dependencies: - hoek "4.x.x" - mime-db "1.x.x" - mimos@4.x.x: version "4.0.0" resolved "https://registry.yarnpkg.com/mimos/-/mimos-4.0.0.tgz#76e3d27128431cb6482fd15b20475719ad626a5a" @@ -11241,7 +11054,7 @@ moment-timezone@^0.5.14: dependencies: moment ">= 2.9.0" -moment@2.x.x, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.13.0, moment@^2.20.1: +"moment@>= 2.9.0", moment@^2.10.6, moment@^2.13.0, moment@^2.20.1: version "2.21.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a" integrity sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ== @@ -11388,14 +11201,6 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" integrity sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA== -nigel@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/nigel/-/nigel-2.0.2.tgz#93a1866fb0c52d87390aa75e2b161f4b5c75e5b1" - integrity sha1-k6GGb7DFLYc5CqdeKxYfS1x15bE= - dependencies: - hoek "4.x.x" - vise "2.x.x" - nigel@3.x.x: version "3.0.1" resolved "https://registry.yarnpkg.com/nigel/-/nigel-3.0.1.tgz#48a08859d65177312f1c25af7252c1e07bb07c2a" @@ -11866,6 +11671,13 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +oppsy@2.x.x, oppsy@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/oppsy/-/oppsy-2.0.0.tgz#3a194517adc24c3c61cdc56f35f4537e93a35e34" + integrity sha1-OhlFF63CTDxhzcVvNfRTfpOjXjQ= + dependencies: + hoek "5.x.x" + optimist@^0.6.1, optimist@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -12331,11 +12143,6 @@ pdfmake@0.1.33: lodash "^4.17.4" pdfkit "^0.8.3" -peekaboo@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/peekaboo/-/peekaboo-2.0.2.tgz#fc42e139efd698c6ff2870a6b20c047cd9aa29ff" - integrity sha1-/ELhOe/WmMb/KHCmsgwEfNmqKf8= - pegjs@0.9.0, pegjs@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.9.0.tgz#f6aefa2e3ce56169208e52179dfe41f89141a369" @@ -12356,17 +12163,6 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -pez@2.x.x: - version "2.1.5" - resolved "https://registry.yarnpkg.com/pez/-/pez-2.1.5.tgz#5ec2cc62500cc3eb4236d4a414cf5a17b5eb5007" - integrity sha1-XsLMYlAMw+tCNtSkFM9aF7XrUAc= - dependencies: - b64 "3.x.x" - boom "5.x.x" - content "3.x.x" - hoek "4.x.x" - nigel "2.x.x" - pez@4.x.x: version "4.0.2" resolved "https://registry.yarnpkg.com/pez/-/pez-4.0.2.tgz#0a7c81b64968e90b0e9562b398f390939e9c4b53" @@ -12880,10 +12676,10 @@ prettier@^1.14.3: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" integrity sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg== -pretty-format@^23.5.0: - version "23.5.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.5.0.tgz#0f9601ad9da70fe690a269cd3efca732c210687c" - integrity sha512-iFLvYTXOn+C/s7eV+pr4E8DD7lYa2/klXMEz+lvH14qSDWAJ7S+kFmMe1SIWesATHQxopHTxRcB2nrpExhzaBA== +pretty-format@^23.6.0: + version "23.6.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760" + integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw== dependencies: ansi-regex "^3.0.0" ansi-styles "^3.2.0" @@ -13001,7 +12797,7 @@ prr@~1.0.1: resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= -pseudomap@^1.0.1, pseudomap@^1.0.2: +pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= @@ -13165,6 +12961,15 @@ pump@^2.0.0, pump@^2.0.1: end-of-stream "^1.1.0" once "^1.3.1" +pumpify@1.3.x: + version "1.3.6" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.3.6.tgz#00d40e5ded0a3bf1e0788b1c0cf426a42882ab64" + integrity sha512-BurGAcvezsINL5US9T9wGHHcLNrG6MCp//ECtxron3vcR+Rfx5Anqq7HbZXNJvFQli8FGVsWCAvywEJFV5Hx/Q== + dependencies: + duplexify "^3.5.3" + inherits "^2.0.3" + pump "^2.0.0" + pumpify@^1.3.3: version "1.5.1" resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" @@ -14891,14 +14696,6 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -shot@3.x.x: - version "3.4.2" - resolved "https://registry.yarnpkg.com/shot/-/shot-3.4.2.tgz#1e5c3f6f2b26649adc42f7eb350214a5a0291d67" - integrity sha1-Hlw/bysmZJrcQvfrNQIUpaApHWc= - dependencies: - hoek "4.x.x" - joi "10.x.x" - shot@4.x.x: version "4.0.5" resolved "https://registry.yarnpkg.com/shot/-/shot-4.0.5.tgz#c7e7455d11d60f6b6cd3c43e15a3b431c17e5566" @@ -15354,18 +15151,6 @@ state-toggle@^1.0.0: resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.0.tgz#d20f9a616bb4f0c3b98b91922d25b640aa2bc425" integrity sha1-0g+aYWu08MO5i5GSLSW2QKorxCU= -statehood@4.x.x: - version "4.1.0" - resolved "https://registry.yarnpkg.com/statehood/-/statehood-4.1.0.tgz#8a2877d13d9850aab6ce877a54b778df0f43acdb" - integrity sha1-iih30T2YUKq2zod6VLd43w9DrNs= - dependencies: - boom "3.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - iron "4.x.x" - items "2.x.x" - joi "9.x.x" - statehood@6.x.x: version "6.0.6" resolved "https://registry.yarnpkg.com/statehood/-/statehood-6.0.6.tgz#0dbd7c50774d3f61a24e42b0673093bbc81fa5f0" @@ -15662,17 +15447,6 @@ stylis@^3.5.0: resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.1.tgz#fd341d59f57f9aeb412bc14c9d8a8670b438e03b" integrity sha512-yM4PyeHuwhIOUHNJxi1/Mbq8kVLv4AkyE7IYLP/LK0lIFcr3tRa2H1iZlBYKIxOlf+/jruBTe8DdKSyQX9w4OA== -subtext@4.x.x: - version "4.4.1" - resolved "https://registry.yarnpkg.com/subtext/-/subtext-4.4.1.tgz#2fcec945de429283c3d18b151ff0fa1f1b87aec9" - integrity sha1-L87JRd5CkoPD0YsVH/D6HxuHrsk= - dependencies: - boom "5.x.x" - content "3.x.x" - hoek "4.x.x" - pez "2.x.x" - wreck "12.x.x" - subtext@6.x.x: version "6.0.7" resolved "https://registry.yarnpkg.com/subtext/-/subtext-6.0.7.tgz#8e40a67901a734d598142665c90e398369b885f9" @@ -16144,20 +15918,6 @@ token-stream@0.0.1: resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a" integrity sha1-zu78cXp2xDFvEm0LnbqlXX598Bo= -topo@1.x.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/topo/-/topo-1.1.0.tgz#e9d751615d1bb87dc865db182fa1ca0a5ef536d5" - integrity sha1-6ddRYV0buH3IZdsYL6HKCl71NtU= - dependencies: - hoek "2.x.x" - -topo@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/topo/-/topo-2.0.2.tgz#cd5615752539057c0dc0491a621c3bc6fbe1d182" - integrity sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI= - dependencies: - hoek "4.x.x" - topo@3.x.x: version "3.0.0" resolved "https://registry.yarnpkg.com/topo/-/topo-3.0.0.tgz#37e48c330efeac784538e0acd3e62ca5e231fe7a" @@ -17284,13 +17044,6 @@ vinyl@^2.0.0: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" -vise@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vise/-/vise-2.0.2.tgz#6b08e8fb4cb76e3a50cd6dd0ec37338e811a0d39" - integrity sha1-awjo+0y3bjpQzW3Q7DczjoEaDTk= - dependencies: - hoek "4.x.x" - vise@3.x.x: version "3.0.0" resolved "https://registry.yarnpkg.com/vise/-/vise-3.0.0.tgz#76ad14ab31669c50fbb0817bc0e72fedcbb3bf4c" @@ -17298,15 +17051,15 @@ vise@3.x.x: dependencies: hoek "5.x.x" -vision@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/vision/-/vision-4.1.0.tgz#c0c49c9287423cfcf7dbedf51ae6a67b065c6ae7" - integrity sha1-wMSckodCPPz32+31GuamewZcauc= +vision@^5.3.3: + version "5.4.0" + resolved "https://registry.yarnpkg.com/vision/-/vision-5.4.0.tgz#fc620deb95227881ea8b8d8a044dc1d1fd40e584" + integrity sha512-f8kbjvo/dUbR4ZDF0pHPuOjQFg/6zOMlP1Tb9gK2ukCa7Ksd24174DCzubtov6AxIDhZhO5RYQeeDlF8ujlKWQ== dependencies: - boom "3.x.x" - hoek "3.x.x" + boom "7.x.x" + hoek "5.x.x" items "2.x.x" - joi "8.x.x" + joi "13.x.x" vlq@^0.2.2: version "0.2.3" @@ -17583,22 +17336,6 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -wreck@12.4.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/wreck/-/wreck-12.4.0.tgz#bd931e1de059f1390f6c67bc29b91053cc479d3f" - integrity sha512-5QWJGTyt/yX9QIu6/bnAuiPnODVmIhnJNLyBSb5hb0NeGXKiMjm8bIhKJW5zNN09tGOQlnp2Awmo4Y5yI3uP+w== - dependencies: - boom "5.x.x" - hoek "4.x.x" - -wreck@12.x.x: - version "12.5.1" - resolved "https://registry.yarnpkg.com/wreck/-/wreck-12.5.1.tgz#cd2ffce167449e1f0242ed9cf80552e20fb6902a" - integrity sha512-l5DUGrc+yDyIflpty1x9XuMj1ehVjC/dTbF3/BasOO77xk0EdEa4M/DuOY8W88MQDAD0fEDqyjc8bkIMHd2E9A== - dependencies: - boom "5.x.x" - hoek "4.x.x" - wreck@14.x.x: version "14.0.2" resolved "https://registry.yarnpkg.com/wreck/-/wreck-14.0.2.tgz#89c17a9061c745ed1c3aebcb66ea181dbaab454c" @@ -17607,21 +17344,13 @@ wreck@14.x.x: boom "7.x.x" hoek "5.x.x" -wreck@6.x.x: - version "6.3.0" - resolved "https://registry.yarnpkg.com/wreck/-/wreck-6.3.0.tgz#a1369769f07bbb62d6a378336a7871fc773c740b" - integrity sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs= +wreck@^14.0.2: + version "14.1.0" + resolved "https://registry.yarnpkg.com/wreck/-/wreck-14.1.0.tgz#b13e526b6a8318e5ebc6969c0b21075c06337067" + integrity sha512-y/iwFhwdGoM8Hk1t1I4LbuLhM3curVD8STd5NcFI0c/4b4cQAMLcnCRxXX9sLQAggDC8dXYSaQNsT64hga6lvA== dependencies: - boom "2.x.x" - hoek "2.x.x" - -wreck@9.X.X: - version "9.0.0" - resolved "https://registry.yarnpkg.com/wreck/-/wreck-9.0.0.tgz#1de63d49bb07b94fe718864b8be63176e63331ec" - integrity sha1-HeY9SbsHuU/nGIZLi+YxduYzMew= - dependencies: - boom "3.x.x" - hoek "4.x.x" + boom "7.x.x" + hoek "5.x.x" write-file-atomic@^1.1.2: version "1.3.4" @@ -17788,7 +17517,7 @@ y18n@^3.2.1: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yallist@^2.0.0, yallist@^2.1.2: +yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=