From 14c82a2e9569b65345de8dc3e875c0d92e38f8ff Mon Sep 17 00:00:00 2001 From: agusgroh Date: Thu, 30 Nov 2023 10:16:11 -0300 Subject: [PATCH] DT-1100 Fixes missing cryptography --- src/main/model/ResultModel.ts | 167 ++++++++++-------- src/main/services/ReportService.ts | 3 +- .../task/cryptography/AddCryptographyTask.ts | 19 +- .../components/CryptographyDataTable.tsx | 11 +- .../pages/Components/CircularComponent.tsx | 8 +- 5 files changed, 113 insertions(+), 95 deletions(-) diff --git a/src/main/model/ResultModel.ts b/src/main/model/ResultModel.ts index 4cfab131..7256d0f1 100644 --- a/src/main/model/ResultModel.ts +++ b/src/main/model/ResultModel.ts @@ -14,8 +14,11 @@ import { QueryBuilderCreator } from './queryBuilder/QueryBuilderCreator'; const query = new Querys(); export class ResultModel extends Model { - public static readonly entityMapper = { path: 'f.path', source: 'comp.source', purl: 'comp.purl', - version: 'comp.version' + public static readonly entityMapper = { + path: 'f.path', + source: 'comp.source', + purl: 'comp.purl', + version: 'comp.version', }; component: ComponentModel; @@ -57,73 +60,79 @@ export class ResultModel extends Model { } }); } - public async insertFromFile(resultPath: string, files: any): Promise { - const resultLicense: any = {}; - const result: Record = await utilModel.readFile(resultPath); - const db = await this.openDb(); - const promises = []; - const call = util.promisify(db.run.bind(db)); - let resultId = 1; - let data: any; - for (const [key, value] of Object.entries(result)) { - for (let i = 0; i < value.length; i += 1) { - const filePath = key; - data = value[i]; - if (data.id !== 'none') { - promises.push(call( query.SQL_INSERT_RESULTS, - data.file_hash, - data.vendor, - data.component, - data.version, - data.latest, - data.url, - data.lines, - data.oss_lines, - data.matched, - data.file, - data.id, - data.url_hash, - data.purl ? data.purl[0] : ' ', - files[filePath], - data.file_url, - 'engine')); - resultLicense[resultId] = data.licenses; - resultId +=1; - } - } - } - await Promise.all(promises); - db.close(); - return resultLicense; + + public async insertFromFile(resultPath: string, files: any): Promise { + const resultLicense: any = {}; + const result: Record = await utilModel.readFile(resultPath); + const db = await this.openDb(); + const promises = []; + const call = util.promisify(db.run.bind(db)); + let resultId = 1; + let data: any; + for (const [key, value] of Object.entries(result)) { + for (let i = 0; i < value.length; i += 1) { + const filePath = key; + data = value[i]; + if (data.id !== 'none') { + promises.push(call( + query.SQL_INSERT_RESULTS, + data.file_hash, + data.vendor, + data.component, + data.version, + data.latest, + data.url, + data.lines, + data.oss_lines, + data.matched, + data.file, + data.id, + data.url_hash, + data.purl ? data.purl[0] : ' ', + files[filePath], + data.file_url, + 'engine', + )); + resultLicense[resultId] = data.licenses; + resultId += 1; + } + } + } + await Promise.all(promises); + db.close(); + return resultLicense; } + public async insertResultLicense(data: IInsertResult):Promise { const db = await this.openDb(); const promises = []; const call = util.promisify(db.run.bind(db)); - for (const [resultId, value] of Object.entries>(data)) { - for (let i = 0; i < value.length; i += 1) { - promises.push(call('INSERT OR IGNORE INTO result_license (spdxid,source,resultId,patent_hints,copyLeft,osadl_updated,incompatible_with,checklist_url) VALUES (?,?,?,?,?,?,?,?);', - value[i].name, - value[i].source, - resultId, - value[i].patent_hints ? value[i].patent_hints : null, - value[i].copyleft ? value[i].copyleft : null, - value[i].osadl_updated ? value[i].osadl_updated : null, - value[i].incompatible_with ? value[i].incompatible_with : null, - value[i].checklist_url ? value[i].checklist_url : null)); - } - } - await Promise.all(promises); - db.close(); + for (const [resultId, value] of Object.entries>(data)) { + for (let i = 0; i < value.length; i += 1) { + promises.push(call( + 'INSERT OR IGNORE INTO result_license (spdxid,source,resultId,patent_hints,copyLeft,osadl_updated,incompatible_with,checklist_url) VALUES (?,?,?,?,?,?,?,?);', + value[i].name, + value[i].source, + resultId, + value[i].patent_hints ? value[i].patent_hints : null, + value[i].copyleft ? value[i].copyleft : null, + value[i].osadl_updated ? value[i].osadl_updated : null, + value[i].incompatible_with ? value[i].incompatible_with : null, + value[i].checklist_url ? value[i].checklist_url : null, + )); + } + } + await Promise.all(promises); + db.close(); } - public async count(): Promise { - const db = await this.openDb(); - const call = util.promisify(db.get.bind(db)); - const result = await call('SELECT COUNT(*)as count FROM results;'); - db.close(); - return result.count; - } + public async count(): Promise { + const db = await this.openDb(); + const call = util.promisify(db.get.bind(db)); + const result = await call('SELECT COUNT(*)as count FROM results;'); + db.close(); + return result.count; + } public async updateDirty(value: number):Promise { const db = await this.openDb(); @@ -135,10 +144,10 @@ export class ResultModel extends Model { public async deleteDirty(): Promise { const db = await this.openDb(); const call = util.promisify(db.run.bind(db)); - await call(`DELETE FROM results WHERE dirty=1;`); + await call('DELETE FROM results WHERE dirty=1;'); db.close(); } - + private insertResultBulk(db: any, data: any, fileId: number): Promise { return new Promise((resolve) => { db.run( @@ -161,7 +170,7 @@ export class ResultModel extends Model { 'engine', function (this: any, error: any) { resolve(this.lastID); - } + }, ); }); } @@ -191,7 +200,7 @@ export class ResultModel extends Model { data.id }' ; `; db.serialize(() => { - db.get(SQLquery, function (err: any, result: any) { + db.get(SQLquery, (err: any, result: any) => { if (result !== undefined) { db.run('UPDATE results SET dirty=0 WHERE id=?', result.id); resolve(-1); @@ -208,7 +217,7 @@ export class ResultModel extends Model { const call = util.promisify(db.all.bind(db)); const results = await call(query.SQL_SCAN_SELECT_FILE_RESULTS, path); db.close(); - if(results) return results; + if (results) return results; return []; } @@ -220,6 +229,7 @@ export class ResultModel extends Model { db.close(); return summary; } + public async getResultsPreLoadInventory(queryBuilder: QueryBuilder) { const SQLquery = this.getSQL(queryBuilder, query.SQL_GET_RESULTS_PRELOADINVENTORY, this.getEntityMapper()); const db = await this.openDb(); @@ -228,6 +238,7 @@ export class ResultModel extends Model { db.close(); return results; } + public async getAll(queryBuilder: QueryBuilder) { const SQLquery = this.getSQL(queryBuilder, query.SQL_GET_ALL_RESULTS, this.getEntityMapper()); const db = await this.openDb(); @@ -236,14 +247,15 @@ export class ResultModel extends Model { db.close(); return results; } + public async getDetectedReport() { - const db = await this.openDb(); - const call = util.promisify(db.all.bind(db)); - const response = await call(`SELECT cv.purl,cv.version,cv.name, r.vendor, rl.spdxid,rl.patent_hints,rl.copyLeft,rl.incompatible_with FROM component_versions cv + const db = await this.openDb(); + const call = util.promisify(db.all.bind(db)); + const response = await call(`SELECT cv.purl,cv.version,cv.name, r.vendor, rl.spdxid,rl.patent_hints,rl.copyLeft,rl.incompatible_with FROM component_versions cv INNER JOIN results r ON cv.purl = r.purl AND cv.version = r.version - INNER JOIN result_license rl ON rl.resultId = r.id;`); - db.close(); - return response; + LEFT JOIN result_license rl ON rl.resultId = r.id;`); + db.close(); + return response; } public async getIdentifiedReport() { @@ -257,12 +269,15 @@ export class ResultModel extends Model { } public async getFileMatch(queryBuilder: QueryBuilder) { - const SQLquery = this.getSQL(queryBuilder,`SELECT * from files f LEFT JOIN results r ON f.fileId = r.fileId #FILTER`, { filePath: 'f.path', purl: 'r.purl', - version: 'r.version', url: 'r.url' + const SQLquery = this.getSQL(queryBuilder, 'SELECT * from files f LEFT JOIN results r ON f.fileId = r.fileId #FILTER', { + filePath: 'f.path', + purl: 'r.purl', + version: 'r.version', + url: 'r.url', }); const db = await this.openDb(); const call = util.promisify(db.get.bind(db)); - const response = await call(SQLquery.SQL,...SQLquery.params); + const response = await call(SQLquery.SQL, ...SQLquery.params); db.close(); return response; } diff --git a/src/main/services/ReportService.ts b/src/main/services/ReportService.ts index f98e6eb4..be393880 100644 --- a/src/main/services/ReportService.ts +++ b/src/main/services/ReportService.ts @@ -115,6 +115,7 @@ class ReportService { try { const results = await modelProvider.model.result.getDetectedReport(); let licenses = this.getLicenseReportFromResults(results); + const crypto = await modelProvider.model.cryptography.findAllDetected(); const vulnerabilities = await modelProvider.model.vulnerability.getDetectedReport(); @@ -144,7 +145,7 @@ class ReportService { private getLicenseReportFromResults(results: any): Array { const licenses: Record = results.reduce( (acc, curr) => { - const key = curr.spdxid; + const key = curr.spdxid ? curr.spdxid : 'unknown'; if (!acc[key]) { acc[key] = { label: key, diff --git a/src/main/task/cryptography/AddCryptographyTask.ts b/src/main/task/cryptography/AddCryptographyTask.ts index a65132b5..f3045e1f 100644 --- a/src/main/task/cryptography/AddCryptographyTask.ts +++ b/src/main/task/cryptography/AddCryptographyTask.ts @@ -2,6 +2,7 @@ import log from 'electron-log'; import { CryptographyService, } from 'scanoss'; +import fs from 'fs'; import { ITask } from '../Task'; import { modelProvider } from '../../services/ModelProvider'; import { ICryptographyTask } from './ICryptographyTask'; @@ -10,26 +11,24 @@ export class AddCryptographyTask implements ITask { async run(params: ICryptographyTask): Promise { try { const reqData = { - purlsList: params.components.map((item) => { - const component = item.split('@'); - return { purl: component[0], requirement: component[1] ?? undefined }; - }), + purlsList: params.components.map((purl) => ({ purl })), }; const crypto = new CryptographyService(params.token); const response: any = await crypto.getAlgorithms(reqData); // Convert response into Cryptography entity - const cryptography: Array< { purl: string, version: string, algorithms: string } > = []; - response.purlsList.forEach((p) => { - if (p.algorithmsList.length > 0) { // avoids empty crypto from response - const crypto = { purl: p.purl, version: p.version, algorithms: JSON.stringify(p.algorithmsList) }; - cryptography.push(crypto); + const cryptographies: Array< { purl: string, version: string, algorithms: string } > = []; + response.purlsList.forEach((crypto) => { + if (crypto.algorithmsList.length > 0) { // avoids empty crypto from response + const [purl, version] = crypto.purl.split('@'); + const cryptography = { purl, version, algorithms: JSON.stringify(crypto.algorithmsList) }; + cryptographies.push(cryptography); } }); // Import Crypto into Database - await modelProvider.model.cryptography.insertAll(cryptography); + await modelProvider.model.cryptography.insertAll(cryptographies); } catch (e) { log.error(e); } diff --git a/src/renderer/features/workbench/pages/report/components/CryptographyDataTable.tsx b/src/renderer/features/workbench/pages/report/components/CryptographyDataTable.tsx index 54ae94bb..1e38b1bf 100644 --- a/src/renderer/features/workbench/pages/report/components/CryptographyDataTable.tsx +++ b/src/renderer/features/workbench/pages/report/components/CryptographyDataTable.tsx @@ -66,11 +66,12 @@ const CryptographyDataTable = ({ data }) => { width={500} flexGrow={10} flexShrink={0} - cellRenderer={({ cellData }) => cellData.map((algorithm) => ( - - {algorithm.algorithm} ({algorithm.strength}) - {' '} - - ))} + cellRenderer={({ cellData }) => cellData + .map((algorithm) => ( + + {algorithm.algorithm} ({algorithm.strength}) + + )).reduce((acc, curr) => [acc, ' - ', curr])} /> )} diff --git a/src/renderer/features/workspace/pages/Components/CircularComponent.tsx b/src/renderer/features/workspace/pages/Components/CircularComponent.tsx index 603a0e52..6a2ac653 100644 --- a/src/renderer/features/workspace/pages/Components/CircularComponent.tsx +++ b/src/renderer/features/workspace/pages/Components/CircularComponent.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { CircularProgress, Button } from '@mui/material'; +import { Button, CircularProgress } from '@mui/material'; import { makeStyles } from '@mui/styles'; import PauseIcon from '@mui/icons-material/Pause'; import { ScannerStage } from '@api/types'; @@ -94,14 +94,16 @@ const CircularComponent = ({ stage.stageName === ScannerStage.UNZIP || stage.stageName === ScannerStage.INDEX || stage.stageName === ScannerStage.VULNERABILITY || - stage.stageName === ScannerStage.DEPENDENCY + stage.stageName === ScannerStage.DEPENDENCY || + stage.stageName === ScannerStage.CRYPTOGRAPHY ? 'indeterminate' : 'determinate'; const noProgress = stage.stageName === ScannerStage.DEPENDENCY || stage.stageName === ScannerStage.VULNERABILITY || - stage.stageName === ScannerStage.UNZIP; + stage.stageName === ScannerStage.UNZIP || + stage.stageName === ScannerStage.CRYPTOGRAPHY; const resumeEnable = stage.stageName === ScannerStage.SCAN ||