diff --git a/app/v2/broadcast/broadcast_schemas.py b/app/v2/broadcast/broadcast_schemas.py index 67886507e..99dd572d7 100644 --- a/app/v2/broadcast/broadcast_schemas.py +++ b/app/v2/broadcast/broadcast_schemas.py @@ -76,6 +76,7 @@ post_broadcast_schema = { "properties": { "name": { "type": "string", + "pattern": "([a-zA-Z1-9]+ )*[a-zA-Z1-9]+", }, "polygons": { "type": "array", diff --git a/app/v2/broadcast/post_broadcast.py b/app/v2/broadcast/post_broadcast.py index ae5f0823d..0a04bd26d 100644 --- a/app/v2/broadcast/post_broadcast.py +++ b/app/v2/broadcast/post_broadcast.py @@ -41,27 +41,12 @@ def create_broadcast(): broadcast_json = cap_xml_to_dict(cap_xml) validate(broadcast_json, post_broadcast_schema) + _validate_template(broadcast_json) polygons = Polygons(list(chain.from_iterable(( area['polygons'] for area in broadcast_json['areas'] )))) - template = BroadcastMessageTemplate.from_content( - broadcast_json['content'] - ) - - if template.content_too_long: - raise ValidationError( - message=( - f'description must be {template.max_content_count:,.0f} ' - f'characters or fewer' - ) + ( - ' (because it could not be GSM7 encoded)' - if template.non_gsm_characters else '' - ), - status_code=400, - ) - broadcast_message = BroadcastMessage( service_id=authenticated_service.id, content=broadcast_json['content'], @@ -89,3 +74,21 @@ def create_broadcast(): ) return jsonify(broadcast_message.serialize()), 201 + + +def _validate_template(broadcast_json): + template = BroadcastMessageTemplate.from_content( + broadcast_json['content'] + ) + + if template.content_too_long: + raise ValidationError( + message=( + f'description must be {template.max_content_count:,.0f} ' + f'characters or fewer' + ) + ( + ' (because it could not be GSM7 encoded)' + if template.non_gsm_characters else '' + ), + status_code=400, + ) diff --git a/tests/app/v2/broadcast/sample_cap_xml_documents.py b/tests/app/v2/broadcast/sample_cap_xml_documents.py index a8a0b8cab..a17691e63 100644 --- a/tests/app/v2/broadcast/sample_cap_xml_documents.py +++ b/tests/app/v2/broadcast/sample_cap_xml_documents.py @@ -1,3 +1,5 @@ +import re + WAINFLEET = """ 50385fcb0ab7aa447bbd46d848ce8466E @@ -235,3 +237,4 @@ WITH_PLACEHOLDER_FOR_CONTENT = """ LONG_GSM7 = WITH_PLACEHOLDER_FOR_CONTENT.format('a' * 1396) LONG_UCS2 = WITH_PLACEHOLDER_FOR_CONTENT.format('ลต' * 616) +MISSING_AREA_NAMES = re.sub(".*", " ", WAINFLEET) diff --git a/tests/app/v2/broadcast/test_post_broadcast.py b/tests/app/v2/broadcast/test_post_broadcast.py index 6bca0991d..aa70ca2c7 100644 --- a/tests/app/v2/broadcast/test_post_broadcast.py +++ b/tests/app/v2/broadcast/test_post_broadcast.py @@ -28,7 +28,7 @@ def test_broadcast_for_service_without_permission_returns_400( ) -def test_valid_post_broadcast_returns_201( +def test_post_broadcast_non_cap_xml_returns_415( client, sample_broadcast_service, ): @@ -229,3 +229,24 @@ def test_content_too_long_returns_400( }], 'status_code': 400, } + + +def test_invalid_areas_returns_400( + client, + sample_broadcast_service +): + auth_header = create_service_authorization_header(service_id=sample_broadcast_service.id) + response = client.post( + path='/v2/broadcast', + data=sample_cap_xml_documents.MISSING_AREA_NAMES, + headers=[('Content-Type', 'application/cap+xml'), auth_header], + ) + + assert json.loads(response.get_data(as_text=True)) == { + 'errors': [{ + 'error': 'ValidationError', + # the blank spaces represent the blank areaDesc in the XML + 'message': 'areas does not match ([a-zA-Z1-9]+ )*[a-zA-Z1-9]+', + }], + 'status_code': 400, + }