mirror of
https://github.com/GSA/notifications-api.git
synced 2026-08-19 14:08:47 -04:00
Merge branch 'master' into rate-limit-api-calls
Conflicts: requirements.txt tests/app/notifications/rest/test_send_notification.py tests/app/notifications/test_validators.py tests/app/v2/notifications/test_post_notifications.py
This commit is contained in:
@@ -13,6 +13,16 @@ 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"})
|
||||
response = client.post(
|
||||
path='/notifications/letter/dvla',
|
||||
data=data,
|
||||
headers=[('Content-Type', 'application/json')])
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_firetext_callback_should_not_need_auth(client, mocker):
|
||||
mocker.patch('app.statsd_client.incr')
|
||||
response = client.post(
|
||||
|
||||
@@ -21,8 +21,8 @@ from tests.app.conftest import (
|
||||
sample_email_template as create_sample_email_template,
|
||||
sample_template as create_sample_template,
|
||||
sample_service_whitelist as create_sample_service_whitelist,
|
||||
sample_api_key as create_sample_api_key
|
||||
)
|
||||
sample_api_key as create_sample_api_key,
|
||||
sample_service)
|
||||
|
||||
from app.models import Template
|
||||
from app.errors import InvalidRequest
|
||||
@@ -1093,3 +1093,75 @@ def test_returns_a_429_limit_exceeded_if_rate_limit_exceeded(
|
||||
|
||||
assert not persist_mock.called
|
||||
assert not deliver_mock.called
|
||||
|
||||
|
||||
def test_should_allow_store_original_number_on_sms_notification(client, sample_template, mocker):
|
||||
mocked = mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
|
||||
mocker.patch('app.encryption.encrypt', return_value="something_encrypted")
|
||||
|
||||
data = {
|
||||
'to': '+(44) 7700-900 855',
|
||||
'template': str(sample_template.id)
|
||||
}
|
||||
|
||||
auth_header = create_authorization_header(service_id=sample_template.service_id)
|
||||
|
||||
response = client.post(
|
||||
path='/notifications/sms',
|
||||
data=json.dumps(data),
|
||||
headers=[('Content-Type', 'application/json'), auth_header])
|
||||
|
||||
response_data = json.loads(response.data)['data']
|
||||
notification_id = response_data['notification']['id']
|
||||
|
||||
mocked.assert_called_once_with([notification_id], queue='send-sms')
|
||||
assert response.status_code == 201
|
||||
assert notification_id
|
||||
notifications = Notification.query.all()
|
||||
assert len(notifications) == 1
|
||||
assert '+(44) 7700-900 855' == notifications[0].to
|
||||
|
||||
|
||||
def test_should_not_allow_international_number_on_sms_notification(client, sample_template, mocker):
|
||||
mocked = mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
|
||||
mocker.patch('app.encryption.encrypt', return_value="something_encrypted")
|
||||
|
||||
data = {
|
||||
'to': '20-12-1234-1234',
|
||||
'template': str(sample_template.id)
|
||||
}
|
||||
|
||||
auth_header = create_authorization_header(service_id=sample_template.service_id)
|
||||
|
||||
response = client.post(
|
||||
path='/notifications/sms',
|
||||
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] == 'Cannot send to international mobile numbers'
|
||||
|
||||
|
||||
def test_should_allow_international_number_on_sms_notification(client, notify_db, notify_db_session, mocker):
|
||||
mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
|
||||
mocker.patch('app.encryption.encrypt', return_value="something_encrypted")
|
||||
|
||||
service = sample_service(notify_db, notify_db_session, can_send_international_sms=True)
|
||||
template = create_sample_template(notify_db, notify_db_session, service=service)
|
||||
|
||||
data = {
|
||||
'to': '20-12-1234-1234',
|
||||
'template': str(template.id)
|
||||
}
|
||||
|
||||
auth_header = create_authorization_header(service_id=service.id)
|
||||
|
||||
response = client.post(
|
||||
path='/notifications/sms',
|
||||
data=json.dumps(data),
|
||||
headers=[('Content-Type', 'application/json'), auth_header])
|
||||
|
||||
assert response.status_code == 201
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import datetime
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
|
||||
from boto3.exceptions import Boto3Error
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from freezegun import freeze_time
|
||||
@@ -9,10 +9,13 @@ from collections import namedtuple
|
||||
|
||||
from app.models import Template, Notification, NotificationHistory
|
||||
from app.notifications import SendNotificationToQueueError
|
||||
from app.notifications.process_notifications import (create_content_for_notification,
|
||||
persist_notification,
|
||||
send_notification_to_queue,
|
||||
simulated_recipient)
|
||||
from app.notifications.process_notifications import (
|
||||
create_content_for_notification,
|
||||
persist_notification,
|
||||
send_notification_to_queue,
|
||||
simulated_recipient
|
||||
)
|
||||
from notifications_utils.recipients import validate_and_format_phone_number, validate_and_format_email_address
|
||||
from app.utils import cache_key_for_service_template_counter
|
||||
from app.v2.errors import BadRequestError
|
||||
from tests.app.conftest import sample_api_key as create_api_key
|
||||
@@ -169,18 +172,21 @@ def test_persist_notification_with_optionals(sample_job, sample_api_key, mocker)
|
||||
'app.notifications.process_notifications.redis_store.get_all_from_hash')
|
||||
n_id = uuid.uuid4()
|
||||
created_at = datetime.datetime(2016, 11, 11, 16, 8, 18)
|
||||
persist_notification(template_id=sample_job.template.id,
|
||||
template_version=sample_job.template.version,
|
||||
recipient='+447111111111',
|
||||
service=sample_job.service,
|
||||
personalisation=None, notification_type='sms',
|
||||
api_key_id=sample_api_key.id,
|
||||
key_type=sample_api_key.key_type,
|
||||
created_at=created_at,
|
||||
job_id=sample_job.id,
|
||||
job_row_number=10,
|
||||
client_reference="ref from client",
|
||||
notification_id=n_id)
|
||||
persist_notification(
|
||||
template_id=sample_job.template.id,
|
||||
template_version=sample_job.template.version,
|
||||
recipient='+447111111111',
|
||||
service=sample_job.service,
|
||||
personalisation=None,
|
||||
notification_type='sms',
|
||||
api_key_id=sample_api_key.id,
|
||||
key_type=sample_api_key.key_type,
|
||||
created_at=created_at,
|
||||
job_id=sample_job.id,
|
||||
job_row_number=10,
|
||||
client_reference="ref from client",
|
||||
notification_id=n_id
|
||||
)
|
||||
assert Notification.query.count() == 1
|
||||
assert NotificationHistory.query.count() == 1
|
||||
persisted_notification = Notification.query.all()[0]
|
||||
@@ -192,6 +198,9 @@ def test_persist_notification_with_optionals(sample_job, sample_api_key, mocker)
|
||||
mock_service_template_cache.assert_called_once_with(cache_key_for_service_template_counter(sample_job.service_id))
|
||||
assert persisted_notification.client_reference == "ref from client"
|
||||
assert persisted_notification.reference is None
|
||||
assert persisted_notification.international is False
|
||||
assert persisted_notification.phone_prefix == '44'
|
||||
assert persisted_notification.rate_multiplier == 1
|
||||
|
||||
|
||||
@freeze_time("2016-01-01 11:09:00.061258")
|
||||
@@ -255,22 +264,97 @@ def test_send_notification_to_queue_throws_exception_deletes_notification(sample
|
||||
assert NotificationHistory.query.count() == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize("to_address, notification_type, expected",
|
||||
[("+447700900000", "sms", True),
|
||||
("+447700900111", "sms", True),
|
||||
("+447700900222", "sms", True),
|
||||
("simulate-delivered@notifications.service.gov.uk", "email", True),
|
||||
("simulate-delivered-2@notifications.service.gov.uk", "email", True),
|
||||
("simulate-delivered-3@notifications.service.gov.uk", "email", True),
|
||||
("07515896969", "sms", False),
|
||||
("valid_email@test.com", "email", False)])
|
||||
@pytest.mark.parametrize("to_address, notification_type, expected", [
|
||||
("+447700900000", "sms", True),
|
||||
("+447700900111", "sms", True),
|
||||
("+447700900222", "sms", True),
|
||||
("07700900000", "sms", True),
|
||||
("7700900111", "sms", True),
|
||||
("simulate-delivered@notifications.service.gov.uk", "email", True),
|
||||
("simulate-delivered-2@notifications.service.gov.uk", "email", True),
|
||||
("simulate-delivered-3@notifications.service.gov.uk", "email", True),
|
||||
("07515896969", "sms", False),
|
||||
("valid_email@test.com", "email", False)
|
||||
])
|
||||
def test_simulated_recipient(notify_api, to_address, notification_type, expected):
|
||||
# The values where the expected = 'research-mode' are listed in the config['SIMULATED_EMAIL_ADDRESSES']
|
||||
# and config['SIMULATED_SMS_NUMBERS']. These values should result in using the research mode queue.
|
||||
# SIMULATED_EMAIL_ADDRESSES = ('simulate-delivered@notifications.service.gov.uk',
|
||||
# 'simulate-delivered-2@notifications.service.gov.uk',
|
||||
# 'simulate-delivered-2@notifications.service.gov.uk')
|
||||
# SIMULATED_SMS_NUMBERS = ('+447700900000', '+447700900111', '+447700900222')
|
||||
"""
|
||||
The values where the expected = 'research-mode' are listed in the config['SIMULATED_EMAIL_ADDRESSES']
|
||||
and config['SIMULATED_SMS_NUMBERS']. These values should result in using the research mode queue.
|
||||
SIMULATED_EMAIL_ADDRESSES = (
|
||||
'simulate-delivered@notifications.service.gov.uk',
|
||||
'simulate-delivered-2@notifications.service.gov.uk',
|
||||
'simulate-delivered-2@notifications.service.gov.uk'
|
||||
)
|
||||
SIMULATED_SMS_NUMBERS = ('+447700900000', '+447700900111', '+447700900222')
|
||||
"""
|
||||
formatted_address = None
|
||||
|
||||
actual = simulated_recipient(to_address, notification_type)
|
||||
assert actual == expected
|
||||
if notification_type == 'email':
|
||||
formatted_address = validate_and_format_email_address(to_address)
|
||||
else:
|
||||
formatted_address = validate_and_format_phone_number(to_address)
|
||||
|
||||
is_simulated_address = simulated_recipient(formatted_address, notification_type)
|
||||
|
||||
assert is_simulated_address == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('recipient, expected_international, expected_prefix, expected_units', [
|
||||
('7900900123', False, '44', 1), # UK
|
||||
('+447900900123', False, '44', 1), # UK
|
||||
('07700900222', False, '44', 1), # UK
|
||||
('73122345678', True, '7', 1), # Russia
|
||||
('360623400400', True, '36', 3)] # Hungary
|
||||
)
|
||||
def test_persist_notification_with_international_info_stores_correct_info(
|
||||
sample_job,
|
||||
sample_api_key,
|
||||
mocker,
|
||||
recipient,
|
||||
expected_international,
|
||||
expected_prefix,
|
||||
expected_units
|
||||
):
|
||||
persist_notification(
|
||||
template_id=sample_job.template.id,
|
||||
template_version=sample_job.template.version,
|
||||
recipient=recipient,
|
||||
service=sample_job.service,
|
||||
personalisation=None,
|
||||
notification_type='sms',
|
||||
api_key_id=sample_api_key.id,
|
||||
key_type=sample_api_key.key_type,
|
||||
job_id=sample_job.id,
|
||||
job_row_number=10,
|
||||
client_reference="ref from client"
|
||||
)
|
||||
persisted_notification = Notification.query.all()[0]
|
||||
|
||||
assert persisted_notification.international is expected_international
|
||||
assert persisted_notification.phone_prefix == expected_prefix
|
||||
assert persisted_notification.rate_multiplier == expected_units
|
||||
|
||||
|
||||
def test_persist_notification_with_international_info_does_not_store_for_email(
|
||||
sample_job,
|
||||
sample_api_key,
|
||||
mocker
|
||||
):
|
||||
persist_notification(
|
||||
template_id=sample_job.template.id,
|
||||
template_version=sample_job.template.version,
|
||||
recipient='foo@bar.com',
|
||||
service=sample_job.service,
|
||||
personalisation=None,
|
||||
notification_type='email',
|
||||
api_key_id=sample_api_key.id,
|
||||
key_type=sample_api_key.key_type,
|
||||
job_id=sample_job.id,
|
||||
job_row_number=10,
|
||||
client_reference="ref from client"
|
||||
)
|
||||
persisted_notification = Notification.query.all()[0]
|
||||
|
||||
assert persisted_notification.international is False
|
||||
assert persisted_notification.phone_prefix is None
|
||||
assert persisted_notification.rate_multiplier is None
|
||||
|
||||
@@ -8,7 +8,10 @@ from app.notifications.validators import (
|
||||
check_template_is_active,
|
||||
service_can_send_to_recipient,
|
||||
check_sms_content_char_count,
|
||||
check_service_over_api_rate_limit)
|
||||
check_service_over_api_rate_limit,
|
||||
validate_and_format_recipient
|
||||
)
|
||||
|
||||
from app.v2.errors import (
|
||||
BadRequestError,
|
||||
TooManyRequestsError,
|
||||
@@ -337,3 +340,19 @@ def test_should_not_rate_limit_if_limiting_is_disabled(
|
||||
|
||||
check_service_over_api_rate_limit(service, api_key)
|
||||
assert not app.redis_store.exceeded_rate_limit.called
|
||||
|
||||
|
||||
@pytest.mark.parametrize('key_type', ['test', 'normal'])
|
||||
def test_rejects_api_calls_with_international_numbers_if_service_does_not_allow_int_sms(sample_service, key_type):
|
||||
with pytest.raises(BadRequestError) as e:
|
||||
validate_and_format_recipient('20-12-1234-1234', key_type, sample_service, 'sms')
|
||||
assert e.value.status_code == 400
|
||||
assert e.value.message == 'Cannot send to international mobile numbers'
|
||||
assert e.value.fields == []
|
||||
|
||||
|
||||
@pytest.mark.parametrize('key_type', ['test', 'normal'])
|
||||
def test_allows_api_calls_with_international_numbers_if_service_does_allow_int_sms(sample_service, key_type):
|
||||
sample_service.can_send_international_sms = True
|
||||
result = validate_and_format_recipient('20-12-1234-1234', key_type, sample_service, 'sms')
|
||||
assert result == '201212341234'
|
||||
|
||||
Reference in New Issue
Block a user