Browse Source

Fix a crash in hc.api.views.pause with an int in request body

The jsonify decorator parses request payload as JSON
and puts it in request.json. The payload would normally
be a complex object, but if a client sends, let's say,
a single integer, then request.json is a python int.

The authorize decorator looks for API key first in request
headers, then in request body. It expects the request
body to be a complex object.

This commit changes adds the following validation rule in
the jsonify decorator: if request body is not empty, it
*must* parse as JSON, and the root element of the parsed
document *must* be a dict.
master
Pēteris Caune 3 years ago
parent
commit
ba3f222f37
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
3 changed files with 15 additions and 8 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +7
    -8
      hc/api/decorators.py
  3. +7
    -0
      hc/api/tests/test_pause.py

+ 1
- 0
CHANGELOG.md View File

@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
### Bug Fixes
- Fix hc.api.views.ping to handle non-utf8 data in request body (#574)
- Fix a crash when hc.api.views.pause receives a single integer in request body
## v1.23.1 - 2021-10-13


+ 7
- 8
hc/api/decorators.py View File

@ -61,12 +61,12 @@ def authorize_read(f):
return wrapper
def validate_json(schema=None):
def validate_json(schema={"type": "object"}):
""" Parse request json and validate it against `schema`.
Put the parsed result in `request.json`.
If schema is None then only parse and don't validate.
Supports a limited subset of JSON schema spec.
If schema is None then only parse and check if the root
element is a dict. Supports a limited subset of JSON schema spec.
"""
@ -81,11 +81,10 @@ def validate_json(schema=None):
else:
request.json = {}
if schema:
try:
validate(request.json, schema)
except ValidationError as e:
return error("json validation error: %s" % e)
try:
validate(request.json, schema)
except ValidationError as e:
return error("json validation error: %s" % e)
return f(request, *args, **kwds)


+ 7
- 0
hc/api/tests/test_pause.py View File

@ -94,3 +94,10 @@ class PauseTestCase(BaseTestCase):
self.profile.refresh_from_db()
self.assertIsNone(self.profile.next_nag_date)
def test_it_rejects_non_dict_post_body(self):
r = self.csrf_client.post(self.url, "123", content_type="application/json")
self.assertEqual(r.status_code, 400)
self.assertEqual(
r.json()["error"], "json validation error: value is not an object"
)

Loading…
Cancel
Save