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))
)
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):
self.finish()

View File

@@ -38,34 +38,9 @@ class GroupListAPIHandler(_GroupAPIHandler):
@admin_only
def get(self):
"""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)
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)
offset, limit = self.get_api_pagination()
query = query.offset(offset).limit(limit)
data = [self.group_model(group) for group in query]
self.write(json.dumps(data))
@@ -104,36 +79,8 @@ class GroupAPIHandler(_GroupAPIHandler):
@admin_only
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)
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)
self.write(json.dumps(group_model))
@admin_only

View File

@@ -17,38 +17,16 @@ class ProxyAPIHandler(APIHandler):
This is the same as fetching the routing table directly from the proxy,
but without clients needing to maintain separate
"""
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
offset, limit = self.get_api_pagination()
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 = {
key: routes[key]
for key in list(routes.keys())[offset:]
for key in list(routes.keys())[offset:limit]
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))
@admin_only

View File

@@ -55,9 +55,7 @@ class UserListAPIHandler(APIHandler):
@admin_only
def get(self):
state_filter = self.get_argument("state", None)
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
offset, limit = self.get_api_pagination()
# post_filter
post_filter = None
@@ -98,27 +96,7 @@ class UserListAPIHandler(APIHandler):
# no filter, return all users
query = self.db.query(orm.User)
# Apply offset and limit for request pagination
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)
query = query.offset(offset).limit(limit)
data = [
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
async def test_group_create_delete(app):
db = app.db