Unified user representation for web and API calls
Both approaches now use a pillar.auth.UserClass instance. g.current_user is now always set to that instance, even for web entry points. This UserClass instance can still be keyed like the old dict, but this is for temporary compatibility and shouldn't be relied on in new or touched code.
This commit is contained in:
@@ -110,6 +110,8 @@ def after_inserting_projects(projects):
|
||||
|
||||
|
||||
def after_inserting_project(project, db_user):
|
||||
from pillar.auth import UserClass
|
||||
|
||||
project_id = project['_id']
|
||||
user_id = db_user['_id']
|
||||
|
||||
@@ -135,7 +137,8 @@ def after_inserting_project(project, db_user):
|
||||
log.debug('Made user %s member of group %s', user_id, admin_group_id)
|
||||
|
||||
# Assign the group to the project with admin rights
|
||||
is_admin = authorization.is_admin(db_user)
|
||||
owner_user = UserClass.construct('', db_user)
|
||||
is_admin = authorization.is_admin(owner_user)
|
||||
world_permissions = ['GET'] if is_admin else []
|
||||
permissions = {
|
||||
'world': world_permissions,
|
||||
|
@@ -15,13 +15,17 @@ from flask import g
|
||||
from flask import request
|
||||
from flask import current_app
|
||||
|
||||
from pillar.auth import UserClass
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
CLI_USER = {
|
||||
'user_id': 'CLI',
|
||||
CLI_USER = UserClass.construct('CLI', {
|
||||
'_id': 'CLI',
|
||||
'groups': [],
|
||||
'roles': {'admin'},
|
||||
}
|
||||
'email': 'local@nowhere',
|
||||
'username': 'CLI',
|
||||
})
|
||||
|
||||
|
||||
def force_cli_user():
|
||||
@@ -74,6 +78,8 @@ def validate_this_token(token, oauth_subclient=None):
|
||||
:rtype: dict
|
||||
"""
|
||||
|
||||
from pillar.auth import UserClass
|
||||
|
||||
g.current_user = None
|
||||
_delete_expired_tokens()
|
||||
|
||||
@@ -98,9 +104,7 @@ def validate_this_token(token, oauth_subclient=None):
|
||||
log.debug('Validation failed, user not logged in')
|
||||
return None
|
||||
|
||||
g.current_user = {'user_id': db_user['_id'],
|
||||
'groups': db_user['groups'],
|
||||
'roles': set(db_user.get('roles', []))}
|
||||
g.current_user = UserClass.construct(token, db_user)
|
||||
|
||||
return db_user
|
||||
|
||||
|
@@ -7,6 +7,8 @@ from flask import abort
|
||||
from flask import current_app
|
||||
from werkzeug.exceptions import Forbidden
|
||||
|
||||
from pillar.auth import UserClass
|
||||
|
||||
CHECK_PERMISSIONS_IMPLEMENTED_FOR = {'projects', 'nodes', 'flamenco_jobs'}
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -334,17 +336,20 @@ def ab_testing(require_roles=set(),
|
||||
return decorator
|
||||
|
||||
|
||||
def user_has_role(role, user=None):
|
||||
def user_has_role(role, user: UserClass=None):
|
||||
"""Returns True iff the user is logged in and has the given role."""
|
||||
|
||||
if user is None:
|
||||
user = g.get('current_user')
|
||||
if user is not None and not isinstance(user, UserClass):
|
||||
raise TypeError(f'g.current_user should be instance of UserClass, not {type(user)}')
|
||||
elif not isinstance(user, UserClass):
|
||||
raise TypeError(f'user should be instance of UserClass, not {type(user)}')
|
||||
|
||||
if user is None:
|
||||
return False
|
||||
|
||||
roles = user.get('roles') or ()
|
||||
return role in roles
|
||||
return user.has_role(role)
|
||||
|
||||
|
||||
def user_matches_roles(require_roles=set(),
|
||||
@@ -359,22 +364,14 @@ def user_matches_roles(require_roles=set(),
|
||||
returning True.
|
||||
"""
|
||||
|
||||
if not isinstance(require_roles, set):
|
||||
raise TypeError('require_roles param should be a set, but is a %r' % type(require_roles))
|
||||
|
||||
if require_all and not require_roles:
|
||||
raise ValueError('require_login(require_all=True) cannot be used with empty require_roles.')
|
||||
|
||||
current_user = g.get('current_user')
|
||||
|
||||
current_user: UserClass = g.get('current_user')
|
||||
if current_user is None:
|
||||
return False
|
||||
|
||||
intersection = require_roles.intersection(current_user['roles'])
|
||||
if require_all:
|
||||
return len(intersection) == len(require_roles)
|
||||
if not isinstance(current_user, UserClass):
|
||||
raise TypeError(f'g.current_user should be instance of UserClass, not {type(current_user)}')
|
||||
|
||||
return not bool(require_roles) or bool(intersection)
|
||||
return current_user.matches_roles(require_roles, require_all)
|
||||
|
||||
|
||||
def is_admin(user):
|
||||
|
Reference in New Issue
Block a user