Implemented filter list skeleton

This commit is contained in:
0mar
2021-01-04 16:24:50 +01:00
parent 6ad757f7e7
commit f4ba57b1d7
4 changed files with 50 additions and 19 deletions

View File

@@ -35,10 +35,12 @@ class _GroupAPIHandler(APIHandler):
class GroupListAPIHandler(_GroupAPIHandler):
@needs_scope('read:groups') # Todo: Apply filter on results
def get(self):
@needs_scope('read:groups')
def get(self, scope_filter=None):
"""List groups"""
groups = self.db.query(orm.Group)
if scope_filter is not None:
groups.filter(orm.Group.name._in(scope_filter))
data = [self.group_model(g) for g in groups]
self.write(json.dumps(data))

View File

@@ -31,8 +31,10 @@ def service_model(service):
class ServiceListAPIHandler(APIHandler):
@needs_scope('read:services')
def get(self):
def get(self, scope_filter=None):
data = {name: service_model(service) for name, service in self.services.items()}
if scope_filter is not None:
data = dict(filter(lambda tup: tup[0] in scope_filter))
self.write(json.dumps(data))

View File

@@ -38,8 +38,6 @@ class SelfAPIHandler(APIHandler):
user = self.get_current_user_oauth_token()
if user is None:
raise web.HTTPError(403)
# Later: filter based on scopes.
# Perhaps user
self.write(json.dumps(self.user_model(user)))
@@ -53,7 +51,7 @@ class UserListAPIHandler(APIHandler):
return any(spawner.ready for spawner in user.spawners.values())
@needs_scope('read:users')
def get(self):
def get(self, scope_filter=None):
state_filter = self.get_argument("state", None)
# post_filter
@@ -94,6 +92,8 @@ class UserListAPIHandler(APIHandler):
else:
# no filter, return all users
query = self.db.query(orm.User)
if scope_filter is not None:
query.filter(orm.User.name.in_(scope_filter))
data = [
self.user_model(u, include_servers=True, include_state=True)

View File

@@ -320,9 +320,7 @@ def get_user_scopes(name):
'users:servers',
'users:tokens',
]
scope_list.extend(
['read:' + scope for scope in scope_list]
) # Todo: Put this in closure
scope_list.extend(['read:' + scope for scope in scope_list])
return {"{}!user={}".format(scope, name) for scope in scope_list}
@@ -348,6 +346,29 @@ def check_user_in_expanded_scope(handler, user_name, scope_group_names):
return bool(set(scope_group_names) & group_names)
def _flatten_groups(groups):
user_set = {}
for group in groups:
user_set |= group.users
return user_set
def _get_scope_filter(req_scope, sub_scope):
# Rough draft
scope_translator = {
'read:users': 'users',
'users': 'users',
'read:groups': 'groups',
}
if req_scope not in scope_translator:
raise AttributeError("Scope not found")
kind = scope_translator[req_scope]
scope_filter = None # todo: orm.Class(kind).find
if 'group' in sub_scope and kind == 'user':
scope_filter += _flatten_groups(sub_scope['group'])
return set(scope_filter)
def check_scope(api_handler, req_scope, scopes, **kwargs):
# Parse user name and server name together
if 'user' in kwargs and 'server' in kwargs:
@@ -358,10 +379,13 @@ def check_scope(api_handler, req_scope, scopes, **kwargs):
return True
# Apply filters
sub_scope = scopes[req_scope]
for (
filter_,
filter_value,
) in kwargs.items(): # Interface change: Now can have multiple filters
if 'scope_filter' in kwargs:
scope_filter = _get_scope_filter(req_scope, sub_scope)
kwargs['scope_filter'] = scope_filter
return True
else:
# Interface change: Now can have multiple filters
for (filter_, filter_value) in kwargs.items():
if filter_ in sub_scope and filter_value in sub_scope[filter_]:
return True
if needs_scope_expansion(filter_, filter_value, sub_scope):
@@ -371,6 +395,9 @@ def check_scope(api_handler, req_scope, scopes, **kwargs):
return False
# Todo: make some methods private
def parse_scopes(scope_list):
"""
Parses scopes and filters in something akin to JSON style