diff --git a/app/notifications/notifications_letter_callback.py b/app/notifications/notifications_letter_callback.py index f7c357055..3b4a0fbb3 100644 --- a/app/notifications/notifications_letter_callback.py +++ b/app/notifications/notifications_letter_callback.py @@ -9,6 +9,7 @@ from flask import ( ) from app import statsd_client +from app.celery.tasks import update_letter_notifications_statuses from app.clients.email.aws_ses import get_aws_responses from app.dao import ( notifications_dao @@ -29,11 +30,18 @@ register_errors(letter_callback_blueprint) @letter_callback_blueprint.route('/notifications/letter/dvla', methods=['POST']) def process_letter_response(): try: - dvla_request = json.loads(request.data) - current_app.logger.info(dvla_request) + req_json = json.loads(request.data) + # The callback should have one record for an S3 Put Event. + filename = req_json['Message']['Records'][0]['s3']['object']['key'] + + except (ValueError, KeyError): + error = "DVLA callback failed: Invalid JSON" + raise InvalidRequest(error, status_code=400) + + else: + current_app.logger.info('DVLA callback: Calling task to update letter notifications') + update_letter_notifications_statuses.apply_async([filename], queue='notify') + return jsonify( result="success", message="DVLA callback succeeded" ), 200 - except ValueError: - error = "DVLA callback failed: invalid json" - raise InvalidRequest(error, status_code=400) diff --git a/tests/app/notifications/rest/test_callbacks.py b/tests/app/notifications/rest/test_callbacks.py index 780076b34..0dd070271 100644 --- a/tests/app/notifications/rest/test_callbacks.py +++ b/tests/app/notifications/rest/test_callbacks.py @@ -1,3 +1,4 @@ +import pytest import uuid from datetime import datetime @@ -6,6 +7,7 @@ from flask import json from freezegun import freeze_time import app.celery.tasks +from app.errors import InvalidRequest from app.dao.notifications_dao import ( get_notification_by_id ) @@ -13,16 +15,47 @@ from app.models import NotificationStatistics from tests.app.conftest import sample_notification as create_sample_notification -def test_dvla_callback_should_not_need_auth(client): - data = json.dumps({"somekey": "somevalue"}) +def test_dvla_callback_returns_400_with_invalid_request(client): + data = json.dumps({"foo": "bar"}) response = client.post( path='/notifications/letter/dvla', data=data, - headers=[('Content-Type', 'application/json')]) + headers=[('Content-Type', 'application/json')] + ) + json_resp = json.loads(response.get_data(as_text=True)) + + assert response.status_code == 400 + assert json_resp['result'] == 'error' + assert json_resp['message'] == 'DVLA callback failed: Invalid JSON' + + +def test_dvla_callback_returns_200_with_valid_request(client): + data = _sample_sns_s3_callback() + response = client.post( + path='/notifications/letter/dvla', + data=data, + headers=[('Content-Type', 'application/json')] + ) + json_resp = json.loads(response.get_data(as_text=True)) assert response.status_code == 200 +def test_dvla_callback_calls_update_letter_notifications_task(client, mocker): + update_notifications_mock = \ + mocker.patch('app.notifications.notifications_letter_callback.update_letter_notifications_statuses') + data = _sample_sns_s3_callback() + response = client.post( + path='/notifications/letter/dvla', + data=data, + headers=[('Content-Type', 'application/json')] + ) + json_resp = json.loads(response.get_data(as_text=True)) + + assert response.status_code == 200 + assert update_notifications_mock.apply_async.called is True + + def test_firetext_callback_should_not_need_auth(client, mocker): mocker.patch('app.statsd_client.incr') response = client.post( @@ -458,3 +491,46 @@ def test_firetext_callback_should_record_statsd(client, notify_db, notify_db_ses def get_notification_stats(service_id): return NotificationStatistics.query.filter_by(service_id=service_id).one() + + +def _sample_sns_s3_callback(): + return json.dumps({ + "SigningCertURL": "foo.pem", + "UnsubscribeURL": "bar", + "Signature": "some-signature", + "Type": "Notification", + "Timestamp": "2016-05-03T08:35:12.884Z", + "SignatureVersion": "1", + "MessageId": "6adbfe0a-d610-509a-9c47-af894e90d32d", + "Subject": "Amazon S3 Notification", + "TopicArn": "sample-topic-arn", + "Message": { + "Records": [{ + "eventVersion": "2.0", + "eventSource": "aws:s3", + "awsRegion": "eu-west-1", + "eventTime": "2017-05-03T08:35:12.826Z", + "eventName": "ObjectCreated:Put", + "userIdentity": {"principalId": "some-p-id"}, + "requestParameters": {"sourceIPAddress": "8.8.8.8"}, + "responseElements": {"x-amz-request-id": "some-req-id", "x-amz-id-2": "some-amz-id"}, + "s3": { + "s3SchemaVersion": "1.0", + "configurationId": "some-config-id", + "bucket": { + "name": "some-bucket", + "ownerIdentity": {"principalId": "some-p-id"}, + "arn": "some-bucket-arn" + }, + "object": { + "key": "bar.txt", + "size": 200, + "eTag": "some-etag", + "versionId": "some-v-id", + "sequencer": "some-seq" + } + } + } + ] + } + })