WIP: UI for QuaySec

This commit is contained in:
Joseph Schorr 2015-10-28 15:38:55 -04:00 committed by Jimmy Zelinskie
parent 75dfec7875
commit 8c144397e9
5 changed files with 177 additions and 1 deletions

View file

@ -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 {

View file

@ -86,6 +86,12 @@
style="min-width: 62px;">
<a href="javascript:void(0)" ng-click="orderBy('size')">Size</a>
</td>
<td ng-class="tablePredicateClass('vuln_level', options.predicate, options.reverse)"
style="width: 60px;">
<a href="javascript:void(0)" ng-click="orderBy('vuln_level')">
<i class="fa fa-flag"></i>
</a>
</td>
<td class="hidden-xs"
ng-class="tablePredicateClass('image_id', options.predicate, options.reverse)"
colspan="{{ imageTracks.length + 1 }}"
@ -108,6 +114,42 @@
<span bo-if="!tag.last_modified">Unknown</span>
</td>
<td class="hidden-xs" bo-text="tag.size | bytes"></td>
<td>
<span class="cor-loader-inline" ng-if="getTagVulnerabilities(tag).loading"></span>
<span ng-if="!getTagVulnerabilities(tag).loading">
<i class="fa fa-flag-o" ng-if="!getTagVulnerabilities(tag).indexed"
data-title="Image is currently being checked for vulnerabilities"
bs-tooltip>
</i>
<i class="fa fa-flag None"
ng-if="getTagVulnerabilities(tag).indexed && !getTagVulnerabilities(tag).hasVulnerabilities"
data-title="Image has no vulnerabilities"
bs-tooltip>
</i>
<div class="dropdown" style="text-align: left;"
ng-if="getTagVulnerabilities(tag).indexed && getTagVulnerabilities(tag).hasVulnerabilities">
<i class="fa fa-flag"
data-title="Image has vulnerabilities"
data-toggle="dropdown"
ng-class="getTagVulnerabilities(tag).highestVulnerability.Priority"
bs-tooltip>
</i>
<ul class="dropdown-menu pull-right">
<li ng-repeat="vuln in getTagVulnerabilities(tag).vulnerabilities">
<a href="{{ vuln.Link }}" target="_new">
<div class="vuln-name">
<i class="fa fa-flag" bo-class="vuln.Priority"></i>
{{ vuln.ID }}
</div>
<div class="vuln-description">
{{ vuln.Description }}
</div>
</a>
</li>
</ul>
</div>
</span>
</td>
<td class="hidden-xs image-id-col">
<span class="image-link" repository="repository" image-id="tag.image_id"></span>
</td>

View file

@ -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([]);
};

View file

@ -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; }

View file

@ -25,6 +25,10 @@
tab-init="downloadChanges()">
<i class="fa fa-code-fork"></i>
</span>
<span class="cor-tab" tab-title="Packages" tab-target="#packages"
tab-init="downloadPackages()">
<i class="fa ci-package"></i>
</span>
</div> <!-- /cor-tabs -->
<div class="cor-tab-content">
@ -53,6 +57,39 @@
</div>
</div>
</div>
<!-- Packages -->
<div id="packages" class="tab-pane">
<div class="resource-view" resource="packagesResource" error-message="'Could not load image packages'">
<h3>Image Packages</h3>
<div class="empty" ng-if="!packages.security_indexed">
<div class="empty-primary-msg">This image has not been indexed yet</div>
<div class="empty-secondary-msg">
Please try again in a few minutes.
</div>
</div>
<div class="empty" ng-if="packages.security_indexed && !packages.data.InstalledPackages.length">
<div class="empty-primary-msg">This image contains no recognized packages</div>
<div class="empty-secondary-msg">
Quay currently indexes Debian, Red Hat and Ubuntu packages.
</div>
</div>
<table class="table" ng-if="packages.security_indexed && packages.data.InstalledPackages.length">
<thead>
<th>Package Name</th>
<th>Package Version</th>
<th>OS</th>
</thead>
<tr ng-repeat="package in packages.data.InstalledPackages | orderBy:'Name'">
<td>{{ package.Name }}</td>
<td>{{ package.Version }}</td>
<td>{{ package.OS }}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>