Add a user info scope and thread it through the code. Protect the org modification API.

This commit is contained in:
jakedt 2014-03-18 19:21:27 -04:00
parent 89556172d5
commit 64071b9e8e
13 changed files with 144 additions and 115 deletions

View file

@ -1,9 +1,7 @@
import logging
from flask.ext.principal import (identity_loaded, UserNeed, Permission,
Identity, identity_changed)
from flask.ext.login import current_user
from collections import namedtuple
from flask.ext.principal import identity_loaded, Permission, Identity, identity_changed
from collections import namedtuple, defaultdict
from functools import partial
from data import model
@ -17,27 +15,36 @@ _ResourceNeed = namedtuple('resource', ['type', 'namespace', 'name', 'role'])
_RepositoryNeed = partial(_ResourceNeed, 'repository')
_OrganizationNeed = namedtuple('organization', ['orgname', 'role'])
_TeamNeed = namedtuple('orgteam', ['orgname', 'teamname', 'role'])
_UserNeed = namedtuple('user', ['username', 'role'])
REPO_ROLES = [None, 'read', 'write', 'admin']
TEAM_ROLES = [None, 'member', 'creator', 'admin']
USER_ROLES = [None, 'read', 'admin']
SCOPE_MAX_REPO_ROLES = {
SCOPE_MAX_REPO_ROLES = defaultdict(lambda: None)
SCOPE_MAX_REPO_ROLES.update({
'repo:read': 'read',
'repo:write': 'write',
'repo:admin': 'admin',
'repo:create': None,
}
'direct_user_login': 'admin',
})
SCOPE_MAX_TEAM_ROLES = {
'repo:read': None,
'repo:write': None,
'repo:admin': None,
SCOPE_MAX_TEAM_ROLES = defaultdict(lambda: None)
SCOPE_MAX_TEAM_ROLES.update({
'repo:create': 'creator',
}
'direct_user_login': 'admin',
})
SCOPE_MAX_USER_ROLES = defaultdict(lambda: None)
SCOPE_MAX_USER_ROLES.update({
'user:read': 'admin',
'direct_user_login': 'admin',
})
class QuayDeferredPermissionUser(Identity):
def __init__(self, id, auth_type=None, scopes=None):
def __init__(self, id, auth_type, scopes):
super(QuayDeferredPermissionUser, self).__init__(id, auth_type)
self._permissions_loaded = False
@ -61,16 +68,18 @@ class QuayDeferredPermissionUser(Identity):
def _repo_role_for_scopes(self, role):
return self._translate_role_for_scopes(REPO_ROLES, SCOPE_MAX_REPO_ROLES, role)
def _user_role_for_scopes(self, role):
return self._translate_role_for_scopes(USER_ROLES, SCOPE_MAX_USER_ROLES, role)
def can(self, permission):
if not self._permissions_loaded:
logger.debug('Loading user permissions after deferring.')
user_object = model.get_user(self.id)
# Add the user specific permissions, only for non-oauth permission
if self._scope_set is None:
user_grant = UserNeed(user_object.username)
self.provides.add(user_grant)
logger.debug('Add admin to user namespace: %s', user_object.username)
# Add the user specific permissions, only for non-oauth permission
user_grant = _UserNeed(user_object.username, self._user_role_for_scopes('admin'))
self.provides.add(user_grant)
logger.debug('User permission: {0}'.format(user_grant))
# Every user is the admin of their own 'org'
user_namespace = _OrganizationNeed(user_object.username, self._team_role_for_scopes('admin'))
@ -135,10 +144,17 @@ class CreateRepositoryPermission(Permission):
create_repo_org)
class UserPermission(Permission):
class UserAdminPermission(Permission):
def __init__(self, username):
user_need = UserNeed(username)
super(UserPermission, self).__init__(user_need)
user_admin = _UserNeed(username, 'admin')
super(UserAdminPermission, self).__init__(user_admin)
class UserReadPermission(Permission):
def __init__(self, username):
user_admin = _UserNeed(username, 'admin')
user_read = _UserNeed(username, 'read')
super(UserReadPermission, self).__init__(user_read, user_admin)
class AdministerOrganizationPermission(Permission):
@ -176,7 +192,7 @@ def on_identity_loaded(sender, identity):
elif identity.auth_type == 'username':
logger.debug('Switching username permission to deferred object: %s', identity.id)
switch_to_deferred = QuayDeferredPermissionUser(identity.id, 'username')
switch_to_deferred = QuayDeferredPermissionUser(identity.id, 'username', {'direct_user_login'})
identity_changed.send(app, identity=switch_to_deferred)
elif identity.auth_type == 'token':