Merge branch 'master' into features-content-updates

This commit is contained in:
karlchillmaid
2019-04-16 13:50:50 +01:00
committed by GitHub
56 changed files with 894 additions and 5545 deletions

View File

@@ -36,10 +36,8 @@ from wtforms.widgets import CheckboxInput, ListWidget
from app.main.validators import (
Blacklist,
CanonicalGovernmentDomain,
CsvFileValidator,
DoesNotStartWithDoubleZero,
KnownGovernmentDomain,
LettersNumbersAndFullStopsOnly,
NoCommasInPlaceHolders,
OnlyGSMCharacters,
@@ -47,7 +45,7 @@ from app.main.validators import (
ValidGovEmail,
)
from app.models.user import permissions, roles
from app.utils import AgreementInfo, guess_name_from_email_address
from app.utils import guess_name_from_email_address
def get_time_value_and_label(future_time):
@@ -990,23 +988,9 @@ class PreviewBranding(StripWhitespaceForm):
branding_style = HiddenFieldWithNoneOption('branding_style')
class GovernmentDomainField(StringField):
validators = [
KnownGovernmentDomain(),
CanonicalGovernmentDomain(),
]
def post_validate(self, form, validation_stopped):
if self.data == '':
self.data = None
if self.data and not self.errors:
self.data = AgreementInfo(self.data).canonical_domain
class ServiceUpdateEmailBranding(StripWhitespaceForm):
name = StringField('Name of brand')
text = StringField('Text')
domain = GovernmentDomainField('Domain')
colour = StringField(
'Colour',
validators=[
@@ -1041,7 +1025,6 @@ class SVGFileUpload(StripWhitespaceForm):
class ServiceLetterBrandingDetails(StripWhitespaceForm):
name = StringField('Name of brand', validators=[DataRequired()])
domain = GovernmentDomainField('Domain')
class PDFUploadForm(StripWhitespaceForm):

View File

@@ -11,7 +11,7 @@ from wtforms.validators import Email
from app import formatted_list
from app.main._blacklisted_passwords import blacklisted_passwords
from app.utils import AgreementInfo, Spreadsheet, is_gov_user
from app.utils import Spreadsheet, is_gov_user
class Blacklist:
@@ -111,34 +111,3 @@ class DoesNotStartWithDoubleZero:
def __call__(self, form, field):
if field.data and field.data.startswith("00"):
raise ValidationError(self.message)
class KnownGovernmentDomain:
message = 'Not a known government domain (you might need to update domains.yml)'
def __call__(self, form, field):
if field.data and AgreementInfo(field.data).owner is None:
raise ValidationError(self.message)
class CanonicalGovernmentDomain:
message = 'Not {} domain (use {} if appropriate)'
def __call__(self, form, field):
if not field.data:
return
domain = AgreementInfo(field.data)
if not domain.is_canonical:
raise ValidationError(
self.message.format('a canonical', domain.canonical_domain)
)
if field.data != domain.canonical_domain:
raise ValidationError(
self.message.format('an organisation-level', domain.canonical_domain)
)

View File

@@ -2,17 +2,15 @@ from flask import current_app, redirect, render_template, session, url_for
from flask_login import login_required
from notifications_python_client.errors import HTTPError
from app import billing_api_client, email_branding_client, service_api_client
from app import billing_api_client, service_api_client
from app.main import main
from app.main.forms import CreateServiceForm
from app.utils import AgreementInfo, email_safe, user_is_gov_user
from app.utils import email_safe, user_is_gov_user
def _create_service(service_name, organisation_type, email_from, form):
free_sms_fragment_limit = current_app.config['DEFAULT_FREE_SMS_FRAGMENT_LIMITS'].get(organisation_type)
domain = 'nhs.uk' if organisation_type == 'nhs' else AgreementInfo.from_current_user().canonical_domain
email_branding = email_branding_client.get_email_branding_id_for_domain(domain)
try:
service_id = service_api_client.create_service(
service_name=service_name,
@@ -21,13 +19,9 @@ def _create_service(service_name, organisation_type, email_from, form):
restricted=True,
user_id=session['user_id'],
email_from=email_from,
service_domain=domain
)
session['service_id'] = service_id
if email_branding:
service_api_client.update_service(service_id, email_branding=email_branding)
billing_api_client.create_or_update_free_sms_fragment_limit(service_id, free_sms_fragment_limit)
return service_id, None

View File

@@ -1,21 +1,17 @@
from flask import abort, render_template, request, send_file, url_for
from flask_login import login_required
from flask_login import current_user, login_required
from app.main import main
from app.main.views.sub_navigation_dictionaries import features_nav
from app.s3_client.s3_mou_client import get_mou
from app.utils import AgreementInfo
@main.route('/agreement')
@login_required
def agreement():
agreement_info = AgreementInfo.from_current_user()
return render_template(
'views/{}.html'.format(agreement_info.as_jinja_template),
owner=agreement_info.owner,
'views/{}.html'.format(current_user.default_organisation.as_jinja_template),
owner=current_user.default_organisation.name,
navigation_links=features_nav(),
)
@@ -24,7 +20,7 @@ def agreement():
@login_required
def download_agreement():
return send_file(**get_mou(
AgreementInfo.from_current_user().crown_status_or_404
current_user.default_organisation.crown_status_or_404
))
@@ -40,10 +36,8 @@ def public_agreement(variant):
organisation_is_crown=(variant == 'crown')
))
agreement_info = AgreementInfo.from_current_user()
return render_template(
'views/agreement-public.html',
owner=agreement_info.owner,
owner=current_user.default_organisation.name,
download_link=url_for('.public_download_agreement', variant=variant),
)

View File

@@ -39,7 +39,6 @@ def update_email_branding(branding_id, logo=None):
name=email_branding['name'],
text=email_branding['text'],
colour=email_branding['colour'],
domain=email_branding['domain'],
brand_type=email_branding['brand_type']
)
@@ -67,7 +66,6 @@ def update_email_branding(branding_id, logo=None):
name=form.name.data,
text=form.text.data,
colour=form.colour.data,
domain=form.domain.data,
brand_type=form.brand_type.data,
)
@@ -115,7 +113,6 @@ def create_email_branding(logo=None):
name=form.name.data,
text=form.text.data,
colour=form.colour.data,
domain=form.domain.data,
brand_type=form.brand_type.data,
)

