diff --git a/app/assets/js/main.js b/app/assets/js/main.js index 4a9e01f..47cce0e 100644 --- a/app/assets/js/main.js +++ b/app/assets/js/main.js @@ -62,5 +62,24 @@ function updatePosition(){ // document.getElementById(…) is used over $('#'+…) in order to reduce attack surface: It does not look like a good idea to pass untrusted input to “omnipotent” `$` function. $.scrollTo(document.getElementById(location.hash.substr(1)), {offset: -$('#navbar').height()}); } +function lazyLoad(el){ + var $el = $(el); + var url = $el.attr("data-lazyload-url"); + function setUrl(newUrl){ + $el.attr("data-lazyload-url", newUrl); + } + if(url){ + $el.html("Loading"); + $el.load(url, function( response, status, xhr ) { + if ( status == "error" ) { + $el.html("Error when loading data"); + setUrl(url); + } + }); + setUrl(null); + } +} + $(window).bind('hashchange', function(e) { updatePosition(); }); -$(window).bind('load', function(e) { updatePosition(); }); \ No newline at end of file +$(window).bind('load', function(e) { updatePosition(); }); +$(window).bind('show.bs.collapse', function(e){ lazyLoad(e.target); }); \ No newline at end of file diff --git a/app/binders/QueryBinders.scala b/app/binders/QueryBinders.scala index da10186..541eb2a 100644 --- a/app/binders/QueryBinders.scala +++ b/app/binders/QueryBinders.scala @@ -3,6 +3,7 @@ package binders import java.net.URLDecoder.decode import java.net.URLEncoder.encode +import com.ysoft.odc.Hashes import play.api.mvc.{JavascriptLiteral, PathBindable, QueryStringBindable} object QueryBinders { @@ -21,6 +22,13 @@ object QueryBinders { QueryStringBindable.bindableString.transform(s => formats.reads(Json.parse(s)).getOrElse(Map()), map => formats.writes(map).toString()) } + implicit val hashedBindable = QueryStringBindable.bindableString.transform[Hashes]( + str => str.split('-') match { + case Array(sha1, md5) => Hashes(sha1 = sha1, md5 = md5) + }, + hashes => s"${hashes.sha1}-${hashes.md5}" + ) + implicit object MapStringIntJavascriptLiteral extends JavascriptLiteral[Map[String, Int]] { override def to(value: Map[String, Int]): String = formats.writes(value).toString() } diff --git a/app/controllers/DependencyCheckReportsParser.scala b/app/controllers/DependencyCheckReportsParser.scala index 9a0cf87..74b24ae 100644 --- a/app/controllers/DependencyCheckReportsParser.scala +++ b/app/controllers/DependencyCheckReportsParser.scala @@ -121,6 +121,7 @@ object DependencyCheckReportsParser{ lazy val groupedDependencies = allDependencies.groupBy(_._1.hashes).values.map(GroupedDependency(_)).toSeq lazy val groupedDependenciesByPlainLibraryIdentifier: Map[PlainLibraryIdentifier, Set[GroupedDependency]] = groupedDependencies.toSet.flatMap((grDep: GroupedDependency) => grDep.plainLibraryIdentifiers.map(_ -> grDep)).groupBy(_._1).mapValues(_.map(_._2)).map(identity) + lazy val groupedDependenciesByHashes: Map[Hashes, GroupedDependency] = groupedDependencies.map(gd => gd.hashes -> gd).toMap lazy val vulnerableDependencies = groupedDependencies.filter(_.vulnerabilities.nonEmpty) lazy val suppressedOnlyDependencies = groupedDependencies.filter(gd => gd.vulnerabilities.isEmpty && gd.suppressedIdentifiers.nonEmpty) diff --git a/app/controllers/Statistics.scala b/app/controllers/Statistics.scala index 187b6d7..c8ca079 100644 --- a/app/controllers/Statistics.scala +++ b/app/controllers/Statistics.scala @@ -274,6 +274,17 @@ class Statistics @Inject()( } } + def dependencyDetails(selectorOption: Option[String], depPrefix: String, depId: Hashes) = ReadAction.async { implicit req => + val (lastRefreshTime, resultsFuture) = projectReportsProvider.resultsForVersions(versions) + resultsFuture flatMap { allResults => + println(selectorOption) + select(allResults, selectorOption).fold(Future.successful(notFound())) { selection => + val dep = selection.result.groupedDependenciesByHashes(depId) + Future.successful(Ok(views.html.dependencyDetailsInner(depPrefix = depPrefix, dep = dep, selectorOption = selectorOption))) + } + } + } + def allFiles(selectorOption: Option[String]) = ReadAction.async { implicit req => val (lastRefreshTime, resultsFuture) = projectReportsProvider.resultsForVersions(versions) resultsFuture flatMap { allResults => diff --git a/app/views/dependencyDetails.scala.html b/app/views/dependencyDetails.scala.html new file mode 100644 index 0000000..12fc03f --- /dev/null +++ b/app/views/dependencyDetails.scala.html @@ -0,0 +1,16 @@ +@(depPrefix: String, expandByDefault: Boolean, dep: GroupedDependency, selectorOption: Option[String]) +
\ No newline at end of file diff --git a/app/views/dependencyDetailsInner.scala.html b/app/views/dependencyDetailsInner.scala.html new file mode 100644 index 0000000..4155733 --- /dev/null +++ b/app/views/dependencyDetailsInner.scala.html @@ -0,0 +1,59 @@ +@(depPrefix: String, dep: GroupedDependency, selectorOption: Option[String]) + +@if(dep.descriptions.size > 1){ +
+ @for(line <- descriptionParagraphLines) {
+ @line
+ }
+
| confidence | +evidence type | +name | +source | +value | +
|---|---|---|---|---|
| + | filename | ++ | + | @fileName | +
| @ev.confidence + | @ev.evidenceType + | @ev.name + | @ev.source + | @ev.value + |