Merge pull request #3053 from alphagov/ibag-message-number

Add sequential message number to broadcast provider messages
This commit is contained in:
Pea M. Tyczynska
2020-12-09 13:02:25 +00:00
committed by GitHub
11 changed files with 343 additions and 42 deletions

View File

@@ -2,12 +2,15 @@ import uuid
from flask import current_app from flask import current_app
from notifications_utils.statsd_decorators import statsd from notifications_utils.statsd_decorators import statsd
from sqlalchemy.schema import Sequence
from app import cbc_proxy_client, notify_celery from app import cbc_proxy_client, db, notify_celery
from app.config import QueueNames from app.config import QueueNames
from app.models import BroadcastEventMessageType from app.models import BroadcastEventMessageType, BroadcastProvider
from app.dao.broadcast_message_dao import dao_get_broadcast_event_by_id, create_broadcast_provider_message from app.dao.broadcast_message_dao import dao_get_broadcast_event_by_id, create_broadcast_provider_message
from app.utils import format_sequential_number
@notify_celery.task(name="send-broadcast-event") @notify_celery.task(name="send-broadcast-event")
@statsd(namespace="tasks") @statsd(namespace="tasks")
@@ -30,6 +33,9 @@ def send_broadcast_provider_message(broadcast_event_id, provider):
broadcast_event = dao_get_broadcast_event_by_id(broadcast_event_id) broadcast_event = dao_get_broadcast_event_by_id(broadcast_event_id)
broadcast_provider_message = create_broadcast_provider_message(broadcast_event, provider) broadcast_provider_message = create_broadcast_provider_message(broadcast_event, provider)
formatted_message_number = None
if provider == BroadcastProvider.VODAFONE:
formatted_message_number = format_sequential_number(broadcast_provider_message.message_number)
current_app.logger.info( current_app.logger.info(
f'invoking cbc proxy to send ' f'invoking cbc proxy to send '
@@ -47,6 +53,7 @@ def send_broadcast_provider_message(broadcast_event_id, provider):
if broadcast_event.message_type == BroadcastEventMessageType.ALERT: if broadcast_event.message_type == BroadcastEventMessageType.ALERT:
cbc_proxy_provider_client.create_and_send_broadcast( cbc_proxy_provider_client.create_and_send_broadcast(
identifier=str(broadcast_provider_message.id), identifier=str(broadcast_provider_message.id),
message_number=formatted_message_number,
headline="GOV.UK Notify Broadcast", headline="GOV.UK Notify Broadcast",
description=broadcast_event.transmitted_content['body'], description=broadcast_event.transmitted_content['body'],
areas=areas, areas=areas,
@@ -56,6 +63,7 @@ def send_broadcast_provider_message(broadcast_event_id, provider):
elif broadcast_event.message_type == BroadcastEventMessageType.UPDATE: elif broadcast_event.message_type == BroadcastEventMessageType.UPDATE:
cbc_proxy_provider_client.update_and_send_broadcast( cbc_proxy_provider_client.update_and_send_broadcast(
identifier=str(broadcast_provider_message.id), identifier=str(broadcast_provider_message.id),
message_number=formatted_message_number,
headline="GOV.UK Notify Broadcast", headline="GOV.UK Notify Broadcast",
description=broadcast_event.transmitted_content['body'], description=broadcast_event.transmitted_content['body'],
areas=areas, areas=areas,
@@ -66,6 +74,7 @@ def send_broadcast_provider_message(broadcast_event_id, provider):
elif broadcast_event.message_type == BroadcastEventMessageType.CANCEL: elif broadcast_event.message_type == BroadcastEventMessageType.CANCEL:
cbc_proxy_provider_client.cancel_broadcast( cbc_proxy_provider_client.cancel_broadcast(
identifier=str(broadcast_provider_message.id), identifier=str(broadcast_provider_message.id),
message_number=formatted_message_number,
headline="GOV.UK Notify Broadcast", headline="GOV.UK Notify Broadcast",
description=broadcast_event.transmitted_content['body'], description=broadcast_event.transmitted_content['body'],
areas=areas, areas=areas,
@@ -78,6 +87,11 @@ def send_broadcast_provider_message(broadcast_event_id, provider):
@notify_celery.task(name='trigger-link-test') @notify_celery.task(name='trigger-link-test')
def trigger_link_test(provider): def trigger_link_test(provider):
identifier = str(uuid.uuid4()) identifier = str(uuid.uuid4())
formatted_seq_number = None
if provider == BroadcastProvider.VODAFONE:
sequence = Sequence('broadcast_provider_message_number_seq')
sequential_number = db.session.connection().execute(sequence)
formatted_seq_number = format_sequential_number(sequential_number)
message = f"Sending a link test to CBC proxy for provider {provider} with ID {identifier}" message = f"Sending a link test to CBC proxy for provider {provider} with ID {identifier}"
current_app.logger.info(message) current_app.logger.info(message)
cbc_proxy_client.get_proxy(provider).send_link_test(identifier) cbc_proxy_client.get_proxy(provider).send_link_test(identifier, formatted_seq_number)

View File

@@ -42,6 +42,7 @@ class CBCProxyClient:
proxy_classes = { proxy_classes = {
'canary': CBCProxyCanary, 'canary': CBCProxyCanary,
BroadcastProvider.EE: CBCProxyEE, BroadcastProvider.EE: CBCProxyEE,
BroadcastProvider.VODAFONE: CBCProxyVodafone,
} }
return proxy_classes[provider](self._lambda_client) return proxy_classes[provider](self._lambda_client)
@@ -61,13 +62,13 @@ class CBCProxyClientBase:
def send_link_test( def send_link_test(
self, self,
identifier, identifier,
sequential_number,
message_format
): ):
pass pass
def create_and_send_broadcast( def create_and_send_broadcast(
self, self, identifier, message_number, message_format, headline, description, areas, sent, expires,
identifier, headline, description, areas,
sent, expires,
): ):
pass pass
@@ -75,7 +76,7 @@ class CBCProxyClientBase:
def update_and_send_broadcast( def update_and_send_broadcast(
self, self,
identifier, previous_provider_messages, headline, description, areas, identifier, previous_provider_messages, headline, description, areas,
sent, expires, sent, expires, message_number, message_format
): ):
pass pass
@@ -83,7 +84,7 @@ class CBCProxyClientBase:
def cancel_broadcast( def cancel_broadcast(
self, self,
identifier, previous_provider_messages, headline, description, areas, identifier, previous_provider_messages, headline, description, areas,
sent, expires, sent, expires, message_number, message_format
): ):
pass pass
@@ -131,23 +132,69 @@ class CBCProxyEE(CBCProxyClientBase):
def send_link_test( def send_link_test(
self, self,
identifier, identifier,
sequential_number=None,
): ):
pass
""" """
link test - open up a connection to a specific provider, and send them an xml payload with a <msgType> of link test - open up a connection to a specific provider, and send them an xml payload with a <msgType> of
test. test.
""" """
payload = {'message_type': 'test', 'identifier': identifier} payload = {
'message_type': 'test',
'identifier': identifier,
'message_format': 'cbc'
}
self._invoke_lambda(payload=payload) self._invoke_lambda(payload=payload)
def create_and_send_broadcast( def create_and_send_broadcast(
self, self, identifier, headline, description, areas, sent, expires, message_number=None
identifier, headline, description, areas,
sent, expires,
): ):
pass
payload = { payload = {
'message_type': 'alert', 'message_type': 'alert',
'identifier': identifier, 'identifier': identifier,
'message_format': 'cbc',
'headline': headline,
'description': description,
'areas': areas,
'sent': sent,
'expires': expires,
}
self._invoke_lambda(payload=payload)
class CBCProxyVodafone(CBCProxyClientBase):
lambda_name = 'vodafone-1-proxy'
def send_link_test(
self,
identifier,
sequential_number,
):
pass
"""
link test - open up a connection to a specific provider, and send them an xml payload with a <msgType> of
test.
"""
payload = {
'message_type': 'test',
'identifier': identifier,
'message_number': sequential_number,
'message_format': 'ibag'
}
self._invoke_lambda(payload=payload)
def create_and_send_broadcast(
self, identifier, message_number, headline, description, areas, sent, expires,
):
pass
payload = {
'message_type': 'alert',
'identifier': identifier,
'message_number': message_number,
'message_format': 'ibag',
'headline': headline, 'headline': headline,
'description': description, 'description': description,
'areas': areas, 'areas': areas,

View File

@@ -378,7 +378,7 @@ class Config(object):
CBC_PROXY_ENABLED = bool(CBC_PROXY_AWS_ACCESS_KEY_ID) CBC_PROXY_ENABLED = bool(CBC_PROXY_AWS_ACCESS_KEY_ID)
ENABLED_CBCS = {BroadcastProvider.EE} ENABLED_CBCS = {BroadcastProvider.EE, BroadcastProvider.VODAFONE}
###################### ######################

View File

@@ -1,6 +1,15 @@
import uuid
from app import db from app import db
from app.dao.dao_utils import transactional from app.dao.dao_utils import transactional
from app.models import BroadcastMessage, BroadcastEvent, BroadcastProviderMessage, BroadcastProviderMessageStatus from app.models import (
BroadcastMessage,
BroadcastEvent,
BroadcastProvider,
BroadcastProviderMessage,
BroadcastProviderMessageNumber,
BroadcastProviderMessageStatus
)
def dao_get_broadcast_message_by_id_and_service_id(broadcast_message_id, service_id): def dao_get_broadcast_message_by_id_and_service_id(broadcast_message_id, service_id):
@@ -36,10 +45,19 @@ def get_earlier_events_for_broadcast_event(broadcast_event_id):
@transactional @transactional
def create_broadcast_provider_message(broadcast_event, provider): def create_broadcast_provider_message(broadcast_event, provider):
broadcast_provider_message_id = uuid.uuid4()
provider_message = BroadcastProviderMessage( provider_message = BroadcastProviderMessage(
id=broadcast_provider_message_id,
broadcast_event=broadcast_event, broadcast_event=broadcast_event,
provider=provider, provider=provider,
status=BroadcastProviderMessageStatus.SENDING, status=BroadcastProviderMessageStatus.SENDING,
) )
db.session.add(provider_message) db.session.add(provider_message)
db.session.commit()
provider_message_number = None
if provider == BroadcastProvider.VODAFONE:
provider_message_number = BroadcastProviderMessageNumber(
broadcast_provider_message_id=broadcast_provider_message_id)
db.session.add(provider_message_number)
db.session.commit()
return provider_message return provider_message

View File

@@ -6,6 +6,7 @@ from flask import url_for, current_app
from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.schema import Sequence
from sqlalchemy.dialects.postgresql import ( from sqlalchemy.dialects.postgresql import (
UUID, UUID,
JSON, JSON,
@@ -2482,6 +2483,29 @@ class BroadcastProviderMessage(db.Model):
UniqueConstraint(broadcast_event_id, provider) UniqueConstraint(broadcast_event_id, provider)
message_number = association_proxy('broadcast_provider_message_number', 'broadcast_provider_message_number')
class BroadcastProviderMessageNumber(db.Model):
"""
To send IBAG messages via the CBC proxy to Nokia CBC appliances, Notify must generate and store a numeric
message_number alongside the message ID (GUID).
Subsequent messages (Update, Cancel) in IBAG format must reference the original message_number & message_id.
This model relates broadcast_provider_message_id to that numeric message_number.
"""
__tablename__ = 'broadcast_provider_message_number'
sequence = Sequence('broadcast_provider_message_number_seq')
broadcast_provider_message_number = db.Column(
db.Integer, sequence, server_default=sequence.next_value(), primary_key=True
)
broadcast_provider_message_id = db.Column(
UUID(as_uuid=True), db.ForeignKey('broadcast_provider_message.id'), nullable=False
)
broadcast_provider_message = db.relationship(
'BroadcastProviderMessage', backref=db.backref("broadcast_provider_message_number", uselist=False)
)
class ServiceBroadcastProviderRestriction(db.Model): class ServiceBroadcastProviderRestriction(db.Model):
""" """

View File

@@ -146,3 +146,7 @@ def get_archived_db_column_value(column):
def get_dt_string_or_none(val): def get_dt_string_or_none(val):
return val.strftime(DATETIME_FORMAT) if val else None return val.strftime(DATETIME_FORMAT) if val else None
def format_sequential_number(sequential_number):
return format(sequential_number, "x").zfill(8)

View File

@@ -0,0 +1,38 @@
"""
Revision ID: 0334_broadcast_message_number
Revises: 0333_service_broadcast_provider
Create Date: 2020-12-04 15:06:22.544803
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
revision = '0334_broadcast_message_number'
down_revision = '0333_service_broadcast_provider'
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.execute("create sequence broadcast_provider_message_number_seq")
op.create_table(
'broadcast_provider_message_number',
sa.Column(
'broadcast_provider_message_number',
sa.Integer(),
server_default=sa.text("nextval('broadcast_provider_message_number_seq')"),
nullable=False
),
sa.Column('broadcast_provider_message_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.ForeignKeyConstraint(['broadcast_provider_message_id'], ['broadcast_provider_message.id'], ),
sa.PrimaryKeyConstraint('broadcast_provider_message_number')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('broadcast_provider_message_number')
op.execute("drop sequence broadcast_provider_message_number_seq")
# ### end Alembic commands ###

View File

@@ -105,7 +105,13 @@ def test_send_broadcast_event_does_nothing_if_cbc_proxy_disabled(mocker, notify_
@freeze_time('2020-08-01 12:00') @freeze_time('2020-08-01 12:00')
def test_send_broadcast_provider_message_sends_data_correctly(mocker, sample_service): @pytest.mark.parametrize('provider,provider_capitalised', [
['ee', 'EE'],
['vodafone', 'Vodafone'],
])
def test_send_broadcast_provider_message_sends_data_correctly(
mocker, sample_service, provider, provider_capitalised
):
template = create_template(sample_service, BROADCAST_TYPE) template = create_template(sample_service, BROADCAST_TYPE)
broadcast_message = create_broadcast_message( broadcast_message = create_broadcast_message(
template, template,
@@ -121,18 +127,19 @@ def test_send_broadcast_provider_message_sends_data_correctly(mocker, sample_ser
event = create_broadcast_event(broadcast_message) event = create_broadcast_event(broadcast_message)
mock_create_broadcast = mocker.patch( mock_create_broadcast = mocker.patch(
'app.clients.cbc_proxy.CBCProxyEE.create_and_send_broadcast', f'app.clients.cbc_proxy.CBCProxy{provider_capitalised}.create_and_send_broadcast',
) )
assert event.get_provider_message('ee') is None assert event.get_provider_message(provider) is None
send_broadcast_provider_message(provider='ee', broadcast_event_id=str(event.id)) send_broadcast_provider_message(provider=provider, broadcast_event_id=str(event.id))
broadcast_provider_message = event.get_provider_message('ee') broadcast_provider_message = event.get_provider_message(provider)
assert broadcast_provider_message.status == BroadcastProviderMessageStatus.SENDING assert broadcast_provider_message.status == BroadcastProviderMessageStatus.SENDING
mock_create_broadcast.assert_called_once_with( mock_create_broadcast.assert_called_once_with(
identifier=str(broadcast_provider_message.id), identifier=str(broadcast_provider_message.id),
message_number=mocker.ANY,
headline='GOV.UK Notify Broadcast', headline='GOV.UK Notify Broadcast',
description='this is an emergency broadcast message', description='this is an emergency broadcast message',
areas=[{ areas=[{
@@ -149,7 +156,13 @@ def test_send_broadcast_provider_message_sends_data_correctly(mocker, sample_ser
) )
def test_send_broadcast_provider_message_sends_update_with_references(mocker, sample_service): @pytest.mark.parametrize('provider,provider_capitalised', [
['ee', 'EE'],
['vodafone', 'Vodafone'],
])
def test_send_broadcast_provider_message_sends_update_with_references(
mocker, sample_service, provider, provider_capitalised
):
template = create_template(sample_service, BROADCAST_TYPE, content='content') template = create_template(sample_service, BROADCAST_TYPE, content='content')
broadcast_message = create_broadcast_message( broadcast_message = create_broadcast_message(
@@ -164,34 +177,41 @@ def test_send_broadcast_provider_message_sends_update_with_references(mocker, sa
) )
alert_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.ALERT) alert_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.ALERT)
create_broadcast_provider_message(alert_event, 'ee') create_broadcast_provider_message(alert_event, provider)
update_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.UPDATE) update_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.UPDATE)
mock_update_broadcast = mocker.patch( mock_update_broadcast = mocker.patch(
'app.clients.cbc_proxy.CBCProxyEE.update_and_send_broadcast', f'app.clients.cbc_proxy.CBCProxy{provider_capitalised}.update_and_send_broadcast',
) )
send_broadcast_provider_message(provider='ee', broadcast_event_id=str(update_event.id)) send_broadcast_provider_message(provider=provider, broadcast_event_id=str(update_event.id))
broadcast_provider_message = update_event.get_provider_message('ee') broadcast_provider_message = update_event.get_provider_message(provider)
assert broadcast_provider_message.status == BroadcastProviderMessageStatus.SENDING assert broadcast_provider_message.status == BroadcastProviderMessageStatus.SENDING
mock_update_broadcast.assert_called_once_with( mock_update_broadcast.assert_called_once_with(
identifier=str(broadcast_provider_message.id), identifier=str(broadcast_provider_message.id),
message_number=mocker.ANY,
headline="GOV.UK Notify Broadcast", headline="GOV.UK Notify Broadcast",
description='this is an emergency broadcast message', description='this is an emergency broadcast message',
areas=[{ areas=[{
"polygon": [[50.12, 1.2], [50.13, 1.2], [50.14, 1.21]], "polygon": [[50.12, 1.2], [50.13, 1.2], [50.14, 1.21]],
}], }],
previous_provider_messages=[ previous_provider_messages=[
alert_event.get_provider_message('ee') alert_event.get_provider_message(provider)
], ],
sent=update_event.sent_at_as_cap_datetime_string, sent=update_event.sent_at_as_cap_datetime_string,
expires=update_event.transmitted_finishes_at_as_cap_datetime_string, expires=update_event.transmitted_finishes_at_as_cap_datetime_string,
) )
def test_send_broadcast_provider_message_sends_cancel_with_references(mocker, sample_service): @pytest.mark.parametrize('provider,provider_capitalised', [
['ee', 'EE'],
['vodafone', 'Vodafone'],
])
def test_send_broadcast_provider_message_sends_cancel_with_references(
mocker, sample_service, provider, provider_capitalised
):
template = create_template(sample_service, BROADCAST_TYPE, content='content') template = create_template(sample_service, BROADCAST_TYPE, content='content')
broadcast_message = create_broadcast_message( broadcast_message = create_broadcast_message(
@@ -209,28 +229,29 @@ def test_send_broadcast_provider_message_sends_cancel_with_references(mocker, sa
update_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.UPDATE) update_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.UPDATE)
cancel_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.CANCEL) cancel_event = create_broadcast_event(broadcast_message, message_type=BroadcastEventMessageType.CANCEL)
create_broadcast_provider_message(alert_event, 'ee') create_broadcast_provider_message(alert_event, provider)
create_broadcast_provider_message(update_event, 'ee') create_broadcast_provider_message(update_event, provider)
mock_cancel_broadcast = mocker.patch( mock_cancel_broadcast = mocker.patch(
'app.clients.cbc_proxy.CBCProxyEE.cancel_broadcast', f'app.clients.cbc_proxy.CBCProxy{provider_capitalised}.cancel_broadcast',
) )
send_broadcast_provider_message(provider='ee', broadcast_event_id=str(cancel_event.id)) send_broadcast_provider_message(provider=provider, broadcast_event_id=str(cancel_event.id))
broadcast_provider_message = cancel_event.get_provider_message('ee') broadcast_provider_message = cancel_event.get_provider_message(provider)
assert broadcast_provider_message.status == BroadcastProviderMessageStatus.SENDING assert broadcast_provider_message.status == BroadcastProviderMessageStatus.SENDING
mock_cancel_broadcast.assert_called_once_with( mock_cancel_broadcast.assert_called_once_with(
identifier=str(broadcast_provider_message.id), identifier=str(broadcast_provider_message.id),
message_number=mocker.ANY,
headline="GOV.UK Notify Broadcast", headline="GOV.UK Notify Broadcast",
description='this is an emergency broadcast message', description='this is an emergency broadcast message',
areas=[{ areas=[{
"polygon": [[50.12, 1.2], [50.13, 1.2], [50.14, 1.21]], "polygon": [[50.12, 1.2], [50.13, 1.2], [50.14, 1.21]],
}], }],
previous_provider_messages=[ previous_provider_messages=[
alert_event.get_provider_message('ee'), alert_event.get_provider_message(provider),
update_event.get_provider_message('ee') update_event.get_provider_message(provider)
], ],
sent=cancel_event.sent_at_as_cap_datetime_string, sent=cancel_event.sent_at_as_cap_datetime_string,
expires=cancel_event.transmitted_finishes_at_as_cap_datetime_string, expires=cancel_event.transmitted_finishes_at_as_cap_datetime_string,
@@ -265,6 +286,7 @@ def test_send_broadcast_provider_message_errors(mocker, sample_service):
mock_create_broadcast.assert_called_once_with( mock_create_broadcast.assert_called_once_with(
identifier=ANY, identifier=ANY,
message_number=mocker.ANY,
headline="GOV.UK Notify Broadcast", headline="GOV.UK Notify Broadcast",
description='this is an emergency broadcast message', description='this is an emergency broadcast message',
areas=[{ areas=[{
@@ -279,14 +301,18 @@ def test_send_broadcast_provider_message_errors(mocker, sample_service):
) )
@pytest.mark.parametrize("provider,provider_capitalised", [
["ee", "EE"],
["vodafone", "Vodafone"]
])
def test_trigger_link_tests_invokes_cbc_proxy_client( def test_trigger_link_tests_invokes_cbc_proxy_client(
mocker, mocker, provider, provider_capitalised
): ):
mock_send_link_test = mocker.patch( mock_send_link_test = mocker.patch(
'app.clients.cbc_proxy.CBCProxyEE.send_link_test', f'app.clients.cbc_proxy.CBCProxy{provider_capitalised}.send_link_test',
) )
trigger_link_test('ee') trigger_link_test(provider)
assert mock_send_link_test.called assert mock_send_link_test.called
# the 0th argument of the call to send_link_test # the 0th argument of the call to send_link_test
@@ -296,3 +322,10 @@ def test_trigger_link_tests_invokes_cbc_proxy_client(
uuid.UUID(identifier) uuid.UUID(identifier)
except BaseException: except BaseException:
pytest.fail(f"{identifier} is not a valid uuid") pytest.fail(f"{identifier} is not a valid uuid")
# testing sequential number:
if provider == 'vodafone':
assert type(mock_send_link_test.mock_calls[0][1][1]) is str
assert len(mock_send_link_test.mock_calls[0][1][1]) == 8
else:
assert not mock_send_link_test.mock_calls[0][1][1]

View File

@@ -24,6 +24,11 @@ def cbc_proxy_ee(cbc_proxy_client):
return cbc_proxy_client.get_proxy('ee') return cbc_proxy_client.get_proxy('ee')
@pytest.fixture
def cbc_proxy_vodafone(cbc_proxy_client):
return cbc_proxy_client.get_proxy('vodafone')
@pytest.mark.parametrize('provider_name, expected_provider_class', [ @pytest.mark.parametrize('provider_name, expected_provider_class', [
('ee', CBCProxyEE), ('ee', CBCProxyEE),
('canary', CBCProxyCanary), ('canary', CBCProxyCanary),
@@ -51,7 +56,7 @@ def test_cbc_proxy_lambda_client_has_correct_keys(cbc_proxy_ee):
assert secret == 'cbc-proxy-aws-secret-access-key' assert secret == 'cbc-proxy-aws-secret-access-key'
def test_cbc_proxy_create_and_send_invokes_function(mocker, cbc_proxy_ee): def test_cbc_proxy_ee_create_and_send_invokes_function(mocker, cbc_proxy_ee):
identifier = 'my-identifier' identifier = 'my-identifier'
headline = 'my-headline' headline = 'my-headline'
description = 'my-description' description = 'my-description'
@@ -83,6 +88,7 @@ def test_cbc_proxy_create_and_send_invokes_function(mocker, cbc_proxy_ee):
cbc_proxy_ee.create_and_send_broadcast( cbc_proxy_ee.create_and_send_broadcast(
identifier=identifier, identifier=identifier,
message_number='0000007b',
headline=headline, headline=headline,
description=description, description=description,
areas=areas, areas=areas,
@@ -100,6 +106,68 @@ def test_cbc_proxy_create_and_send_invokes_function(mocker, cbc_proxy_ee):
payload = json.loads(payload_bytes) payload = json.loads(payload_bytes)
assert payload['identifier'] == identifier assert payload['identifier'] == identifier
assert 'message_number' not in payload
assert payload['message_format'] == 'cbc'
assert payload['message_type'] == 'alert'
assert payload['headline'] == headline
assert payload['description'] == description
assert payload['areas'] == areas
assert payload['sent'] == sent
assert payload['expires'] == expires
def test_cbc_proxy_vodafone_create_and_send_invokes_function(mocker, cbc_proxy_vodafone):
identifier = 'my-identifier'
headline = 'my-headline'
description = 'my-description'
sent = 'a-passed-through-sent-value'
expires = 'a-passed-through-expires-value'
# a single area which is a square including london
areas = [{
'description': 'london',
'polygon': [
[51.12, -1.2],
[51.12, 1.2],
[51.74, 1.2],
[51.74, -1.2],
[51.12, -1.2],
],
}]
ld_client_mock = mocker.patch.object(
cbc_proxy_vodafone,
'_lambda_client',
create=True,
)
ld_client_mock.invoke.return_value = {
'StatusCode': 200,
}
cbc_proxy_vodafone.create_and_send_broadcast(
identifier=identifier,
message_number='0000007b',
headline=headline,
description=description,
areas=areas,
sent=sent, expires=expires,
)
ld_client_mock.invoke.assert_called_once_with(
FunctionName='vodafone-1-proxy',
InvocationType='RequestResponse',
Payload=mocker.ANY,
)
kwargs = ld_client_mock.invoke.mock_calls[0][-1]
payload_bytes = kwargs['Payload']
payload = json.loads(payload_bytes)
assert payload['identifier'] == identifier
assert payload['message_number'] == '0000007b'
assert payload['message_format'] == 'ibag'
assert payload['message_type'] == 'alert' assert payload['message_type'] == 'alert'
assert payload['headline'] == headline assert payload['headline'] == headline
assert payload['description'] == description assert payload['description'] == description
@@ -141,6 +209,7 @@ def test_cbc_proxy_create_and_send_handles_invoke_error(mocker, cbc_proxy_ee):
with pytest.raises(CBCProxyException) as e: with pytest.raises(CBCProxyException) as e:
cbc_proxy_ee.create_and_send_broadcast( cbc_proxy_ee.create_and_send_broadcast(
identifier=identifier, identifier=identifier,
message_number='0000007b',
headline=headline, headline=headline,
description=description, description=description,
areas=areas, areas=areas,
@@ -190,6 +259,7 @@ def test_cbc_proxy_create_and_send_handles_function_error(mocker, cbc_proxy_ee):
with pytest.raises(CBCProxyException) as e: with pytest.raises(CBCProxyException) as e:
cbc_proxy_ee.create_and_send_broadcast( cbc_proxy_ee.create_and_send_broadcast(
identifier=identifier, identifier=identifier,
message_number='0000007b',
headline=headline, headline=headline,
description=description, description=description,
areas=areas, areas=areas,
@@ -237,7 +307,7 @@ def test_cbc_proxy_send_canary_invokes_function(mocker, cbc_proxy_client):
assert payload['identifier'] == identifier assert payload['identifier'] == identifier
def test_cbc_proxy_send_link_test_invokes_function(mocker, cbc_proxy_ee): def test_cbc_proxy_ee_send_link_test_invokes_function(mocker, cbc_proxy_ee):
identifier = str(uuid.uuid4()) identifier = str(uuid.uuid4())
ld_client_mock = mocker.patch.object( ld_client_mock = mocker.patch.object(
@@ -252,6 +322,7 @@ def test_cbc_proxy_send_link_test_invokes_function(mocker, cbc_proxy_ee):
cbc_proxy_ee.send_link_test( cbc_proxy_ee.send_link_test(
identifier=identifier, identifier=identifier,
sequential_number='0000007b',
) )
ld_client_mock.invoke.assert_called_once_with( ld_client_mock.invoke.assert_called_once_with(
@@ -266,3 +337,39 @@ def test_cbc_proxy_send_link_test_invokes_function(mocker, cbc_proxy_ee):
assert payload['identifier'] == identifier assert payload['identifier'] == identifier
assert payload['message_type'] == 'test' assert payload['message_type'] == 'test'
assert 'message_number' not in payload
assert payload['message_format'] == 'cbc'
def test_cbc_proxy_vodafone_send_link_test_invokes_function(mocker, cbc_proxy_vodafone):
identifier = str(uuid.uuid4())
ld_client_mock = mocker.patch.object(
cbc_proxy_vodafone,
'_lambda_client',
create=True,
)
ld_client_mock.invoke.return_value = {
'StatusCode': 200,
}
cbc_proxy_vodafone.send_link_test(
identifier=identifier,
sequential_number='0000007b',
)
ld_client_mock.invoke.assert_called_once_with(
FunctionName='vodafone-1-proxy',
InvocationType='RequestResponse',
Payload=mocker.ANY,
)
kwargs = ld_client_mock.invoke.mock_calls[0][-1]
payload_bytes = kwargs['Payload']
payload = json.loads(payload_bytes)
assert payload['identifier'] == identifier
assert payload['message_type'] == 'test'
assert payload['message_number'] == '0000007b'
assert payload['message_format'] == 'ibag'

View File

@@ -63,7 +63,9 @@ from app.models import (
BroadcastMessage, BroadcastMessage,
BroadcastStatusType, BroadcastStatusType,
BroadcastEvent, BroadcastEvent,
BroadcastProviderMessage BroadcastProvider,
BroadcastProviderMessage,
BroadcastProviderMessageNumber
) )
@@ -1058,11 +1060,20 @@ def create_broadcast_provider_message(
provider, provider,
status='sending' status='sending'
): ):
broadcast_provider_message_id = uuid.uuid4()
provider_message = BroadcastProviderMessage( provider_message = BroadcastProviderMessage(
id=broadcast_provider_message_id,
broadcast_event=broadcast_event, broadcast_event=broadcast_event,
provider=provider, provider=provider,
status=status status=status,
) )
db.session.add(provider_message) db.session.add(provider_message)
db.session.commit() db.session.commit()
return provider_message
provider_message_number = None
if provider == BroadcastProvider.VODAFONE:
provider_message_number = BroadcastProviderMessageNumber(
broadcast_provider_message_id=broadcast_provider_message_id)
db.session.add(provider_message_number)
db.session.commit()
return provider_message, provider_message_number

View File

@@ -4,10 +4,11 @@ import pytest
from freezegun import freeze_time from freezegun import freeze_time
from app.utils import ( from app.utils import (
format_sequential_number,
get_london_midnight_in_utc, get_london_midnight_in_utc,
get_midnight_for_day_before, get_midnight_for_day_before,
midnight_n_days_ago,
get_notification_table_to_use, get_notification_table_to_use,
midnight_n_days_ago
) )
from app.models import Notification, NotificationHistory from app.models import Notification, NotificationHistory
@@ -99,3 +100,7 @@ def test_get_notification_table_to_use_checks_service_data_retention(sample_serv
# falls back to 7 days if not specified # falls back to 7 days if not specified
assert get_notification_table_to_use(sample_service, 'sms', date(2019, 1, 1), False) == NotificationHistory assert get_notification_table_to_use(sample_service, 'sms', date(2019, 1, 1), False) == NotificationHistory
assert get_notification_table_to_use(sample_service, 'sms', date(2019, 1, 2), False) == Notification assert get_notification_table_to_use(sample_service, 'sms', date(2019, 1, 2), False) == Notification
def test_format_sequential_number():
assert format_sequential_number(123) == '0000007b'