View File

@@ -12,18 +12,23 @@ from notifications_utils.international_billing_rates import (
)
from notifications_utils.template import HTMLEmailTemplate, LetterImageTemplate
from app import email_branding_client, letter_branding_client
from app import email_branding_client, letter_branding_client, status_api_client
from app.main import main
from app.main.forms import FieldWithNoneOption, SearchByNameForm
from app.main.views.sub_navigation_dictionaries import features_nav
from app.utils import AgreementInfo, get_logo_cdn_domain
from app.utils import get_logo_cdn_domain
@main.route('/')
def index():
if current_user and current_user.is_authenticated:
return redirect(url_for('main.choose_account'))
return render_template('views/signedout.html')
return render_template(
'views/signedout.html',
counts=status_api_client.get_count_of_live_services_and_organisations(),
)
@main.route('/robots.txt')
@@ -70,7 +75,6 @@ def pricing():
for cc, country in INTERNATIONAL_BILLING_RATES.items()
], key=lambda x: x[0]),
search_form=SearchByNameForm(),
agreement_info=AgreementInfo.from_current_user(),
)
@@ -268,7 +272,6 @@ def terms():
return render_template(
'views/terms-of-use.html',
navigation_links=features_nav(),
agreement_info=AgreementInfo.from_current_user(),
)

View File

@@ -56,7 +56,6 @@ def update_letter_branding(branding_id, logo=None):
file_upload_form = SVGFileUpload()
letter_branding_details_form = ServiceLetterBrandingDetails(
name=letter_branding['name'],
domain=letter_branding['domain']
)
file_upload_form_submitted = file_upload_form.file.data
@@ -87,7 +86,6 @@ def update_letter_branding(branding_id, logo=None):
branding_id=branding_id,
filename=db_filename,
name=letter_branding_details_form.name.data,
domain=letter_branding_details_form.domain.data
)
return redirect(url_for('main.letter_branding'))
@@ -98,7 +96,6 @@ def update_letter_branding(branding_id, logo=None):
branding_id=branding_id,
filename=db_filename,
name=letter_branding_details_form.name.data,
domain=letter_branding_details_form.domain.data
)
upload_letter_logos(logo, db_filename, png_file, session['user_id'])
@@ -106,9 +103,7 @@ def update_letter_branding(branding_id, logo=None):
return redirect(url_for('main.letter_branding'))
except HTTPError as e:
if 'domain' in e.message:
letter_branding_details_form.domain.errors.append(e.message['domain'][0])
elif 'name' in e.message:
if 'name' in e.message:
letter_branding_details_form.name.errors.append(e.message['name'][0])
else:
raise e
@@ -118,7 +113,6 @@ def update_letter_branding(branding_id, logo=None):
branding_id=branding_id,
filename=letter_branding['filename'],
name=letter_branding['name'],
domain=letter_branding['domain']
)
file_upload_form.file.errors = ['Error saving uploaded file - try uploading again']
@@ -165,7 +159,6 @@ def create_letter_branding(logo=None):
letter_branding_client.create_letter_branding(
filename=db_filename,
name=letter_branding_details_form.name.data,
domain=letter_branding_details_form.domain.data,
)
upload_letter_logos(logo, db_filename, png_file, session['user_id'])
@@ -173,9 +166,7 @@ def create_letter_branding(logo=None):
return redirect(url_for('main.letter_branding'))
except HTTPError as e:
if 'domain' in e.message:
letter_branding_details_form.domain.errors.append(e.message['domain'][0])
elif 'name' in e.message:
if 'name' in e.message:
letter_branding_details_form.name.errors.append(e.message['name'][0])
else:
raise e

View File

