From 3d74bc80fa2f8456af536c6422e03aee30f06a8c Mon Sep 17 00:00:00 2001
From: Tim Sullivan <tsullivan@users.noreply.github.com>
Date: Thu, 16 Jan 2020 15:15:25 -0700
Subject: [PATCH] [Reporting] Define shims of legacy dependencies (#54082)

* simplify serverfacade definition

* simplify requestfacade definition

* use the shim

* makeRequestFacade

* requestFacade

* import sorting

* originalServer

* reduce loc change

* remove consolelog

* hacks to fix tests

* ServerFacade in index

* Cosmetic

* remove field from serverfacade

* add raw to the request

* fix types

* add fieldFormatServiceFactory to legacy

* Pass the complete request object to sec plugin

* Fix test

* fix test 2

* getUser takes a legacy request

* add unit test for new lib

* add getRawRequest to pass to saved objects method

* update test snapshot

* leave a TODO comment for type import

* variable rename for legacy id

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
---
 .../export_types/csv/server/execute_job.ts    |  1 -
 .../server/lib/generate_csv_search.ts         |  2 +-
 x-pack/legacy/plugins/reporting/index.ts      | 63 ++++++++++++++-----
 .../server/lib/{get_user.js => get_user.ts}   | 12 +++-
 .../reporting/server/lib/level_logger.ts      |  8 +--
 .../reporting/server/lib/once_per_server.ts   |  4 --
 .../server/routes/generate_from_jobparams.ts  |  9 ++-
 .../routes/generate_from_savedobject.ts       | 13 ++--
 .../generate_from_savedobject_immediate.ts    |  8 ++-
 .../reporting/server/routes/generation.ts     |  6 +-
 .../plugins/reporting/server/routes/jobs.ts   | 21 ++++---
 .../routes/lib/make_request_facade.test.ts    | 62 ++++++++++++++++++
 .../server/routes/lib/make_request_facade.ts  | 32 ++++++++++
 .../reporting/server/routes/types.d.ts        |  3 +-
 x-pack/legacy/plugins/reporting/types.d.ts    | 51 ++++++++-------
 15 files changed, 221 insertions(+), 74 deletions(-)
 rename x-pack/legacy/plugins/reporting/server/lib/{get_user.js => get_user.ts} (57%)
 create mode 100644 x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.test.ts
 create mode 100644 x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.ts

diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts
index fef45f5a5eae8..ae603d93245a3 100644
--- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts
+++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts
@@ -86,7 +86,6 @@ export const executeJobFactory: ExecuteJobFactory<ESQueueWorkerExecuteFn<
 
     const [formatsMap, uiSettings] = await Promise.all([
       (async () => {
-        // @ts-ignore fieldFormatServiceFactory' does not exist on type 'ServerFacade TODO
         const fieldFormats = await server.fieldFormatServiceFactory(uiConfig);
         return fieldFormatMapFactory(indexPatternSavedObject, fieldFormats);
       })(),
diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts
index 7e12adefca38d..d39d2bbf08c9f 100644
--- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts
+++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts
@@ -57,7 +57,7 @@ export async function generateCsvSearch(
   jobParams: JobParamsDiscoverCsv
 ): Promise<CsvResultFromSearch> {
   const { savedObjects, uiSettingsServiceFactory } = server;
-  const savedObjectsClient = savedObjects.getScopedSavedObjectsClient(req);
+  const savedObjectsClient = savedObjects.getScopedSavedObjectsClient(req.getRawRequest());
   const { indexPatternSavedObjectId, timerange } = searchPanel;
   const savedSearchObjectAttr = searchPanel.attributes as SavedSearchObjectAttributes;
   const { indexPatternSavedObject } = await getDataSource(
diff --git a/x-pack/legacy/plugins/reporting/index.ts b/x-pack/legacy/plugins/reporting/index.ts
index ef0ab37738362..82d94422b70ce 100644
--- a/x-pack/legacy/plugins/reporting/index.ts
+++ b/x-pack/legacy/plugins/reporting/index.ts
@@ -6,6 +6,9 @@
 
 import { resolve } from 'path';
 import { i18n } from '@kbn/i18n';
+import { Legacy } from 'kibana';
+import { IUiSettingsClient } from 'src/core/server';
+import { XPackMainPlugin } from '../xpack_main/server/xpack_main';
 import { PLUGIN_ID, UI_SETTINGS_CUSTOM_PDF_LOGO } from './common/constants';
 // @ts-ignore untyped module defintition
 import { mirrorPluginStatus } from '../../server/lib/mirror_plugin_status';
@@ -16,16 +19,35 @@ import {
   getExportTypesRegistry,
   runValidations,
 } from './server/lib';
-import { config as reportingConfig } from './config';
-import { logConfiguration } from './log_configuration';
 import { createBrowserDriverFactory } from './server/browsers';
 import { registerReportingUsageCollector } from './server/usage';
-import { ReportingConfigOptions, ReportingPluginSpecOptions, ServerFacade } from './types.d';
+import { ReportingConfigOptions, ReportingPluginSpecOptions } from './types.d';
+import { config as reportingConfig } from './config';
+import { logConfiguration } from './log_configuration';
 
 const kbToBase64Length = (kb: number) => {
   return Math.floor((kb * 1024 * 8) / 6);
 };
 
+type LegacyPlugins = Legacy.Server['plugins'];
+
+export interface ServerFacade {
+  config: Legacy.Server['config'];
+  info: Legacy.Server['info'];
+  log: Legacy.Server['log'];
+  plugins: {
+    elasticsearch: LegacyPlugins['elasticsearch'];
+    security: LegacyPlugins['security'];
+    xpack_main: XPackMainPlugin & {
+      status?: any;
+    };
+  };
+  route: Legacy.Server['route'];
+  savedObjects: Legacy.Server['savedObjects'];
+  uiSettingsServiceFactory: Legacy.Server['uiSettingsServiceFactory'];
+  fieldFormatServiceFactory: (uiConfig: IUiSettingsClient) => unknown;
+}
+
 export const reporting = (kibana: any) => {
   return new kibana.Plugin({
     id: PLUGIN_ID,
@@ -42,7 +64,7 @@ export const reporting = (kibana: any) => {
       embeddableActions: ['plugins/reporting/panel_actions/get_csv_panel_action'],
       home: ['plugins/reporting/register_feature'],
       managementSections: ['plugins/reporting/views/management'],
-      injectDefaultVars(server: ServerFacade, options?: ReportingConfigOptions) {
+      injectDefaultVars(server: Legacy.Server, options?: ReportingConfigOptions) {
         const config = server.config();
         return {
           reportingPollConfig: options ? options.poll : {},
@@ -70,9 +92,22 @@ export const reporting = (kibana: any) => {
       },
     },
 
-    // TODO: Decouple Hapi: Build a server facade object based on the server to
-    // pass through to the libs. Do not pass server directly
-    async init(server: ServerFacade) {
+    async init(server: Legacy.Server) {
+      const serverFacade: ServerFacade = {
+        config: server.config,
+        info: server.info,
+        route: server.route.bind(server),
+        plugins: {
+          elasticsearch: server.plugins.elasticsearch,
+          xpack_main: server.plugins.xpack_main,
+          security: server.plugins.security,
+        },
+        savedObjects: server.savedObjects,
+        uiSettingsServiceFactory: server.uiSettingsServiceFactory,
+        // @ts-ignore Property 'fieldFormatServiceFactory' does not exist on type 'Server'.
+        fieldFormatServiceFactory: server.fieldFormatServiceFactory,
+        log: server.log.bind(server),
+      };
       const exportTypesRegistry = getExportTypesRegistry();
 
       let isCollectorReady = false;
@@ -80,18 +115,18 @@ export const reporting = (kibana: any) => {
       const { usageCollection } = server.newPlatform.setup.plugins;
       registerReportingUsageCollector(
         usageCollection,
-        server,
+        serverFacade,
         () => isCollectorReady,
         exportTypesRegistry
       );
 
-      const logger = LevelLogger.createForServer(server, [PLUGIN_ID]);
-      const browserDriverFactory = await createBrowserDriverFactory(server);
+      const logger = LevelLogger.createForServer(serverFacade, [PLUGIN_ID]);
+      const browserDriverFactory = await createBrowserDriverFactory(serverFacade);
 
-      logConfiguration(server, logger);
-      runValidations(server, logger, browserDriverFactory);
+      logConfiguration(serverFacade, logger);
+      runValidations(serverFacade, logger, browserDriverFactory);
 
-      const { xpack_main: xpackMainPlugin } = server.plugins;
+      const { xpack_main: xpackMainPlugin } = serverFacade.plugins;
       mirrorPluginStatus(xpackMainPlugin, this);
       const checkLicense = checkLicenseFactory(exportTypesRegistry);
       (xpackMainPlugin as any).status.once('green', () => {
@@ -104,7 +139,7 @@ export const reporting = (kibana: any) => {
       isCollectorReady = true;
 
       // Reporting routes
-      registerRoutes(server, exportTypesRegistry, browserDriverFactory, logger);
+      registerRoutes(serverFacade, exportTypesRegistry, browserDriverFactory, logger);
     },
 
     deprecations({ unused }: any) {
diff --git a/x-pack/legacy/plugins/reporting/server/lib/get_user.js b/x-pack/legacy/plugins/reporting/server/lib/get_user.ts
similarity index 57%
rename from x-pack/legacy/plugins/reporting/server/lib/get_user.js
rename to x-pack/legacy/plugins/reporting/server/lib/get_user.ts
index 04c9516cb99d4..e2921de795012 100644
--- a/x-pack/legacy/plugins/reporting/server/lib/get_user.js
+++ b/x-pack/legacy/plugins/reporting/server/lib/get_user.ts
@@ -4,8 +4,14 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-export function getUserFactory(server) {
-  return async request => {
+import { Legacy } from 'kibana';
+import { ServerFacade } from '../../types';
+
+export function getUserFactory(server: ServerFacade) {
+  /*
+   * Legacy.Request because this is called from routing middleware
+   */
+  return async (request: Legacy.Request) => {
     if (!server.plugins.security) {
       return null;
     }
@@ -13,7 +19,7 @@ export function getUserFactory(server) {
     try {
       return await server.plugins.security.getUser(request);
     } catch (err) {
-      server.log(['reporting', 'getUser', 'debug'], err);
+      server.log(['reporting', 'getUser', 'error'], err);
       return null;
     }
   };
diff --git a/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts b/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts
index c67a9cd32d50d..839fa16a716b7 100644
--- a/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts
+++ b/x-pack/legacy/plugins/reporting/server/lib/level_logger.ts
@@ -4,7 +4,7 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-type ServerLog = (tags: string[], msg: string) => void;
+import { ServerFacade } from '../../types';
 
 const trimStr = (toTrim: string) => {
   return typeof toTrim === 'string' ? toTrim.trim() : toTrim;
@@ -16,12 +16,12 @@ export class LevelLogger {
 
   public warn: (msg: string, tags?: string[]) => void;
 
-  static createForServer(server: any, tags: string[]) {
-    const serverLog: ServerLog = (tgs: string[], msg: string) => server.log(tgs, msg);
+  static createForServer(server: ServerFacade, tags: string[]) {
+    const serverLog: ServerFacade['log'] = (tgs: string[], msg: string) => server.log(tgs, msg);
     return new LevelLogger(serverLog, tags);
   }
 
-  constructor(logger: ServerLog, tags: string[]) {
+  constructor(logger: ServerFacade['log'], tags: string[]) {
     this._logger = logger;
     this._tags = tags;
 
diff --git a/x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts b/x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts
index d73a5b73fecd0..ae3636079a9bb 100644
--- a/x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts
+++ b/x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts
@@ -27,10 +27,6 @@ export function oncePerServer(fn: ServerFn) {
       throw new TypeError('This function expects to be called with a single argument');
     }
 
-    if (!server || typeof server.expose !== 'function') {
-      throw new TypeError('This function expects to be passed the server');
-    }
-
     // @ts-ignore
     return fn.call(this, server);
   });
diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts
index 128cc44db4dc4..c9225dfee6978 100644
--- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts
+++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts
@@ -4,16 +4,18 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
+import { Legacy } from 'kibana';
 import boom from 'boom';
 import Joi from 'joi';
 import rison from 'rison-node';
 import { API_BASE_URL } from '../../common/constants';
-import { ServerFacade, RequestFacade, ReportingResponseToolkit } from '../../types';
+import { ServerFacade, ReportingResponseToolkit } from '../../types';
 import {
   getRouteConfigFactoryReportingPre,
   GetRouteConfigFactoryFn,
   RouteConfigFactory,
 } from './lib/route_config_factories';
+import { makeRequestFacade } from './lib/make_request_facade';
 import { HandlerErrorFunction, HandlerFunction } from './types';
 
 const BASE_GENERATE = `${API_BASE_URL}/generate`;
@@ -54,7 +56,8 @@ export function registerGenerateFromJobParams(
     path: `${BASE_GENERATE}/{exportType}`,
     method: 'POST',
     options: getRouteConfig(),
-    handler: async (request: RequestFacade, h: ReportingResponseToolkit) => {
+    handler: async (legacyRequest: Legacy.Request, h: ReportingResponseToolkit) => {
+      const request = makeRequestFacade(legacyRequest);
       let jobParamsRison: string | null;
 
       if (request.payload) {
@@ -80,7 +83,7 @@ export function registerGenerateFromJobParams(
         if (!jobParams) {
           throw new Error('missing jobParams!');
         }
-        response = await handler(exportType, jobParams, request, h);
+        response = await handler(exportType, jobParams, legacyRequest, h);
       } catch (err) {
         throw boom.badRequest(`invalid rison: ${jobParamsRison}`);
       }
diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts
index 72c8055614065..2c509136b1b44 100644
--- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts
+++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts
@@ -4,11 +4,13 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
+import { Legacy } from 'kibana';
 import { get } from 'lodash';
 import { API_BASE_GENERATE_V1, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../common/constants';
-import { ServerFacade, RequestFacade, ReportingResponseToolkit } from '../../types';
+import { ServerFacade, ReportingResponseToolkit } from '../../types';
 import { HandlerErrorFunction, HandlerFunction, QueuedJobPayload } from './types';
 import { getRouteOptionsCsv } from './lib/route_config_factories';
+import { makeRequestFacade } from './lib/make_request_facade';
 import { getJobParamsFromRequest } from '../../export_types/csv_from_savedobject/server/lib/get_job_params_from_request';
 
 /*
@@ -31,17 +33,18 @@ export function registerGenerateCsvFromSavedObject(
     path: `${API_BASE_GENERATE_V1}/csv/saved-object/{savedObjectType}:{savedObjectId}`,
     method: 'POST',
     options: routeOptions,
-    handler: async (request: RequestFacade, h: ReportingResponseToolkit) => {
+    handler: async (legacyRequest: Legacy.Request, h: ReportingResponseToolkit) => {
+      const requestFacade = makeRequestFacade(legacyRequest);
+
       /*
        * 1. Build `jobParams` object: job data that execution will need to reference in various parts of the lifecycle
        * 2. Pass the jobParams and other common params to `handleRoute`, a shared function to enqueue the job with the params
        * 3. Ensure that details for a queued job were returned
        */
-
       let result: QueuedJobPayload<any>;
       try {
-        const jobParams = getJobParamsFromRequest(request, { isImmediate: false });
-        result = await handleRoute(CSV_FROM_SAVEDOBJECT_JOB_TYPE, jobParams, request, h);
+        const jobParams = getJobParamsFromRequest(requestFacade, { isImmediate: false });
+        result = await handleRoute(CSV_FROM_SAVEDOBJECT_JOB_TYPE, jobParams, legacyRequest, h); // pass the original request because the handler will make the request facade on its own
       } catch (err) {
         throw handleRouteError(CSV_FROM_SAVEDOBJECT_JOB_TYPE, err);
       }
diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts
index bc96c27f64c10..8d1c84664cbe9 100644
--- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts
+++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts
@@ -4,11 +4,11 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
+import { Legacy } from 'kibana';
 import { API_BASE_GENERATE_V1 } from '../../common/constants';
 import { createJobFactory, executeJobFactory } from '../../export_types/csv_from_savedobject';
 import {
   ServerFacade,
-  RequestFacade,
   ResponseFacade,
   HeadlessChromiumDriverFactory,
   ReportingResponseToolkit,
@@ -16,8 +16,9 @@ import {
   JobDocOutputExecuted,
 } from '../../types';
 import { JobDocPayloadPanelCsv } from '../../export_types/csv_from_savedobject/types';
-import { getRouteOptionsCsv } from './lib/route_config_factories';
 import { getJobParamsFromRequest } from '../../export_types/csv_from_savedobject/server/lib/get_job_params_from_request';
+import { getRouteOptionsCsv } from './lib/route_config_factories';
+import { makeRequestFacade } from './lib/make_request_facade';
 
 /*
  * This function registers API Endpoints for immediate Reporting jobs. The API inputs are:
@@ -43,7 +44,8 @@ export function registerGenerateCsvFromSavedObjectImmediate(
     path: `${API_BASE_GENERATE_V1}/immediate/csv/saved-object/{savedObjectType}:{savedObjectId}`,
     method: 'POST',
     options: routeOptions,
-    handler: async (request: RequestFacade, h: ReportingResponseToolkit) => {
+    handler: async (legacyRequest: Legacy.Request, h: ReportingResponseToolkit) => {
+      const request = makeRequestFacade(legacyRequest);
       const logger = parentLogger.clone(['savedobject-csv']);
       const jobParams = getJobParamsFromRequest(request, { isImmediate: true });
 
diff --git a/x-pack/legacy/plugins/reporting/server/routes/generation.ts b/x-pack/legacy/plugins/reporting/server/routes/generation.ts
index 73450b7641c8e..21af54ddf11e3 100644
--- a/x-pack/legacy/plugins/reporting/server/routes/generation.ts
+++ b/x-pack/legacy/plugins/reporting/server/routes/generation.ts
@@ -5,12 +5,12 @@
  */
 
 import boom from 'boom';
+import { Legacy } from 'kibana';
 import { API_BASE_URL } from '../../common/constants';
 import {
   ServerFacade,
   ExportTypesRegistry,
   HeadlessChromiumDriverFactory,
-  RequestFacade,
   ReportingResponseToolkit,
   Logger,
 } from '../../types';
@@ -18,6 +18,7 @@ import { registerGenerateFromJobParams } from './generate_from_jobparams';
 import { registerGenerateCsvFromSavedObject } from './generate_from_savedobject';
 import { registerGenerateCsvFromSavedObjectImmediate } from './generate_from_savedobject_immediate';
 import { createQueueFactory, enqueueJobFactory } from '../lib';
+import { makeRequestFacade } from './lib/make_request_facade';
 
 export function registerJobGenerationRoutes(
   server: ServerFacade,
@@ -39,9 +40,10 @@ export function registerJobGenerationRoutes(
   async function handler(
     exportTypeId: string,
     jobParams: object,
-    request: RequestFacade,
+    legacyRequest: Legacy.Request,
     h: ReportingResponseToolkit
   ) {
+    const request = makeRequestFacade(legacyRequest);
     const user = request.pre.user;
     const headers = request.headers;
 
diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts
index fd5014911d262..a0be15d60f316 100644
--- a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts
+++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts
@@ -4,16 +4,17 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
+import { Legacy } from 'kibana';
 import boom from 'boom';
 import { API_BASE_URL } from '../../common/constants';
 import {
   ServerFacade,
   ExportTypesRegistry,
   Logger,
-  RequestFacade,
   ReportingResponseToolkit,
   JobDocOutput,
   JobSource,
+  ListQuery,
 } from '../../types';
 // @ts-ignore
 import { jobsQueryFactory } from '../lib/jobs_query';
@@ -23,6 +24,7 @@ import {
   getRouteConfigFactoryDownloadPre,
   getRouteConfigFactoryManagementPre,
 } from './lib/route_config_factories';
+import { makeRequestFacade } from './lib/make_request_facade';
 
 const MAIN_ENTRY = `${API_BASE_URL}/jobs`;
 
@@ -40,8 +42,9 @@ export function registerJobInfoRoutes(
     path: `${MAIN_ENTRY}/list`,
     method: 'GET',
     options: getRouteConfig(),
-    handler: (request: RequestFacade) => {
-      const { page: queryPage, size: querySize, ids: queryIds } = request.query;
+    handler: (legacyRequest: Legacy.Request) => {
+      const request = makeRequestFacade(legacyRequest);
+      const { page: queryPage, size: querySize, ids: queryIds } = request.query as ListQuery;
       const page = parseInt(queryPage, 10) || 0;
       const size = Math.min(100, parseInt(querySize, 10) || 10);
       const jobIds = queryIds ? queryIds.split(',') : null;
@@ -62,7 +65,8 @@ export function registerJobInfoRoutes(
     path: `${MAIN_ENTRY}/count`,
     method: 'GET',
     options: getRouteConfig(),
-    handler: (request: RequestFacade) => {
+    handler: (legacyRequest: Legacy.Request) => {
+      const request = makeRequestFacade(legacyRequest);
       const results = jobsQuery.count(request.pre.management.jobTypes, request.pre.user);
       return results;
     },
@@ -73,7 +77,8 @@ export function registerJobInfoRoutes(
     path: `${MAIN_ENTRY}/output/{docId}`,
     method: 'GET',
     options: getRouteConfig(),
-    handler: (request: RequestFacade) => {
+    handler: (legacyRequest: Legacy.Request) => {
+      const request = makeRequestFacade(legacyRequest);
       const { docId } = request.params;
 
       return jobsQuery.get(request.pre.user, docId, { includeContent: true }).then(
@@ -98,7 +103,8 @@ export function registerJobInfoRoutes(
     path: `${MAIN_ENTRY}/info/{docId}`,
     method: 'GET',
     options: getRouteConfig(),
-    handler: (request: RequestFacade) => {
+    handler: (legacyRequest: Legacy.Request) => {
+      const request = makeRequestFacade(legacyRequest);
       const { docId } = request.params;
 
       return jobsQuery
@@ -130,7 +136,8 @@ export function registerJobInfoRoutes(
     path: `${MAIN_ENTRY}/download/{docId}`,
     method: 'GET',
     options: getRouteConfigDownload(),
-    handler: async (request: RequestFacade, h: ReportingResponseToolkit) => {
+    handler: async (legacyRequest: Legacy.Request, h: ReportingResponseToolkit) => {
+      const request = makeRequestFacade(legacyRequest);
       const { docId } = request.params;
 
       let response = await jobResponseHandler(
diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.test.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.test.ts
new file mode 100644
index 0000000000000..8cdb7b4c018d7
--- /dev/null
+++ b/x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.test.ts
@@ -0,0 +1,62 @@
+/*
+ * 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 { Legacy } from 'kibana';
+import { makeRequestFacade } from './make_request_facade';
+
+describe('makeRequestFacade', () => {
+  test('creates a default object', () => {
+    const legacyRequest = ({
+      getBasePath: () => 'basebase',
+      params: {
+        param1: 123,
+      },
+      payload: {
+        payload1: 123,
+      },
+      headers: {
+        user: 123,
+      },
+    } as unknown) as Legacy.Request;
+
+    expect(makeRequestFacade(legacyRequest)).toMatchInlineSnapshot(`
+      Object {
+        "getBasePath": [Function],
+        "getRawRequest": [Function],
+        "getSavedObjectsClient": undefined,
+        "headers": Object {
+          "user": 123,
+        },
+        "params": Object {
+          "param1": 123,
+        },
+        "payload": Object {
+          "payload1": 123,
+        },
+        "pre": undefined,
+        "query": undefined,
+        "route": undefined,
+      }
+    `);
+  });
+
+  test('getRawRequest', () => {
+    const legacyRequest = ({
+      getBasePath: () => 'basebase',
+      params: {
+        param1: 123,
+      },
+      payload: {
+        payload1: 123,
+      },
+      headers: {
+        user: 123,
+      },
+    } as unknown) as Legacy.Request;
+
+    expect(makeRequestFacade(legacyRequest).getRawRequest()).toBe(legacyRequest);
+  });
+});
diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.ts
new file mode 100644
index 0000000000000..fb8a2dbbff17b
--- /dev/null
+++ b/x-pack/legacy/plugins/reporting/server/routes/lib/make_request_facade.ts
@@ -0,0 +1,32 @@
+/*
+ * 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 { RequestQuery } from 'hapi';
+import { Legacy } from 'kibana';
+import {
+  RequestFacade,
+  ReportingRequestPayload,
+  ReportingRequestPre,
+  ReportingRequestQuery,
+} from '../../../types';
+
+export function makeRequestFacade(request: Legacy.Request): RequestFacade {
+  // This condition is for unit tests
+  const getSavedObjectsClient = request.getSavedObjectsClient
+    ? request.getSavedObjectsClient.bind(request)
+    : request.getSavedObjectsClient;
+  return {
+    getSavedObjectsClient,
+    headers: request.headers,
+    params: request.params,
+    payload: (request.payload as object) as ReportingRequestPayload,
+    query: ((request.query as RequestQuery) as object) as ReportingRequestQuery,
+    pre: (request.pre as Record<string, any>) as ReportingRequestPre,
+    getBasePath: request.getBasePath,
+    route: request.route,
+    getRawRequest: () => request,
+  };
+}
diff --git a/x-pack/legacy/plugins/reporting/server/routes/types.d.ts b/x-pack/legacy/plugins/reporting/server/routes/types.d.ts
index b50d443ec00b9..f3660a22cbac1 100644
--- a/x-pack/legacy/plugins/reporting/server/routes/types.d.ts
+++ b/x-pack/legacy/plugins/reporting/server/routes/types.d.ts
@@ -4,12 +4,13 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
+import { Legacy } from 'kibana';
 import { RequestFacade, ReportingResponseToolkit, JobDocPayload } from '../../types';
 
 export type HandlerFunction = (
   exportType: string,
   jobParams: object,
-  request: RequestFacade,
+  request: Legacy.Request,
   h: ReportingResponseToolkit
 ) => any;
 
diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts
index c17b969d5d7fa..fd2ca424f4db7 100644
--- a/x-pack/legacy/plugins/reporting/types.d.ts
+++ b/x-pack/legacy/plugins/reporting/types.d.ts
@@ -7,7 +7,6 @@
 import { ResponseObject } from 'hapi';
 import { EventEmitter } from 'events';
 import { Legacy } from 'kibana';
-import { XPackMainPlugin } from '../xpack_main/server/xpack_main';
 import {
   ElasticsearchPlugin,
   CallCluster,
@@ -16,6 +15,7 @@ import { CancellationToken } from './common/cancellation_token';
 import { LevelLogger } from './server/lib/level_logger';
 import { HeadlessChromiumDriverFactory } from './server/browsers/chromium/driver_factory';
 import { BrowserType } from './server/browsers/types';
+import { ServerFacade } from './index';
 
 export type ReportingPlugin = object; // For Plugin contract
 
@@ -53,7 +53,7 @@ export interface NetworkPolicy {
   rules: NetworkPolicyRule[];
 }
 
-interface ListQuery {
+export interface ListQuery {
   page: string;
   size: string;
   ids?: string; // optional field forbids us from extending RequestQuery
@@ -64,9 +64,6 @@ interface GenerateQuery {
 interface GenerateExportTypePayload {
   jobParams: string;
 }
-interface DownloadParams {
-  docId: string;
-}
 
 /*
  * Legacy System
@@ -74,26 +71,6 @@ interface DownloadParams {
 
 export type ReportingPluginSpecOptions = Legacy.PluginSpecOptions;
 
-export type ServerFacade = Legacy.Server & {
-  plugins: {
-    xpack_main?: XPackMainPlugin & {
-      status?: any;
-    };
-  };
-};
-
-interface ReportingRequest {
-  query: ListQuery & GenerateQuery;
-  params: DownloadParams;
-  payload: GenerateExportTypePayload;
-  pre: {
-    management: {
-      jobTypes: any;
-    };
-    user: any;
-  };
-}
-
 export type EnqueueJobFn = <JobParamsType>(
   parentLogger: LevelLogger,
   exportTypeId: string,
@@ -103,7 +80,27 @@ export type EnqueueJobFn = <JobParamsType>(
   request: RequestFacade
 ) => Promise<Job>;
 
-export type RequestFacade = ReportingRequest & Legacy.Request;
+export type ReportingRequestPayload = GenerateExportTypePayload | JobParamPostPayload;
+export type ReportingRequestQuery = ListQuery | GenerateQuery;
+
+export interface ReportingRequestPre {
+  management: {
+    jobTypes: any;
+  };
+  user: any; // TODO import AuthenticatedUser from security/server
+}
+
+export interface RequestFacade {
+  getBasePath: Legacy.Request['getBasePath'];
+  getSavedObjectsClient: Legacy.Request['getSavedObjectsClient'];
+  headers: Legacy.Request['headers'];
+  params: Legacy.Request['params'];
+  payload: JobParamPostPayload | GenerateExportTypePayload;
+  query: ReportingRequestQuery;
+  route: Legacy.Request['route'];
+  pre: ReportingRequestPre;
+  getRawRequest: () => Legacy.Request;
+}
 
 export type ResponseFacade = ResponseObject & {
   isBoom: boolean;
@@ -341,3 +338,5 @@ export interface AbsoluteURLFactoryOptions {
   hostname: string;
   port: string | number;
 }
+
+export { ServerFacade };