mirror of
https://github.com/GSA/notifications-api.git
synced 2026-09-05 21:28:25 -04:00
Merge pull request #3053 from alphagov/ibag-message-number
Add sequential message number to broadcast provider messages
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|
||||||
|
|
||||||
######################
|
######################
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
38
migrations/versions/0334_broadcast_message_number.py
Normal file
38
migrations/versions/0334_broadcast_message_number.py
Normal 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 ###
|
||||||
@@ -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]
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
Reference in New Issue
Block a user