Skip to content

Commit

Permalink
[7.x] [Reporting] Define shims of legacy dependencies (#54082) (#55134)
Browse files Browse the repository at this point in the history
* [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>

* update legacy to fix ts errors

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
tsullivan and elasticmachine authored Jan 21, 2020
1 parent a8ac40b commit 1cb96c2
Show file tree
Hide file tree
Showing 16 changed files with 224 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
})(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
63 changes: 49 additions & 14 deletions x-pack/legacy/plugins/reporting/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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,
Expand All @@ -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 : {},
Expand Down Expand Up @@ -70,28 +92,41 @@ 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;
// Register a function with server to manage the collection of usage stats
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', () => {
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@
* 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;
}

try {
return await server.plugins.security.getUser(request);
} catch (err) {
server.log(['reporting', 'getUser', 'debug'], err);
server.log(['reporting', 'getUser', 'error'], err);
return null;
}
};
Expand Down
8 changes: 4 additions & 4 deletions x-pack/legacy/plugins/reporting/server/lib/level_logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down
4 changes: 0 additions & 4 deletions x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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`;
Expand Down Expand Up @@ -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) {
Expand All @@ -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}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

/*
Expand All @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@
* 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,
Logger,
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:
Expand All @@ -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 });

Expand Down
6 changes: 4 additions & 2 deletions x-pack/legacy/plugins/reporting/server/routes/generation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -19,6 +19,7 @@ import { registerGenerateCsvFromSavedObject } from './generate_from_savedobject'
import { registerGenerateCsvFromSavedObjectImmediate } from './generate_from_savedobject_immediate';
import { registerLegacy } from './legacy';
import { createQueueFactory, enqueueJobFactory } from '../lib';
import { makeRequestFacade } from './lib/make_request_facade';

export function registerJobGenerationRoutes(
server: ServerFacade,
Expand All @@ -40,9 +41,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;

Expand Down
Loading

0 comments on commit 1cb96c2

Please sign in to comment.