Switch from an image view UI to a manifest view UI
We no longer allow viewing individual images, but instead only manifests. This will help with the transition to Clair V3 (which is manifest based) and, eventually, the the new data model (which will also be manifest based)
This commit is contained in:
parent
d41dcaae23
commit
fc6eb71ab1
24 changed files with 312 additions and 260 deletions
146
static/js/directives/ui/manifest-vulnerability-view.js
Normal file
146
static/js/directives/ui/manifest-vulnerability-view.js
Normal file
|
@ -0,0 +1,146 @@
|
|||
/**
|
||||
* An element which displays the vulnerabilities in a manifest.
|
||||
*/
|
||||
angular.module('quay').directive('manifestVulnerabilityView', function () {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 0,
|
||||
templateUrl: '/static/directives/manifest-vulnerability-view.html',
|
||||
replace: false,
|
||||
transclude: true,
|
||||
restrict: 'C',
|
||||
scope: {
|
||||
'repository': '=repository',
|
||||
'manifest': '=manifest',
|
||||
'isEnabled': '=isEnabled'
|
||||
},
|
||||
controller: function($scope, $element, $routeParams, Config, ApiService, VulnerabilityService, ViewArray, TableService) {
|
||||
$scope.options = {
|
||||
'filter': null,
|
||||
'fixableVulns': $routeParams['fixable'] == 'true',
|
||||
'predicate': 'score',
|
||||
'reverse': false,
|
||||
};
|
||||
|
||||
$scope.TableService = TableService;
|
||||
$scope.loading = false;
|
||||
|
||||
$scope.toggleDetails = function(vuln) {
|
||||
vuln.expanded = !vuln.expanded;
|
||||
};
|
||||
|
||||
$scope.getDistro = function(vuln) {
|
||||
if (vuln['severity'] == 'Defcon 1') {
|
||||
return 'the Quay Engineering Team';
|
||||
}
|
||||
|
||||
return vuln['namespace'].split(':', 1);
|
||||
};
|
||||
|
||||
$scope.getSeverityTooltip = function(vuln) {
|
||||
var distro = $scope.getDistro(vuln);
|
||||
|
||||
if (vuln.scoreDivergence != 'adjusted-lower') {
|
||||
return 'Marked with a ' + vuln['severity'] + ' severity by ' + distro;
|
||||
}
|
||||
|
||||
return 'Note: This vulnerability was originally given a CVSSv2 score ' +
|
||||
'of ' + vuln['cvssScore'] + ' by NVD, but was subsequently reclassifed as a ' +
|
||||
vuln['severity'] + ' issue by ' + distro;
|
||||
};
|
||||
|
||||
var buildOrderedVulnerabilities = function() {
|
||||
if (!$scope.vulnerabilitiesInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
var vulnerabilities = $scope.vulnerabilitiesInfo.vulnerabilities;
|
||||
$scope.orderedVulnerabilities = TableService.buildOrderedItems(vulnerabilities, $scope.options,
|
||||
['name', 'featureName', 'imageCommand'],
|
||||
['score'],
|
||||
function(item) {
|
||||
return !$scope.options.fixableVulns || item['fixedInVersion'];
|
||||
})
|
||||
};
|
||||
|
||||
var buildChart = function() {
|
||||
var chartData = $scope.vulnerabilitiesInfo.severityBreakdown;
|
||||
if (chartData.length == 0) {
|
||||
chartData = [{
|
||||
'label': 'None',
|
||||
'value': 1,
|
||||
'color': '#2FC98E'
|
||||
}];
|
||||
}
|
||||
|
||||
var colors = [];
|
||||
for (var i = 0; i < chartData.length; ++i) {
|
||||
colors.push(chartData[i].color);
|
||||
}
|
||||
|
||||
nv.addGraph(function() {
|
||||
var chart = nv.models.pieChart()
|
||||
.x(function(d) { return d.label })
|
||||
.y(function(d) { return d.value })
|
||||
.margin({left: -10, right: -10, top: -10, bottom: -10})
|
||||
.showLegend(false)
|
||||
.showLabels(true)
|
||||
.labelThreshold(.05)
|
||||
.labelType("percent")
|
||||
.donut(true)
|
||||
.color(colors)
|
||||
.donutRatio(0.5);
|
||||
|
||||
d3.select("#vulnDonutChart svg")
|
||||
.datum(chartData)
|
||||
.transition()
|
||||
.duration(350)
|
||||
.call(chart);
|
||||
|
||||
return chart;
|
||||
});
|
||||
};
|
||||
|
||||
var loadManifestVulnerabilities = function() {
|
||||
if ($scope.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.loading = true;
|
||||
VulnerabilityService.loadManifestVulnerabilities($scope.repository, $scope.manifest.digest, function(resp) {
|
||||
$scope.securityStatus = resp.status;
|
||||
$scope.vulnerabilitiesInfo = VulnerabilityService.buildVulnerabilitiesInfo($scope.manifest.image, resp);
|
||||
|
||||
buildOrderedVulnerabilities();
|
||||
buildChart();
|
||||
return resp;
|
||||
}, function() {
|
||||
$scope.securityStatus = 'error';
|
||||
});
|
||||
};
|
||||
|
||||
$scope.$watch('options.predicate', buildOrderedVulnerabilities);
|
||||
$scope.$watch('options.reverse', buildOrderedVulnerabilities);
|
||||
$scope.$watch('options.filter', buildOrderedVulnerabilities);
|
||||
$scope.$watch('options.fixableVulns', buildOrderedVulnerabilities);
|
||||
|
||||
$scope.$watch('repository', function(repository) {
|
||||
if ($scope.isEnabled && $scope.repository && $scope.manifest) {
|
||||
loadManifestVulnerabilities();
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('manifest', function(manifest) {
|
||||
if ($scope.isEnabled && $scope.repository && $scope.manifest) {
|
||||
loadManifestVulnerabilities();
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('isEnabled', function(isEnabled) {
|
||||
if ($scope.isEnabled && $scope.repository && $scope.manifest) {
|
||||
loadManifestVulnerabilities();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
return directiveDefinitionObject;
|
||||
});
|
Reference in a new issue