Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add initial phone validation ability #1331

Merged
merged 3 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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]
Expand Down
Empty file.
64 changes: 64 additions & 0 deletions app/clients/pinpoint/aws_pinpoint.py
Original file line number Diff line number Diff line change
@@ -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'
# }
# }
13 changes: 12 additions & 1 deletion app/delivery/send_to_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
Loading