@@ -60,7 +60,9 @@ def view_notification(service_id, notification_id):
if notification['template']['is_precompiled_letter']:
try:
file_contents = view_letter_notification_as_preview(service_id, notification_id, "pdf")
file_contents = view_letter_notification_as_preview(
service_id, notification_id, "pdf"
)
page_count = pdf_page_count(io.BytesIO(file_contents))
except PdfReadError:
return render_template(
@@ -72,7 +74,6 @@ def view_notification(service_id, notification_id):
if notification.get('postage'):
notification['template']['postage'] = notification['postage']
template = get_template(
notification['template'],
current_service,
@@ -173,14 +174,22 @@ def view_letter_notification_as_preview(service_id, notification_id, filetype):
if filetype not in ('pdf', 'png'):
abort(404)
notification = notification_api_client.get_notification(service_id, str(notification_id))
try:
preview = notification_api_client.get_notification_letter_preview(
service_id,
notification_id,
filetype,
page=request.args.get('page')
)
if notification['status'] == "validation-failed":
preview = notification_api_client.get_notification_letter_preview_with_overlay(
service_id,
notification_id,
filetype,
page=request.args.get('page')
)
else:
preview = notification_api_client.get_notification_letter_preview(
service_id,
notification_id,
filetype,
page=request.args.get('page')
)
display_file = base64.b64decode(preview['content'])
except APIError:

View File

@@ -54,7 +54,6 @@ from app.main.forms import (
branding_options_dict,
)
from app.utils import (
AgreementInfo,
email_safe,
user_has_permissions,
user_is_gov_user,
@@ -180,7 +179,7 @@ def estimate_usage(service_id):
@user_has_permissions('manage_service')
def request_to_go_live(service_id):
agreement_signed = AgreementInfo.from_current_user().agreement_signed
agreement_signed = current_service.organisation.agreement_signed
return render_template(
'views/service-settings/request-to-go-live.html',
@@ -226,7 +225,7 @@ def submit_request_to_go_live(service_id):
service_name=current_service.name,
service_dashboard=url_for('main.service_dashboard', service_id=current_service.id, _external=True),
organisation_type=str(current_service.organisation_type).title(),
agreement=AgreementInfo.from_current_user().as_human_readable,
agreement=current_service.organisation.as_human_readable(current_user.email_domain),
checklist=current_service.go_live_checklist_completed_as_yes_no,
volume_email=print_if_number(current_service.volume_email),
volume_email_formatted=format_if_number(current_service.volume_email),
@@ -237,7 +236,7 @@ def submit_request_to_go_live(service_id):
research_consent='Yes' if current_service.consent_to_research else 'No',
existing_live='Yes' if user_api_client.user_has_live_services(current_user) else 'No',
service_id=current_service.id,
organisation=AgreementInfo.from_current_user().owner,
organisation=current_service.organisation.name,
user_name=current_user.name,
user_email=current_user.email_address,
date=datetime.now(tz=pytz.timezone('Europe/London')).strftime('%d/%m/%Y'),
@@ -245,7 +244,7 @@ def submit_request_to_go_live(service_id):
ticket_type=zendesk_client.TYPE_QUESTION,
user_email=current_user.email_address,
user_name=current_user.name,
tags=get_request_to_go_live_tags(current_service, current_user),
tags=current_service.request_to_go_live_tags,
)
flash('Thanks for your request to go live. Well get back to you within one working day.', 'default')
@@ -262,12 +261,7 @@ def service_switch_live(service_id):
)
if form.validate_on_submit():
current_service.update(
# TODO This limit should be set depending on the agreement signed by
# with Notify.
message_limit=250000 if form.enabled.data else 50,
restricted=(not form.enabled.data)
)
current_service.update_status(live=form.enabled.data)
return redirect(url_for('.service_settings', service_id=service_id))
return render_template(
@@ -985,7 +979,7 @@ def branding_request(service_id):
'\nCurrent branding: {current_branding}'
'\nBranding requested: {branding_requested}'
).format(
organisation=AgreementInfo.from_current_user().as_info_for_branding_request,
organisation=current_service.organisation.as_info_for_branding_request(current_user.email_domain),
service_name=current_service.name,
dashboard_url=url_for('main.service_dashboard', service_id=current_service.id, _external=True),
current_branding=current_service.email_branding_name,
@@ -1073,37 +1067,6 @@ def check_contact_details_type(contact_details):
return 'phone_number'
def get_request_to_go_live_tags(service, user):
return list(_get_request_to_go_live_tags(
service,
AgreementInfo.from_user(user).agreement_signed,
))
def _get_request_to_go_live_tags(service, agreement_signed):
BASE = 'notify_request_to_go_live'
yield BASE
if service.go_live_checklist_completed and agreement_signed:
yield BASE + '_complete'
return
for test, tag in (
(True, ''),
(not service.volumes, '_volumes'),
(not service.go_live_checklist_completed, '_checklist'),
(not agreement_signed, '_mou'),
(service.needs_to_add_email_reply_to_address, '_email_reply_to'),
(not service.has_team_members, '_team_member'),
(not service.has_templates, '_template_content'),
(service.needs_to_change_sms_sender, '_sms_sender'),
):
if test:
yield BASE + '_incomplete' + tag
def print_if_number(value):
return value if isinstance(value, int) else ''