- Fix tests
- Add new endpoints for retrieving the repo permissions for a robot account - Have the robots list return the number of repositories for which there are permissions - Other UI fixes
This commit is contained in:
parent
bb81c05c03
commit
1f5e6df678
16 changed files with 356 additions and 60 deletions
|
@ -818,6 +818,17 @@
|
|||
width: 30px;
|
||||
}
|
||||
|
||||
.co-table td.caret-col {
|
||||
width: 10px;
|
||||
padding-left: 6px;
|
||||
padding-right: 0px;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.co-table td.caret-col i.fa {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.co-table .add-row-spacer td {
|
||||
padding: 5px;
|
||||
}
|
||||
|
|
86
static/css/directives/ui/robots-manager.css
Normal file
86
static/css/directives/ui/robots-manager.css
Normal file
|
@ -0,0 +1,86 @@
|
|||
.robots-manager-element .manager-header {
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.robots-manager-element .manager-header h3 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.robots-manager-element .robot a {
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.robots-manager-element .robot .prefix {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.robots-manager-element .robot i {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.robots-manager-element .popup-input-button i.fa {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.robots-manager-element .empty {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.robots-manager-element tr.open td {
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
|
||||
.robots-manager-element .permissions-table-wrapper {
|
||||
margin-left: 0px;
|
||||
border-left: 2px solid #ccc;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.robots-manager-element .permissions-table tbody tr:last-child td {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
.robots-manager-element .permissions-display-row {
|
||||
position: relative;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.robots-manager-element .permissions-display-row td:first-child {
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.robots-manager-element .repo-circle {
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
background: #eee;
|
||||
padding: 4px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.robots-manager-element .repo-circle .fa-hdd-o {
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
.robots-manager-element .repo-circle.no-background .fa-hdd-o {
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
.robots-manager-element .repo-circle .fa-lock {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
.robots-manager-element .repo-circle.no-background .fa-lock {
|
||||
bottom: 5px;
|
||||
right: 2px;
|
||||
}
|
|
@ -6,4 +6,20 @@
|
|||
.org-view h3 {
|
||||
margin-bottom: 20px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.org-view .section-description-header {
|
||||
padding-left: 40px;
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.org-view .section-description-header:before {
|
||||
font-family: FontAwesome;
|
||||
content: "\f05a";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 6px;
|
||||
font-size: 27px;
|
||||
color: #888;
|
||||
}
|
|
@ -525,27 +525,6 @@ i.toggle-icon:hover {
|
|||
visibility: hidden;
|
||||
}
|
||||
|
||||
.robots-manager-element {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.robots-manager-element .alert {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.robots-manager-element .robot a {
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.robots-manager-element .robot .prefix {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.robots-manager-element .robot i {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.logs-view-element .header {
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #eee;
|
||||
|
|
|
@ -1,32 +1,102 @@
|
|||
<div class="robots-manager-element">
|
||||
<div class="quay-spinner" ng-show="loading"></div>
|
||||
<div class="alert alert-info">Robot accounts allow for delegating access in multiple repositories to role-based accounts that you manage</div>
|
||||
<div class="cor-loader" ng-show="loading"></div>
|
||||
|
||||
<div ng-show="!loading">
|
||||
<div class="side-controls">
|
||||
<span class="popup-input-button" pattern="ROBOT_PATTERN" placeholder="'Robot Account Name'"
|
||||
submitted="createRobot(value)">
|
||||
<i class="fa fa-wrench"></i> Create Robot Account
|
||||
</span>
|
||||
<div class="manager-header">
|
||||
<div class="side-controls">
|
||||
<span class="popup-input-button" pattern="ROBOT_PATTERN"
|
||||
placeholder="'Robot Account Name'"
|
||||
submitted="createRobot(value)">
|
||||
<i class="fa fa-plus"></i> Create Robot Account
|
||||
</span>
|
||||
</div>
|
||||
<h3>Robot Accounts</h3>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<div class="manager-header section-description-header">
|
||||
Robot Accounts are named tokens that can be granted permissions on multiple repositories
|
||||
under this <span ng-if="organization">organization</span><span ng-if="!organization">user namespace</span>. They are typically used in environments where credentials will
|
||||
be shared, such as deployment systems.
|
||||
</div>
|
||||
|
||||
<div class="empty" ng-if="!robots.length">
|
||||
<div class="empty-primary-msg">No robot accounts defined.</div>
|
||||
<div class="empty-secondary-msg">
|
||||
Click the "Create Robot Account" button above to create a robot account.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="co-table" ng-if="robots.length">
|
||||
<thead>
|
||||
<th>Robot Account Name</th>
|
||||
<th style="width: 150px"></th>
|
||||
<td class="caret-col" ng-if="organization.is_admin"></td>
|
||||
<td>Robot Account Name</td>
|
||||
<td>Repository Permissions</td>
|
||||
<td class="options-col"></td>
|
||||
</thead>
|
||||
|
||||
<tr ng-repeat="robotInfo in robots">
|
||||
<td class="robot">
|
||||
<i class="fa fa-wrench"></i>
|
||||
<a ng-click="showRobot(robotInfo)">
|
||||
<span class="prefix">{{ getPrefix(robotInfo.name) }}+</span>{{ getShortenedName(robotInfo.name) }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="delete-ui" delete-title="'Delete Robot Account'" perform-delete="deleteRobot(robotInfo)"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tbody ng-repeat="robotInfo in robots">
|
||||
<tr ng-class="robotInfo.showing_permissions ? 'open' : 'closed'">
|
||||
<td class="caret-col" ng-if="organization.is_admin">
|
||||
<span ng-if="robotInfo.permission_count > 0" ng-click="showPermissions(robotInfo)">
|
||||
<i class="fa"
|
||||
ng-class="robotInfo.showing_permissions ? 'fa-caret-down' : 'fa-caret-right'"
|
||||
data-title="View Permissions List" bs-tooltip></i>
|
||||
</span>
|
||||
</td>
|
||||
<td class="robot">
|
||||
<i class="fa fa-wrench"></i>
|
||||
<a ng-click="showRobot(robotInfo)">
|
||||
<span class="prefix">{{ getPrefix(robotInfo.name) }}+</span>{{ getShortenedName(robotInfo.name) }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="empty" ng-if="robotInfo.permission_count == 0">(No permissions on any repositories)</span>
|
||||
<span ng-if="robotInfo.permission_count > 0">
|
||||
Permissions on
|
||||
<span class="anchor" href="javascript:void(0)" is-text-only="!organization.is_admin" ng-click="showPermissions(robotInfo)">{{ robotInfo.permission_count }}
|
||||
<span ng-if="robotInfo.permission_count == 1">repository</span>
|
||||
<span ng-if="robotInfo.permission_count > 1">repositories</span>
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
<td class="options-col">
|
||||
<span class="cor-options-menu">
|
||||
<span class="cor-option" option-click="showRobot(robotInfo)">
|
||||
<i class="fa fa-key"></i> View Credentials
|
||||
</span>
|
||||
<span class="cor-option" option-click="deleteRobot(robotInfo)">
|
||||
<i class="fa fa-times"></i> Delete Robot {{ robotInfo.name }}
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="robotInfo.showing_permissions">
|
||||
<td class="permissions-display-row" colspan="4">
|
||||
<span class="cor-loader" ng-if="robotInfo.loading_permissions"></span>
|
||||
<div class="permissions-table-wrapper">
|
||||
<table class="permissions-table" ng-if="!robotInfo.loading_permissions">
|
||||
<thead>
|
||||
<td>Repository</td>
|
||||
<td>Permission</td>
|
||||
</thead>
|
||||
|
||||
<tr ng-repeat="permission in robotInfo.permissions">
|
||||
<td>
|
||||
<span class="repo-icon repo-circle no-background" repo="permission.repository"></span>
|
||||
<a ng-href="/repository/{{ getPrefix(robotInfo.name) }}/{{ permission.repository.name }}">{{ getPrefix(robotInfo.name) }}/{{ permission.repository.name }}</a>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<span class="role-group" current-role="permission.role" roles="roles"
|
||||
read-only="true"></span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<div class="btn-group btn-group-sm">
|
||||
<button ng-repeat="role in roles"
|
||||
type="button" class="btn" ng-click="setRole(role.id)"
|
||||
ng-class="(currentRole == role.id) ? ('active btn-' + role.kind) : 'btn-default'">{{ role.title }}</button>
|
||||
ng-class="(currentRole == role.id) ? ('active btn-' + role.kind) : 'btn-default'"
|
||||
ng-disabled="readOnly">{{ role.title }}</button>
|
||||
</div>
|
||||
|
|
|
@ -13,6 +13,7 @@ angular.module('quay').directive('repositoryPermissionsTable', function () {
|
|||
'repository': '=repository'
|
||||
},
|
||||
controller: function($scope, $element, ApiService, Restangular, UtilService) {
|
||||
// TODO(jschorr): move this to a service.
|
||||
$scope.roles = [
|
||||
{ 'id': 'read', 'title': 'Read', 'kind': 'success' },
|
||||
{ 'id': 'write', 'title': 'Write', 'kind': 'success' },
|
||||
|
|
|
@ -14,11 +14,36 @@ angular.module('quay').directive('robotsManager', function () {
|
|||
},
|
||||
controller: function($scope, $element, ApiService, $routeParams, CreateService) {
|
||||
$scope.ROBOT_PATTERN = ROBOT_PATTERN;
|
||||
|
||||
// TODO(jschorr): move this to a service.
|
||||
$scope.roles = [
|
||||
{ 'id': 'read', 'title': 'Read', 'kind': 'success' },
|
||||
{ 'id': 'write', 'title': 'Write', 'kind': 'success' },
|
||||
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary' }
|
||||
];
|
||||
|
||||
$scope.robots = null;
|
||||
$scope.loading = false;
|
||||
$scope.shownRobot = null;
|
||||
$scope.showRobotCounter = 0;
|
||||
|
||||
var loadRobotPermissions = function(info) {
|
||||
var shortName = $scope.getShortenedName(info.name);
|
||||
info.loading_permissions = true;
|
||||
ApiService.getRobotPermissions($scope.organization, null, {'robot_shortname': shortName}).then(function(resp) {
|
||||
info.permissions = resp.permissions;
|
||||
info.loading_permissions = false;
|
||||
}, ApiService.errorDisplay('Could not load robot permissions'));
|
||||
};
|
||||
|
||||
$scope.showPermissions = function(robotInfo) {
|
||||
robotInfo.showing_permissions = !robotInfo.showing_permissions;
|
||||
|
||||
if (robotInfo.showing_permissions) {
|
||||
loadRobotPermissions(robotInfo);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.regenerateToken = function(username) {
|
||||
if (!username) { return; }
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ angular.module('quay').directive('roleGroup', function () {
|
|||
scope: {
|
||||
'roles': '=roles',
|
||||
'currentRole': '=currentRole',
|
||||
'readOnly': '=readOnly',
|
||||
'roleChanged': '&roleChanged'
|
||||
},
|
||||
controller: function($scope, $element) {
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
<span class="cor-tab" tab-title="Teams" tab-target="#teams">
|
||||
<i class="fa fa-users"></i>
|
||||
</span>
|
||||
<span class="cor-tab" tab-title="Robot Accounts" tab-target="#robots" ng-if="isAdmin">
|
||||
<span class="cor-tab" tab-title="Robot Accounts" tab-target="#robots" ng-show="isAdmin">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</span>
|
||||
<span class="cor-tab" tab-title="Default Permissions" tab-target="#default" ng-if="isAdmin">
|
||||
<span class="cor-tab" tab-title="Default Permissions" tab-target="#default" ng-show="isAdmin">
|
||||
<i class="fa ci-stamp"></i>
|
||||
</span>
|
||||
<span class="cor-tab" tab-title="Billing" tab-target="#usage"
|
||||
|
@ -33,15 +33,15 @@
|
|||
<i class="fa ci-invoice"></i>
|
||||
</span>
|
||||
<span class="cor-tab" tab-title="Usage Logs" tab-target="#logs"
|
||||
tab-init="showLogs()" ng-if="isAdmin">
|
||||
tab-init="showLogs()" ng-show="isAdmin">
|
||||
<i class="fa fa-bar-chart"></i>
|
||||
</span>
|
||||
<span class="cor-tab" tab-title="Applications" tab-target="#applications"
|
||||
tab-init="showApplications()"ng-if="isAdmin">
|
||||
tab-init="showApplications()" ng-show="isAdmin">
|
||||
<i class="fa ci-application"></i>
|
||||
</span>
|
||||
<span class="cor-tab" tab-title="Organization Settings" tab-target="#settings"
|
||||
ng-if="isAdmin">
|
||||
ng-show="isAdmin">
|
||||
<i class="fa fa-gears"></i>
|
||||
</span>
|
||||
</div> <!-- /cor-tabs -->
|
||||
|
@ -65,7 +65,6 @@
|
|||
|
||||
<!-- Robot Accounts -->
|
||||
<div id="robots" class="tab-pane">
|
||||
<h3>Robot Accounts</h3>
|
||||
<div class="robots-manager" organization="organization"></div>
|
||||
</div>
|
||||
|
||||
|
|
Reference in a new issue