mirror of
https://github.com/GSA/notifications-api.git
synced 2025-12-18 08:02:31 -05:00
@@ -94,7 +94,6 @@ def register_blueprint(application):
|
|||||||
from app.inbound_number.rest import inbound_number_blueprint
|
from app.inbound_number.rest import inbound_number_blueprint
|
||||||
from app.inbound_sms.rest import inbound_sms as inbound_sms_blueprint
|
from app.inbound_sms.rest import inbound_sms as inbound_sms_blueprint
|
||||||
from app.notifications.receive_notifications import receive_notifications_blueprint
|
from app.notifications.receive_notifications import receive_notifications_blueprint
|
||||||
from app.notifications.notifications_ses_callback import ses_callback_blueprint
|
|
||||||
from app.notifications.notifications_sms_callback import sms_callback_blueprint
|
from app.notifications.notifications_sms_callback import sms_callback_blueprint
|
||||||
from app.notifications.notifications_letter_callback import letter_callback_blueprint
|
from app.notifications.notifications_letter_callback import letter_callback_blueprint
|
||||||
from app.authentication.auth import requires_admin_auth, requires_auth, requires_no_auth, restrict_ip_sms
|
from app.authentication.auth import requires_admin_auth, requires_auth, requires_no_auth, restrict_ip_sms
|
||||||
@@ -113,9 +112,6 @@ def register_blueprint(application):
|
|||||||
status_blueprint.before_request(requires_no_auth)
|
status_blueprint.before_request(requires_no_auth)
|
||||||
application.register_blueprint(status_blueprint)
|
application.register_blueprint(status_blueprint)
|
||||||
|
|
||||||
ses_callback_blueprint.before_request(requires_no_auth)
|
|
||||||
application.register_blueprint(ses_callback_blueprint)
|
|
||||||
|
|
||||||
# delivery receipts
|
# delivery receipts
|
||||||
# TODO: make sure research mode can still trigger sms callbacks, then re-enable this
|
# TODO: make sure research mode can still trigger sms callbacks, then re-enable this
|
||||||
# sms_callback_blueprint.before_request(restrict_ip_sms)
|
# sms_callback_blueprint.before_request(restrict_ip_sms)
|
||||||
|
|||||||
@@ -46,12 +46,12 @@ def register_errors(blueprint):
|
|||||||
return jsonify(result='error', message=error.message), error.code
|
return jsonify(result='error', message=error.message), error.code
|
||||||
|
|
||||||
@blueprint.errorhandler(ValidationError)
|
@blueprint.errorhandler(ValidationError)
|
||||||
def validation_error(error):
|
def marshmallow_validation_error(error):
|
||||||
current_app.logger.error(error)
|
current_app.logger.error(error)
|
||||||
return jsonify(result='error', message=error.messages), 400
|
return jsonify(result='error', message=error.messages), 400
|
||||||
|
|
||||||
@blueprint.errorhandler(JsonSchemaValidationError)
|
@blueprint.errorhandler(JsonSchemaValidationError)
|
||||||
def validation_error(error):
|
def jsonschema_validation_error(error):
|
||||||
current_app.logger.exception(error)
|
current_app.logger.exception(error)
|
||||||
return jsonify(json.loads(error.message)), 400
|
return jsonify(json.loads(error.message)), 400
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from flask import (
|
from flask import (
|
||||||
Blueprint,
|
|
||||||
jsonify,
|
|
||||||
request,
|
|
||||||
current_app,
|
current_app,
|
||||||
json
|
json
|
||||||
)
|
)
|
||||||
@@ -16,35 +13,10 @@ from app.dao import (
|
|||||||
from app.celery.statistics_tasks import create_outcome_notification_statistic_tasks
|
from app.celery.statistics_tasks import create_outcome_notification_statistic_tasks
|
||||||
from app.notifications.process_client_response import validate_callback_data
|
from app.notifications.process_client_response import validate_callback_data
|
||||||
|
|
||||||
ses_callback_blueprint = Blueprint('notifications_ses_callback', __name__)
|
|
||||||
|
|
||||||
from app.errors import (
|
|
||||||
register_errors,
|
|
||||||
InvalidRequest
|
|
||||||
)
|
|
||||||
register_errors(ses_callback_blueprint)
|
|
||||||
|
|
||||||
|
|
||||||
@ses_callback_blueprint.route('/notifications/email/ses', methods=['POST'])
|
|
||||||
def sns_callback_handler():
|
|
||||||
errors = process_ses_response(json.loads(request.data))
|
|
||||||
if errors:
|
|
||||||
current_app.logger.error(errors)
|
|
||||||
raise InvalidRequest(errors, 400)
|
|
||||||
|
|
||||||
return jsonify(
|
|
||||||
result="success", message="SES callback succeeded"
|
|
||||||
), 200
|
|
||||||
|
|
||||||
|
|
||||||
def process_ses_response(ses_request):
|
def process_ses_response(ses_request):
|
||||||
client_name = 'SES'
|
client_name = 'SES'
|
||||||
try:
|
try:
|
||||||
|
|
||||||
# TODO: remove this check once the sns_callback_handler is removed
|
|
||||||
if not isinstance(ses_request, dict):
|
|
||||||
ses_request = json.loads(ses_request)
|
|
||||||
|
|
||||||
errors = validate_callback_data(data=ses_request, fields=['Message'], client_name=client_name)
|
errors = validate_callback_data(data=ses_request, fields=['Message'], client_name=client_name)
|
||||||
if errors:
|
if errors:
|
||||||
return errors
|
return errors
|
||||||
@@ -56,6 +28,7 @@ def process_ses_response(ses_request):
|
|||||||
|
|
||||||
notification_type = ses_message['notificationType']
|
notification_type = ses_message['notificationType']
|
||||||
if notification_type == 'Bounce':
|
if notification_type == 'Bounce':
|
||||||
|
current_app.logger.info('SES bounce dict: {}'.format(ses_message['bounce']))
|
||||||
if ses_message['bounce']['bounceType'] == 'Permanent':
|
if ses_message['bounce']['bounceType'] == 'Permanent':
|
||||||
notification_type = ses_message['bounce']['bounceType'] # permanent or not
|
notification_type = ses_message['bounce']['bounceType'] # permanent or not
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -10,24 +10,6 @@ from app.notifications.notifications_ses_callback import process_ses_response
|
|||||||
from tests.app.conftest import sample_notification as create_sample_notification
|
from tests.app.conftest import sample_notification as create_sample_notification
|
||||||
|
|
||||||
|
|
||||||
def test_ses_callback_should_not_need_auth(client):
|
|
||||||
response = client.post(
|
|
||||||
path='/notifications/email/ses',
|
|
||||||
data=ses_notification_callback(),
|
|
||||||
headers=[('Content-Type', 'text/plain; charset=UTF-8')]
|
|
||||||
)
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
def test_ses_callback_should_fail_if_invalid_json(client, mocker):
|
|
||||||
stats_mock = mocker.patch(
|
|
||||||
'app.notifications.notifications_ses_callback.create_outcome_notification_statistic_tasks'
|
|
||||||
)
|
|
||||||
errors = process_ses_response('nonsense')
|
|
||||||
assert errors == 'SES callback failed: invalid json'
|
|
||||||
stats_mock.assert_not_called()
|
|
||||||
|
|
||||||
|
|
||||||
def test_ses_callback_should_fail_if_invalid_notification_type(client, mocker):
|
def test_ses_callback_should_fail_if_invalid_notification_type(client, mocker):
|
||||||
stats_mock = mocker.patch(
|
stats_mock = mocker.patch(
|
||||||
'app.notifications.notifications_ses_callback.create_outcome_notification_statistic_tasks'
|
'app.notifications.notifications_ses_callback.create_outcome_notification_statistic_tasks'
|
||||||
|
|||||||
Reference in New Issue
Block a user