diff --git a/app/celery/process_sms_client_response_tasks.py b/app/celery/process_sms_client_response_tasks.py index 2a1cc4dd4..aff0aad15 100644 --- a/app/celery/process_sms_client_response_tasks.py +++ b/app/celery/process_sms_client_response_tasks.py @@ -1,88 +1,80 @@ -import uuid -from datetime import datetime - -from flask import current_app -from notifications_utils.template import SMSMessageTemplate - -from app import notify_celery, statsd_client -from app.celery.process_ses_receipts_tasks import check_and_queue_callback_task -from app.clients import ClientException -from app.dao import notifications_dao -from app.dao.templates_dao import dao_get_template_by_id -from app.models import NOTIFICATION_PENDING +from app import notify_celery sms_response_mapper = { # 'SNS': get_sns_responses, } -# gUpdate with new providers") +# this is used by notifications_sms_callback and needs to be heavily changed for SNS +# leaving for now as an example of what MMG did and what we may want to replicate in the eventual +# SNS method @notify_celery.task(bind=True, name="process-sms-client-response", max_retries=5, default_retry_delay=300) def process_sms_client_response(self, status, provider_reference, client_name, detailed_status_code=None): - # validate reference - try: - uuid.UUID(provider_reference, version=4) - except ValueError as e: - current_app.logger.exception(f'{client_name} callback with invalid reference {provider_reference}') - raise e + raise Exception("process_sms_client_response not implemented") +# # validate reference +# try: +# uuid.UUID(provider_reference, version=4) +# except ValueError as e: +# current_app.logger.exception(f'{client_name} callback with invalid reference {provider_reference}') +# raise e - response_parser = sms_response_mapper[client_name] +# response_parser = sms_response_mapper[client_name] - # validate status - try: - notification_status, detailed_status = response_parser(status, detailed_status_code) - current_app.logger.info( - f'{client_name} callback returned status of {notification_status}' - f'({status}): {detailed_status}({detailed_status_code}) for reference: {provider_reference}' - ) - except KeyError: - _process_for_status( - notification_status='technical-failure', - client_name=client_name, - provider_reference=provider_reference - ) - raise ClientException(f'{client_name} callback failed: status {status} not found.') +# # validate status +# try: +# notification_status, detailed_status = response_parser(status, detailed_status_code) +# current_app.logger.info( +# f'{client_name} callback returned status of {notification_status}' +# f'({status}): {detailed_status}({detailed_status_code}) for reference: {provider_reference}' +# ) +# except KeyError: +# _process_for_status( +# notification_status='technical-failure', +# client_name=client_name, +# provider_reference=provider_reference +# ) +# raise ClientException(f'{client_name} callback failed: status {status} not found.') - _process_for_status( - notification_status=notification_status, - client_name=client_name, - provider_reference=provider_reference, - detailed_status_code=detailed_status_code - ) +# _process_for_status( +# notification_status=notification_status, +# client_name=client_name, +# provider_reference=provider_reference, +# detailed_status_code=detailed_status_code +# ) -def _process_for_status(notification_status, client_name, provider_reference, detailed_status_code=None): - # record stats - notification = notifications_dao.update_notification_status_by_id( - notification_id=provider_reference, - status=notification_status, - sent_by=client_name.lower(), - detailed_status_code=detailed_status_code - ) - if not notification: - return +# def _process_for_status(notification_status, client_name, provider_reference, detailed_status_code=None): +# # record stats +# notification = notifications_dao.update_notification_status_by_id( +# notification_id=provider_reference, +# status=notification_status, +# sent_by=client_name.lower(), +# detailed_status_code=detailed_status_code +# ) +# if not notification: +# return - statsd_client.incr('callback.{}.{}'.format(client_name.lower(), notification_status)) +# statsd_client.incr('callback.{}.{}'.format(client_name.lower(), notification_status)) - if notification.sent_at: - statsd_client.timing_with_dates( - f'callback.{client_name.lower()}.{notification_status}.elapsed-time', - datetime.utcnow(), - notification.sent_at - ) +# if notification.sent_at: +# statsd_client.timing_with_dates( +# f'callback.{client_name.lower()}.{notification_status}.elapsed-time', +# datetime.utcnow(), +# notification.sent_at +# ) - if notification.billable_units == 0: - service = notification.service - template_model = dao_get_template_by_id(notification.template_id, notification.template_version) +# if notification.billable_units == 0: +# service = notification.service +# template_model = dao_get_template_by_id(notification.template_id, notification.template_version) - template = SMSMessageTemplate( - template_model.__dict__, - values=notification.personalisation, - prefix=service.name, - show_prefix=service.prefix_sms, - ) - notification.billable_units = template.fragment_count - notifications_dao.dao_update_notification(notification) +# template = SMSMessageTemplate( +# template_model.__dict__, +# values=notification.personalisation, +# prefix=service.name, +# show_prefix=service.prefix_sms, +# ) +# notification.billable_units = template.fragment_count +# notifications_dao.dao_update_notification(notification) - if notification_status != NOTIFICATION_PENDING: - check_and_queue_callback_task(notification) +# if notification_status != NOTIFICATION_PENDING: +# check_and_queue_callback_task(notification) diff --git a/app/notifications/notifications_sms_callback.py b/app/notifications/notifications_sms_callback.py index 4448191d2..87fb99c3d 100644 --- a/app/notifications/notifications_sms_callback.py +++ b/app/notifications/notifications_sms_callback.py @@ -6,6 +6,9 @@ sms_callback_blueprint = Blueprint("sms_callback", __name__, url_prefix="/notifi register_errors(sms_callback_blueprint) # TODO SNS SMS delivery receipts delivered here +# This file should likely be deleted, since SNS does not use callback https calls +# Leaving for now to have an example of what jobs MMG did that we may want to replicate in the +# eventual SNS method. # @sms_callback_blueprint.route('/mmg', methods=['POST']) # def process_mmg_response(): @@ -30,27 +33,6 @@ register_errors(sms_callback_blueprint) # return jsonify(result='success'), 200 -# @sms_callback_blueprint.route('/firetext', methods=['POST']) -# def process_firetext_response(): -# client_name = 'Firetext' -# errors = validate_callback_data(data=request.form, -# fields=['status', 'reference'], -# client_name=client_name) -# if errors: -# raise InvalidRequest(errors, status_code=400) - -# status = request.form.get('status') -# detailed_status_code = request.form.get('code') -# provider_reference = request.form.get('reference') - -# process_sms_client_response.apply_async( -# [status, provider_reference, client_name, detailed_status_code], -# queue=QueueNames.SMS_CALLBACKS, -# ) - -# return jsonify(result='success'), 200 - - def validate_callback_data(data, fields, client_name): errors = [] for f in fields: diff --git a/tests/app/notifications/test_notifications_sms_callbacks.py b/tests/app/notifications/test_notifications_sms_callbacks.py index 523e7e584..773aba892 100644 --- a/tests/app/notifications/test_notifications_sms_callbacks.py +++ b/tests/app/notifications/test_notifications_sms_callbacks.py @@ -4,13 +4,6 @@ from flask import json from app.notifications.notifications_sms_callback import validate_callback_data -def firetext_post(client, data): - return client.post( - path='/notifications/sms/firetext', - data=data, - headers=[('Content-Type', 'application/x-www-form-urlencoded')]) - - def mmg_post(client, data): return client.post( path='/notifications/sms/mmg', @@ -18,80 +11,6 @@ def mmg_post(client, data): headers=[('Content-Type', 'application/json')]) -@pytest.mark.skip(reason="Needs updating for TTS: Firetext removal") -def test_firetext_callback_should_not_need_auth(client, mocker): - mocker.patch('app.notifications.notifications_sms_callback.process_sms_client_response') - data = 'mobile=441234123123&status=0&reference=notification_id&time=2016-03-10 14:17:00' - - response = firetext_post(client, data) - assert response.status_code == 200 - - -@pytest.mark.skip(reason="Needs updating for TTS: Firetext removal") -def test_firetext_callback_should_return_400_if_empty_reference(client, mocker): - data = 'mobile=441234123123&status=0&reference=&time=2016-03-10 14:17:00' - response = firetext_post(client, data) - - json_resp = json.loads(response.get_data(as_text=True)) - assert response.status_code == 400 - assert json_resp['result'] == 'error' - assert json_resp['message'] == ['Firetext callback failed: reference missing'] - - -@pytest.mark.skip(reason="Needs updating for TTS: Firetext removal") -def test_firetext_callback_should_return_400_if_no_reference(client, mocker): - data = 'mobile=441234123123&status=0&time=2016-03-10 14:17:00' - response = firetext_post(client, data) - json_resp = json.loads(response.get_data(as_text=True)) - assert response.status_code == 400 - assert json_resp['result'] == 'error' - assert json_resp['message'] == ['Firetext callback failed: reference missing'] - - -@pytest.mark.skip(reason="Needs updating for TTS: Firetext removal") -def test_firetext_callback_should_return_400_if_no_status(client, mocker): - data = 'mobile=441234123123&time=2016-03-10 14:17:00&reference=notification_id' - response = firetext_post(client, data) - json_resp = json.loads(response.get_data(as_text=True)) - assert response.status_code == 400 - assert json_resp['result'] == 'error' - assert json_resp['message'] == ['Firetext callback failed: status missing'] - - -@pytest.mark.skip(reason="Needs updating for TTS: Firetext removal") -def test_firetext_callback_should_return_200_and_call_task_with_valid_data(client, mocker): - mock_celery = mocker.patch( - 'app.notifications.notifications_sms_callback.process_sms_client_response.apply_async') - - data = 'mobile=441234123123&status=0&time=2016-03-10 14:17:00&reference=notification_id' - response = firetext_post(client, data) - json_resp = json.loads(response.get_data(as_text=True)) - assert response.status_code == 200 - assert json_resp['result'] == 'success' - - mock_celery.assert_called_once_with( - ['0', 'notification_id', 'Firetext', None], - queue='sms-callbacks', - ) - - -@pytest.mark.skip(reason="Needs updating for TTS: Firetext removal") -def test_firetext_callback_including_a_code_should_return_200_and_call_task_with_valid_data(client, mocker): - mock_celery = mocker.patch( - 'app.notifications.notifications_sms_callback.process_sms_client_response.apply_async') - - data = 'mobile=441234123123&status=1&code=101&time=2016-03-10 14:17:00&reference=notification_id' - response = firetext_post(client, data) - json_resp = json.loads(response.get_data(as_text=True)) - assert response.status_code == 200 - assert json_resp['result'] == 'success' - - mock_celery.assert_called_once_with( - ['1', 'notification_id', 'Firetext', '101'], - queue='sms-callbacks', - ) - - @pytest.mark.skip(reason="Needs updating for TTS: MMG removal") def test_mmg_callback_should_not_need_auth(client, mocker, sample_notification): mocker.patch('app.notifications.notifications_sms_callback.process_sms_client_response') diff --git a/tests/app/notifications/test_receive_notification.py b/tests/app/notifications/test_receive_notification.py index 61a967d58..90ddbd6a5 100644 --- a/tests/app/notifications/test_receive_notification.py +++ b/tests/app/notifications/test_receive_notification.py @@ -262,7 +262,7 @@ def test_strip_leading_country_code(number, expected): ["", [], 401], ["testkey", [], 403], ]) -def test_mmg_inbound_sms_auth(notify_db_session, notify_api, client, mocker, auth, keys, status_code): +def test_sns_inbound_sms_auth(notify_db_session, notify_api, client, mocker, auth, keys, status_code): mocker.patch("app.notifications.receive_notifications.tasks.send_inbound_sms_to_service.apply_async") create_service_with_inbound_number(