From 35f66cae238eaf96ac0b0b8a9d9c84242f86a83d Mon Sep 17 00:00:00 2001 From: Ken Tsang Date: Mon, 24 Jul 2017 15:20:40 +0100 Subject: [PATCH] Update emails to use logos cdn --- app/__init__.py | 5 +++-- app/config.py | 8 ++++++++ app/main/views/service_settings.py | 4 ++-- app/utils.py | 13 +++++++++++++ tests/app/main/views/test_headers.py | 6 ++++-- tests/app/test_utils.py | 17 +++++++++++++++++ 6 files changed, 47 insertions(+), 6 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index f1b1a2909..fe77d1b9d 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -54,6 +54,7 @@ from app.notify_client.provider_client import ProviderClient from app.notify_client.organisations_client import OrganisationsClient from app.notify_client.models import AnonymousUser from app.notify_client.letter_jobs_client import LetterJobsClient +from app.utils import get_cdn_domain from app.utils import gmt_timezones @@ -415,8 +416,8 @@ def useful_headers_after_request(response): "script-src 'self' *.google-analytics.com 'unsafe-inline' 'unsafe-eval' data:;" "object-src 'self';" "font-src 'self' data:;" - "img-src 'self' *.google-analytics.com *.notifications.service.gov.uk data:;" - "frame-src www.youtube.com;" + "img-src 'self' *.google-analytics.com *.notifications.service.gov.uk {} data:;" + "frame-src www.youtube.com;".format(get_cdn_domain()) )) if 'Cache-Control' in response.headers: del response.headers['Cache-Control'] diff --git a/app/config.py b/app/config.py index eabd7391f..77a3e0781 100644 --- a/app/config.py +++ b/app/config.py @@ -87,6 +87,8 @@ class Config(object): r"cqc\.org\.uk", ] + LOGO_UPLOAD_BUCKET_NAME = 'local-notifications-logo-upload' + class Development(Config): DEBUG = True @@ -94,6 +96,7 @@ class Development(Config): SESSION_PROTECTION = None STATSD_ENABLED = False CSV_UPLOAD_BUCKET_NAME = 'development-notifications-csv-upload' + LOGO_UPLOAD_BUCKET_NAME = 'development-notifications-logo-upload' class Test(Development): @@ -102,6 +105,7 @@ class Test(Development): STATSD_ENABLED = True WTF_CSRF_ENABLED = False CSV_UPLOAD_BUCKET_NAME = 'test-notifications-csv-upload' + LOGO_UPLOAD_BUCKET_NAME = 'test-notifications-logo-upload' NOTIFY_ENVIRONMENT = 'test' TEMPLATE_PREVIEW_API_HOST = 'http://localhost:9999' @@ -111,6 +115,7 @@ class Preview(Config): HEADER_COLOUR = '#F499BE' # $baby-pink STATSD_ENABLED = True CSV_UPLOAD_BUCKET_NAME = 'preview-notifications-csv-upload' + LOGO_UPLOAD_BUCKET_NAME = 'preview-notifications-logo-upload' NOTIFY_ENVIRONMENT = 'preview' @@ -120,6 +125,7 @@ class Staging(Config): HEADER_COLOUR = '#6F72AF' # $mauve STATSD_ENABLED = True CSV_UPLOAD_BUCKET_NAME = 'staging-notify-csv-upload' + LOGO_UPLOAD_BUCKET_NAME = 'staging-notifications-logo-upload' NOTIFY_ENVIRONMENT = 'staging' @@ -129,6 +135,7 @@ class Live(Config): HTTP_PROTOCOL = 'https' STATSD_ENABLED = True CSV_UPLOAD_BUCKET_NAME = 'live-notifications-csv-upload' + LOGO_UPLOAD_BUCKET_NAME = 'live-notifications-logo-upload' NOTIFY_ENVIRONMENT = 'live' @@ -142,6 +149,7 @@ class Sandbox(CloudFoundryConfig): HEADER_COLOUR = '#F499BE' # $baby-pink STATSD_ENABLED = True CSV_UPLOAD_BUCKET_NAME = 'cf-sandbox-notifications-csv-upload' + LOGO_UPLOAD_BUCKET_NAME = 'cf-sandbox-notifications-logo-upload' NOTIFY_ENVIRONMENT = 'sandbox' diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 1aeb8f922..7e694cb06 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -22,7 +22,7 @@ from notifications_python_client.errors import HTTPError from app import service_api_client from app.main import main -from app.utils import user_has_permissions, email_safe +from app.utils import user_has_permissions, email_safe, get_cdn_domain from app.main.forms import ( ConfirmPasswordForm, ServiceNameForm, @@ -464,7 +464,7 @@ def get_branding_as_value_and_label(organisations): def get_branding_as_dict(organisations): return { organisation['id']: { - 'logo': '/static/images/email-template/crests/{}'.format(organisation['logo']), + 'logo': 'https://{}/{}'.format(get_cdn_domain(), organisation['logo']), 'colour': organisation['colour'] } for organisation in organisations } diff --git a/app/utils.py b/app/utils.py index 2ec2702ad..a0c8747e6 100644 --- a/app/utils.py +++ b/app/utils.py @@ -5,6 +5,7 @@ from io import StringIO from os import path from functools import wraps import unicodedata +from urllib.parse import urlparse from collections import namedtuple from datetime import datetime, timedelta, timezone from dateutil import parser @@ -364,3 +365,15 @@ def gmt_timezones(date): date = dateutil.parser.parse(date) forced_utc = date.replace(tzinfo=pytz.utc) return forced_utc.astimezone(pytz.timezone('Europe/London')) + + +def get_cdn_domain(): + parsed_uri = urlparse(current_app.config['ADMIN_BASE_URL']) + + if parsed_uri.netloc.startswith('localhost'): + return 'static-logos.notify.tools' + + subdomain = parsed_uri.hostname.split('.')[0] + domain = parsed_uri.netloc[len(subdomain + '.'):] + + return "static-logos.{}".format(domain) diff --git a/tests/app/main/views/test_headers.py b/tests/app/main/views/test_headers.py index 9ac6d844a..130beac20 100644 --- a/tests/app/main/views/test_headers.py +++ b/tests/app/main/views/test_headers.py @@ -1,6 +1,8 @@ +def test_owasp_useful_headers_set(client, mocker): + mocker.patch('app.get_cdn_domain', return_value='static-logos.test.com') -def test_owasp_useful_headers_set(client): response = client.get('/') + assert response.status_code == 200 assert response.headers['X-Frame-Options'] == 'deny' assert response.headers['X-Content-Type-Options'] == 'nosniff' @@ -10,6 +12,6 @@ def test_owasp_useful_headers_set(client): "script-src 'self' *.google-analytics.com 'unsafe-inline' 'unsafe-eval' data:;" "object-src 'self';" "font-src 'self' data:;" - "img-src 'self' *.google-analytics.com *.notifications.service.gov.uk data:;" + "img-src 'self' *.google-analytics.com *.notifications.service.gov.uk static-logos.test.com data:;" "frame-src www.youtube.com;" ) diff --git a/tests/app/test_utils.py b/tests/app/test_utils.py index d9b754e73..cb242c700 100644 --- a/tests/app/test_utils.py +++ b/tests/app/test_utils.py @@ -13,7 +13,11 @@ from app.utils import ( generate_previous_dict, generate_next_dict, Spreadsheet, +<<<<<<< HEAD get_letter_timings, +======= + get_cdn_domain +>>>>>>> Update emails to use logos cdn ) from tests import notification_json, single_notification_json @@ -158,6 +162,7 @@ def test_generate_notifications_csv_calls_twice_if_next_link(mocker): assert mock_get_notifications.mock_calls[1][2]['page'] == 2 +<<<<<<< HEAD @freeze_time('2017-07-14 14:59:59') # Friday, before print deadline @pytest.mark.parametrize('upload_time, expected_print_time, is_printed, expected_earliest, expected_latest', [ @@ -290,3 +295,15 @@ def test_get_estimated_delivery_date_for_letter( assert timings.is_printed == is_printed assert timings.earliest_delivery.strftime('%A %Y-%m-%d') == expected_earliest assert timings.latest_delivery.strftime('%A %Y-%m-%d') == expected_latest +======= +def test_get_cdn_domain_on_localhost(client, mocker): + mocker.patch.dict('app.current_app.config', values={'ADMIN_BASE_URL': 'http://localhost:6012'}) + domain = get_cdn_domain() + assert domain == 'static-logos.notify.tools' + + +def test_get_cdn_domain_without_logo_base_domain_env_returns_admin_base_domain(client, mocker): + mocker.patch.dict('app.current_app.config', values={'ADMIN_BASE_URL': 'https://some.admintest.com'}) + domain = get_cdn_domain() + assert domain == 'static-logos.admintest.com' +>>>>>>> Update emails to use logos cdn