diff --git a/app/notifications/rest.py b/app/notifications/rest.py index 5c7fba5d3..b4984bc2c 100644 --- a/app/notifications/rest.py +++ b/app/notifications/rest.py @@ -16,7 +16,7 @@ from app.errors import ( InvalidRequest ) from app.models import KEY_TYPE_TEAM, PRIORITY -from app.models import INTERNATIONAL_SMS_TYPE, SMS_TYPE +from app.models import INTERNATIONAL_SMS_TYPE, SMS_TYPE, INBOUND_SMS_TYPE, EMAIL_TYPE from app.notifications.process_notifications import ( persist_notification, send_notification_to_queue, @@ -119,7 +119,11 @@ def send_notification(notification_type): _service_allowed_to_send_to(notification_form, authenticated_service) if notification_type == SMS_TYPE: + _service_has_permission(authenticated_service, SMS_TYPE) _service_can_send_internationally(authenticated_service, notification_form['to']) + elif notification_type == EMAIL_TYPE: + print('email') + _service_has_permission(authenticated_service, EMAIL_TYPE) # Do not persist or send notification to the queue if it is a simulated recipient simulated = simulated_recipient(notification_form['to'], notification_type) @@ -162,6 +166,22 @@ def get_notification_return_data(notification_id, notification, template): return output +def _service_has_permission(service, notify_type): + print(service.permissions) + if notify_type not in [p.permission for p in service.permissions]: + notify_type_text = notify_type + 's' + action = 'send' + if notify_type == SMS_TYPE or notify_type == INBOUND_SMS_TYPE: + notify_type_text = 'text messages' + if notify_type == INBOUND_SMS_TYPE: + action = 'receive' + + raise InvalidRequest( + {'to': ["Cannot {action} {type}".format(action=action, type=notify_type_text)]}, + status_code=400 + ) + + def _service_can_send_internationally(service, number): international_phone_info = get_international_phone_info(number) diff --git a/tests/app/conftest.py b/tests/app/conftest.py index d3d1a650c..8ac5f13db 100644 --- a/tests/app/conftest.py +++ b/tests/app/conftest.py @@ -163,12 +163,13 @@ def sample_template( user=None, service=None, created_by=None, - process_type='normal' + process_type='normal', + permissions=[EMAIL_TYPE, SMS_TYPE] ): if user is None: user = create_user() if service is None: - service = sample_service(notify_db, notify_db_session) + service = sample_service(notify_db, notify_db_session, permissions=permissions) if created_by is None: created_by = create_user() @@ -190,6 +191,11 @@ def sample_template( return template +@pytest.fixture(scope='function') +def sample_template_without_sms_permission(notify_db, notify_db_session): + return sample_template(notify_db, notify_db_session, permissions=[EMAIL_TYPE]) + + @pytest.fixture(scope='function') def sample_template_with_placeholders(notify_db, notify_db_session): # deliberate space and title case in placeholder @@ -213,11 +219,12 @@ def sample_email_template( user=None, content="This is a template", subject_line='Email Subject', - service=None): + service=None, + permissions=[EMAIL_TYPE, SMS_TYPE]): if user is None: user = create_user() if service is None: - service = sample_service(notify_db, notify_db_session) + service = sample_service(notify_db, notify_db_session, permissions=permissions) data = { 'name': template_name, 'template_type': template_type, @@ -231,6 +238,11 @@ def sample_email_template( return template +@pytest.fixture(scope='function') +def sample_template_without_email_permission(notify_db, notify_db_session): + return sample_email_template(notify_db, notify_db_session, permissions=[SMS_TYPE]) + + @pytest.fixture def sample_letter_template(sample_service): return create_template(sample_service, template_type=LETTER_TYPE) diff --git a/tests/app/notifications/rest/test_send_notification.py b/tests/app/notifications/rest/test_send_notification.py index 89df8c76b..4a1da98ab 100644 --- a/tests/app/notifications/rest/test_send_notification.py +++ b/tests/app/notifications/rest/test_send_notification.py @@ -23,7 +23,9 @@ from tests.app.conftest import ( sample_template as create_sample_template, sample_service_whitelist as create_sample_service_whitelist, sample_api_key as create_sample_api_key, - sample_service) + sample_service, + sample_template_without_sms_permission, + sample_template_without_email_permission) from app.models import Template from app.errors import InvalidRequest @@ -1164,3 +1166,34 @@ def test_should_allow_international_number_on_sms_notification(client, notify_db headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 201 + + +@pytest.mark.parametrize( + 'template_factory, to, expected_error', [ + (sample_template_without_sms_permission, '+447700900986', 'Cannot send text messages'), + (sample_template_without_email_permission, 'notify@digital.cabinet-office.gov.uk', 'Cannot send emails') + ]) +def test_should_not_allow_notification_if_service_permission_not_set( + client, notify_db, notify_db_session, mocker, template_factory, to, expected_error): + template_without_permission = template_factory(notify_db, notify_db_session) + mocked = mocker.patch( + 'app.celery.provider_tasks.deliver_{}.apply_async'.format(template_without_permission.template_type)) + + data = { + 'to': to, + 'template': str(template_without_permission.id) + } + + auth_header = create_authorization_header(service_id=template_without_permission.service_id) + + response = client.post( + path='/notifications/{}'.format(template_without_permission.template_type), + data=json.dumps(data), + headers=[('Content-Type', 'application/json'), auth_header]) + + assert not mocked.called + assert response.status_code == 400 + error_json = json.loads(response.get_data(as_text=True)) + + assert error_json['result'] == 'error' + assert error_json['message']['to'][0] == expected_error diff --git a/tests/app/service/test_rest.py b/tests/app/service/test_rest.py index 6dc8ccd45..0eea25672 100644 --- a/tests/app/service/test_rest.py +++ b/tests/app/service/test_rest.py @@ -523,7 +523,7 @@ def test_update_service_flags_will_remove_service_permissions(client, notify_db, service = create_service( notify_db, notify_db_session, permissions=[SMS_TYPE, EMAIL_TYPE, INTERNATIONAL_SMS_TYPE]) - assert INTERNATIONAL_SMS_TYPE in service.permissions + assert INTERNATIONAL_SMS_TYPE in [p.permission for p in service.permissions] data = { 'permissions': [SMS_TYPE, EMAIL_TYPE]