diff --git a/static/css/directives/repo-view/repo-panel-tags.css b/static/css/directives/repo-view/repo-panel-tags.css index 267daf9e9..fe9a60385 100644 --- a/static/css/directives/repo-view/repo-panel-tags.css +++ b/static/css/directives/repo-view/repo-panel-tags.css @@ -85,6 +85,42 @@ margin-right: 2px; } +.repo-panel-tags-element .fa-flag { + cursor: pointer; +} + +.repo-panel-tags-element .vuln-name { + +} + +.repo-panel-tags-element .vuln-description { + color: #ccc; + font-size: 10px; +} + +.repo-panel-tags-element .fa-flag.None { + color: #00CA00; +} + +.repo-panel-tags-element .fa-flag.Medium { + color: orange; +} + +.repo-panel-tags-element .fa-flag.High { + color: red; +} + +@keyframes flickerAnimation { /* flame pulses */ + 0% { opacity:1; } + 50% { opacity:0; } + 100% { opacity:1; } +} + +.repo-panel-tags-element .fa-flag.Critical { + color: red; + opacity:1; + animation: flickerAnimation 1s infinite; +} @media (max-width: 767px) { .repo-panel-tags-element .tag-span { diff --git a/static/directives/repo-view/repo-panel-tags.html b/static/directives/repo-view/repo-panel-tags.html index 420f95f60..f5690d29b 100644 --- a/static/directives/repo-view/repo-panel-tags.html +++ b/static/directives/repo-view/repo-panel-tags.html @@ -86,6 +86,12 @@ style="min-width: 62px;"> Size + + + + + Unknown + + + + + + + + + + diff --git a/static/js/directives/repo-view/repo-panel-tags.js b/static/js/directives/repo-view/repo-panel-tags.js index 95e365a56..fcc5d950e 100644 --- a/static/js/directives/repo-view/repo-panel-tags.js +++ b/static/js/directives/repo-view/repo-panel-tags.js @@ -18,7 +18,7 @@ angular.module('quay').directive('repoPanelTags', function () { 'getImages': '&getImages' }, - controller: function($scope, $element, $filter, $location, ApiService, UIService) { + controller: function($scope, $element, $filter, $location, ApiService, UIService, VulnerabilityService) { var orderBy = $filter('orderBy'); $scope.checkedTags = UIService.createCheckStateController([], 'name'); @@ -35,6 +35,7 @@ angular.module('quay').directive('repoPanelTags', function () { $scope.tagActionHandler = null; $scope.showingHistory = false; $scope.tagsPerPage = 50; + $scope.tagVulnerabilities = {}; var setTagState = function() { if (!$scope.repository || !$scope.selectedTags) { return; } @@ -149,6 +150,53 @@ angular.module('quay').directive('repoPanelTags', function () { setTagState(); }); + $scope.loadTagVulnerabilities = function(tag, tagData) { + var params = { + 'tag': tag.name, + 'repository': $scope.repository.namespace + '/' + $scope.repository.name, + }; + + ApiService.getRepoTagVulnerabilities(null, params).then(function(resp) { + tagData.indexed = resp.security_indexed; + tagData.loading = false; + + if (resp.security_indexed) { + tagData.hasVulnerabilities = !!resp.data.Vulnerabilities.length; + tagData.vulnerabilities = resp.data.Vulnerabilities; + + var highest = null; + resp.data.Vulnerabilities.forEach(function(v) { + if (highest == null || + VulnerabilityService.LEVELS[v.Priority].index < VulnerabilityService.LEVELS[highest.Priority].index) { + highest = v; + } + }); + + tagData.highestVulnerability = highest; + } + }, function() { + tagData.loading = false; + tagData.hasError = true; + }); + }; + + $scope.getTagVulnerabilities = function(tag) { + if (!$scope.repository) { + return + } + + var tagName = tag.name; + if (!$scope.tagVulnerabilities[tagName]) { + $scope.tagVulnerabilities[tagName] = { + 'loading': true + }; + + $scope.loadTagVulnerabilities(tag, $scope.tagVulnerabilities[tagName]); + } + + return $scope.tagVulnerabilities[tagName]; + }; + $scope.clearSelectedTags = function() { $scope.checkedTags.setChecked([]); }; diff --git a/static/js/pages/image-view.js b/static/js/pages/image-view.js index d8d3adc22..d848440f2 100644 --- a/static/js/pages/image-view.js +++ b/static/js/pages/image-view.js @@ -40,6 +40,19 @@ loadImage(); loadRepository(); + $scope.downloadPackages = function() { + if ($scope.packagesResource) { return; } + + var params = { + 'repository': namespace + '/' + name, + 'imageid': imageid + }; + + $scope.packagesResource = ApiService.getRepoImagePackagesAsResource(params).get(function(packages) { + $scope.packages = packages; + }); + }; + $scope.downloadChanges = function() { if ($scope.changesResource) { return; } diff --git a/static/partials/image-view.html b/static/partials/image-view.html index 181938afc..3213ee7ac 100644 --- a/static/partials/image-view.html +++ b/static/partials/image-view.html @@ -25,6 +25,10 @@ tab-init="downloadChanges()"> + + +
@@ -53,6 +57,39 @@
+ + +
+
+

Image Packages

+
+
This image has not been indexed yet
+
+ Please try again in a few minutes. +
+
+
+
This image contains no recognized packages
+
+ Quay currently indexes Debian, Red Hat and Ubuntu packages. +
+
+ + + + + + + + + + + + + +
Package NamePackage VersionOS
{{ package.Name }}{{ package.Version }}{{ package.OS }}
+
+