/** * An element which displays a panel for managing keys for external services. */ angular.module('quay').directive('serviceKeysManager', function () { var directiveDefinitionObject = { priority: 0, templateUrl: '/static/directives/service-keys-manager.html', replace: false, transclude: true, restrict: 'C', scope: { 'isEnabled': '=isEnabled' }, controller: function($scope, $element, ApiService, TableService) { $scope.options = { 'filter': null, 'predicate': 'expiration_datetime', 'reverse': false, }; $scope.TableService = TableService; $scope.newKey = null; $scope.creatingKey = false; $scope.context = { 'expirationChangeInfo': null }; var buildOrderedKeys = function() { if (!$scope.keys) { return; } var keys = $scope.keys.map(function(key) { var expiration_datetime = -Number.MAX_VALUE; if (key.expiration_date) { expiration_datetime = new Date(key.expiration_date).valueOf() * (-1); } return $.extend(key, { 'creation_datetime': new Date(key.creation_date).valueOf() * (-1), 'expiration_datetime': expiration_datetime, 'expanded': false }); }); $scope.orderedKeys = TableService.buildOrderedItems(keys, $scope.options, ['name', 'kid', 'service'], ['creation_datetime', 'expiration_datetime']) }; var loadServiceKeys = function() { $scope.options.filter = null; $scope.now = new Date(); $scope.keysResource = ApiService.listServiceKeysAsResource().get(function(resp) { $scope.keys = resp['keys']; buildOrderedKeys(); }); }; $scope.getKeyTitle = function(key) { if (!key) { return ''; } return key.name || key.kid.substr(0, 12); }; $scope.toggleDetails = function(key) { key.expanded = !key.expanded; }; $scope.getExpirationInfo = function(key) { if (!key.expiration_date) { return ''; } if (key.metadata.rotation_ttl) { var rotate_date = moment(key.created_date).add(key.metadata.rotation_ttl, 's') if (moment().isBefore(rotate_date)) { return {'className': 'rotation', 'icon': 'fa-refresh', 'rotateDate': rotate_date}; } } expiration_date = moment(key.expiration_date); if (moment().isAfter(expiration_date)) { return {'className': 'expired', 'icon': 'fa-warning'}; } if (moment().add(1, 'week').isAfter(expiration_date)) { return {'className': 'critical', 'icon': 'fa-warning'}; } if (moment().add(1, 'month').isAfter(expiration_date)) { return {'className': 'warning', 'icon': 'fa-warning'}; } return {'className': 'info', 'icon': 'fa-check'}; }; $scope.showChangeName = function(key) { bootbox.prompt({ 'size': 'small', 'title': 'Enter a friendly name for key ' + $scope.getKeyTitle(key), 'value': key.name || '', 'callback': function(value) { if (value != null) { var data = { 'name': value }; var params = { 'kid': key.kid }; ApiService.updateServiceKey(data, params).then(function(resp) { loadServiceKeys(); }, ApiService.errorDisplay('Could not update service key')); } } }); }; $scope.showChangeExpiration = function(key) { $scope.context.expirationChangeInfo = { 'key': key, 'expiration_date': key.expiration_date ? (new Date(key.expiration_date).getTime() / 1000) : null }; }; $scope.changeKeyExpiration = function(changeInfo, callback) { var errorHandler = ApiService.errorDisplay('Could not change expiration on service key', callback); var data = { 'expiration': changeInfo.expiration_date }; var params = { 'kid': changeInfo.key.kid }; ApiService.updateServiceKey(data, params).then(function(resp) { loadServiceKeys(); callback(true); }, errorHandler); }; $scope.createServiceKey = function() { $scope.creatingKey = true; ApiService.createServiceKey($scope.newKey).then(function(resp) { $scope.creatingKey = false; $('#createKeyModal').modal('hide'); $scope.createdKey = resp; $('#createdKeyModal').modal('show'); loadServiceKeys(); }, ApiService.errorDisplay('Could not create service key')); }; $scope.showApproveKey = function(key) { $scope.approvalKeyInfo = { 'key': key, 'notes': '' }; }; $scope.approveKey = function(approvalKeyInfo, callback) { var errorHandler = ApiService.errorDisplay('Could not approve service key', callback); var data = { 'notes': approvalKeyInfo.notes }; var params = { 'kid': approvalKeyInfo.key.kid }; ApiService.approveServiceKey(data, params).then(function(resp) { loadServiceKeys(); callback(true); }, errorHandler); }; $scope.showCreateKey = function() { $scope.newKey = { 'expiration': null }; $('#createKeyModal').modal('show'); }; $scope.showDeleteKey = function(key) { $scope.deleteKeyInfo = { 'key': key }; }; $scope.deleteKey = function(deleteKeyInfo, callback) { var errorHandler = ApiService.errorDisplay('Could not delete service key', callback); var params = { 'kid': deleteKeyInfo.key.kid }; ApiService.deleteServiceKey(null, params).then(function(resp) { loadServiceKeys(); callback(true); }, errorHandler); }; $scope.isDownloadSupported = function() { var isSafari = /^((?!chrome).)*safari/i.test(navigator.userAgent); if (isSafari) { // Doesn't work properly in Safari, sadly. return false; } try { return !!new Blob(); } catch(e) {} return false; }; $scope.downloadPrivateKey = function(key) { var blob = new Blob([key.private_key]); saveAs(blob, $scope.getKeyTitle(key) + '.pem'); }; $scope.$watch('options.filter', buildOrderedKeys); $scope.$watch('options.predicate', buildOrderedKeys); $scope.$watch('options.reverse', buildOrderedKeys); $scope.$watch('isEnabled', function(value) { if (value) { loadServiceKeys(); } }); } }; return directiveDefinitionObject; });