Merge pull request #1671 from alphagov/fix-uuid-validation

Fix UUID validate in the JSON schema
This commit is contained in:
Rebecca Law
2018-02-15 14:23:02 +00:00
committed by GitHub
4 changed files with 35 additions and 2 deletions

View File

@@ -1,5 +1,5 @@
from notifications_utils.statsd_decorators import statsd from notifications_utils.statsd_decorators import statsd
from sqlalchemy import or_, and_ from sqlalchemy import or_, and_, desc
from app import db from app import db
from app.dao.dao_utils import transactional from app.dao.dao_utils import transactional
@@ -54,4 +54,6 @@ def dao_get_template_usage_stats_by_service(service_id, year):
StatsTemplateUsageByMonth.year == year + 1 StatsTemplateUsageByMonth.year == year + 1
) )
) )
).order_by(
desc(StatsTemplateUsageByMonth.month)
).all() ).all()

View File

@@ -1,5 +1,6 @@
import json import json
from datetime import datetime, timedelta from datetime import datetime, timedelta
from uuid import UUID
from iso8601 import iso8601, ParseError from iso8601 import iso8601, ParseError
from jsonschema import (Draft4Validator, ValidationError, FormatChecker) from jsonschema import (Draft4Validator, ValidationError, FormatChecker)
@@ -10,6 +11,12 @@ from notifications_utils.recipients import (validate_phone_number, validate_emai
def validate(json_to_validate, schema): def validate(json_to_validate, schema):
format_checker = FormatChecker() format_checker = FormatChecker()
@format_checker.checks("validate_uuid", raises=Exception)
def validate_uuid(instance):
if isinstance(instance, str):
UUID(instance)
return True
@format_checker.checks('phone_number', raises=InvalidPhoneError) @format_checker.checks('phone_number', raises=InvalidPhoneError)
def validate_schema_phone_number(instance): def validate_schema_phone_number(instance):
if isinstance(instance, str): if isinstance(instance, str):

View File

@@ -5,7 +5,7 @@ If the definition is specific to a version put it in a definition file in the ve
uuid = { uuid = {
"type": "string", "type": "string",
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$", "format": "validate_uuid",
"validationMessage": "is not a valid UUID", "validationMessage": "is not a valid UUID",
"code": "1001", # yet to be implemented "code": "1001", # yet to be implemented
"link": "link to our error documentation not yet implemented" "link": "link to our error documentation not yet implemented"

View File

@@ -115,6 +115,30 @@ def test_post_sms_schema_is_valid(input):
assert validate(input, post_sms_request_schema) == input assert validate(input, post_sms_request_schema) == input
@pytest.mark.parametrize("template_id",
['2ebe4da8-17be-49fe-b02f-dff2760261a0' + "\n",
'2ebe4da8-17be-49fe-b02f-dff2760261a0' + " ",
'2ebe4da8-17be-49fe-b02f-dff2760261a0' + "\r",
"\t" + '2ebe4da8-17be-49fe-b02f-dff2760261a0',
'2ebe4da8-17be-49fe-b02f-dff2760261a0'[4:],
"bad_uuid"
]
)
def test_post_sms_json_schema_bad_uuid(template_id):
j = {
"template_id": template_id,
"phone_number": "07515111111"
}
with pytest.raises(ValidationError) as e:
validate(j, post_sms_request_schema)
error = json.loads(str(e.value))
assert len(error.keys()) == 2
assert error.get('status_code') == 400
assert len(error.get('errors')) == 1
assert {'error': 'ValidationError',
'message': "template_id is not a valid UUID"} in error['errors']
def test_post_sms_json_schema_bad_uuid_and_missing_phone_number(): def test_post_sms_json_schema_bad_uuid_and_missing_phone_number():
j = {"template_id": "notUUID"} j = {"template_id": "notUUID"}
with pytest.raises(ValidationError) as e: with pytest.raises(ValidationError) as e: