import Boom from '@hapi/boom' ; import { i18n } from '@kbn/i18n' ; import { KibanaRequest , KibanaResponseFactory } from 'kibana/server' ; import { ReportingCore } from '../..' ; import { API_BASE_URL } from '../../../common/constants' ; import { checkParamsVersion , cryptoFactory , LevelLogger } from '../../lib' ; import { Report } from '../../lib/store' ; import { BaseParams , ReportingRequestHandlerContext , ReportingUser } from '../../types' ; export const handleUnavailable = ( res ) => { return res . custom ( { statusCode : 503 , body : 'Not Available' } ) ; } ; const getDownloadBaseUrl = ( reporting ) => { const config = reporting . getConfig ( ) ; return config . kbnConfig . get ( 'server' , 'basePath' ) + `${ API_BASE_URL }/jobs/download` ; } ; export class RequestHandler { constructor ( private reporting , private user , private context , private req , private res , private logger ) { } private async encryptHeaders ( ) { const encryptionKey = this . reporting . getConfig ( ) . get ( 'encryptionKey' ) ; const crypto = cryptoFactory ( encryptionKey ) ; return await crypto . encrypt ( this . req . headers ) ; } public async enqueueJob ( exportTypeId , jobParams ) { const { reporting , logger , context , req : request , user } = this ; const exportType = reporting . getExportTypesRegistry ( ) . getById ( exportTypeId ) ; if ( exportType == null ) { throw new Error ( `Export type ${ exportTypeId } does not exist in the registry!` ) ; } if ( ! exportType . createJobFnFactory ) { throw new Error ( `Export type ${ exportTypeId } is not an async job type!` ) ; } const [ createJob , store ] = await Promise . all ( [ exportType . createJobFnFactory ( reporting , logger . clone ( [ exportType . id ] ) ) , reporting . getStore ( ) , ] ) ; if ( ! createJob ) { throw new Error ( `Export type ${ exportTypeId } is not an async job type!` ) ; } jobParams . version = checkParamsVersion ( jobParams , logger ) ; const [ headers , job ] = await Promise . all ( [ this . encryptHeaders ( ) , createJob ( jobParams , context ) , ] ) ; const payload = { ... job , headers , spaceId : reporting . getSpaceId ( request , logger ) , } ; const report = await store . addReport ( new Report ( { jobtype : exportType . jobType , created_by : user ? user . username : false , payload , meta : { objectType : jobParams . objectType , layout : jobParams . layout ?. id , isDeprecated : job . isDeprecated , } , } ) ) ; logger . debug ( `Successfully stored pending job: ${ report . _index }/${ report . _id }` ) ; const task = await reporting . scheduleTask ( report . toReportTaskJSON ( ) ) ; logger . info ( `Scheduled ${ exportType . name } reporting task. Task ID: task:${ task . id }. Report ID: ${ report . _id }` ) ; reporting . getEventLogger ( report , task ) . logScheduleTask ( ) ; return report ; } public async handleGenerateRequest ( exportTypeId , jobParams ) { if ( ! this . context . reporting ) { return handleUnavailable ( this . res ) ; } const licenseInfo = await this . reporting . getLicenseInfo ( ) ; const licenseResults = licenseInfo [ exportTypeId ] ; if ( ! licenseResults ) { return this . res . badRequest ( { body : `Invalid export-type of ${ exportTypeId }` } ) ; } if ( ! licenseResults . enableLinks ) { return this . res . forbidden ( { body : licenseResults . message } ) ; } try { const report = await this . enqueueJob ( exportTypeId , jobParams ) ; const downloadBaseUrl = getDownloadBaseUrl ( this . reporting ) ; return this . res . ok ( { headers : { 'content-type' : 'application/json' } , body : { path : `${ downloadBaseUrl }/${ report . _id }` , job : report . toApiJSON ( ) , } , } ) ; } catch ( err ) { this . logger . error ( err ) ; throw err ; } } public handleError ( err ) { if ( err instanceof Boom . Boom ) { return this . res . customError ( { statusCode : err . output . statusCode , body : err . output . payload . message , } ) ; } return this . res . customError ( { statusCode : 500 , body : err ?. message || i18n . translate ( 'xpack.reporting.errorHandler.unknownError' , { defaultMessage : 'Unknown error' , } ) , } ) ; } }