misc: raise bad requests on invalid integers for limit/offset (#42818)

This commit is contained in:
Frédéric Péters 2020-05-13 12:42:13 +02:00
parent d46f05b8b3
commit ad6be53657
4 changed files with 30 additions and 29 deletions

View File

@ -448,6 +448,10 @@ def test_backoffice_listing_pagination(pub):
resp = resp.follow()
assert resp.forms['listing-settings']['offset'].value == '0'
# try invalid values
resp = app.get('/backoffice/management/form-title/?limit=toto&offset=30', status=400)
resp = app.get('/backoffice/management/form-title/?limit=5&offset=toto', status=400)
def test_backoffice_listing_order(pub):
if not pub.is_using_postgresql():

View File

@ -260,15 +260,9 @@ class ApiFormsDirectory(Directory):
if not get_query_flag('include-anonymised', default=True):
criterias.append(st.Null('anonymised'))
try:
limit = int(get_request().form.get('limit',
limit = misc.get_int_or_400(get_request().form.get('limit',
get_publisher().get_site_option('default-page-size') or 20))
except ValueError:
raise RequestError('invalid limit parameter')
try:
offset = int(get_request().form.get('offset', 0))
except ValueError:
raise RequestError('invalid offset parameter')
offset = misc.get_int_or_400(get_request().form.get('offset', 0))
order_by = get_request().form.get('order_by',
get_publisher().get_site_option('default-sort-order') or '-receipt_time')
@ -666,8 +660,8 @@ class ApiUserDirectory(Directory):
order_by = '-receipt_time'
user_forms = sql.AnyFormData.select(
[Equal('user_id', str(user.id))],
limit=get_request().form.get('limit'),
offset=get_request().form.get('offset'),
limit=misc.get_int_or_400(get_request().form.get('limit')),
offset=misc.get_int_or_400(get_request().form.get('offset')),
order_by=order_by)
else:
formdefs = FormDef.select()
@ -780,7 +774,7 @@ class ApiUsersDirectory(Directory):
user_info['text'] = user_info['user_display_name']
return user_info
limit = int(get_request().form.get('limit') or '0') or None
limit = misc.get_int_or_400(get_request().form.get('limit'))
users = get_publisher().user_class.select(order_by='name',
clause=criterias, limit=limit)
data = [as_dict(x) for x in users]

View File

@ -356,9 +356,9 @@ class UsersViewDirectory(Directory):
html_top('management', _('Management'))
r = TemplateIO(html=True)
limit = int(get_request().form.get('limit',
limit = misc.get_int_or_400(get_request().form.get('limit',
get_publisher().get_site_option('default-page-size')) or 20)
offset = int(get_request().form.get('offset', 0))
offset = misc.get_int_or_400(get_request().form.get('offset', 0))
order_by = get_request().form.get('order_by', None) or 'name'
query = get_request().form.get('q')
@ -857,9 +857,9 @@ class ManagementDirectory(Directory):
if FormDef.count() == 0:
return self.empty_site_message(_('Global View'))
limit = int(get_request().form.get('limit',
limit = misc.get_int_or_400(get_request().form.get('limit',
get_publisher().get_site_option('default-page-size') or 20))
offset = int(get_request().form.get('offset', 0))
offset = misc.get_int_or_400(get_request().form.get('offset', 0))
order_by = get_request().form.get('order_by',
get_publisher().get_site_option('default-sort-order') or '-receipt_time')
@ -1676,11 +1676,11 @@ class FormPage(Directory):
if get_publisher().is_using_postgresql():
# only enable pagination in SQL mode, as we do not have sorting in
# the other case.
limit = get_request().form.get('limit',
int(get_publisher().get_site_option('default-page-size') or 20))
limit = misc.get_int_or_400(get_request().form.get('limit',
get_publisher().get_site_option('default-page-size') or 20))
else:
limit = get_request().form.get('limit', 0)
offset = get_request().form.get('offset', 0)
limit = misc.get_int_or_400(get_request().form.get('limit', 0))
offset = misc.get_int_or_400(get_request().form.get('offset', 0))
order_by = get_request().form.get('order_by')
if self.view and not order_by:
order_by = self.view.order_by
@ -1716,7 +1716,7 @@ class FormPage(Directory):
table = FormDefUI(self.formdef).listing(fields=fields,
selected_filter=selected_filter,
limit=int(limit), offset=int(offset), query=query,
limit=limit, offset=offset, query=query,
order_by=order_by, criterias=criterias,
include_checkboxes=bool(multi_actions))
if get_response().status_code == 302:
@ -2063,16 +2063,10 @@ class FormPage(Directory):
query = get_request().form.get('q') if not anonymise else None
offset = None
if 'offset' in get_request().form:
try:
offset = int(get_request().form['offset'])
except ValueError:
raise errors.RequestError('invalid offset parameter')
offset = misc.get_int_or_400(get_request().form['offset'])
limit = None
if 'limit' in get_request().form:
try:
limit = int(get_request().form['limit'])
except ValueError:
raise errors.RequestError('invalid limit parameter')
limit = misc.get_int_or_400(get_request().form['limit'])
items, total_count = FormDefUI(self.formdef).get_listing_items(
selected_filter, user=user, query=query, criterias=criterias,
order_by=order_by, anonymise=anonymise, offset=offset, limit=limit)

View File

@ -49,7 +49,7 @@ from quixote.html import htmltext
from . import _, force_str
from . import get_cfg, get_logger, ezt
from .errors import ConnectionError
from .errors import ConnectionError, RequestError
from .template import Template
from django.utils.six import BytesIO, StringIO
@ -798,3 +798,12 @@ def validate_iban(string_value):
if not is_ascii_digit(dummy_iban_converted):
return False
return int(iban_key) == 98 - int(dummy_iban_converted) % 97
def get_int_or_400(value):
if value is None:
return None
try:
return int(value)
except ValueError:
raise RequestError()