mirror of
https://github.com/GSA/notifications-api.git
synced 2026-02-03 01:41:05 -05:00
Merge pull request #3461 from alphagov/be-more-robust-around-references-to-cancel
Be more robust in handling ambiguous references to cancel an alert
This commit is contained in:
@@ -26,6 +26,10 @@ def dao_get_broadcast_message_by_id_and_service_id(broadcast_message_id, service
|
||||
|
||||
def dao_get_broadcast_message_by_references_and_service_id(references_to_original_broadcast, service_id):
|
||||
return BroadcastMessage.query.filter(
|
||||
BroadcastMessage.status.in_((
|
||||
BroadcastStatusType.PENDING_APPROVAL,
|
||||
BroadcastStatusType.BROADCASTING,
|
||||
)),
|
||||
BroadcastMessage.reference.in_(references_to_original_broadcast),
|
||||
BroadcastMessage.service_id == service_id
|
||||
).one()
|
||||
|
||||
@@ -3,6 +3,7 @@ from itertools import chain
|
||||
from flask import current_app, jsonify, request
|
||||
from notifications_utils.polygons import Polygons
|
||||
from notifications_utils.template import BroadcastMessageTemplate
|
||||
from sqlalchemy.orm.exc import MultipleResultsFound
|
||||
|
||||
from app import api_user, authenticated_service
|
||||
from app.broadcast_message.translators import cap_xml_to_dict
|
||||
@@ -105,10 +106,17 @@ def create_broadcast():
|
||||
|
||||
|
||||
def _cancel_or_reject_broadcast(references_to_original_broadcast, service_id):
|
||||
broadcast_message = dao_get_broadcast_message_by_references_and_service_id(
|
||||
references_to_original_broadcast,
|
||||
service_id
|
||||
)
|
||||
try:
|
||||
broadcast_message = dao_get_broadcast_message_by_references_and_service_id(
|
||||
references_to_original_broadcast,
|
||||
service_id
|
||||
)
|
||||
except MultipleResultsFound:
|
||||
raise BadRequestError(
|
||||
message='Multiple alerts found - unclear which one to cancel',
|
||||
status_code=400,
|
||||
)
|
||||
|
||||
if broadcast_message.status == BroadcastStatusType.PENDING_APPROVAL:
|
||||
new_status = BroadcastStatusType.REJECTED
|
||||
else:
|
||||
|
||||
@@ -79,6 +79,15 @@ WAINFLEET_CANCEL_WITH_EMPTY_REFERENCES = WAINFLEET_CANCEL.format(
|
||||
"<references></references>"
|
||||
)
|
||||
|
||||
WAINFLEET_CANCEL_WITH_WINDMERE_REFERENCES = WAINFLEET_CANCEL.format(
|
||||
"<references>"
|
||||
# Wainfleet
|
||||
"www.gov.uk/environment-agency,50385fcb0ab7aa447bbd46d848ce8466E,2020-02-16T23:01:13-00:00,"
|
||||
# Windemere
|
||||
"www.gov.uk/environment-agency,4f6d28b10ab7aa447bbd46d85f1e9effE,2020-02-16T19:20:03+00:00"
|
||||
"</references>"
|
||||
)
|
||||
|
||||
UPDATE = """
|
||||
<alert xmlns="urn:oasis:names:tc:emergency:cap:1.2">
|
||||
<identifier>PAAQ-4-mg5a94</identifier>
|
||||
|
||||
@@ -220,6 +220,38 @@ def test_cancel_request_does_not_cancel_broadcast_if_reference_does_not_match(
|
||||
assert response_for_cancel_json["errors"] == expected_error
|
||||
|
||||
|
||||
def test_cancel_raises_error_if_multiple_broadcasts_referenced(
|
||||
client,
|
||||
sample_broadcast_service,
|
||||
):
|
||||
auth_header = create_service_authorization_header(service_id=sample_broadcast_service.id)
|
||||
|
||||
for cap_document in (
|
||||
sample_cap_xml_documents.WAINFLEET,
|
||||
sample_cap_xml_documents.WINDEMERE,
|
||||
):
|
||||
response_for_create = client.post(
|
||||
path='/v2/broadcast',
|
||||
data=cap_document,
|
||||
headers=[('Content-Type', 'application/cap+xml'), auth_header],
|
||||
)
|
||||
assert response_for_create.status_code == 201
|
||||
|
||||
# try to cancel two broadcasts with one request
|
||||
response_for_cancel = client.post(
|
||||
path='/v2/broadcast',
|
||||
data=sample_cap_xml_documents.WAINFLEET_CANCEL_WITH_WINDMERE_REFERENCES,
|
||||
headers=[('Content-Type', 'application/cap+xml'), auth_header],
|
||||
)
|
||||
response_for_cancel_json = json.loads(response_for_cancel.get_data(as_text=True))
|
||||
|
||||
assert response_for_cancel.status_code == 400
|
||||
assert response_for_cancel_json["errors"] == [{
|
||||
'error': 'BadRequestError',
|
||||
'message': 'Multiple alerts found - unclear which one to cancel',
|
||||
}]
|
||||
|
||||
|
||||
def test_cancel_request_does_not_cancel_broadcast_if_service_id_does_not_match(
|
||||
client,
|
||||
sample_broadcast_service,
|
||||
@@ -253,6 +285,56 @@ def test_cancel_request_does_not_cancel_broadcast_if_service_id_does_not_match(
|
||||
assert response_for_cancel.status_code == 404
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_approved, expected_cancel_tasks", (
|
||||
(True, 1),
|
||||
(False, 0),
|
||||
))
|
||||
def test_same_broadcast_cant_be_cancelled_twice(
|
||||
mocker,
|
||||
client,
|
||||
sample_broadcast_service,
|
||||
is_approved,
|
||||
expected_cancel_tasks,
|
||||
):
|
||||
mock_send_broadcast_event_task = mocker.patch(
|
||||
'app.celery.broadcast_message_tasks.send_broadcast_event.apply_async'
|
||||
)
|
||||
auth_header = create_service_authorization_header(service_id=sample_broadcast_service.id)
|
||||
|
||||
# create a broadcast
|
||||
response_for_create = client.post(
|
||||
path='/v2/broadcast',
|
||||
data=sample_cap_xml_documents.WAINFLEET,
|
||||
headers=[('Content-Type', 'application/cap+xml'), auth_header],
|
||||
)
|
||||
assert response_for_create.status_code == 201
|
||||
|
||||
response_json_for_create = json.loads(response_for_create.get_data(as_text=True))
|
||||
|
||||
broadcast_message = dao_get_broadcast_message_by_id_and_service_id(
|
||||
response_json_for_create["id"], response_json_for_create["service_id"]
|
||||
)
|
||||
# approve broadcast
|
||||
if is_approved:
|
||||
broadcast_message.status = 'broadcasting'
|
||||
|
||||
first_response_for_cancel = client.post(
|
||||
path='/v2/broadcast',
|
||||
data=sample_cap_xml_documents.WAINFLEET_CANCEL_WITH_REFERENCES,
|
||||
headers=[('Content-Type', 'application/cap+xml'), auth_header],
|
||||
)
|
||||
assert first_response_for_cancel.status_code == 201
|
||||
|
||||
second_response_for_cancel = client.post(
|
||||
path='/v2/broadcast',
|
||||
data=sample_cap_xml_documents.WAINFLEET_CANCEL_WITH_REFERENCES,
|
||||
headers=[('Content-Type', 'application/cap+xml'), auth_header],
|
||||
)
|
||||
assert second_response_for_cancel.status_code == 404
|
||||
|
||||
assert len(mock_send_broadcast_event_task.call_args_list) == expected_cancel_tasks
|
||||
|
||||
|
||||
def test_large_polygon_is_simplified(
|
||||
client,
|
||||
sample_broadcast_service,
|
||||
|
||||
Reference in New Issue
Block a user