Merge pull request #2878 from alphagov/uk-prefix

Make sure people without international sms permission can send to crown dependencies
This commit is contained in:
Pea M. Tyczynska
2020-06-19 16:58:48 +01:00
committed by GitHub
6 changed files with 52 additions and 28 deletions

View File

@@ -15,7 +15,7 @@ from app.errors import (
InvalidRequest InvalidRequest
) )
from app.models import ( from app.models import (
EMAIL_TYPE, INTERNATIONAL_SMS_TYPE, SMS_TYPE, EMAIL_TYPE, SMS_TYPE,
KEY_TYPE_TEAM, PRIORITY, KEY_TYPE_TEAM, PRIORITY,
LETTER_TYPE) LETTER_TYPE)
from app.notifications.process_notifications import ( from app.notifications.process_notifications import (
@@ -24,9 +24,10 @@ from app.notifications.process_notifications import (
simulated_recipient simulated_recipient
) )
from app.notifications.validators import ( from app.notifications.validators import (
check_if_service_can_send_to_number,
check_rate_limiting, check_rate_limiting,
service_has_permission, service_has_permission,
validate_template validate_template,
) )
from app.schemas import ( from app.schemas import (
email_notification_schema, email_notification_schema,
@@ -38,7 +39,6 @@ from app.service.utils import service_allowed_to_send_to
from app.utils import pagination_links, get_public_notify_type_text from app.utils import pagination_links, get_public_notify_type_text
from notifications_utils import SMS_CHAR_COUNT_LIMIT from notifications_utils import SMS_CHAR_COUNT_LIMIT
from notifications_utils.recipients import get_international_phone_info
notifications = Blueprint('notifications', __name__) notifications = Blueprint('notifications', __name__)
@@ -115,7 +115,7 @@ def send_notification(notification_type):
) )
if notification_type == SMS_TYPE: if notification_type == SMS_TYPE:
_service_can_send_internationally(authenticated_service, notification_form['to']) check_if_service_can_send_to_number(authenticated_service, notification_form['to'])
# Do not persist or send notification to the queue if it is a simulated recipient # Do not persist or send notification to the queue if it is a simulated recipient
simulated = simulated_recipient(notification_form['to'], notification_type) simulated = simulated_recipient(notification_form['to'], notification_type)
notification_model = persist_notification(template_id=template.id, notification_model = persist_notification(template_id=template.id,
@@ -160,17 +160,6 @@ def get_notification_return_data(notification_id, notification, template):
return output return output
def _service_can_send_internationally(service, number):
international_phone_info = get_international_phone_info(number)
if international_phone_info.international and \
INTERNATIONAL_SMS_TYPE not in [p.permission for p in service.permissions]:
raise InvalidRequest(
{'to': ["Cannot send to international mobile numbers"]},
status_code=400
)
def _service_allowed_to_send_to(notification, service): def _service_allowed_to_send_to(notification, service):
if not service_allowed_to_send_to(notification['to'], service, api_user.key_type): if not service_allowed_to_send_to(notification['to'], service, api_user.key_type):
if api_user.key_type == KEY_TYPE_TEAM: if api_user.key_type == KEY_TYPE_TEAM:

View File

@@ -120,11 +120,7 @@ def validate_and_format_recipient(send_to, key_type, service, notification_type,
service_can_send_to_recipient(send_to, key_type, service, allow_whitelisted_recipients) service_can_send_to_recipient(send_to, key_type, service, allow_whitelisted_recipients)
if notification_type == SMS_TYPE: if notification_type == SMS_TYPE:
international_phone_info = get_international_phone_info(send_to) international_phone_info = check_if_service_can_send_to_number(service, send_to)
if international_phone_info.international and \
INTERNATIONAL_SMS_TYPE not in [p.permission for p in service.permissions]:
raise BadRequestError(message="Cannot send to international mobile numbers")
return validate_and_format_phone_number( return validate_and_format_phone_number(
number=send_to, number=send_to,
@@ -134,6 +130,18 @@ def validate_and_format_recipient(send_to, key_type, service, notification_type,
return validate_and_format_email_address(email_address=send_to) return validate_and_format_email_address(email_address=send_to)
def check_if_service_can_send_to_number(service, number):
international_phone_info = get_international_phone_info(number)
if (
# if number is international and not a crown dependency
international_phone_info.international and international_phone_info.country_prefix != '44'
) and INTERNATIONAL_SMS_TYPE not in [p.permission for p in service.permissions]:
raise BadRequestError(message="Cannot send to international mobile numbers")
else:
return international_phone_info
def check_content_char_count(template_with_content): def check_content_char_count(template_with_content):
if template_with_content.is_message_too_long(): if template_with_content.is_message_too_long():
message = f"Text messages cannot be longer than {SMS_CHAR_COUNT_LIMIT} characters. " \ message = f"Text messages cannot be longer than {SMS_CHAR_COUNT_LIMIT} characters. " \

View File

@@ -26,7 +26,7 @@ notifications-python-client==5.5.1
# PaaS # PaaS
awscli-cwlogs>=1.4,<1.5 awscli-cwlogs>=1.4,<1.5
git+https://github.com/alphagov/notifications-utils.git@39.6.0#egg=notifications-utils==39.6.0 git+https://github.com/alphagov/notifications-utils.git@39.7.0#egg=notifications-utils==39.7.0
# gds-metrics requires prometheseus 0.2.0, override that requirement as 0.7.1 brings significant performance gains # gds-metrics requires prometheseus 0.2.0, override that requirement as 0.7.1 brings significant performance gains
prometheus-client==0.7.1 prometheus-client==0.7.1

View File

@@ -28,7 +28,7 @@ notifications-python-client==5.5.1
# PaaS # PaaS
awscli-cwlogs>=1.4,<1.5 awscli-cwlogs>=1.4,<1.5
git+https://github.com/alphagov/notifications-utils.git@39.6.0#egg=notifications-utils==39.6.0 git+https://github.com/alphagov/notifications-utils.git@39.7.0#egg=notifications-utils==39.7.0
# gds-metrics requires prometheseus 0.2.0, override that requirement as 0.7.1 brings significant performance gains # gds-metrics requires prometheseus 0.2.0, override that requirement as 0.7.1 brings significant performance gains
prometheus-client==0.7.1 prometheus-client==0.7.1
@@ -39,14 +39,14 @@ alembic==1.4.2
amqp==1.4.9 amqp==1.4.9
anyjson==0.3.3 anyjson==0.3.3
attrs==19.3.0 attrs==19.3.0
awscli==1.18.82 awscli==1.18.83
bcrypt==3.1.7 bcrypt==3.1.7
billiard==3.3.0.23 billiard==3.3.0.23
bleach==3.1.4 bleach==3.1.4
blinker==1.4 blinker==1.4
boto==2.49.0 boto==2.49.0
boto3==1.10.38 boto3==1.10.38
botocore==1.17.5 botocore==1.17.6
cachetools==4.1.0 cachetools==4.1.0
certifi==2020.4.5.2 certifi==2020.4.5.2
chardet==3.0.4 chardet==3.0.4

View File

@@ -1051,7 +1051,9 @@ def test_should_allow_store_original_number_on_sms_notification(client, sample_t
assert '+(44) 7700-900 855' == notifications[0].to assert '+(44) 7700-900 855' == notifications[0].to
def test_should_not_allow_international_number_on_sms_notification(client, sample_template, mocker): def test_should_not_allow_sending_to_international_number_without_international_permission(
client, sample_template, mocker
):
mocked = mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async') mocked = mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
data = { data = {
@@ -1070,10 +1072,35 @@ def test_should_not_allow_international_number_on_sms_notification(client, sampl
assert response.status_code == 400 assert response.status_code == 400
error_json = json.loads(response.get_data(as_text=True)) error_json = json.loads(response.get_data(as_text=True))
assert error_json['result'] == 'error' assert error_json['result'] == 'error'
assert error_json['message']['to'][0] == 'Cannot send to international mobile numbers' assert error_json['message'] == 'Cannot send to international mobile numbers'
def test_should_allow_international_number_on_sms_notification(client, sample_service_full_permissions, mocker): def test_should_allow_sending_to_crown_dependency_number_without_international_permission(
client, mocker, notify_db_session
):
service = create_service()
mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
template = create_template(service)
data = {
'to': '07700-900-123',
'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
def test_should_allow_sending_to_international_number_with_international_permission(
client, sample_service_full_permissions, mocker
):
mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async') mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async')
template = create_template(sample_service_full_permissions) template = create_template(sample_service_full_permissions)

View File

@@ -356,7 +356,7 @@ def test_simulated_recipient(notify_api, to_address, notification_type, expected
@pytest.mark.parametrize('recipient, expected_international, expected_prefix, expected_units', [ @pytest.mark.parametrize('recipient, expected_international, expected_prefix, expected_units', [
('7900900123', False, '44', 1), # UK ('7900900123', False, '44', 1), # UK
('+447900900123', False, '44', 1), # UK ('+447900900123', False, '44', 1), # UK
('07700900222', False, '44', 1), # UK ('07700900222', True, '44', 1), # UK (Jersey)
('73122345678', True, '7', 1), # Russia ('73122345678', True, '7', 1), # Russia
('360623400400', True, '36', 3)] # Hungary ('360623400400', True, '36', 3)] # Hungary
) )