mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-11 02:23:19 -04:00
Merge pull request #3498 from alphagov/add-broadcast-template
Allow adding broadcast templates
This commit is contained in:
+23
-3
@@ -777,7 +777,12 @@ class BaseTemplateForm(StripWhitespaceForm):
|
|||||||
|
|
||||||
class SMSTemplateForm(BaseTemplateForm):
|
class SMSTemplateForm(BaseTemplateForm):
|
||||||
def validate_template_content(self, field):
|
def validate_template_content(self, field):
|
||||||
OnlySMSCharacters()(None, field)
|
OnlySMSCharacters(template_type='sms')(None, field)
|
||||||
|
|
||||||
|
|
||||||
|
class BroadcastTemplateForm(SMSTemplateForm):
|
||||||
|
def validate_template_content(self, field):
|
||||||
|
OnlySMSCharacters(template_type='broadcast')(None, field)
|
||||||
|
|
||||||
|
|
||||||
class LetterAddressForm(StripWhitespaceForm):
|
class LetterAddressForm(StripWhitespaceForm):
|
||||||
@@ -1644,7 +1649,7 @@ class TemplateAndFoldersSelectionForm(Form):
|
|||||||
self,
|
self,
|
||||||
all_template_folders,
|
all_template_folders,
|
||||||
template_list,
|
template_list,
|
||||||
allow_adding_letter_template,
|
available_template_types,
|
||||||
allow_adding_copy_of_template,
|
allow_adding_copy_of_template,
|
||||||
*args,
|
*args,
|
||||||
**kwargs
|
**kwargs
|
||||||
@@ -1652,6 +1657,8 @@ class TemplateAndFoldersSelectionForm(Form):
|
|||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.available_template_types = available_template_types
|
||||||
|
|
||||||
self.templates_and_folders.choices = template_list.as_id_and_name
|
self.templates_and_folders.choices = template_list.as_id_and_name
|
||||||
|
|
||||||
self.op = None
|
self.op = None
|
||||||
@@ -1664,12 +1671,25 @@ class TemplateAndFoldersSelectionForm(Form):
|
|||||||
]
|
]
|
||||||
|
|
||||||
self.add_template_by_template_type.choices = list(filter(None, [
|
self.add_template_by_template_type.choices = list(filter(None, [
|
||||||
|
# We want to show email and text message to everyone,
|
||||||
|
# whether or not the service has them switched on. The
|
||||||
|
# option to add letter or broadcast templates should only
|
||||||
|
# be shown to services which have that permission
|
||||||
('email', 'Email'),
|
('email', 'Email'),
|
||||||
('sms', 'Text message'),
|
('sms', 'Text message'),
|
||||||
('letter', 'Letter') if allow_adding_letter_template else None,
|
('letter', 'Letter') if 'letter' in available_template_types else None,
|
||||||
|
('broadcast', 'Broadcast') if 'broadcast' in available_template_types else None,
|
||||||
('copy-existing', 'Copy an existing template') if allow_adding_copy_of_template else None,
|
('copy-existing', 'Copy an existing template') if allow_adding_copy_of_template else None,
|
||||||
]))
|
]))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def trying_to_add_unavailable_template_type(self):
|
||||||
|
return all((
|
||||||
|
self.is_add_template_op,
|
||||||
|
self.add_template_by_template_type.data,
|
||||||
|
self.add_template_by_template_type.data not in self.available_template_types,
|
||||||
|
))
|
||||||
|
|
||||||
def is_selected(self, template_folder_id):
|
def is_selected(self, template_folder_id):
|
||||||
return template_folder_id in (self.templates_and_folders.data or [])
|
return template_folder_id in (self.templates_and_folders.data or [])
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -88,12 +88,21 @@ class NoEmbeddedImagesInSVG:
|
|||||||
|
|
||||||
|
|
||||||
class OnlySMSCharacters:
|
class OnlySMSCharacters:
|
||||||
|
|
||||||
|
def __init__(self, *args, template_type, **kwargs):
|
||||||
|
self._template_type = template_type
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def __call__(self, form, field):
|
def __call__(self, form, field):
|
||||||
non_sms_characters = sorted(list(SanitiseSMS.get_non_compatible_characters(field.data)))
|
non_sms_characters = sorted(list(SanitiseSMS.get_non_compatible_characters(field.data)))
|
||||||
if non_sms_characters:
|
if non_sms_characters:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
'You cannot use {} in text messages. {} will not show up properly on everyone’s phones.'.format(
|
'You cannot use {} in {}. {} will not show up properly on everyone’s phones.'.format(
|
||||||
formatted_list(non_sms_characters, conjunction='or', before_each='', after_each=''),
|
formatted_list(non_sms_characters, conjunction='or', before_each='', after_each=''),
|
||||||
|
{
|
||||||
|
'broadcast': 'broadcasts',
|
||||||
|
'sms': 'text messages',
|
||||||
|
}.get(self._template_type),
|
||||||
('It' if len(non_sms_characters) == 1 else 'They')
|
('It' if len(non_sms_characters) == 1 else 'They')
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ from app.template_previews import TemplatePreview, get_page_count_for_letter
|
|||||||
from app.utils import (
|
from app.utils import (
|
||||||
PermanentRedirect,
|
PermanentRedirect,
|
||||||
Spreadsheet,
|
Spreadsheet,
|
||||||
email_or_sms_not_enabled,
|
|
||||||
get_errors_for_csv,
|
get_errors_for_csv,
|
||||||
get_help_argument,
|
get_help_argument,
|
||||||
get_template,
|
get_template,
|
||||||
@@ -128,7 +127,7 @@ def send_messages(service_id, template_id):
|
|||||||
elif db_template['template_type'] == 'sms':
|
elif db_template['template_type'] == 'sms':
|
||||||
sms_sender = get_sms_sender_from_session()
|
sms_sender = get_sms_sender_from_session()
|
||||||
|
|
||||||
if email_or_sms_not_enabled(db_template['template_type'], current_service.permissions):
|
if db_template['template_type'] not in current_service.available_template_types:
|
||||||
return redirect(url_for(
|
return redirect(url_for(
|
||||||
'.action_blocked',
|
'.action_blocked',
|
||||||
service_id=service_id,
|
service_id=service_id,
|
||||||
@@ -302,8 +301,11 @@ def send_test(service_id, template_id):
|
|||||||
db_template = current_service.get_template_with_user_permission_or_403(template_id, current_user)
|
db_template = current_service.get_template_with_user_permission_or_403(template_id, current_user)
|
||||||
if db_template['template_type'] == 'letter':
|
if db_template['template_type'] == 'letter':
|
||||||
session['sender_id'] = None
|
session['sender_id'] = None
|
||||||
|
return redirect(
|
||||||
|
url_for('.send_one_off_letter_address', service_id=service_id, template_id=template_id)
|
||||||
|
)
|
||||||
|
|
||||||
if email_or_sms_not_enabled(db_template['template_type'], current_service.permissions):
|
if db_template['template_type'] not in current_service.available_template_types:
|
||||||
return redirect(url_for(
|
return redirect(url_for(
|
||||||
'.action_blocked',
|
'.action_blocked',
|
||||||
service_id=service_id,
|
service_id=service_id,
|
||||||
@@ -311,11 +313,6 @@ def send_test(service_id, template_id):
|
|||||||
return_to='view_template',
|
return_to='view_template',
|
||||||
template_id=template_id))
|
template_id=template_id))
|
||||||
|
|
||||||
if db_template['template_type'] == 'letter':
|
|
||||||
return redirect(
|
|
||||||
url_for('.send_one_off_letter_address', service_id=service_id, template_id=template_id)
|
|
||||||
)
|
|
||||||
|
|
||||||
return redirect(url_for(
|
return redirect(url_for(
|
||||||
{
|
{
|
||||||
'main.send_test': '.send_test_step',
|
'main.send_test': '.send_test_step',
|
||||||
|
|||||||
+35
-37
@@ -16,6 +16,7 @@ from app import (
|
|||||||
)
|
)
|
||||||
from app.main import main, no_cookie
|
from app.main import main, no_cookie
|
||||||
from app.main.forms import (
|
from app.main.forms import (
|
||||||
|
BroadcastTemplateForm,
|
||||||
EmailTemplateForm,
|
EmailTemplateForm,
|
||||||
LetterTemplateForm,
|
LetterTemplateForm,
|
||||||
LetterTemplatePostageForm,
|
LetterTemplatePostageForm,
|
||||||
@@ -30,7 +31,6 @@ from app.models.service import Service
|
|||||||
from app.models.template_list import TemplateList, TemplateLists
|
from app.models.template_list import TemplateList, TemplateLists
|
||||||
from app.template_previews import TemplatePreview, get_page_count_for_letter
|
from app.template_previews import TemplatePreview, get_page_count_for_letter
|
||||||
from app.utils import (
|
from app.utils import (
|
||||||
email_or_sms_not_enabled,
|
|
||||||
get_template,
|
get_template,
|
||||||
should_skip_template_page,
|
should_skip_template_page,
|
||||||
user_has_permissions,
|
user_has_permissions,
|
||||||
@@ -40,7 +40,8 @@ from app.utils import (
|
|||||||
form_objects = {
|
form_objects = {
|
||||||
'email': EmailTemplateForm,
|
'email': EmailTemplateForm,
|
||||||
'sms': SMSTemplateForm,
|
'sms': SMSTemplateForm,
|
||||||
'letter': LetterTemplateForm
|
'letter': LetterTemplateForm,
|
||||||
|
'broadcast': BroadcastTemplateForm,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ def choose_template(service_id, template_type='all', template_folder_id=None):
|
|||||||
all_template_folders=current_service.get_user_template_folders(current_user),
|
all_template_folders=current_service.get_user_template_folders(current_user),
|
||||||
template_list=template_list,
|
template_list=template_list,
|
||||||
template_type=template_type,
|
template_type=template_type,
|
||||||
allow_adding_letter_template=current_service.has_permission('letter'),
|
available_template_types=current_service.available_template_types,
|
||||||
allow_adding_copy_of_template=(
|
allow_adding_copy_of_template=(
|
||||||
current_service.all_templates or len(current_user.service_ids) > 1
|
current_service.all_templates or len(current_user.service_ids) > 1
|
||||||
),
|
),
|
||||||
@@ -136,6 +137,13 @@ def choose_template(service_id, template_type='all', template_folder_id=None):
|
|||||||
return process_folder_management_form(templates_and_folders_form, template_folder_id)
|
return process_folder_management_form(templates_and_folders_form, template_folder_id)
|
||||||
except HTTPError as e:
|
except HTTPError as e:
|
||||||
flash(e.message)
|
flash(e.message)
|
||||||
|
elif templates_and_folders_form.trying_to_add_unavailable_template_type:
|
||||||
|
return redirect(url_for(
|
||||||
|
'.action_blocked',
|
||||||
|
service_id=current_service.id,
|
||||||
|
notification_type=templates_and_folders_form.add_template_by_template_type.data,
|
||||||
|
return_to='add_new_template',
|
||||||
|
))
|
||||||
|
|
||||||
if 'templates_and_folders' in templates_and_folders_form.errors:
|
if 'templates_and_folders' in templates_and_folders_form.errors:
|
||||||
flash('Select at least one template or folder')
|
flash('Select at least one template or folder')
|
||||||
@@ -199,6 +207,7 @@ def get_template_nav_label(value):
|
|||||||
'sms': 'Text message',
|
'sms': 'Text message',
|
||||||
'email': 'Email',
|
'email': 'Email',
|
||||||
'letter': 'Letter',
|
'letter': 'Letter',
|
||||||
|
'broadcast': 'Broadcast',
|
||||||
}[value]
|
}[value]
|
||||||
|
|
||||||
|
|
||||||
@@ -310,20 +319,12 @@ def _add_template_by_type(template_type, template_folder_id):
|
|||||||
template_id=blank_letter['data']['id'],
|
template_id=blank_letter['data']['id'],
|
||||||
))
|
))
|
||||||
|
|
||||||
if email_or_sms_not_enabled(template_type, current_service.permissions):
|
return redirect(url_for(
|
||||||
return redirect(url_for(
|
'.add_service_template',
|
||||||
'.action_blocked',
|
service_id=current_service.id,
|
||||||
service_id=current_service.id,
|
template_type=template_type,
|
||||||
notification_type=template_type,
|
template_folder_id=template_folder_id,
|
||||||
return_to='add_new_template',
|
))
|
||||||
))
|
|
||||||
else:
|
|
||||||
return redirect(url_for(
|
|
||||||
'.add_service_template',
|
|
||||||
service_id=current_service.id,
|
|
||||||
template_type=template_type,
|
|
||||||
template_folder_id=template_folder_id,
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
@main.route("/services/<uuid:service_id>/templates/copy")
|
@main.route("/services/<uuid:service_id>/templates/copy")
|
||||||
@@ -437,7 +438,7 @@ def action_blocked(service_id, notification_type, return_to, template_id=None):
|
|||||||
service_id=service_id,
|
service_id=service_id,
|
||||||
notification_type=notification_type,
|
notification_type=notification_type,
|
||||||
back_link=back_link(),
|
back_link=back_link(),
|
||||||
)
|
), 403
|
||||||
|
|
||||||
|
|
||||||
@main.route("/services/<uuid:service_id>/templates/folders/<uuid:template_folder_id>/manage", methods=['GET', 'POST'])
|
@main.route("/services/<uuid:service_id>/templates/folders/<uuid:template_folder_id>/manage", methods=['GET', 'POST'])
|
||||||
@@ -527,8 +528,14 @@ def delete_template_folder(service_id, template_folder_id):
|
|||||||
@user_has_permissions('manage_templates')
|
@user_has_permissions('manage_templates')
|
||||||
def add_service_template(service_id, template_type, template_folder_id=None):
|
def add_service_template(service_id, template_type, template_folder_id=None):
|
||||||
|
|
||||||
if not current_service.has_permission('letter') and template_type == 'letter':
|
if template_type not in current_service.available_template_types:
|
||||||
abort(403)
|
return redirect(url_for(
|
||||||
|
'.action_blocked',
|
||||||
|
service_id=service_id,
|
||||||
|
notification_type=template_type,
|
||||||
|
template_folder_id=template_folder_id,
|
||||||
|
return_to='templates',
|
||||||
|
))
|
||||||
|
|
||||||
form = form_objects[template_type]()
|
form = form_objects[template_type]()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
@@ -558,22 +565,13 @@ def add_service_template(service_id, template_type, template_folder_id=None):
|
|||||||
url_for('.view_template', service_id=service_id, template_id=new_template['data']['id'])
|
url_for('.view_template', service_id=service_id, template_id=new_template['data']['id'])
|
||||||
)
|
)
|
||||||
|
|
||||||
if email_or_sms_not_enabled(template_type, current_service.permissions):
|
return render_template(
|
||||||
return redirect(url_for(
|
'views/edit-{}-template.html'.format(template_type),
|
||||||
'.action_blocked',
|
form=form,
|
||||||
service_id=service_id,
|
template_type=template_type,
|
||||||
notification_type=template_type,
|
template_folder_id=template_folder_id,
|
||||||
template_folder_id=template_folder_id,
|
heading_action='New',
|
||||||
return_to='templates',
|
)
|
||||||
))
|
|
||||||
else:
|
|
||||||
return render_template(
|
|
||||||
'views/edit-{}-template.html'.format(template_type),
|
|
||||||
form=form,
|
|
||||||
template_type=template_type,
|
|
||||||
template_folder_id=template_folder_id,
|
|
||||||
heading_action='New',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def abort_403_if_not_admin_user():
|
def abort_403_if_not_admin_user():
|
||||||
@@ -642,7 +640,7 @@ def edit_service_template(service_id, template_id):
|
|||||||
template_id=template_id
|
template_id=template_id
|
||||||
))
|
))
|
||||||
|
|
||||||
if email_or_sms_not_enabled(template['template_type'], current_service.permissions):
|
if template['template_type'] not in current_service.available_template_types:
|
||||||
return redirect(url_for(
|
return redirect(url_for(
|
||||||
'.action_blocked',
|
'.action_blocked',
|
||||||
service_id=service_id,
|
service_id=service_id,
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class Service(JSONModel):
|
|||||||
'email',
|
'email',
|
||||||
'sms',
|
'sms',
|
||||||
'letter',
|
'letter',
|
||||||
|
'broadcast',
|
||||||
)
|
)
|
||||||
|
|
||||||
ALL_PERMISSIONS = TEMPLATE_TYPES + (
|
ALL_PERMISSIONS = TEMPLATE_TYPES + (
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ class TemplateListTemplate(TemplateListItem):
|
|||||||
'email': 'Email template',
|
'email': 'Email template',
|
||||||
'sms': 'Text message template',
|
'sms': 'Text message template',
|
||||||
'letter': 'Letter template',
|
'letter': 'Letter template',
|
||||||
|
'broadcast': 'Broadcast template',
|
||||||
}.get(template['template_type'])
|
}.get(template['template_type'])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,12 @@
|
|||||||
{%- else -%}
|
{%- else -%}
|
||||||
letters
|
letters
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
{%- elif template_type == 'broadcast' -%}
|
||||||
|
{%- if count == 1 -%}
|
||||||
|
broadcast
|
||||||
|
{%- else -%}
|
||||||
|
broadcasts
|
||||||
|
{%- endif -%}
|
||||||
{%- endif %} {{ suffix }}
|
{%- endif %} {{ suffix }}
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
{% extends "withnav_template.html" %}
|
||||||
|
{% from "components/textbox.html" import textbox %}
|
||||||
|
{% from "components/page-header.html" import page_header %}
|
||||||
|
{% from "components/page-footer.html" import sticky_page_footer %}
|
||||||
|
{% from "components/form.html" import form_wrapper %}
|
||||||
|
|
||||||
|
{% block service_page_title %}
|
||||||
|
{{ heading_action }} broadcast template
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block maincolumn_content %}
|
||||||
|
|
||||||
|
{{ page_header(
|
||||||
|
'{} broadcast template'.format(heading_action),
|
||||||
|
back_link=url_for('main.view_template', service_id=current_service.id, template_id=template.id) if template else url_for('main.choose_template', service_id=current_service.id, template_folder_id=template_folder_id)
|
||||||
|
) }}
|
||||||
|
|
||||||
|
{% call form_wrapper() %}
|
||||||
|
<div class="govuk-grid-row">
|
||||||
|
<div class="govuk-grid-column-two-thirds">
|
||||||
|
{{ textbox(form.name, width='1-1', hint='Your recipients will not see this') }}
|
||||||
|
</div>
|
||||||
|
<div class="govuk-grid-column-two-thirds">
|
||||||
|
{{ textbox(form.template_content, highlight_placeholders=True, width='1-1', rows=5) }}
|
||||||
|
{{ sticky_page_footer('Save') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endcall %}
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -28,6 +28,14 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% elif template.template_type == 'broadcast' %}
|
||||||
|
{% if current_user.has_permissions('manage_templates') %}
|
||||||
|
<div class="govuk-grid-column-full">
|
||||||
|
<a href="{{ url_for(".edit_service_template", service_id=current_service.id, template_id=template.id) }}" class="govuk-link govuk-link--no-visited-state pill-separate-item">
|
||||||
|
Edit
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if current_user.has_permissions('send_messages', restrict_admin_usage=True) %}
|
{% if current_user.has_permissions('send_messages', restrict_admin_usage=True) %}
|
||||||
<div class="govuk-grid-column-one-half">
|
<div class="govuk-grid-column-one-half">
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ from app.models.feedback import (
|
|||||||
PROBLEM_TICKET_TYPE,
|
PROBLEM_TICKET_TYPE,
|
||||||
QUESTION_TICKET_TYPE,
|
QUESTION_TICKET_TYPE,
|
||||||
)
|
)
|
||||||
|
from app.models.service import Service
|
||||||
|
|
||||||
|
|
||||||
class TemplateTypeConverter(BaseConverter):
|
class TemplateTypeConverter(BaseConverter):
|
||||||
|
|
||||||
regex = '(?:email|sms|letter)'
|
regex = '(?:{})'.format('|'.join(Service.TEMPLATE_TYPES))
|
||||||
|
|
||||||
|
|
||||||
class TicketTypeConverter(BaseConverter):
|
class TicketTypeConverter(BaseConverter):
|
||||||
|
|||||||
+5
-4
@@ -37,6 +37,7 @@ from notifications_utils.postal_address import PostalAddress
|
|||||||
from notifications_utils.recipients import RecipientCSV
|
from notifications_utils.recipients import RecipientCSV
|
||||||
from notifications_utils.take import Take
|
from notifications_utils.take import Take
|
||||||
from notifications_utils.template import (
|
from notifications_utils.template import (
|
||||||
|
BroadcastPreviewTemplate,
|
||||||
EmailPreviewTemplate,
|
EmailPreviewTemplate,
|
||||||
LetterImageTemplate,
|
LetterImageTemplate,
|
||||||
LetterPreviewTemplate,
|
LetterPreviewTemplate,
|
||||||
@@ -451,6 +452,10 @@ def get_template(
|
|||||||
admin_base_url=current_app.config['ADMIN_BASE_URL'],
|
admin_base_url=current_app.config['ADMIN_BASE_URL'],
|
||||||
redact_missing_personalisation=redact_missing_personalisation,
|
redact_missing_personalisation=redact_missing_personalisation,
|
||||||
)
|
)
|
||||||
|
if 'broadcast' == template['template_type']:
|
||||||
|
return BroadcastPreviewTemplate(
|
||||||
|
template,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_current_financial_year():
|
def get_current_financial_year():
|
||||||
@@ -475,10 +480,6 @@ def get_time_left(created_at, service_data_retention_days=7):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def email_or_sms_not_enabled(template_type, permissions):
|
|
||||||
return (template_type in ['email', 'sms']) and (template_type not in permissions)
|
|
||||||
|
|
||||||
|
|
||||||
def get_logo_cdn_domain():
|
def get_logo_cdn_domain():
|
||||||
parsed_uri = urlparse(current_app.config['ADMIN_BASE_URL'])
|
parsed_uri = urlparse(current_app.config['ADMIN_BASE_URL'])
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ notifications-python-client==5.6.0
|
|||||||
awscli-cwlogs>=1.4,<1.5
|
awscli-cwlogs>=1.4,<1.5
|
||||||
itsdangerous==1.1.0
|
itsdangerous==1.1.0
|
||||||
|
|
||||||
git+https://github.com/alphagov/notifications-utils.git@39.7.0#egg=notifications-utils==39.7.0
|
git+https://github.com/alphagov/notifications-utils.git@40.1.0#egg=notifications-utils==40.1.0
|
||||||
git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha
|
git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha
|
||||||
|
|
||||||
# gds-metrics requires prometheseus 0.2.0, override that requirement as later versions bring significant performance gains
|
# gds-metrics requires prometheseus 0.2.0, override that requirement as later versions bring significant performance gains
|
||||||
|
|||||||
+3
-3
@@ -25,7 +25,7 @@ notifications-python-client==5.6.0
|
|||||||
awscli-cwlogs>=1.4,<1.5
|
awscli-cwlogs>=1.4,<1.5
|
||||||
itsdangerous==1.1.0
|
itsdangerous==1.1.0
|
||||||
|
|
||||||
git+https://github.com/alphagov/notifications-utils.git@39.7.0#egg=notifications-utils==39.7.0
|
git+https://github.com/alphagov/notifications-utils.git@40.1.0#egg=notifications-utils==40.1.0
|
||||||
git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha
|
git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha
|
||||||
|
|
||||||
# gds-metrics requires prometheseus 0.2.0, override that requirement as later versions bring significant performance gains
|
# gds-metrics requires prometheseus 0.2.0, override that requirement as later versions bring significant performance gains
|
||||||
@@ -33,10 +33,10 @@ prometheus-client==0.8.0
|
|||||||
gds-metrics==0.2.0
|
gds-metrics==0.2.0
|
||||||
|
|
||||||
## The following requirements were added by pip freeze:
|
## The following requirements were added by pip freeze:
|
||||||
awscli==1.18.90
|
awscli==1.18.91
|
||||||
bleach==3.1.4
|
bleach==3.1.4
|
||||||
boto3==1.10.38
|
boto3==1.10.38
|
||||||
botocore==1.17.13
|
botocore==1.17.14
|
||||||
cachetools==4.1.0
|
cachetools==4.1.0
|
||||||
certifi==2020.6.20
|
certifi==2020.6.20
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ def test_for_commas_in_placeholders(
|
|||||||
|
|
||||||
@pytest.mark.parametrize('msg', ['The quick brown fox', 'Thé “quick” bröwn fox\u200B'])
|
@pytest.mark.parametrize('msg', ['The quick brown fox', 'Thé “quick” bröwn fox\u200B'])
|
||||||
def test_sms_character_validation(client, msg):
|
def test_sms_character_validation(client, msg):
|
||||||
OnlySMSCharacters()(None, _gen_mock_field(msg))
|
OnlySMSCharacters(template_type='sms')(None, _gen_mock_field(msg))
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('data, err_msg', [
|
@pytest.mark.parametrize('data, err_msg', [
|
||||||
@@ -175,7 +175,7 @@ def test_sms_character_validation(client, msg):
|
|||||||
])
|
])
|
||||||
def test_non_sms_character_validation(data, err_msg, client):
|
def test_non_sms_character_validation(data, err_msg, client):
|
||||||
with pytest.raises(ValidationError) as error:
|
with pytest.raises(ValidationError) as error:
|
||||||
OnlySMSCharacters()(None, _gen_mock_field(data))
|
OnlySMSCharacters(template_type='sms')(None, _gen_mock_field(data))
|
||||||
|
|
||||||
assert str(error.value) == err_msg
|
assert str(error.value) == err_msg
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ letters_urls = [
|
|||||||
([], 403)
|
([], 403)
|
||||||
])
|
])
|
||||||
def test_letters_access_restricted(
|
def test_letters_access_restricted(
|
||||||
platform_admin_client,
|
client_request,
|
||||||
|
platform_admin_user,
|
||||||
mocker,
|
mocker,
|
||||||
permissions,
|
permissions,
|
||||||
response_code,
|
response_code,
|
||||||
@@ -23,12 +24,12 @@ def test_letters_access_restricted(
|
|||||||
service_one,
|
service_one,
|
||||||
):
|
):
|
||||||
service_one['permissions'] = permissions
|
service_one['permissions'] = permissions
|
||||||
|
client_request.login(platform_admin_user)
|
||||||
mocker.patch('app.service_api_client.get_service', return_value={"data": service_one})
|
client_request.get_url(
|
||||||
|
url(service_id=service_one['id']),
|
||||||
response = platform_admin_client.get(url(service_id=service_one['id']))
|
_follow_redirects=True,
|
||||||
|
_expected_status=response_code,
|
||||||
assert response.status_code == response_code
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('url', letters_urls)
|
@pytest.mark.parametrize('url', letters_urls)
|
||||||
|
|||||||
@@ -280,6 +280,7 @@ def test_should_not_allow_files_to_be_uploaded_without_the_correct_permission(
|
|||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
template_id=template_id,
|
template_id=template_id,
|
||||||
_follow_redirects=True,
|
_follow_redirects=True,
|
||||||
|
_expected_status=403,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert page.select('main p')[0].text.strip() == "Sending text messages has been disabled for your service."
|
assert page.select('main p')[0].text.strip() == "Sending text messages has been disabled for your service."
|
||||||
@@ -312,10 +313,12 @@ def test_example_spreadsheet(
|
|||||||
|
|
||||||
def test_example_spreadsheet_for_letters(
|
def test_example_spreadsheet_for_letters(
|
||||||
client_request,
|
client_request,
|
||||||
|
service_one,
|
||||||
mocker,
|
mocker,
|
||||||
mock_get_service_letter_template_with_placeholders,
|
mock_get_service_letter_template_with_placeholders,
|
||||||
fake_uuid,
|
fake_uuid,
|
||||||
):
|
):
|
||||||
|
service_one['permissions'] += ['letter']
|
||||||
mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=1)
|
mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=1)
|
||||||
|
|
||||||
page = client_request.get(
|
page = client_request.get(
|
||||||
@@ -600,6 +603,7 @@ def test_upload_csv_file_with_bad_postal_address_shows_check_page_with_errors(
|
|||||||
mock_get_jobs,
|
mock_get_jobs,
|
||||||
fake_uuid,
|
fake_uuid,
|
||||||
):
|
):
|
||||||
|
service_one['permissions'] += ['letter']
|
||||||
mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=9)
|
mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=9)
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
'app.main.views.send.s3download',
|
'app.main.views.send.s3download',
|
||||||
@@ -658,7 +662,7 @@ def test_upload_csv_file_with_international_letters_permission_shows_appropriate
|
|||||||
mock_get_jobs,
|
mock_get_jobs,
|
||||||
fake_uuid,
|
fake_uuid,
|
||||||
):
|
):
|
||||||
service_one['permissions'] += ['international_letters']
|
service_one['permissions'] += ['letter', 'international_letters']
|
||||||
mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=9)
|
mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=9)
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
'app.main.views.send.s3download',
|
'app.main.views.send.s3download',
|
||||||
@@ -1328,6 +1332,7 @@ def test_send_one_off_does_not_send_without_the_correct_permissions(
|
|||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
template_id=template_id,
|
template_id=template_id,
|
||||||
_follow_redirects=True,
|
_follow_redirects=True,
|
||||||
|
_expected_status=403,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert page.select('main p')[0].text.strip() == "Sending text messages has been disabled for your service."
|
assert page.select('main p')[0].text.strip() == "Sending text messages has been disabled for your service."
|
||||||
|
|||||||
@@ -674,6 +674,41 @@ def test_should_be_able_to_view_a_template_with_links(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_view_broadcast_template(
|
||||||
|
client_request,
|
||||||
|
service_one,
|
||||||
|
mock_get_broadcast_template,
|
||||||
|
mock_get_template_folders,
|
||||||
|
active_user_with_permissions,
|
||||||
|
fake_uuid,
|
||||||
|
):
|
||||||
|
page = client_request.get(
|
||||||
|
'.view_template',
|
||||||
|
service_id=SERVICE_ONE_ID,
|
||||||
|
template_id=fake_uuid,
|
||||||
|
_test_page_title=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
(link.text.strip(), link['href'])
|
||||||
|
for link in page.select('.pill-separate-item')
|
||||||
|
] == [
|
||||||
|
('Edit', url_for(
|
||||||
|
'.edit_service_template',
|
||||||
|
service_id=SERVICE_ONE_ID,
|
||||||
|
template_id=fake_uuid,
|
||||||
|
)),
|
||||||
|
]
|
||||||
|
|
||||||
|
assert (
|
||||||
|
normalize_spaces(page.select_one('.template-container').text)
|
||||||
|
) == (
|
||||||
|
normalize_spaces(page.select_one('.broadcast-message-wrapper').text)
|
||||||
|
) == (
|
||||||
|
'This is a test'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_should_show_template_id_on_template_page(
|
def test_should_show_template_id_on_template_page(
|
||||||
client_request,
|
client_request,
|
||||||
mock_get_service_template,
|
mock_get_service_template,
|
||||||
@@ -1241,9 +1276,9 @@ def test_cant_copy_template_from_non_member_service(
|
|||||||
assert mock_get_service_email_template.call_args_list == []
|
assert mock_get_service_email_template.call_args_list == []
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('endpoint, data, expected_error', (
|
@pytest.mark.parametrize('service_permissions, data, expected_error', (
|
||||||
(
|
(
|
||||||
'main.choose_template',
|
['letter'],
|
||||||
{
|
{
|
||||||
'operation': 'add-new-template',
|
'operation': 'add-new-template',
|
||||||
'add_template_by_template_type': 'email',
|
'add_template_by_template_type': 'email',
|
||||||
@@ -1251,30 +1286,47 @@ def test_cant_copy_template_from_non_member_service(
|
|||||||
"Sending emails has been disabled for your service."
|
"Sending emails has been disabled for your service."
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
'main.choose_template',
|
['email'],
|
||||||
{
|
{
|
||||||
'operation': 'add-new-template',
|
'operation': 'add-new-template',
|
||||||
'add_template_by_template_type': 'sms',
|
'add_template_by_template_type': 'sms',
|
||||||
},
|
},
|
||||||
"Sending text messages has been disabled for your service."
|
"Sending text messages has been disabled for your service."
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
['sms'],
|
||||||
|
{
|
||||||
|
'operation': 'add-new-template',
|
||||||
|
'add_template_by_template_type': 'letter',
|
||||||
|
},
|
||||||
|
"Sending letters has been disabled for your service."
|
||||||
|
),
|
||||||
|
(
|
||||||
|
['letter'],
|
||||||
|
{
|
||||||
|
'operation': 'add-new-template',
|
||||||
|
'add_template_by_template_type': 'broadcast',
|
||||||
|
},
|
||||||
|
"Sending broadcasts has been disabled for your service."
|
||||||
|
),
|
||||||
))
|
))
|
||||||
def test_should_not_allow_creation_of_template_through_form_without_correct_permission(
|
def test_should_not_allow_creation_of_template_through_form_without_correct_permission(
|
||||||
client_request,
|
client_request,
|
||||||
service_one,
|
service_one,
|
||||||
mock_get_service_templates,
|
mock_get_service_templates,
|
||||||
mock_get_template_folders,
|
mock_get_template_folders,
|
||||||
endpoint,
|
service_permissions,
|
||||||
data,
|
data,
|
||||||
expected_error,
|
expected_error,
|
||||||
fake_uuid,
|
fake_uuid,
|
||||||
):
|
):
|
||||||
service_one['permissions'] = []
|
service_one['permissions'] = service_permissions
|
||||||
page = client_request.post(
|
page = client_request.post(
|
||||||
endpoint,
|
'main.choose_template',
|
||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
_data=data,
|
_data=data,
|
||||||
_follow_redirects=True,
|
_follow_redirects=True,
|
||||||
|
_expected_status=403,
|
||||||
)
|
)
|
||||||
assert normalize_spaces(page.select('main p')[0].text) == expected_error
|
assert normalize_spaces(page.select('main p')[0].text) == expected_error
|
||||||
assert page.select(".govuk-back-link")[0].text == "Back"
|
assert page.select(".govuk-back-link")[0].text == "Back"
|
||||||
@@ -1284,24 +1336,31 @@ def test_should_not_allow_creation_of_template_through_form_without_correct_perm
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('type_of_template', ['email', 'sms'])
|
@pytest.mark.parametrize('method', ('get', 'post'))
|
||||||
|
@pytest.mark.parametrize('type_of_template, expected_error', [
|
||||||
|
('email', 'Sending emails has been disabled for your service.'),
|
||||||
|
('sms', 'Sending text messages has been disabled for your service.'),
|
||||||
|
('letter', 'Sending letters has been disabled for your service.'),
|
||||||
|
('broadcast', 'Sending broadcasts has been disabled for your service.'),
|
||||||
|
])
|
||||||
def test_should_not_allow_creation_of_a_template_without_correct_permission(
|
def test_should_not_allow_creation_of_a_template_without_correct_permission(
|
||||||
client_request,
|
client_request,
|
||||||
service_one,
|
service_one,
|
||||||
mocker,
|
mocker,
|
||||||
|
method,
|
||||||
type_of_template,
|
type_of_template,
|
||||||
|
expected_error,
|
||||||
):
|
):
|
||||||
service_one['permissions'] = []
|
service_one['permissions'] = []
|
||||||
template_description = {'sms': 'text messages', 'email': 'emails'}
|
|
||||||
|
|
||||||
page = client_request.get(
|
page = getattr(client_request, method)(
|
||||||
'.add_service_template',
|
'.add_service_template',
|
||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
template_type=type_of_template,
|
template_type=type_of_template,
|
||||||
_follow_redirects=True,
|
_follow_redirects=True,
|
||||||
|
_expected_status=403,
|
||||||
)
|
)
|
||||||
assert page.select('main p')[0].text.strip() == \
|
assert page.select('main p')[0].text.strip() == expected_error
|
||||||
"Sending {} has been disabled for your service.".format(template_description[type_of_template])
|
|
||||||
assert page.select(".govuk-back-link")[0].text == "Back"
|
assert page.select(".govuk-back-link")[0].text == "Back"
|
||||||
assert page.select(".govuk-back-link")[0]['href'] == url_for(
|
assert page.select(".govuk-back-link")[0]['href'] == url_for(
|
||||||
'.choose_template',
|
'.choose_template',
|
||||||
@@ -1419,6 +1478,7 @@ def test_should_not_allow_template_edits_without_correct_permission(
|
|||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
template_id=fake_uuid,
|
template_id=fake_uuid,
|
||||||
_follow_redirects=True,
|
_follow_redirects=True,
|
||||||
|
_expected_status=403,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert page.select('main p')[0].text.strip() == "Sending text messages has been disabled for your service."
|
assert page.select('main p')[0].text.strip() == "Sending text messages has been disabled for your service."
|
||||||
@@ -1934,15 +1994,26 @@ def test_can_create_email_template_with_emoji(
|
|||||||
assert mock_create_service_template.called is True
|
assert mock_create_service_template.called is True
|
||||||
|
|
||||||
|
|
||||||
def test_should_not_create_sms_template_with_emoji(
|
@pytest.mark.parametrize('template_type, expected_error', (
|
||||||
|
('sms', (
|
||||||
|
'You cannot use 🍜 in text messages.'
|
||||||
|
)),
|
||||||
|
('broadcast', (
|
||||||
|
'You cannot use 🍜 in broadcasts.'
|
||||||
|
)),
|
||||||
|
))
|
||||||
|
def test_should_not_create_sms_or_broadcast_template_with_emoji(
|
||||||
client_request,
|
client_request,
|
||||||
service_one,
|
service_one,
|
||||||
mock_create_service_template,
|
mock_create_service_template,
|
||||||
|
template_type,
|
||||||
|
expected_error,
|
||||||
):
|
):
|
||||||
|
service_one['permissions'] += [template_type]
|
||||||
page = client_request.post(
|
page = client_request.post(
|
||||||
'.add_service_template',
|
'.add_service_template',
|
||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
template_type='sms',
|
template_type=template_type,
|
||||||
_data={
|
_data={
|
||||||
'name': "new name",
|
'name': "new name",
|
||||||
'template_content': "here are some noodles 🍜",
|
'template_content': "here are some noodles 🍜",
|
||||||
@@ -1952,16 +2023,37 @@ def test_should_not_create_sms_template_with_emoji(
|
|||||||
},
|
},
|
||||||
_expected_status=200,
|
_expected_status=200,
|
||||||
)
|
)
|
||||||
assert "You cannot use 🍜 in text messages." in page.text
|
assert expected_error in page.text
|
||||||
assert mock_create_service_template.called is False
|
assert mock_create_service_template.called is False
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('template_type, expected_error', (
|
||||||
|
('sms', (
|
||||||
|
'You cannot use 🍔 in text messages.'
|
||||||
|
)),
|
||||||
|
('broadcast', (
|
||||||
|
'You cannot use 🍔 in broadcasts.'
|
||||||
|
)),
|
||||||
|
))
|
||||||
def test_should_not_update_sms_template_with_emoji(
|
def test_should_not_update_sms_template_with_emoji(
|
||||||
|
mocker,
|
||||||
client_request,
|
client_request,
|
||||||
|
service_one,
|
||||||
mock_get_service_template,
|
mock_get_service_template,
|
||||||
mock_update_service_template,
|
mock_update_service_template,
|
||||||
fake_uuid,
|
fake_uuid,
|
||||||
|
template_type,
|
||||||
|
expected_error,
|
||||||
):
|
):
|
||||||
|
service_one['permissions'] += [template_type]
|
||||||
|
return mocker.patch(
|
||||||
|
'app.service_api_client.get_service_template',
|
||||||
|
return_value=template_json(
|
||||||
|
SERVICE_ONE_ID,
|
||||||
|
fake_uuid,
|
||||||
|
type_=template_type,
|
||||||
|
),
|
||||||
|
)
|
||||||
page = client_request.post(
|
page = client_request.post(
|
||||||
'.edit_service_template',
|
'.edit_service_template',
|
||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
@@ -1971,19 +2063,26 @@ def test_should_not_update_sms_template_with_emoji(
|
|||||||
'name': "new name",
|
'name': "new name",
|
||||||
'template_content': "here's a burger 🍔",
|
'template_content': "here's a burger 🍔",
|
||||||
'service': SERVICE_ONE_ID,
|
'service': SERVICE_ONE_ID,
|
||||||
'template_type': 'sms',
|
'template_type': template_type,
|
||||||
'process_type': 'normal'
|
'process_type': 'normal'
|
||||||
},
|
},
|
||||||
_expected_status=200,
|
_expected_status=200,
|
||||||
)
|
)
|
||||||
assert "You cannot use 🍔 in text messages." in page.text
|
assert expected_error in page.text
|
||||||
assert mock_update_service_template.called is False
|
assert mock_update_service_template.called is False
|
||||||
|
|
||||||
|
|
||||||
def test_should_create_sms_template_without_downgrading_unicode_characters(
|
@pytest.mark.parametrize('template_type', (
|
||||||
|
'sms', 'broadcast'
|
||||||
|
))
|
||||||
|
def test_should_create_sms_or_broadcast_template_without_downgrading_unicode_characters(
|
||||||
client_request,
|
client_request,
|
||||||
mock_create_service_template
|
service_one,
|
||||||
|
mock_create_service_template,
|
||||||
|
template_type,
|
||||||
):
|
):
|
||||||
|
service_one['permissions'] += [template_type]
|
||||||
|
|
||||||
msg = 'here:\tare some “fancy quotes” and non\u200Bbreaking\u200Bspaces'
|
msg = 'here:\tare some “fancy quotes” and non\u200Bbreaking\u200Bspaces'
|
||||||
|
|
||||||
client_request.post(
|
client_request.post(
|
||||||
@@ -1993,7 +2092,7 @@ def test_should_create_sms_template_without_downgrading_unicode_characters(
|
|||||||
_data={
|
_data={
|
||||||
'name': "new name",
|
'name': "new name",
|
||||||
'template_content': msg,
|
'template_content': msg,
|
||||||
'template_type': 'sms',
|
'template_type': template_type,
|
||||||
'service': SERVICE_ONE_ID,
|
'service': SERVICE_ONE_ID,
|
||||||
'process_type': 'normal'
|
'process_type': 'normal'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -841,6 +841,26 @@ def mock_get_service_email_template(mocker):
|
|||||||
'app.service_api_client.get_service_template', side_effect=_get)
|
'app.service_api_client.get_service_template', side_effect=_get)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='function')
|
||||||
|
def mock_get_broadcast_template(mocker):
|
||||||
|
def _get(service_id, template_id, version=None):
|
||||||
|
template = template_json(
|
||||||
|
service_id,
|
||||||
|
template_id,
|
||||||
|
'Test alert',
|
||||||
|
'broadcast',
|
||||||
|
'This is a test',
|
||||||
|
)
|
||||||
|
if version:
|
||||||
|
template.update({'version': version})
|
||||||
|
return {'data': template}
|
||||||
|
|
||||||
|
return mocker.patch(
|
||||||
|
'app.service_api_client.get_service_template',
|
||||||
|
side_effect=_get
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='function')
|
@pytest.fixture(scope='function')
|
||||||
def mock_get_service_email_template_without_placeholders(mocker):
|
def mock_get_service_email_template_without_placeholders(mocker):
|
||||||
def _get(service_id, template_id, version=None):
|
def _get(service_id, template_id, version=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user