Have the fetch tag dialog show a warning for robot accounts without access
Before this change, we'd show the squash pulling command with the proper credentials, but it then 403s on the end user.
This commit is contained in:
parent
7aeaf2344e
commit
b535e222b8
5 changed files with 108 additions and 2 deletions
|
@ -1201,6 +1201,12 @@ def update_email(user, new_email, auto_verify=False):
|
|||
|
||||
|
||||
def get_all_user_permissions(user):
|
||||
return _get_user_repo_permissions(user)
|
||||
|
||||
def get_user_repo_permissions(user, repo):
|
||||
return _get_user_repo_permissions(user, limit_to_repository_obj=repo)
|
||||
|
||||
def _get_user_repo_permissions(user, limit_to_repository_obj=None):
|
||||
UserThroughTeam = User.alias()
|
||||
|
||||
base_query = (RepositoryPermission
|
||||
|
@ -1211,6 +1217,9 @@ def get_all_user_permissions(user):
|
|||
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
|
||||
.switch(RepositoryPermission))
|
||||
|
||||
if limit_to_repository_obj is not None:
|
||||
base_query = base_query.where(RepositoryPermission.repository == limit_to_repository_obj)
|
||||
|
||||
direct = (base_query
|
||||
.clone()
|
||||
.join(User)
|
||||
|
|
|
@ -6,7 +6,8 @@ from flask import request
|
|||
|
||||
from app import avatar
|
||||
from endpoints.api import (resource, nickname, require_repo_admin, RepositoryParamResource,
|
||||
log_action, request_error, validate_json_request, path_param)
|
||||
log_action, request_error, validate_json_request, path_param,
|
||||
NotFound)
|
||||
from data import model
|
||||
|
||||
|
||||
|
@ -96,6 +97,30 @@ class RepositoryUserPermissionList(RepositoryParamResource):
|
|||
}
|
||||
|
||||
|
||||
@resource('/v1/repository/<repopath:repository>/permissions/user/<username>/transitive')
|
||||
@path_param('repository', 'The full path of the repository. e.g. namespace/name')
|
||||
@path_param('username', 'The username of the user to which the permissions apply')
|
||||
class RepositoryUserTransitivePermission(RepositoryParamResource):
|
||||
""" Resource for retrieving whether a user has access to a repository, either directly
|
||||
or via a team. """
|
||||
@require_repo_admin
|
||||
@nickname('getUserTransitivePermission')
|
||||
def get(self, namespace, repository, username):
|
||||
""" Get the fetch the permission for the specified user. """
|
||||
user = model.get_user(username)
|
||||
if not user:
|
||||
raise NotFound
|
||||
|
||||
repo = model.get_repository(namespace, repository)
|
||||
if not repo:
|
||||
raise NotFound
|
||||
|
||||
permissions = list(model.get_user_repo_permissions(user, repo))
|
||||
return {
|
||||
'permissions': [role_view(permission) for permission in permissions]
|
||||
}
|
||||
|
||||
|
||||
@resource('/v1/repository/<repopath:repository>/permissions/user/<username>')
|
||||
@path_param('repository', 'The full path of the repository. e.g. namespace/name')
|
||||
@path_param('username', 'The username of the user to which the permission applies')
|
||||
|
|
|
@ -56,6 +56,13 @@
|
|||
</table>
|
||||
|
||||
<div class="cor-loader-inline" ng-if="currentEntity && !currentRobot"></div>
|
||||
|
||||
<div class="co-alert co-alert-warning"
|
||||
ng-if="currentRobotHasPermission === false">
|
||||
Warning: Robot account <strong>{{ currentRobot.name }}</strong> does not have
|
||||
read permission on this repository, so the command below will fail with an authorization error.
|
||||
</div>
|
||||
|
||||
<div ng-if="getCommand(currentFormat, currentRobot)">
|
||||
Command:
|
||||
<pre class="command">{{ getCommand(currentFormat, currentRobot) }}</pre>
|
||||
|
|
|
@ -18,6 +18,7 @@ angular.module('quay').directive('fetchTagDialog', function () {
|
|||
$scope.currentEntity = null;
|
||||
$scope.currentRobot = null;
|
||||
$scope.formats = [];
|
||||
$scope.currentRobotHasPermission = null;
|
||||
|
||||
UserService.updateUserIn($scope, updateFormats);
|
||||
|
||||
|
@ -58,6 +59,7 @@ angular.module('quay').directive('fetchTagDialog', function () {
|
|||
}
|
||||
|
||||
$scope.currentRobot = null;
|
||||
$scope.currentRobotHasPermission = null;
|
||||
|
||||
var parts = entity.name.split('+');
|
||||
var namespace = parts[0];
|
||||
|
@ -71,6 +73,15 @@ angular.module('quay').directive('fetchTagDialog', function () {
|
|||
ApiService.getRobot(orgname, null, params).then(function(resp) {
|
||||
$scope.currentRobot = resp;
|
||||
}, ApiService.errorDisplay('Cannot download robot token'));
|
||||
|
||||
var permParams = {
|
||||
'repository': $scope.repository.namespace + '/' + $scope.repository.name,
|
||||
'username': entity.name
|
||||
};
|
||||
|
||||
ApiService.getUserTransitivePermission(null, permParams).then(function(resp) {
|
||||
$scope.currentRobotHasPermission = resp['permissions'].length > 0;
|
||||
});
|
||||
});
|
||||
|
||||
$scope.getCommand = function(format, robot) {
|
||||
|
@ -106,6 +117,7 @@ angular.module('quay').directive('fetchTagDialog', function () {
|
|||
$scope.currentFormat = null;
|
||||
$scope.currentEntity = null;
|
||||
$scope.currentRobot = null;
|
||||
$scope.currentRobotHasPermission = null;
|
||||
|
||||
$scope.clearCounter++;
|
||||
|
||||
|
|
|
@ -43,7 +43,8 @@ from endpoints.api.organization import (OrganizationList, OrganizationMember,
|
|||
OrganizationApplicationResetClientSecret)
|
||||
from endpoints.api.repository import RepositoryList, RepositoryVisibility, Repository
|
||||
from endpoints.api.permission import (RepositoryUserPermission, RepositoryTeamPermission,
|
||||
RepositoryTeamPermissionList, RepositoryUserPermissionList)
|
||||
RepositoryTeamPermissionList, RepositoryUserPermissionList,
|
||||
RepositoryUserTransitivePermission)
|
||||
from endpoints.api.superuser import (SuperUserLogs, SuperUserList, SuperUserManagement,
|
||||
SuperUserSendRecoveryEmail, ChangeLog,
|
||||
SuperUserOrganizationManagement, SuperUserOrganizationList)
|
||||
|
@ -728,6 +729,58 @@ class TestTeamMemberListBuynlargeOwners(ApiTestCase):
|
|||
self._run_test('GET', 200, 'devtable', None)
|
||||
|
||||
|
||||
class TestRepositoryUserTransitivePermissionA2o9PublicPublicrepo(ApiTestCase):
|
||||
def setUp(self):
|
||||
ApiTestCase.setUp(self)
|
||||
self._set_url(RepositoryUserTransitivePermission, username="A2O9", repository="public/publicrepo")
|
||||
|
||||
def test_get_anonymous(self):
|
||||
self._run_test('GET', 401, None, None)
|
||||
|
||||
def test_get_freshuser(self):
|
||||
self._run_test('GET', 403, 'freshuser', None)
|
||||
|
||||
def test_get_reader(self):
|
||||
self._run_test('GET', 403, 'reader', None)
|
||||
|
||||
def test_get_devtable(self):
|
||||
self._run_test('GET', 403, 'devtable', None)
|
||||
|
||||
class TestRepositoryUserTransitivePermissionA2o9DevtableShared(ApiTestCase):
|
||||
def setUp(self):
|
||||
ApiTestCase.setUp(self)
|
||||
self._set_url(RepositoryUserTransitivePermission, username="A2O9", repository="devtable/shared")
|
||||
|
||||
def test_get_anonymous(self):
|
||||
self._run_test('GET', 401, None, None)
|
||||
|
||||
def test_get_freshuser(self):
|
||||
self._run_test('GET', 403, 'freshuser', None)
|
||||
|
||||
def test_get_reader(self):
|
||||
self._run_test('GET', 403, 'reader', None)
|
||||
|
||||
def test_get_devtable(self):
|
||||
self._run_test('GET', 404, 'devtable', None)
|
||||
|
||||
class TestRepositoryUserTransitivePermissionA2o9BuynlargeOrgrepo(ApiTestCase):
|
||||
def setUp(self):
|
||||
ApiTestCase.setUp(self)
|
||||
self._set_url(RepositoryUserTransitivePermission, username="A2O9", repository="buynlarge/orgrepo")
|
||||
|
||||
def test_get_anonymous(self):
|
||||
self._run_test('GET', 401, None, None)
|
||||
|
||||
def test_get_freshuser(self):
|
||||
self._run_test('GET', 403, 'freshuser', None)
|
||||
|
||||
def test_get_reader(self):
|
||||
self._run_test('GET', 403, 'reader', None)
|
||||
|
||||
def test_get_devtable(self):
|
||||
self._run_test('GET', 404, 'devtable', None)
|
||||
|
||||
|
||||
class TestRepositoryUserPermissionA2o9PublicPublicrepo(ApiTestCase):
|
||||
def setUp(self):
|
||||
ApiTestCase.setUp(self)
|
||||
|
|
Reference in a new issue