Merge branch 'orgs' of https://bitbucket.org/yackob03/quay into orgs
This commit is contained in:
commit
0175bd91bf
12 changed files with 13723 additions and 129 deletions
|
@ -14,6 +14,8 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
_ResourceNeed = namedtuple('resource', ['type', 'namespace', 'name', 'role'])
|
_ResourceNeed = namedtuple('resource', ['type', 'namespace', 'name', 'role'])
|
||||||
_RepositoryNeed = partial(_ResourceNeed, 'repository')
|
_RepositoryNeed = partial(_ResourceNeed, 'repository')
|
||||||
|
_OrganizationNeed = namedtuple('organization', ['orgname', 'role'])
|
||||||
|
_TeamNeed = namedtuple('orgteam', ['orgname', 'teamname', 'role'])
|
||||||
|
|
||||||
|
|
||||||
class QuayDeferredPermissionUser(Identity):
|
class QuayDeferredPermissionUser(Identity):
|
||||||
|
@ -27,13 +29,32 @@ class QuayDeferredPermissionUser(Identity):
|
||||||
logger.debug('Loading user permissions after deferring.')
|
logger.debug('Loading user permissions after deferring.')
|
||||||
user_object = model.get_user(self.id)
|
user_object = model.get_user(self.id)
|
||||||
|
|
||||||
for user in model.get_all_user_permissions(user_object):
|
# Add the user specific permissions
|
||||||
grant = _RepositoryNeed(user.repositorypermission.repository.namespace,
|
user_grant = UserNeed(user_object.username)
|
||||||
user.repositorypermission.repository.name,
|
self.provides.add(user_grant)
|
||||||
user.repositorypermission.role.name)
|
|
||||||
|
# Every user is the admin of their own 'org'
|
||||||
|
user_namespace = _OrganizationNeed(user_object.username, 'admin')
|
||||||
|
self.provides.add(user_namespace)
|
||||||
|
|
||||||
|
# Add repository permissions
|
||||||
|
for perm in model.get_all_user_permissions(user_object):
|
||||||
|
grant = _RepositoryNeed(perm.repository.namespace,
|
||||||
|
perm.repository.name, perm.role.name)
|
||||||
logger.debug('User added permission: {0}'.format(grant))
|
logger.debug('User added permission: {0}'.format(grant))
|
||||||
self.provides.add(grant)
|
self.provides.add(grant)
|
||||||
|
|
||||||
|
# Add namespace permissions derived
|
||||||
|
for team in model.get_org_wide_permissions(user_object):
|
||||||
|
grant = _OrganizationNeed(team.organization.username, team.role.name)
|
||||||
|
logger.debug('Organization team added permission: {0}'.format(grant))
|
||||||
|
self.provides.add(grant)
|
||||||
|
|
||||||
|
team_grant = _TeamNeed(team.organization.username, team.name,
|
||||||
|
team.role.name)
|
||||||
|
logger.debug('Team added permission: {0}'.format(team_grant))
|
||||||
|
self.provides.add(team_grant)
|
||||||
|
|
||||||
self._permissions_loaded = True
|
self._permissions_loaded = True
|
||||||
|
|
||||||
return super(QuayDeferredPermissionUser, self).can(permission)
|
return super(QuayDeferredPermissionUser, self).can(permission)
|
||||||
|
@ -43,6 +64,7 @@ class ModifyRepositoryPermission(Permission):
|
||||||
def __init__(self, namespace, name):
|
def __init__(self, namespace, name):
|
||||||
admin_need = _RepositoryNeed(namespace, name, 'admin')
|
admin_need = _RepositoryNeed(namespace, name, 'admin')
|
||||||
write_need = _RepositoryNeed(namespace, name, 'write')
|
write_need = _RepositoryNeed(namespace, name, 'write')
|
||||||
|
org_admin_need = _OrganizationNeed(namespace, 'admin')
|
||||||
super(ModifyRepositoryPermission, self).__init__(admin_need, write_need)
|
super(ModifyRepositoryPermission, self).__init__(admin_need, write_need)
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,14 +73,25 @@ class ReadRepositoryPermission(Permission):
|
||||||
admin_need = _RepositoryNeed(namespace, name, 'admin')
|
admin_need = _RepositoryNeed(namespace, name, 'admin')
|
||||||
write_need = _RepositoryNeed(namespace, name, 'write')
|
write_need = _RepositoryNeed(namespace, name, 'write')
|
||||||
read_need = _RepositoryNeed(namespace, name, 'read')
|
read_need = _RepositoryNeed(namespace, name, 'read')
|
||||||
|
org_admin_need = _OrganizationNeed(namespace, 'admin')
|
||||||
super(ReadRepositoryPermission, self).__init__(admin_need, write_need,
|
super(ReadRepositoryPermission, self).__init__(admin_need, write_need,
|
||||||
read_need)
|
read_need, org_admin_need)
|
||||||
|
|
||||||
|
|
||||||
class AdministerRepositoryPermission(Permission):
|
class AdministerRepositoryPermission(Permission):
|
||||||
def __init__(self, namespace, name):
|
def __init__(self, namespace, name):
|
||||||
admin_need = _RepositoryNeed(namespace, name, 'admin')
|
admin_need = _RepositoryNeed(namespace, name, 'admin')
|
||||||
super(AdministerRepositoryPermission, self).__init__(admin_need)
|
org_admin_need = _OrganizationNeed(namespace, 'admin')
|
||||||
|
super(AdministerRepositoryPermission, self).__init__(admin_need,
|
||||||
|
org_admin_need)
|
||||||
|
|
||||||
|
|
||||||
|
class CreateRepositoryPermission(Permission):
|
||||||
|
def __init__(self, namespace):
|
||||||
|
admin_org = _OrganizationNeed(namespace, 'admin')
|
||||||
|
create_repo_org = _OrganizationNeed(namespace, 'creator')
|
||||||
|
super(CreateRepositoryPermission, self).__init__(admin_org,
|
||||||
|
create_repo_org)
|
||||||
|
|
||||||
|
|
||||||
class UserPermission(Permission):
|
class UserPermission(Permission):
|
||||||
|
@ -67,6 +100,30 @@ class UserPermission(Permission):
|
||||||
super(UserPermission, self).__init__(user_need)
|
super(UserPermission, self).__init__(user_need)
|
||||||
|
|
||||||
|
|
||||||
|
class AdministerOrganizationPermission(Permission):
|
||||||
|
def __init__(self, org_name):
|
||||||
|
admin_org = _OrganizationNeed(org_name, 'admin')
|
||||||
|
super(AdministerOrganizationPermission, self).__init__(admin_org)
|
||||||
|
|
||||||
|
|
||||||
|
class OrganizationMemberPermission(Permission):
|
||||||
|
def __init__(self, org_name):
|
||||||
|
admin_org = _OrganizationNeed(org_name, 'admin')
|
||||||
|
repo_creator_org = _OrganizationNeed(org_name, 'creator')
|
||||||
|
org_member = _OrganizationNeed(org_name, 'member')
|
||||||
|
super(OrganizationMemberPermission, self).__init__(admin_org, org_member,
|
||||||
|
repo_creator_org)
|
||||||
|
|
||||||
|
|
||||||
|
class ViewTeamPermission(Permission):
|
||||||
|
def __init__(self, org_name, team_name):
|
||||||
|
team_admin = _TeamNeed(org_name, team_name, 'admin')
|
||||||
|
team_creator = _TeamNeed(org_name, 'creator')
|
||||||
|
team_member = _TeamNeed(org_name, 'member')
|
||||||
|
super(ViewTeamPermission, self).__init__(team_admin, team_creator,
|
||||||
|
team_member)
|
||||||
|
|
||||||
|
|
||||||
@identity_loaded.connect_via(app)
|
@identity_loaded.connect_via(app)
|
||||||
def on_identity_loaded(sender, identity):
|
def on_identity_loaded(sender, identity):
|
||||||
logger.debug('Identity loaded: %s' % identity)
|
logger.debug('Identity loaded: %s' % identity)
|
||||||
|
|
|
@ -37,9 +37,14 @@ class User(BaseModel):
|
||||||
organization = BooleanField(default=False, index=True)
|
organization = BooleanField(default=False, index=True)
|
||||||
|
|
||||||
|
|
||||||
|
class TeamRole(BaseModel):
|
||||||
|
name = CharField(index=True)
|
||||||
|
|
||||||
|
|
||||||
class Team(BaseModel):
|
class Team(BaseModel):
|
||||||
name = CharField(index=True)
|
name = CharField(index=True)
|
||||||
organization = ForeignKeyField(User, index=True)
|
organization = ForeignKeyField(User, index=True)
|
||||||
|
role = ForeignKeyField(TeamRole)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
database = db
|
database = db
|
||||||
|
@ -117,18 +122,6 @@ class RepositoryPermission(BaseModel):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TeamPermission(BaseModel):
|
|
||||||
team = ForeignKeyField(Team, index=True)
|
|
||||||
organization = ForeignKeyField(User, index=True)
|
|
||||||
role = ForeignKeyField(Role)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
database = db
|
|
||||||
indexes = (
|
|
||||||
(('team', 'organization'), True),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def random_string_generator(length=16):
|
def random_string_generator(length=16):
|
||||||
def random_string():
|
def random_string():
|
||||||
random = SystemRandom()
|
random = SystemRandom()
|
||||||
|
@ -212,10 +205,13 @@ def initialize_db():
|
||||||
RepositoryPermission, Visibility, RepositoryTag,
|
RepositoryPermission, Visibility, RepositoryTag,
|
||||||
EmailConfirmation, FederatedLogin, LoginService,
|
EmailConfirmation, FederatedLogin, LoginService,
|
||||||
QueueItem, RepositoryBuild, Team, TeamMember,
|
QueueItem, RepositoryBuild, Team, TeamMember,
|
||||||
TeamPermission])
|
TeamRole])
|
||||||
Role.create(name='admin')
|
Role.create(name='admin')
|
||||||
Role.create(name='write')
|
Role.create(name='write')
|
||||||
Role.create(name='read')
|
Role.create(name='read')
|
||||||
|
TeamRole.create(name='admin')
|
||||||
|
TeamRole.create(name='creator')
|
||||||
|
TeamRole.create(name='member')
|
||||||
Visibility.create(name='public')
|
Visibility.create(name='public')
|
||||||
Visibility.create(name='private')
|
Visibility.create(name='private')
|
||||||
LoginService.create(name='github')
|
LoginService.create(name='github')
|
||||||
|
|
|
@ -89,20 +89,17 @@ def create_organization(name, email, creating_user):
|
||||||
new_org.save()
|
new_org.save()
|
||||||
|
|
||||||
# Create a team for the owners
|
# Create a team for the owners
|
||||||
owners_team = create_team('Owners', new_org)
|
owners_team = create_team('Owners', new_org, 'admin')
|
||||||
|
|
||||||
# Add the user who created the org to the owners
|
# Add the user who created the org to the owners team
|
||||||
add_user_to_team(creating_user, owners_team)
|
add_user_to_team(creating_user, owners_team)
|
||||||
|
|
||||||
# Give the owners team admin access to the namespace
|
|
||||||
set_team_org_permission(owners_team, new_org, 'admin')
|
|
||||||
|
|
||||||
return new_org
|
return new_org
|
||||||
except InvalidUsernameException:
|
except InvalidUsernameException:
|
||||||
raise InvalidOrganizationException('Invalid organization name: %s' % name)
|
raise InvalidOrganizationException('Invalid organization name: %s' % name)
|
||||||
|
|
||||||
|
|
||||||
def create_team(name, org):
|
def create_team(name, org, team_role_name):
|
||||||
if not validate_username(name):
|
if not validate_username(name):
|
||||||
raise InvalidTeamException('Invalid team name: %s' % name)
|
raise InvalidTeamException('Invalid team name: %s' % name)
|
||||||
|
|
||||||
|
@ -110,7 +107,8 @@ def create_team(name, org):
|
||||||
raise InvalidOrganizationException('User with name %s is not an org.' %
|
raise InvalidOrganizationException('User with name %s is not an org.' %
|
||||||
org.username)
|
org.username)
|
||||||
|
|
||||||
return Team.create(name=name, organization=org)
|
team_role = TeamRole.get(TeamRole.name == team_role_name)
|
||||||
|
return Team.create(name=name, organization=org, role=team_role)
|
||||||
|
|
||||||
|
|
||||||
def add_user_to_team(user, team):
|
def add_user_to_team(user, team):
|
||||||
|
@ -119,10 +117,17 @@ def add_user_to_team(user, team):
|
||||||
|
|
||||||
def remove_user_from_team(user, team):
|
def remove_user_from_team(user, team):
|
||||||
try:
|
try:
|
||||||
found = TeamMember.get(user = user, team = team)
|
found = TeamMember.get(user=user, team=team)
|
||||||
found.delete_instance()
|
found.delete_instance()
|
||||||
except TeamMember.DoesNotExist:
|
except TeamMember.DoesNotExist:
|
||||||
return
|
raise InvalidTeamException('User does not belong to team.')
|
||||||
|
|
||||||
|
|
||||||
|
def set_team_org_permission(team, org, team_role_name):
|
||||||
|
new_role = TeamRole.get(TeamRole.name == tean_role_name)
|
||||||
|
team.role = new_role
|
||||||
|
team.save()
|
||||||
|
return team
|
||||||
|
|
||||||
|
|
||||||
def set_team_org_permission(team, org, role_name):
|
def set_team_org_permission(team, org, role_name):
|
||||||
|
@ -350,10 +355,31 @@ def update_email(user, new_email):
|
||||||
|
|
||||||
|
|
||||||
def get_all_user_permissions(user):
|
def get_all_user_permissions(user):
|
||||||
select = User.select(User, Repository, RepositoryPermission, Role)
|
select = RepositoryPermission.select(RepositoryPermission, Role, Repository)
|
||||||
with_repo = select.join(RepositoryPermission).join(Repository)
|
with_role = select.join(Role)
|
||||||
with_role = with_repo.switch(RepositoryPermission).join(Role)
|
with_repo = with_role.switch(RepositoryPermission).join(Repository)
|
||||||
return with_role.where(User.username == user.username)
|
through_user = with_repo.switch(RepositoryPermission).join(User,
|
||||||
|
JOIN_LEFT_OUTER)
|
||||||
|
as_perm = through_user.switch(RepositoryPermission)
|
||||||
|
through_team = as_perm.join(Team, JOIN_LEFT_OUTER).join(TeamMember,
|
||||||
|
JOIN_LEFT_OUTER)
|
||||||
|
|
||||||
|
UserThroughTeam = User.alias()
|
||||||
|
with_team_member = through_team.join(UserThroughTeam, JOIN_LEFT_OUTER,
|
||||||
|
on=(UserThroughTeam.id ==
|
||||||
|
TeamMember.user))
|
||||||
|
|
||||||
|
return with_team_member.where((User.id == user) |
|
||||||
|
(UserThroughTeam.id == user))
|
||||||
|
|
||||||
|
|
||||||
|
def get_org_wide_permissions(user):
|
||||||
|
Org = User.alias()
|
||||||
|
team_with_role = Team.select(Team, Org, TeamRole).join(TeamRole)
|
||||||
|
with_org = team_with_role.switch(Team).join(Org, on=(Team.organization ==
|
||||||
|
Org.id))
|
||||||
|
with_user = with_org.switch(Team).join(TeamMember).join(User)
|
||||||
|
return with_user.where(User.id == user, Org.organization == True)
|
||||||
|
|
||||||
|
|
||||||
def get_all_repo_teams(namespace_name, repository_name):
|
def get_all_repo_teams(namespace_name, repository_name):
|
||||||
|
|
|
@ -23,7 +23,11 @@ from util.names import parse_repository_name
|
||||||
from util.gravatar import compute_hash
|
from util.gravatar import compute_hash
|
||||||
from auth.permissions import (ReadRepositoryPermission,
|
from auth.permissions import (ReadRepositoryPermission,
|
||||||
ModifyRepositoryPermission,
|
ModifyRepositoryPermission,
|
||||||
AdministerRepositoryPermission)
|
AdministerRepositoryPermission,
|
||||||
|
CreateRepositoryPermission,
|
||||||
|
AdministerOrganizationPermission,
|
||||||
|
OrganizationMemberPermission,
|
||||||
|
ViewTeamPermission)
|
||||||
from endpoints import registry
|
from endpoints import registry
|
||||||
from endpoints.web import common_login
|
from endpoints.web import common_login
|
||||||
from util.cache import cache_control
|
from util.cache import cache_control
|
||||||
|
@ -57,11 +61,11 @@ def plans_list():
|
||||||
@app.route('/api/user/', methods=['GET'])
|
@app.route('/api/user/', methods=['GET'])
|
||||||
def get_logged_in_user():
|
def get_logged_in_user():
|
||||||
def org_view(o):
|
def org_view(o):
|
||||||
# TODO: return whether the user is really the admin of the organization
|
admin_org = AdministerOrganizationPermission(o.username)
|
||||||
return {
|
return {
|
||||||
'name': o.username,
|
'name': o.username,
|
||||||
'gravatar': compute_hash(o.email),
|
'gravatar': compute_hash(o.email),
|
||||||
'is_org_admin': True
|
'is_org_admin': admin_org.can()
|
||||||
}
|
}
|
||||||
|
|
||||||
if current_user.is_anonymous():
|
if current_user.is_anonymous():
|
||||||
|
@ -234,6 +238,7 @@ user_files = UserRequestFiles(app.config['AWS_ACCESS_KEY'],
|
||||||
app.config['AWS_SECRET_KEY'],
|
app.config['AWS_SECRET_KEY'],
|
||||||
app.config['REGISTRY_S3_BUCKET'])
|
app.config['REGISTRY_S3_BUCKET'])
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/organization/<orgname>', methods=['GET'])
|
@app.route('/api/organization/<orgname>', methods=['GET'])
|
||||||
def get_organization(orgname):
|
def get_organization(orgname):
|
||||||
def team_view(t):
|
def team_view(t):
|
||||||
|
@ -293,13 +298,13 @@ def member_view(m):
|
||||||
'username': m.username
|
'username': m.username
|
||||||
}
|
}
|
||||||
|
|
||||||
@app.route('/api/organization/<orgname>/team/<teamname>/members', methods=['GET'])
|
@app.route('/api/organization/<orgname>/team/<teamname>/members',
|
||||||
|
methods=['GET'])
|
||||||
def get_organization_team_members(orgname, teamname):
|
def get_organization_team_members(orgname, teamname):
|
||||||
if current_user.is_anonymous():
|
view_permission = ViewTeamPermission(orgname, teamname)
|
||||||
abort(404)
|
edit_permission = AdministerOrganizationPermission(orgname)
|
||||||
|
|
||||||
# TODO: determine whether the user has permission to view the members of this team
|
if view_permission.can():
|
||||||
# (i.e. they are a member of the team OR they are an admin of the org)
|
|
||||||
user = current_user.db_user()
|
user = current_user.db_user()
|
||||||
team = None
|
team = None
|
||||||
|
|
||||||
|
@ -309,20 +314,19 @@ def get_organization_team_members(orgname, teamname):
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
members = model.get_organization_team_members(team.id)
|
members = model.get_organization_team_members(team.id)
|
||||||
|
|
||||||
# TODO: determine whether the user has permission to *edit* the members of this team.
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'members': { m.username : member_view(m) for m in members },
|
'members': { m.username : member_view(m) for m in members },
|
||||||
'can_edit': True
|
'can_edit': edit_permission.can()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
abort(403)
|
||||||
|
|
||||||
@app.route('/api/organization/<orgname>/team/<teamname>/members/<membername>', methods=['PUT', 'POST'])
|
|
||||||
|
@app.route('/api/organization/<orgname>/team/<teamname>/members/<membername>',
|
||||||
|
methods=['PUT', 'POST'])
|
||||||
def update_organization_team_member(orgname, teamname, membername):
|
def update_organization_team_member(orgname, teamname, membername):
|
||||||
if current_user.is_anonymous():
|
permission = AdministerOrganizationPermission(orgname)
|
||||||
abort(404)
|
if permission.can():
|
||||||
|
|
||||||
# TODO: determine whether the user has permission to put this user as a member of the team.
|
|
||||||
team = None
|
team = None
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
|
@ -342,13 +346,14 @@ def update_organization_team_member(orgname, teamname, membername):
|
||||||
|
|
||||||
return jsonify(member_view(user))
|
return jsonify(member_view(user))
|
||||||
|
|
||||||
|
abort(403)
|
||||||
|
|
||||||
@app.route('/api/organization/<orgname>/team/<teamname>/members/<membername>', methods=['DELETE'])
|
|
||||||
|
@app.route('/api/organization/<orgname>/team/<teamname>/members/<membername>',
|
||||||
|
methods=['DELETE'])
|
||||||
def delete_organization_team_member(orgname, teamname, membername):
|
def delete_organization_team_member(orgname, teamname, membername):
|
||||||
if current_user.is_anonymous():
|
permission = AdministerOrganizationPermission(orgname)
|
||||||
abort(404)
|
if permission.can():
|
||||||
|
|
||||||
# TODO: determine whether the user has permission to delete this user as a member of the team.
|
|
||||||
team = None
|
team = None
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
|
@ -370,16 +375,18 @@ def delete_organization_team_member(orgname, teamname, membername):
|
||||||
'success': True
|
'success': True
|
||||||
})
|
})
|
||||||
|
|
||||||
|
abort(403)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/repository', methods=['POST'])
|
@app.route('/api/repository', methods=['POST'])
|
||||||
@api_login_required
|
@api_login_required
|
||||||
def create_repo_api():
|
def create_repo_api():
|
||||||
owner = current_user.db_user()
|
owner = current_user.db_user()
|
||||||
|
|
||||||
# TODO(jake): Verify that the user can create a repo in this namespace.
|
|
||||||
json = request.get_json()
|
json = request.get_json()
|
||||||
namespace_name = json['namespace'] if 'namespace' in json else owner.username
|
namespace_name = json['namespace'] if 'namespace' in json else owner.username
|
||||||
|
|
||||||
|
permission = CreateRepositoryPermission(namespace_name)
|
||||||
|
if permission.can():
|
||||||
repository_name = json['repository']
|
repository_name = json['repository']
|
||||||
visibility = json['visibility']
|
visibility = json['visibility']
|
||||||
|
|
||||||
|
@ -394,11 +401,18 @@ def create_repo_api():
|
||||||
repo.description = json['description']
|
repo.description = json['description']
|
||||||
repo.save()
|
repo.save()
|
||||||
|
|
||||||
|
repo = model.create_repository(namespace_name, repository_name, owner,
|
||||||
|
visibility)
|
||||||
|
repo.description = json['description']
|
||||||
|
repo.save()
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'namespace': namespace_name,
|
'namespace': namespace_name,
|
||||||
'name': repository_name
|
'name': repository_name
|
||||||
})
|
})
|
||||||
|
|
||||||
|
abort(403)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/find/repository', methods=['GET'])
|
@app.route('/api/find/repository', methods=['GET'])
|
||||||
def match_repos_api():
|
def match_repos_api():
|
||||||
|
@ -642,11 +656,10 @@ def request_repo_build(namespace, repository):
|
||||||
abort(403) # Permissions denied
|
abort(403) # Permissions denied
|
||||||
|
|
||||||
|
|
||||||
def role_view(repo_perm_obj, username=None):
|
def role_view(repo_perm_obj, org_member):
|
||||||
# TODO: Determine whether the user (if given) is outside of the organization.
|
|
||||||
return {
|
return {
|
||||||
'role': repo_perm_obj.role.name,
|
'role': repo_perm_obj.role.name,
|
||||||
'outside_org': username != 'devtable'
|
'outside_org': org_member
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -727,32 +740,36 @@ def list_tag_images(namespace, repository, tag):
|
||||||
abort(403) # Permission denied
|
abort(403) # Permission denied
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/repository/<path:repository>/permissions/team/', methods=['GET'])
|
@app.route('/api/repository/<path:repository>/permissions/team/',
|
||||||
|
methods=['GET'])
|
||||||
@api_login_required
|
@api_login_required
|
||||||
@parse_repository_name
|
@parse_repository_name
|
||||||
def list_repo_team_permissions(namespace, repository):
|
def list_repo_team_permissions(namespace, repository):
|
||||||
permission = AdministerRepositoryPermission(namespace, repository)
|
permission = AdministerRepositoryPermission(namespace, repository)
|
||||||
if permission.can():
|
if permission.can():
|
||||||
repo_perms = model.get_all_repo_teams(namespace, repository)
|
repo_perms = model.get_all_repo_teams(namespace, repository)
|
||||||
|
org_member = OrganizationMemberPermission(namespace).can()
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'permissions': {repo_perm.team.name: role_view(repo_perm)
|
'permissions': {repo_perm.team.name: role_view(repo_perm, org_member)
|
||||||
for repo_perm in repo_perms}
|
for repo_perm in repo_perms}
|
||||||
})
|
})
|
||||||
|
|
||||||
abort(403) # Permission denied
|
abort(403) # Permission denied
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/repository/<path:repository>/permissions/user/', methods=['GET'])
|
@app.route('/api/repository/<path:repository>/permissions/user/',
|
||||||
|
methods=['GET'])
|
||||||
@api_login_required
|
@api_login_required
|
||||||
@parse_repository_name
|
@parse_repository_name
|
||||||
def list_repo_user_permissions(namespace, repository):
|
def list_repo_user_permissions(namespace, repository):
|
||||||
permission = AdministerRepositoryPermission(namespace, repository)
|
permission = AdministerRepositoryPermission(namespace, repository)
|
||||||
if permission.can():
|
if permission.can():
|
||||||
repo_perms = model.get_all_repo_users(namespace, repository)
|
repo_perms = model.get_all_repo_users(namespace, repository)
|
||||||
|
member = OrganizationMemberPermission(namespace).can()
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'permissions': {repo_perm.user.username: role_view(repo_perm, username=repo_perm.user.username)
|
'permissions': {repo_perm.user.username: role_view(repo_perm, member)
|
||||||
for repo_perm in repo_perms}
|
for repo_perm in repo_perms}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -769,7 +786,8 @@ def get_user_permissions(namespace, repository, username):
|
||||||
permission = AdministerRepositoryPermission(namespace, repository)
|
permission = AdministerRepositoryPermission(namespace, repository)
|
||||||
if permission.can():
|
if permission.can():
|
||||||
perm = model.get_user_reponame_permission(username, namespace, repository)
|
perm = model.get_user_reponame_permission(username, namespace, repository)
|
||||||
return jsonify(role_view(perm, username=username))
|
org_member = OrganizationMemberPermission(namespace).can()
|
||||||
|
return jsonify(role_view(perm, org_member))
|
||||||
|
|
||||||
abort(403) # Permission denied
|
abort(403) # Permission denied
|
||||||
|
|
||||||
|
@ -784,7 +802,8 @@ def get_team_permissions(namespace, repository, teamname):
|
||||||
permission = AdministerRepositoryPermission(namespace, repository)
|
permission = AdministerRepositoryPermission(namespace, repository)
|
||||||
if permission.can():
|
if permission.can():
|
||||||
perm = model.get_team_reponame_permission(username, namespace, repository)
|
perm = model.get_team_reponame_permission(username, namespace, repository)
|
||||||
return jsonify(role_view(perm))
|
org_member = OrganizationMemberPermission(namespace).can()
|
||||||
|
return jsonify(role_view(perm, org_member))
|
||||||
|
|
||||||
abort(403) # Permission denied
|
abort(403) # Permission denied
|
||||||
|
|
||||||
|
@ -808,7 +827,8 @@ def change_user_permissions(namespace, repository, username):
|
||||||
logger.warning('User tried to remove themselves as admin.')
|
logger.warning('User tried to remove themselves as admin.')
|
||||||
abort(409)
|
abort(409)
|
||||||
|
|
||||||
resp = jsonify(role_view(perm, username=username))
|
org_member = OrganizationMemberPermission(namespace).can()
|
||||||
|
resp = jsonify(role_view(perm, org_member))
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
resp.status_code = 201
|
resp.status_code = 201
|
||||||
return resp
|
return resp
|
||||||
|
@ -835,7 +855,8 @@ def change_team_permissions(namespace, repository, teamname):
|
||||||
logger.warning('User tried to remove themselves as admin.')
|
logger.warning('User tried to remove themselves as admin.')
|
||||||
abort(409)
|
abort(409)
|
||||||
|
|
||||||
resp = jsonify(role_view(perm))
|
org_member = OrganizationMemberPermission(namespace).can()
|
||||||
|
resp = jsonify(role_view(perm, org_member))
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
resp.status_code = 201
|
resp.status_code = 201
|
||||||
return resp
|
return resp
|
||||||
|
|
|
@ -13,8 +13,9 @@ from auth.auth import (process_auth, get_authenticated_user,
|
||||||
get_validated_token)
|
get_validated_token)
|
||||||
from util.names import parse_namespace_repository, parse_repository_name
|
from util.names import parse_namespace_repository, parse_repository_name
|
||||||
from util.email import send_confirmation_email
|
from util.email import send_confirmation_email
|
||||||
from auth.permissions import (ModifyRepositoryPermission,
|
from auth.permissions import (ModifyRepositoryPermission, UserPermission,
|
||||||
ReadRepositoryPermission, UserPermission)
|
ReadRepositoryPermission,
|
||||||
|
CreateRepositoryPermission)
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -127,7 +128,9 @@ def create_repository(namespace, repository):
|
||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if get_authenticated_user().username != namespace:
|
permission = CreateRepoPermission('namespace')
|
||||||
|
if not permission.can():
|
||||||
|
logger.info('Attempt to create a new repo with insufficient perms.')
|
||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
logger.debug('Creaing repository with owner: %s' %
|
logger.debug('Creaing repository with owner: %s' %
|
||||||
|
|
|
@ -156,7 +156,7 @@ if __name__ == '__main__':
|
||||||
'Repository owned by an org.', False,
|
'Repository owned by an org.', False,
|
||||||
[], (4, [], ['latest', 'prod']))
|
[], (4, [], ['latest', 'prod']))
|
||||||
|
|
||||||
reader_team = model.create_team('Readers', org)
|
reader_team = model.create_team('Readers', org, 'member')
|
||||||
model.set_team_repo_permission(reader_team.name, org_repo.namespace,
|
model.set_team_repo_permission(reader_team.name, org_repo.namespace,
|
||||||
org_repo.name, 'read')
|
org_repo.name, 'read')
|
||||||
model.add_user_to_team(new_user_2, reader_team)
|
model.add_user_to_team(new_user_2, reader_team)
|
||||||
|
|
|
@ -130,10 +130,7 @@ def load(kind=None):
|
||||||
"""Returns the right storage class according to the configuration."""
|
"""Returns the right storage class according to the configuration."""
|
||||||
global _storage
|
global _storage
|
||||||
|
|
||||||
# TODO hard code to local for now
|
|
||||||
kind = app.config['STORAGE_KIND']
|
kind = app.config['STORAGE_KIND']
|
||||||
# if not kind:
|
|
||||||
# kind = cfg.storage.lower()
|
|
||||||
if kind in _storage:
|
if kind in _storage:
|
||||||
return _storage[kind]
|
return _storage[kind]
|
||||||
if kind == 's3':
|
if kind == 's3':
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"removed": [],
|
||||||
|
"added": [
|
||||||
|
"/opt/elasticsearch-0.90.5/LICENSE.txt",
|
||||||
|
"/opt/elasticsearch-0.90.5/NOTICE.txt",
|
||||||
|
"/opt/elasticsearch-0.90.5/README.textile",
|
||||||
|
"/opt/elasticsearch-0.90.5/bin/elasticsearch",
|
||||||
|
"/opt/elasticsearch-0.90.5/bin/elasticsearch.in.sh",
|
||||||
|
"/opt/elasticsearch-0.90.5/bin/plugin",
|
||||||
|
"/opt/elasticsearch-0.90.5/config/elasticsearch.yml",
|
||||||
|
"/opt/elasticsearch-0.90.5/config/logging.yml",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/elasticsearch-0.90.5.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/jna-3.3.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/jts-1.12.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/log4j-1.2.17.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-analyzers-common-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-codecs-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-core-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-grouping-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-highlighter-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-join-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-memory-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-misc-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-queries-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-queryparser-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-sandbox-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-spatial-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/lucene-suggest-4.4.0.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-amd64-freebsd-6.so",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-amd64-linux.so",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-amd64-solaris.so",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-ia64-linux.so",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-sparc-solaris.so",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-sparc64-solaris.so",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-universal-macosx.dylib",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-universal64-macosx.dylib",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-x86-freebsd-5.so",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-x86-freebsd-6.so",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-x86-linux.so",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/libsigar-x86-solaris.so",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/sigar/sigar-1.6.4.jar",
|
||||||
|
"/opt/elasticsearch-0.90.5/lib/spatial4j-0.3.jar"
|
||||||
|
],
|
||||||
|
"changed": []
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"removed": [],
|
||||||
|
"added": [],
|
||||||
|
"changed": []
|
||||||
|
}
|
Binary file not shown.
Reference in a new issue