Add get_api_pagination method to base handler, revert group.users pagination

This commit is contained in:
Nathan Barber
2021-04-21 09:57:30 -04:00
parent 5d095c0234
commit ab130309ec
5 changed files with 24 additions and 135 deletions

View File

@@ -265,6 +265,22 @@ class APIHandler(BaseHandler):
400, ("group names must be str, not %r", type(groupname)) 400, ("group names must be str, not %r", type(groupname))
) )
def get_api_pagination(self):
default_limit = self.settings["app"].api_page_default_limit
max_limit = self.settings["app"].api_page_max_limit
offset = self.get_argument("offset", None)
limit = self.get_argument("limit", default_limit)
try:
offset = abs(int(offset)) if offset is not None else 0
limit = abs(int(limit))
if limit > max_limit:
limit = max_limit
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, offset and limit must be integers"
)
return offset, limit
def options(self, *args, **kwargs): def options(self, *args, **kwargs):
self.finish() self.finish()

View File

@@ -38,34 +38,9 @@ class GroupListAPIHandler(_GroupAPIHandler):
@admin_only @admin_only
def get(self): def get(self):
"""List groups""" """List groups"""
offset = self.get_argument("offset", None)
limit = self.get_argument("limit", self.settings['app'].api_page_default_limit)
max_limit = self.settings['app'].api_page_max_limit
query = self.db.query(orm.Group) query = self.db.query(orm.Group)
offset, limit = self.get_api_pagination()
if offset is not None: query = query.offset(offset).limit(limit)
try:
offset = int(offset)
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, offset must be an integer"
)
query = query.offset(offset)
if limit != self.settings['app'].api_page_default_limit:
try:
limit = int(limit)
if limit > max_limit:
limit = max_limit
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, limit must be an integer"
)
query = query.limit(limit)
data = [self.group_model(group) for group in query] data = [self.group_model(group) for group in query]
self.write(json.dumps(data)) self.write(json.dumps(data))
@@ -104,36 +79,8 @@ class GroupAPIHandler(_GroupAPIHandler):
@admin_only @admin_only
def get(self, name): def get(self, name):
offset = self.get_argument("offset", None)
limit = self.get_argument("limit", self.settings['app'].api_page_default_limit)
max_limit = self.settings['app'].api_page_max_limit
group = self.find_group(name) group = self.find_group(name)
if offset is not None:
try:
offset = int(offset)
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, offset must be an integer"
)
group.users = group.users[offset:]
if limit != self.settings['app'].api_page_default_limit:
try:
limit = int(limit)
if limit > max_limit:
limit = max_limit
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, limit must be an integer"
)
group.users = group.users[:limit]
group_model = self.group_model(group) group_model = self.group_model(group)
self.write(json.dumps(group_model)) self.write(json.dumps(group_model))
@admin_only @admin_only

View File

@@ -17,38 +17,16 @@ class ProxyAPIHandler(APIHandler):
This is the same as fetching the routing table directly from the proxy, This is the same as fetching the routing table directly from the proxy,
but without clients needing to maintain separate but without clients needing to maintain separate
""" """
offset = self.get_argument("offset", None) offset, limit = self.get_api_pagination()
limit = self.get_argument("limit", self.settings['app'].api_page_default_limit)
max_limit = self.settings['app'].api_page_max_limit
routes = await self.proxy.get_all_routes() routes = await self.proxy.get_all_routes()
if offset is not None:
try:
offset = int(offset)
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, offset must be an integer"
)
routes = { routes = {
key: routes[key] key: routes[key]
for key in list(routes.keys())[offset:] for key in list(routes.keys())[offset:limit]
if key in routes if key in routes
} }
if limit != self.settings['app'].api_page_default_limit:
try:
limit = int(limit)
if limit > max_limit:
limit = max_limit
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, limit must be an integer"
)
routes = {
key: routes[key] for key in list(routes.keys())[:limit] if key in routes
}
self.write(json.dumps(routes)) self.write(json.dumps(routes))
@admin_only @admin_only

View File

@@ -55,9 +55,7 @@ class UserListAPIHandler(APIHandler):
@admin_only @admin_only
def get(self): def get(self):
state_filter = self.get_argument("state", None) state_filter = self.get_argument("state", None)
offset = self.get_argument("offset", None) offset, limit = self.get_api_pagination()
limit = self.get_argument("limit", self.settings['app'].api_page_default_limit)
max_limit = self.settings['app'].api_page_max_limit
# post_filter # post_filter
post_filter = None post_filter = None
@@ -98,27 +96,7 @@ class UserListAPIHandler(APIHandler):
# no filter, return all users # no filter, return all users
query = self.db.query(orm.User) query = self.db.query(orm.User)
# Apply offset and limit for request pagination query = query.offset(offset).limit(limit)
if offset is not None:
try:
offset = int(offset)
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, offset must be an integer"
)
query = query.offset(offset)
if limit != self.settings['app'].api_page_default_limit:
try:
limit = int(limit)
if limit > max_limit:
limit = max_limit
except Exception as e:
raise web.HTTPError(
400, "Invalid argument type, limit must be an integer"
)
query = query.limit(limit)
data = [ data = [
self.user_model(u, include_servers=True, include_state=True) self.user_model(u, include_servers=True, include_state=True)

View File

@@ -1504,36 +1504,6 @@ async def test_group_get(app):
} }
@mark.group
async def test_group_user_pagination(app):
group = orm.Group.find(app.db, name='betaflight')
user = add_user(app.db, app=app, name='bigfoot')
second_user = add_user(app.db, app=app, name='birdman')
group.users.append(user)
group.users.append(second_user)
app.db.commit()
# Test offset for pagination
r = await api_request(app, 'groups/betaflight?offset=1')
r.raise_for_status()
reply = r.json()
assert reply == {'kind': 'group', 'name': 'betaflight', 'users': ['birdman']}
r = await api_request(app, 'groups/betaflight?offset=10')
r.raise_for_status()
assert r.json() == {'kind': 'group', 'name': 'betaflight', 'users': []}
# Test limit for pagination
r = await api_request(app, 'groups/betaflight?limit=1')
r.raise_for_status()
reply = r.json()
assert reply == {'kind': 'group', 'name': 'betaflight', 'users': ['bigfoot']}
r = await api_request(app, 'groups/betaflight?limit=0')
r.raise_for_status()
assert r.json() == {'kind': 'group', 'name': 'betaflight', 'users': []}
@mark.group @mark.group
async def test_group_create_delete(app): async def test_group_create_delete(app):
db = app.db db = app.db