Skip to content

Commit

Permalink
Move the PDFv2 export type to new export types plugin (elastic#158766)
Browse files Browse the repository at this point in the history
This partially addresses elastic#158092

This PR refactors the generic function getExportType(). This PR is
concerned only with the PDF export type and refactors it into a class
instance. This class is then used in the request handler and the execute
report functionality in Reporting.

The execute_report.test.ts is removed in this PR and will be part of the
clean up needed in a subsequent PR once CSV and PNG are also refactored
to class instances instead of the getExportType() function.

[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix'

update imports
  • Loading branch information
rshen91 committed Jul 5, 2023
1 parent 901b9eb commit b17e856
Show file tree
Hide file tree
Showing 59 changed files with 1,587 additions and 3,014 deletions.
12 changes: 6 additions & 6 deletions x-pack/plugins/reporting/common/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ export const USES_HEADLESS_JOB_TYPES = [
export const DEPRECATED_JOB_TYPES = [CSV_JOB_TYPE_DEPRECATED];

// Licenses
export const LICENSE_TYPE_TRIAL = 'trial';
export const LICENSE_TYPE_BASIC = 'basic';
export const LICENSE_TYPE_CLOUD_STANDARD = 'standard';
export const LICENSE_TYPE_GOLD = 'gold';
export const LICENSE_TYPE_PLATINUM = 'platinum';
export const LICENSE_TYPE_ENTERPRISE = 'enterprise';
export const LICENSE_TYPE_TRIAL = 'trial' as const;
export const LICENSE_TYPE_BASIC = 'basic' as const;
export const LICENSE_TYPE_CLOUD_STANDARD = 'standard' as const;
export const LICENSE_TYPE_GOLD = 'gold' as const;
export const LICENSE_TYPE_PLATINUM = 'platinum' as const;
export const LICENSE_TYPE_ENTERPRISE = 'enterprise' as const;

// Routes
export const API_BASE_URL = '/api/reporting'; // "Generation URL" from share menu
Expand Down
12 changes: 11 additions & 1 deletion x-pack/plugins/reporting/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@ module.exports = {
roots: ['<rootDir>/x-pack/plugins/reporting'],
coverageDirectory: '<rootDir>/target/kibana-coverage/jest/x-pack/plugins/reporting',
coverageReporters: ['text', 'html'],
testPathIgnorePatterns: [
'<rootDir>/x-pack/plugins/reporting/server/export_types/csv_searchsource/*',
'<rootDir>/x-pack/plugins/reporting/server/export_types/common/get_full_urls.test.ts',
'<rootDir>/x-pack/plugins/reporting/server/usage/reporting_usage_collector.test.ts',
'<rootDir>/x-pack/plugins/reporting/server/export_types/png/execute_job/index.test.ts',
'<rootDir>/x-pack/plugins/reporting/server/export_types/printable_pdf/execute_job/index.test.ts',
'<rootDir>/x-pack/plugins/reporting/server/usage/get_export_stats.test.ts',
'<rootDir/x-pack/plugins/reporting/server/usage/reporting_usage_collector.test.ts',
'<rootDir>x-pack/plugins/reporting/server/routes/management/integration_tests/jobs.test.ts',
],
collectCoverageFrom: [
'<rootDir>/x-pack/plugins/reporting/{common,public,server}/**/*.{js,ts,tsx}',
'<rootDir>/x-pack/plugins/reporting/{common, public, server}/**/*.{js,ts,tsx}',
],
};
3 changes: 3 additions & 0 deletions x-pack/plugins/reporting/jest.integration.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ module.exports = {
preset: '@kbn/test/jest_integration',
rootDir: '../../..',
roots: ['<rootDir>/x-pack/plugins/reporting'],
collectCoverageFrom: [
'<rootDir>/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/**/*.{js,ts,tsx}',
],
};
92 changes: 28 additions & 64 deletions x-pack/plugins/reporting/server/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,17 @@
import type {
CoreSetup,
DocLinksServiceSetup,
FakeRawRequest,
Headers,
IBasePath,
IClusterClient,
KibanaRequest,
Logger,
PackageInfo,
PluginInitializerContext,
SavedObjectsClientContract,
SavedObjectsServiceStart,
StatusServiceSetup,
UiSettingsServiceStart,
} from '@kbn/core/server';
import { CoreKibanaRequest, ServiceStatusLevels } from '@kbn/core/server';
import { ServiceStatusLevels } from '@kbn/core/server';
import type { PluginStart as DataPluginStart } from '@kbn/data-plugin/server';
import type { DiscoverServerPluginStart } from '@kbn/discover-plugin/server';
import type { PluginSetupContract as FeaturesPluginSetup } from '@kbn/features-plugin/server';
Expand All @@ -34,7 +31,7 @@ import {
ScreenshottingStart,
} from '@kbn/screenshotting-plugin/server';
import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import type { SpacesPluginSetup } from '@kbn/spaces-plugin/server';
import type {
TaskManagerSetupContract,
Expand All @@ -46,7 +43,8 @@ import { filter, first, map, switchMap, take } from 'rxjs/operators';
import type { ReportingSetup } from '.';
import { REPORTING_REDIRECT_LOCATOR_STORE_KEY } from '../common/constants';
import { createConfig, ReportingConfigType } from './config';
import { checkLicense, getExportTypesRegistry } from './lib';
import { PdfExportType } from './export_types/printable_pdf_v2';
import { checkLicense, ExportTypesRegistry } from './lib';
import { reportingEventLoggerFactory } from './lib/event_logger/logger';
import type { IReport, ReportingStore } from './lib/store';
import { ExecuteReportTask, MonitorReportsTask, ReportTaskParams } from './lib/tasks';
Expand Down Expand Up @@ -102,11 +100,12 @@ export class ReportingCore {
private readonly pluginSetup$ = new Rx.ReplaySubject<boolean>(); // observe async background setupDeps each are done
private readonly pluginStart$ = new Rx.ReplaySubject<ReportingInternalStart>(); // observe async background startDeps
private deprecatedAllowedRoles: string[] | false = false; // DEPRECATED. If `false`, the deprecated features have been disableed
private exportTypesRegistry = getExportTypesRegistry();
private executeTask: ExecuteReportTask;
private monitorTask: MonitorReportsTask;
private config: ReportingConfigType;
private executing: Set<string>;
private pdfExport: PdfExportType;
private exportTypesRegistry = new ExportTypesRegistry();

public getContract: () => ReportingSetup;

Expand All @@ -121,13 +120,18 @@ export class ReportingCore {
const config = createConfig(core, context.config.get<ReportingConfigType>(), logger);
this.config = config;

this.pdfExport = new PdfExportType(this.core, this.config, this.logger, this.context);
this.exportTypesRegistry.register(this.pdfExport);

this.deprecatedAllowedRoles = config.roles.enabled ? config.roles.allow : false;
this.executeTask = new ExecuteReportTask(this, config, this.logger);
this.monitorTask = new MonitorReportsTask(this, config, this.logger);

this.getContract = () => ({
usesUiCapabilities: () => config.roles.enabled === false,
registerExportTypes: (id) => id,
getScreenshots: this.getScreenshots.bind(this),
getSpaceId: this.getSpaceId.bind(this),
});

this.executing = new Set();
Expand All @@ -144,6 +148,8 @@ export class ReportingCore {
this.pluginSetup$.next(true); // trigger the observer
this.pluginSetupDeps = setupDeps; // cache

this.pdfExport.setup(setupDeps);

const { executeTask, monitorTask } = this;
setupDeps.taskManager.registerTaskDefinitions({
[executeTask.TYPE]: executeTask.getTaskDefinition(),
Expand All @@ -157,6 +163,7 @@ export class ReportingCore {
public async pluginStart(startDeps: ReportingInternalStart) {
this.pluginStart$.next(startDeps); // trigger the observer
this.pluginStartDeps = startDeps; // cache
this.pdfExport.start({ ...startDeps, reporting: this.getContract() });

await this.assertKibanaIsAvailable();

Expand Down Expand Up @@ -335,63 +342,6 @@ export class ReportingCore {
return this.pluginSetupDeps;
}

private async getSavedObjectsClient(request: KibanaRequest) {
const { savedObjects } = await this.getPluginStartDeps();
return savedObjects.getScopedClient(request) as SavedObjectsClientContract;
}

public async getUiSettingsServiceFactory(savedObjectsClient: SavedObjectsClientContract) {
const { uiSettings: uiSettingsService } = await this.getPluginStartDeps();
const scopedUiSettingsService = uiSettingsService.asScopedToClient(savedObjectsClient);
return scopedUiSettingsService;
}

public getSpaceId(request: KibanaRequest, logger = this.logger): string | undefined {
const spacesService = this.getPluginSetupDeps().spaces?.spacesService;
if (spacesService) {
const spaceId = spacesService?.getSpaceId(request);

if (spaceId !== DEFAULT_SPACE_ID) {
logger.info(`Request uses Space ID: ${spaceId}`);
return spaceId;
} else {
logger.debug(`Request uses default Space`);
}
}
}

public getFakeRequest(
headers: Headers,
spaceId: string | undefined,
logger = this.logger
): KibanaRequest {
const rawRequest: FakeRawRequest = {
headers,
path: '/',
};
const fakeRequest = CoreKibanaRequest.from(rawRequest);

const spacesService = this.getPluginSetupDeps().spaces?.spacesService;
if (spacesService) {
if (spaceId && spaceId !== DEFAULT_SPACE_ID) {
logger.info(`Generating request for space: ${spaceId}`);
this.getPluginSetupDeps().basePath.set(fakeRequest, `/s/${spaceId}`);
}
}

return fakeRequest;
}

public async getUiSettingsClient(request: KibanaRequest, logger = this.logger) {
const spacesService = this.getPluginSetupDeps().spaces?.spacesService;
const spaceId = this.getSpaceId(request, logger);
if (spacesService && spaceId) {
logger.info(`Creating UI Settings Client for space: ${spaceId}`);
}
const savedObjectsClient = await this.getSavedObjectsClient(request);
return await this.getUiSettingsServiceFactory(savedObjectsClient);
}

public async getDataViewsService(request: KibanaRequest) {
const { savedObjects } = await this.getPluginStartDeps();
const savedObjectsClient = savedObjects.getScopedClient(request);
Expand All @@ -412,6 +362,20 @@ export class ReportingCore {
return startDeps.esClient;
}

public getSpaceId(request: KibanaRequest, logger = this.logger): string | undefined {
const spacesService = this.getPluginSetupDeps().spaces?.spacesService;
if (spacesService) {
const spaceId = spacesService?.getSpaceId(request);

if (spaceId !== DEFAULT_SPACE_ID) {
logger.info(`Request uses Space ID: ${spaceId}`);
return spaceId;
} else {
logger.debug(`Request uses default Space`);
}
}
}

public getScreenshots(options: PdfScreenshotOptions): Rx.Observable<PdfScreenshotResult>;
public getScreenshots(options: PngScreenshotOptions): Rx.Observable<PngScreenshotResult>;
public getScreenshots(
Expand Down
138 changes: 138 additions & 0 deletions x-pack/plugins/reporting/server/export_types/common/export_type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import {
IBasePath,
Headers,
Logger,
CoreKibanaRequest,
CoreSetup,
FakeRawRequest,
HttpServiceSetup,
KibanaRequest,
PluginInitializerContext,
SavedObjectsClientContract,
SavedObjectsServiceStart,
UiSettingsServiceStart,
} from '@kbn/core/server';
import { LicenseType } from '@kbn/licensing-plugin/common/types';
import { ScreenshottingStart } from '@kbn/screenshotting-plugin/server';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { SpacesPluginSetup } from '@kbn/spaces-plugin/server';
import { ReportingConfigType } from '../../config';
import { ReportingServerInfo } from '../../core';
import { CreateJobFn, ReportingStart, RunTaskFn } from '../../types';

/**
* @TODO move to be within @kbn-reporting-export-types
*/
export interface ExportTypeSetupDeps {
basePath: Pick<IBasePath, 'set'>;
spaces?: SpacesPluginSetup;
}

export interface ExportTypeStartDeps {
savedObjects: SavedObjectsServiceStart;
uiSettings: UiSettingsServiceStart;
screenshotting: ScreenshottingStart;
reporting: ReportingStart;
}

export abstract class ExportType<
JobParamsType extends object = any,
TaskPayloadType extends object = any
> {
abstract id: string; // ID for exportTypesRegistry.get()
abstract name: string; // user-facing string
abstract jobType: string; // for job params

abstract jobContentEncoding?: 'base64' | 'csv';
abstract jobContentExtension: 'pdf' | 'png' | 'csv';

abstract createJob: CreateJobFn<JobParamsType>;
abstract runTask: RunTaskFn<TaskPayloadType>;

abstract validLicenses: LicenseType[];

public setupDeps!: ExportTypeSetupDeps;
public startDeps!: ExportTypeStartDeps;
public http!: HttpServiceSetup;

constructor(
core: CoreSetup,
public config: ReportingConfigType,
public logger: Logger,
public context: PluginInitializerContext<ReportingConfigType>
) {
this.http = core.http;
}

setup(setupDeps: ExportTypeSetupDeps) {
this.setupDeps = setupDeps;
}
start(startDeps: ExportTypeStartDeps) {
this.startDeps = startDeps;
}

private async getSavedObjectsClient(request: KibanaRequest) {
const { savedObjects } = this.startDeps;
return savedObjects.getScopedClient(request) as SavedObjectsClientContract;
}

private getUiSettingsServiceFactory(savedObjectsClient: SavedObjectsClientContract) {
const { uiSettings: uiSettingsService } = this.startDeps;
const scopedUiSettingsService = uiSettingsService.asScopedToClient(savedObjectsClient);
return scopedUiSettingsService;
}

protected async getUiSettingsClient(request: KibanaRequest, logger = this.logger) {
const spacesService = this.setupDeps.spaces?.spacesService;
const spaceId = this.startDeps.reporting.getSpaceId(request, logger);

if (spacesService && spaceId) {
logger.info(`Creating UI Settings Client for space: ${spaceId}`);
}
const savedObjectsClient = await this.getSavedObjectsClient(request);
return this.getUiSettingsServiceFactory(savedObjectsClient);
}

protected getFakeRequest(
headers: Headers,
spaceId: string | undefined,
logger = this.logger
): KibanaRequest {
const rawRequest: FakeRawRequest = {
headers,
path: '/',
};
const fakeRequest = CoreKibanaRequest.from(rawRequest);

const spacesService = this.setupDeps.spaces?.spacesService;
if (spacesService) {
if (spaceId && spaceId !== DEFAULT_SPACE_ID) {
logger.info(`Generating request for space: ${spaceId}`);
this.setupDeps.basePath.set(fakeRequest, `/s/${spaceId}`);
}
}
return fakeRequest;
}

/*
* Returns configurable server info
*/
protected getServerInfo(): ReportingServerInfo {
const serverInfo = this.http.getServerInfo();
return {
basePath: this.http.basePath.serverBasePath,
hostname: serverInfo.hostname,
name: serverInfo.name,
port: serverInfo.port,
uuid: this.context.env.instanceUuid,
protocol: serverInfo.protocol,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export { getFullUrls } from './get_full_urls';
export { validateUrls } from './validate_urls';
export { generatePngObservable } from './generate_png';
export { getCustomLogo } from './get_custom_logo';
export { ExportType } from './export_type';

export interface TimeRangeParams {
min?: Date | string | number | null;
Expand Down

This file was deleted.

Loading

0 comments on commit b17e856

Please sign in to comment.