Respect template’s redaction preference

If a template has the `redact_personalisation` flag set, then this
commit removes the personalisation from the notification before
rehydrating the template.

We’re doing this because we have a need to not show things like one time
passwords or two factor codes when we show the content of messages.

By passing through empty personalisation, and the `redact_missing` flag,
the `Template` instance will make use of the work done in:
- [x] https://github.com/alphagov/notifications-utils/pull/171
This commit is contained in:
Chris Hill-Scott
2017-06-24 17:29:28 +01:00
parent 1d65c19c4e
commit bc880017e5
6 changed files with 129 additions and 18 deletions

View File

@@ -390,12 +390,29 @@ def get_job_partials(job):
def add_preview_of_content_to_notifications(notifications):
for notification in notifications:
yield dict(
preview_of_content=(
str(Template(notification['template'], notification['personalisation']))
if notification['template']['template_type'] == 'sms' else
WithSubjectTemplate(notification['template'], notification['personalisation']).subject
),
**notification
)
if notification['template'].get('redact_personalisation'):
notification['personalisation'] = {}
if notification['template']['template_type'] == 'sms':
yield dict(
preview_of_content=str(Template(
notification['template'],
notification['personalisation'],
redact_missing_personalisation=True,
)),
**notification
)
else:
yield dict(
preview_of_content=(
WithSubjectTemplate(
notification['template'],
notification['personalisation'],
redact_missing_personalisation=True,
).subject
),
**notification
)

View File

@@ -56,6 +56,7 @@ def view_notification(service_id, notification_id):
filetype='png',
),
show_recipient=True,
redact_missing_personalisation=True,
)
template.values = get_all_personalisation_from_notification(notification)
if notification['job']:
@@ -109,15 +110,21 @@ def get_single_notification_partials(notification):
def get_all_personalisation_from_notification(notification):
if notification['template'].get('redact_personalisation'):
notification['personalisation'] = {}
if notification['template']['template_type'] == 'email':
return dict(
email_address=notification['to'],
**notification['personalisation']
)
if notification['template']['template_type'] == 'sms':
return dict(
phone_number=notification['to'],
**notification['personalisation']
)
if notification['template']['template_type'] == 'letter':
return notification['personalisation']

View File

@@ -87,12 +87,12 @@ def template_json(service_id,
id_,
name="sample template",
type_="sms",
content="template content",
content=None,
subject=None,
version=1,
archived=False,
process_type='normal',
redact_personalisation=False,
redact_personalisation=None,
):
template = {
'id': id_,
@@ -105,6 +105,8 @@ def template_json(service_id,
'archived': archived,
'process_type': process_type,
}
if content is None:
template['content'] = "template content"
if subject is None and type_ != 'sms':
template['subject'] = "template subject"
if subject is not None:

View File

@@ -8,7 +8,7 @@ from bs4 import BeautifulSoup
from app.main.views.jobs import get_time_left, get_status_filters
from tests import notification_json
from tests.conftest import SERVICE_ONE_ID
from tests.conftest import SERVICE_ONE_ID, mock_get_notifications
from tests.app.test_utils import normalize_spaces
from freezegun import freeze_time
@@ -321,3 +321,27 @@ def test_html_contains_notification_id(
notifications = page.tbody.find_all('tr')
for tr in notifications:
assert uuid.UUID(tr.attrs['id'])
def test_redacts_templates_that_should_be_redacted(
client_request,
mocker,
active_user_with_permissions,
mock_get_detailed_service,
):
_notifications_mock = mock_get_notifications(
mocker,
active_user_with_permissions,
template_content="hello ((name))",
personalisation={'name': 'Jo'},
redact_personalisation=True,
)
page = client_request.get(
'main.view_notifications',
service_id=SERVICE_ONE_ID,
message_type='sms',
)
assert normalize_spaces(page.select('tbody tr th')[0].text) == (
'07123456789 hello hidden'
)

View File

@@ -57,3 +57,37 @@ def test_notification_status_page_shows_details(
service_one['id'],
fake_uuid
)
@pytest.mark.parametrize('template_redaction_setting, expected_content', [
(False, 'service one: hello Jo'),
(True, 'service one: hello hidden'),
])
@freeze_time("2016-01-01 11:09:00.061258")
def test_notification_status_page_respects_redaction(
client_request,
mocker,
service_one,
fake_uuid,
template_redaction_setting,
expected_content,
):
_mock_get_notification = mock_get_notification(
mocker,
fake_uuid,
redact_personalisation=template_redaction_setting,
)
page = client_request.get(
'main.view_notification',
service_id=service_one['id'],
notification_id=fake_uuid
)
assert normalize_spaces(page.select('.sms-message-wrapper')[0].text) == expected_content
_mock_get_notification.assert_called_with(
service_one['id'],
fake_uuid,
)

View File

@@ -1079,7 +1079,13 @@ def mock_get_jobs(mocker, api_user_active):
@pytest.fixture(scope='function')
def mock_get_notifications(mocker, api_user_active):
def mock_get_notifications(
mocker,
api_user_active,
template_content=None,
personalisation=None,
redact_personalisation=False,
):
def _get_notifications(
service_id,
job_id=None,
@@ -1096,17 +1102,28 @@ def mock_get_notifications(mocker, api_user_active):
job = None
if job_id is not None:
job = job_json(service_id, api_user_active, job_id=job_id)
if template_type:
template = template_json(service_id, id_=str(generate_uuid()), type_=template_type[0])
template = template_json(
service_id,
id_=str(generate_uuid()),
type_=template_type[0],
content=template_content,
redact_personalisation=redact_personalisation,
)
else:
template = template_json(service_id, id_=str(generate_uuid()))
template = template_json(
service_id,
id_=str(generate_uuid()),
content=template_content,
redact_personalisation=redact_personalisation,
)
return notification_json(
service_id,
template=template,
rows=rows,
job=job
job=job,
personalisation=personalisation,
)
return mocker.patch(
@@ -1636,7 +1653,12 @@ def mock_reset_failed_login_count(mocker):
@pytest.fixture
def mock_get_notification(mocker, fake_uuid, notification_status='delivered'):
def mock_get_notification(
mocker,
fake_uuid,
notification_status='delivered',
redact_personalisation=False,
):
def _get_notification(
service_id,
notification_id,
@@ -1654,7 +1676,12 @@ def mock_get_notification(mocker, fake_uuid, notification_status='delivered'):
'email_address': 'test@user.gov.uk'
}
noti['personalisation'] = {'name': 'Jo'}
noti['template'] = template_json(service_id, str(generate_uuid()), content='hello ((name))')
noti['template'] = template_json(
service_id,
str(generate_uuid()),
content='hello ((name))',
redact_personalisation=redact_personalisation,
)
return noti
return mocker.patch(