diff --git a/app/__init__.py b/app/__init__.py index eec6b023f..380964b53 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -21,6 +21,7 @@ from app.clients.document_download import DocumentDownloadClient from app.clients.email.aws_ses import AwsSesClient from app.clients.email.aws_ses_stub import AwsSesStubClient +from app.clients.pinpoint.aws_pinpoint import AwsPinpointClient from app.clients.sms.aws_sns import AwsSnsClient from notifications_utils import logging, request_helper from notifications_utils.clients.encryption.encryption_client import Encryption @@ -68,6 +69,7 @@ def apply_driver_hacks(self, app, info, options): aws_ses_stub_client = AwsSesStubClient() aws_sns_client = AwsSnsClient() aws_cloudwatch_client = AwsCloudwatchClient() +aws_pinpoint_client = AwsPinpointClient() encryption = Encryption() zendesk_client = ZendeskClient() redis_store = RedisClient() @@ -101,6 +103,7 @@ def create_app(application): aws_ses_client.init_app() aws_ses_stub_client.init_app(stub_url=application.config["SES_STUB_URL"]) aws_cloudwatch_client.init_app(application) + aws_pinpoint_client.init_app(application) # If a stub url is provided for SES, then use the stub client rather than the real SES boto client email_clients = ( [aws_ses_stub_client] diff --git a/app/clients/pinpoint/__init__.py b/app/clients/pinpoint/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/app/clients/pinpoint/aws_pinpoint.py b/app/clients/pinpoint/aws_pinpoint.py new file mode 100644 index 000000000..aa454630a --- /dev/null +++ b/app/clients/pinpoint/aws_pinpoint.py @@ -0,0 +1,64 @@ +from boto3 import client +from botocore.exceptions import ClientError +from flask import current_app + +from app.clients import AWS_CLIENT_CONFIG, Client +from app.cloudfoundry_config import cloud_config +from app.utils import hilite + + +class AwsPinpointClient(Client): + + def init_app(self, current_app, *args, **kwargs): + self._client = client( + "pinpoint", + region_name=cloud_config.sns_region, + aws_access_key_id=cloud_config.sns_access_key, + aws_secret_access_key=cloud_config.sns_secret_key, + config=AWS_CLIENT_CONFIG, + ) + + super(Client, self).__init__(*args, **kwargs) + self.current_app = current_app + + @property + def name(self): + return "pinpoint" + + def validate_phone_number(self, country_code, phone_number): + try: + response = self._client.phone_number_validate( + NumberValidateRequest={ + "IsoCountryCode": country_code, + "PhoneNumber": phone_number, + } + ) + + # TODO right now this will only print with AWS simulated numbers, + # but remove this when that changes + current_app.logger.info(hilite(response)) + except ClientError: + current_app.logger.exception("Could not validate with pinpoint") + + # TODO This is the structure of the response. When the phone validation + # capability we want to offer is better defined (it may just be a question + # of checking PhoneType -- i.e., landline or mobile) then do something with + # this info. + # { + # 'NumberValidateResponse': { + # 'Carrier': 'string', + # 'City': 'string', + # 'CleansedPhoneNumberE164': 'string', + # 'CleansedPhoneNumberNational': 'string', + # 'Country': 'string', + # 'CountryCodeIso2': 'string', + # 'CountryCodeNumeric': 'string', + # 'County': 'string', + # 'OriginalCountryCodeIso2': 'string', + # 'OriginalPhoneNumber': 'string', + # 'PhoneType': 'string', + # 'PhoneTypeCode': 123, + # 'Timezone': 'string', + # 'ZipCode': 'string' + # } + # } diff --git a/app/delivery/send_to_providers.py b/app/delivery/send_to_providers.py index e6df568b4..1c29c4ef5 100644 --- a/app/delivery/send_to_providers.py +++ b/app/delivery/send_to_providers.py @@ -5,7 +5,13 @@ from cachetools import TTLCache, cached from flask import current_app -from app import create_uuid, db, notification_provider_clients, redis_store +from app import ( + aws_pinpoint_client, + create_uuid, + db, + notification_provider_clients, + redis_store, +) from app.aws.s3 import get_personalisation_from_s3, get_phone_number_from_s3 from app.celery.test_key_tasks import send_email_response, send_sms_response from app.dao.email_branding_dao import dao_get_email_branding_by_id @@ -92,6 +98,11 @@ def send_sms_to_provider(notification): notification.job_row_number, ) + # TODO This is temporary to test the capability of validating phone numbers + # The future home of the validation is TBD + if recipient in current_app.config["SIMULATED_SMS_NUMBERS"]: + aws_pinpoint_client.validate_phone_number("01", recipient) + sender_numbers = get_sender_numbers(notification) if notification.reply_to_text not in sender_numbers: raise ValueError(