import { schema } from '@kbn/config-schema' ; import { KibanaRequest } from 'src/core/server' ; import { Writable } from 'stream' ; import { ReportingCore } from '../../' ; import { CSV_SEARCHSOURCE_IMMEDIATE_TYPE } from '../../../common/constants' ; import { runTaskFnFactory } from '../../export_types/csv_searchsource_immediate/execute_job' ; import { JobParamsDownloadCSV } from '../../export_types/csv_searchsource_immediate/types' ; import { LevelLogger as Logger } from '../../lib' ; import { TaskRunResult } from '../../lib/tasks' ; import { BaseParams } from '../../types' ; import { authorizedUserPreRouting } from '../lib/authorized_user_pre_routing' ; import { RequestHandler } from '../lib/request_handler' ; const API_BASE_URL_V1 = '/api/reporting/v1' ; const API_BASE_GENERATE_V1 = `${ API_BASE_URL_V1 }/generate` ; export type CsvFromSavedObjectRequest = KibanaRequest < unknown , unknown , JobParamsDownloadCSV > ; export function registerGenerateCsvFromSavedObjectImmediate ( reporting , parentLogger ) { const setupDeps = reporting . getPluginSetupDeps ( ) ; const { router } = setupDeps ; const useKibanaAccessControl = reporting . getDeprecatedAllowedRoles ( ) === false ; const kibanaAccessControlTags = useKibanaAccessControl ? [ 'access:downloadCsv' ] : [ ] ; router . post ( { path : `${ API_BASE_GENERATE_V1 }/immediate/csv_searchsource` , validate : { body : schema . object ( { columns : schema . maybe ( schema . arrayOf ( schema . string ( ) ) ) , searchSource : schema . object ( { } , { unknowns : 'allow' } ) , browserTimezone : schema . string ( { defaultValue : 'UTC' } ) , title : schema . string ( ) , version : schema . maybe ( schema . string ( ) ) , } ) , } , options : { tags : kibanaAccessControlTags , } , } , authorizedUserPreRouting ( reporting , async ( user , context , req , res ) => { const logger = parentLogger . clone ( [ CSV_SEARCHSOURCE_IMMEDIATE_TYPE ] ) ; const runTaskFn = runTaskFnFactory ( reporting , logger ) ; const requestHandler = new RequestHandler ( reporting , user , context , req , res , logger ) ; const eventLog = reporting . getEventLogger ( { jobtype : CSV_SEARCHSOURCE_IMMEDIATE_TYPE , created_by : user && user . username , payload : { browserTimezone : ( req . params as BaseParams ) . browserTimezone } , } ) ; eventLog . logExecutionStart ( ) ; try { let buffer = Buffer . from ( '' ) ; const stream = new Writable ( { write ( chunk , encoding , callback ) { buffer = Buffer . concat ( [ buffer , Buffer . isBuffer ( chunk ) ? chunk : Buffer . from ( chunk , encoding ) , ] ) ; callback ( ) ; } , } ) ; const { content_type : jobOutputContentType } = await runTaskFn ( null , req . body , context , stream , req ) ; stream . end ( ) ; const jobOutputContent = buffer . toString ( ) ; const jobOutputSize = buffer . byteLength ; logger . info ( `Job output size: ${ jobOutputSize } bytes.` ) ; if ( jobOutputContent === null ) { logger . warn ( 'CSV Job Execution created empty content result' ) ; } eventLog . logExecutionComplete ( { byteSize : jobOutputSize } ) ; return res . ok ( { body : jobOutputContent || '' , headers : { 'content-type' : jobOutputContentType ? jobOutputContentType : [ ] , 'accept-ranges' : 'none' , } , } ) ; } catch ( err ) { logger . error ( err ) ; eventLog . logError ( err ) ; return requestHandler . handleError ( err ) ; } } ) ) ; }