mirror of
https://github.com/ysoftdevs/odc-analyzer.git
synced 2026-01-15 08:14:02 +01:00
Added support for comparison of scans
This commit is contained in:
@@ -387,8 +387,10 @@ object OdcParser {
|
||||
|
||||
def parseDependencies(nodes: NodeSeq): Seq[Dependency] = nodes.map(parseDependency(_))
|
||||
|
||||
def parseXmlReport(data: Array[Byte]) = {
|
||||
val xml = SecureXml.loadString(new String(data, "utf-8"))
|
||||
def parseXmlReport(data: Array[Byte]): Analysis = parseXmlReport(new String(data, "utf-8"))
|
||||
|
||||
def parseXmlReport(xmlData: String): Analysis = {
|
||||
val xml = SecureXml.loadString(xmlData)
|
||||
Analysis(
|
||||
scanInfo = SerializableXml((xml \ "scanInfo").head),
|
||||
name = (xml \ "projectInfo" \ "name").text,
|
||||
|
||||
@@ -114,6 +114,12 @@ private final case class BadFilter(pattern: String) extends Filter{
|
||||
|
||||
object DependencyCheckReportsParser{
|
||||
def forAdHocScan(analysis: Analysis): Result = Result(Map(ReportInfo("adHocScan", "Ad hoc scan", "AHS", None) -> analysis), Map(), new ProjectsWithReports(new Projects(Map(), Map(), Map()), Set()), Map())
|
||||
def forAdHocScans(analysises: Map[String, Analysis]): Result = Result(
|
||||
bareFlatReports = analysises.map{case (key, analysis) => ReportInfo("adHocScan", "Ad hoc scan", "AHS:"+key, Some(key)) -> analysis},
|
||||
bareFailedAnalysises = Map(),
|
||||
projectsReportInfo = new ProjectsWithReports(new Projects(Map(), Map(), Map()), Set()),
|
||||
failedReportDownloads = Map()
|
||||
)
|
||||
final case class ResultWithSelection(result: Result, projectsWithSelection: ProjectsWithSelection)
|
||||
final case class Result(bareFlatReports: Map[ReportInfo, Analysis], bareFailedAnalysises: Map[ReportInfo, Throwable], projectsReportInfo: ProjectsWithReports/*TODO: maybe rename to rootProjects*/, failedReportDownloads: Map[ReportInfo, Throwable]){
|
||||
//lazy val projectsReportInfo = new ProjectsWithReports(projects, (bareFlatReports.keySet ++ bareFailedAnalysises.keySet ++ failedReportDownloads.keySet).map(_.fullId)) // TODO: consider renaming to projectsWithReports
|
||||
|
||||
@@ -6,7 +6,7 @@ import com.google.inject.name.Named
|
||||
import com.ysoft.odc.Confidence.Confidence
|
||||
import com.ysoft.odc.statistics.{LibDepStatistics, TagStatistics}
|
||||
import com.ysoft.odc._
|
||||
import controllers.DependencyCheckReportsParser.ResultWithSelection
|
||||
import controllers.DependencyCheckReportsParser.{Result, ResultWithSelection}
|
||||
import controllers.api.{ApiConfig, ApiController}
|
||||
import models.LibraryTag
|
||||
import modules.TemplateCustomization
|
||||
@@ -25,6 +25,8 @@ final case class ScannedProject(name: String, repos: Seq[ScannedRepository], tea
|
||||
|
||||
final case class GroupedDependencyIdentifier(hashes: Hashes, identifiers: Seq[Identifier])
|
||||
|
||||
final case class CompareScanRequest(plan: String, reports: Map[String, String])
|
||||
|
||||
object GroupedDependencyIdentifier{
|
||||
def fromGroupedDependency(groupedDependency: GroupedDependency): GroupedDependencyIdentifier = GroupedDependencyIdentifier(
|
||||
hashes = groupedDependency.hashes,
|
||||
@@ -386,5 +388,34 @@ class Statistics @Inject()(
|
||||
}
|
||||
}
|
||||
|
||||
private implicit val compareScanRequestFormats = Json.format[CompareScanRequest]
|
||||
|
||||
def showSet[T: Writes](set: Set[T]) = JsArray(set.toSeq.map(implicitly[Writes[T]].writes))
|
||||
def showDiff[T: Writes](diff: SetDiff[T]) = Json.obj("added" -> showSet(diff.added), "removed" -> showSet(diff.removed), "old"->showSet(diff.oldSet), "new"->showSet(diff.newSet))
|
||||
|
||||
def compareScan() = ApiAction(ScanResults).async(parse.json[CompareScanRequest]){ implicit req =>
|
||||
val unparsedReports = req.body.reports
|
||||
val reportMapFuture = Future {
|
||||
unparsedReports.mapValues(OdcParser.parseXmlReport).view.force
|
||||
}
|
||||
val (lastRefreshTime, resultsFuture) = projectReportsProvider.resultsForVersions(versions)
|
||||
resultsFuture flatMap { allResults =>
|
||||
select(allResults, Some("project:"+req.body.plan)).fold(Future.successful(NotFound(Json.obj("error"->"not found")))) { selection =>
|
||||
reportMapFuture.map {reportMap =>
|
||||
def extractVulnerabilities(r: Result) = {
|
||||
r.vulnerableDependencies.flatMap(_.vulnerabilities.map(_.name)).toSet
|
||||
}
|
||||
val adHocReports = DependencyCheckReportsParser.forAdHocScans(reportMap)
|
||||
def compare[T](f: Result => Set[T]) = new SetDiff(f(selection.result), f(adHocReports))
|
||||
//adHocReports.dep
|
||||
Ok(Json.obj(
|
||||
"vulnerabilities"->showDiff(compare(extractVulnerabilities)),
|
||||
"dependencies"->showDiff(compare(_.groupedDependencies.map(GroupedDependencyIdentifier.fromGroupedDependency).toSet))
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@ package controllers.api
|
||||
trait ApiResources {
|
||||
val ProjectTable = ApiResource("project-table")
|
||||
val Dependencies = ApiResource("dependencies")
|
||||
val ScanResults = ApiResource("scan-results")
|
||||
}
|
||||
|
||||
object ApiResources extends ApiResources{
|
||||
val All = Set(ProjectTable, Dependencies)
|
||||
val All = Set(ProjectTable, Dependencies, ScanResults)
|
||||
private val AllByName = All.map(res => res.name -> res).toMap
|
||||
def byName(name: String): Option[ApiResource] = AllByName.get(name)
|
||||
}
|
||||
@@ -7,6 +7,7 @@ GET / controllers.Application.homepage()
|
||||
GET /api/table controllers.Statistics.table()
|
||||
GET /api/all-dependencies.json controllers.Statistics.allDependencies(selector: Option[String])
|
||||
GET /api/all-dependencies-verbose.json controllers.Statistics.allDependenciesVerbose(selector: Option[String])
|
||||
POST /api/compare-scan controllers.Statistics.compareScan()
|
||||
GET /status controllers.Application.index(versions: Map[String, Int] = Map())
|
||||
GET /versions controllers.Application.index(versions: Map[String, Int])
|
||||
GET /dependencies controllers.Application.dependencies(classified: Option[Boolean] = None, requiredTags: Seq[Int] ?= Seq(), noTag: Boolean ?= false)
|
||||
|
||||
Reference in New Issue
Block a user