import { inject , injectable } from 'inversify' ; import { isEmpty , isNil } from 'lodash' ; import { DeepScanResultItem , ScanCompletedNotification as NotificationResponse , ScanReport , ScanResultResponse } from 'service-library' ; import { OnDemandPageScanResult , OnDemandPageScanRunState , ScanCompletedNotification as NotificationDb , WebsiteScanResult , } from 'storage-documents' ; import { ScanErrorConverter } from './scan-error-converter' ; @ injectable ( ) export class ScanResponseConverter { constructor ( @ inject ( ScanErrorConverter ) private readonly scanErrorConverter ) { } public getScanResultResponse ( baseUrl , apiVersion , pageScanResult , websiteScanResult ) { const runState = pageScanResult . run . state ; switch ( runState ) { case 'pending' : case 'accepted' : case 'queued' : case 'running' : default : return this . createIncompleteScanResponse ( pageScanResult ) ; case 'failed' : return this . createFailedScanResponse ( pageScanResult ) ; case 'completed' : return this . createCompletedScanResponse ( baseUrl , apiVersion , pageScanResult , websiteScanResult ) ; } } private createIncompleteScanResponse ( pageScanResult ) { return { scanId : pageScanResult . id , url : pageScanResult . url , run : { state : pageScanResult . run . state , } , ... this . getRunCompleteNotificationResponse ( pageScanResult . notification ) , } ; } private createFailedScanResponse ( pageScanResult ) { return { scanId : pageScanResult . id , url : pageScanResult . url , run : { state : pageScanResult . run . state , timestamp : pageScanResult . run . timestamp , error : this . scanErrorConverter . getScanRunErrorCode ( pageScanResult . run . error ) , pageResponseCode : pageScanResult . run . pageResponseCode , pageTitle : pageScanResult . run . pageTitle , } , ... this . getRunCompleteNotificationResponse ( pageScanResult . notification ) , } ; } private createCompletedScanResponse ( baseUrl , apiVersion , pageScanResult , websiteScanResult ) { const scanResultResponse = { scanId : pageScanResult . id , url : pageScanResult . url , scanResult : { state : pageScanResult . scanResult . state , issueCount : pageScanResult . scanResult . issueCount , } , reports : this . getScanReports ( baseUrl , apiVersion , pageScanResult ) , run : { state : pageScanResult . run . state , timestamp : pageScanResult . run . timestamp , pageResponseCode : pageScanResult . run . pageResponseCode , pageTitle : pageScanResult . run . pageTitle , } , ... this . getRunCompleteNotificationResponse ( pageScanResult . notification ) , ... this . getDeepScanResult ( websiteScanResult ) , } ; if ( pageScanResult . scannedUrl !== undefined ) { scanResultResponse . scannedUrl = pageScanResult . scannedUrl ; } if ( scanResultResponse . deepScanResult !== undefined ) { if ( scanResultResponse . deepScanResult . every ( ( scanResult ) => scanResult . scanRunState === 'failed' ) ) { scanResultResponse . run . state = 'failed' ; } else if ( scanResultResponse . deepScanResult . every ( ( scanResult ) => scanResult . scanRunState === 'completed' || scanResult . scanRunState === 'failed' ) ) { scanResultResponse . run . state = 'completed' ; } else { scanResultResponse . run . state = 'pending' ; } } return scanResultResponse ; } private getScanReports ( baseUrl , apiVersion , pageScanResult ) { if ( isEmpty ( pageScanResult . reports ) ) { return undefined ; } const baseUrlFixed = baseUrl . endsWith ( '/' ) ? baseUrl . slice ( 0 , - 1 ) : baseUrl ; return pageScanResult . reports . map ( ( report ) => { return { reportId : report . reportId , format : report . format , links : { rel : 'self' , href : `${ baseUrlFixed }/scans/${ pageScanResult . id }/reports/${ report . reportId }?api-version=${ apiVersion }` , } , } ; } ) ; } private getRunCompleteNotificationResponse ( notification ) { if ( isNil ( notification ) ) { return { } ; } const notificationResponse = { scanNotifyUrl : notification . scanNotifyUrl , state : notification . state , responseCode : notification . responseCode , } ; if ( ! isNil ( notification . error ) ) { notificationResponse . error = this . scanErrorConverter . getScanNotificationErrorCode ( notification . error ) ; } return { notification : notificationResponse } ; } private getDeepScanResult ( websiteScanResult ) { if ( isNil ( websiteScanResult ) || ! ( websiteScanResult . pageScans ?. length > 0 ) ) { return { } ; } const deepScanResult = websiteScanResult . pageScans . map ( ( pageScan ) => { return { scanId : pageScan . scanId , url : pageScan . url , scanResultState : pageScan . scanState , scanRunState : pageScan . runState ?? 'pending' , } ; } ) ; return { deepScanResult } ; } }