diff --git a/app/utils.py b/app/utils.py
index 2a70ab3fb..de4ac69d8 100644
--- a/app/utils.py
+++ b/app/utils.py
@@ -13,15 +13,7 @@ import ago
import dateutil
import pyexcel
import yaml
-from flask import (
- Markup,
- abort,
- current_app,
- redirect,
- request,
- session,
- url_for,
-)
+from flask import abort, current_app, redirect, request, session, url_for
from flask_login import current_user
from notifications_utils.field import Field
from notifications_utils.formatters import make_quotes_smart
@@ -409,143 +401,23 @@ def set_status_filters(filter_args):
_dir_path = os.path.dirname(os.path.realpath(__file__))
-class AgreementInfo:
+class NotGovernmentEmailDomain(Exception):
+ pass
- with open('{}/domains.yml'.format(_dir_path)) as domains:
- domains = yaml.safe_load(domains)
- domain_names = sorted(domains.keys(), key=len, reverse=True)
+
+class GovernmentEmailDomain():
+
+ with open('{}/email_domains.yml'.format(_dir_path)) as email_domains:
+ domain_names = yaml.safe_load(email_domains)
def __init__(self, email_address_or_domain):
-
- self._match = next(filter(
- self.get_matching_function(email_address_or_domain),
- self.domain_names,
- ), None)
-
- self._domain = email_address_or_domain.split('@')[-1]
-
- (
- self.owner,
- self.crown_status,
- self.agreement_signed,
- self.canonical_domain,
- ) = self._get_info()
-
- @classmethod
- def from_user(cls, user):
- return cls(user.email_address if user.is_authenticated else '')
-
- @classmethod
- def from_current_user(cls):
- return cls.from_user(current_user)
-
- @property
- def as_human_readable(self):
- if self.canonical_domain and 'dwp' in self.canonical_domain:
- return 'DWP - Requires OED approval'
- if self.agreement_signed:
- return 'Yes, on behalf of {}'.format(self.owner)
- elif self.owner:
- return '{} (organisation is {}, {})'.format(
- {
- False: 'No',
- None: 'Can’t tell',
- }.get(self.agreement_signed),
- self.owner,
- {
- True: 'a crown body',
- False: 'a non-crown body',
- None: 'crown status unknown',
- }.get(self.crown_status),
- )
- else:
- return 'Can’t tell (domain is {})'.format(self._domain)
-
- @property
- def as_info_for_branding_request(self):
- return self.owner or 'Can’t tell (domain is {})'.format(self._domain)
-
- @property
- def as_jinja_template(self):
- if self.crown_status is None:
- return 'agreement-choose'
- if self.agreement_signed:
- return 'agreement-signed'
- return 'agreement'
-
- def as_terms_of_use_paragraph(self, **kwargs):
- return Markup(self._as_terms_of_use_paragraph(**kwargs))
-
- def _as_terms_of_use_paragraph(self, terms_link, download_link, support_link, signed_in):
-
- if not signed_in:
- return ((
- '{} Sign in to download a copy '
- 'or find out if one is already in place.'
- ).format(self._acceptance_required, terms_link))
-
- if self.agreement_signed is None:
- return ((
- '{} Download the agreement or '
- 'contact us to find out if we already '
- 'have one in place with your organisation.'
- ).format(self._acceptance_required, download_link, support_link))
-
- if self.agreement_signed is False:
- return ((
- '{} Download a copy.'
- ).format(self._acceptance_required, download_link))
-
- return (
- 'Your organisation ({}) has already accepted the '
- 'GOV.UK Notify data sharing and financial '
- 'agreement.'.format(self.owner)
- )
-
- def as_pricing_paragraph(self, **kwargs):
- return Markup(self._as_pricing_paragraph(**kwargs))
-
- def _as_pricing_paragraph(self, pricing_link, download_link, support_link, signed_in):
-
- if not signed_in:
- return ((
- 'Sign in to download a copy or find '
- 'out if one is already in place with your organisation.'
- ).format(pricing_link))
-
- if self.agreement_signed is None:
- return ((
- 'Download the agreement or '
- 'contact us to find out if we already '
- 'have one in place with your organisation.'
- ).format(download_link, support_link))
-
- return (
- 'Download the agreement '
- '({} {}).'.format(
- download_link,
- self.owner,
- {
- True: 'has already accepted it',
- False: 'hasn’t accepted it yet'
- }.get(self.agreement_signed)
- )
- )
-
- @property
- def _acceptance_required(self):
- return (
- 'Your organisation {} must also accept our data sharing '
- 'and financial agreement.'.format(
- '({})'.format(self.owner) if self.owner else '',
- )
- )
-
- @property
- def crown_status_or_404(self):
- if self.crown_status is None:
- abort(404)
- return self.crown_status
+ try:
+ self._match = next(filter(
+ self.get_matching_function(email_address_or_domain),
+ self.domain_names,
+ ))
+ except StopIteration:
+ raise NotGovernmentEmailDomain()
@staticmethod
def get_matching_function(email_address_or_domain):
@@ -564,45 +436,6 @@ class AgreementInfo:
return fn
- def _get_info(self):
-
- details = self.domains.get(self._match, {})
-
- if details is None:
- raise TypeError('Domain must have details ({})'.format(self._domain))
-
- if isinstance(details, str):
- self.is_canonical = False
- return AgreementInfo(details)._get_info()
-
- elif isinstance(details, dict):
- self.is_canonical = bool(details)
- return(
- details.get("owner"),
- details.get("crown"),
- details.get("agreement_signed"),
- self._match,
- )
-
-
-class NotGovernmentEmailDomain(Exception):
- pass
-
-
-class GovernmentEmailDomain(AgreementInfo):
-
- with open('{}/email_domains.yml'.format(_dir_path)) as email_domains:
- domain_names = yaml.safe_load(email_domains)
-
- def __init__(self, email_address_or_domain):
- try:
- self._match = next(filter(
- self.get_matching_function(email_address_or_domain),
- self.domain_names,
- ))
- except StopIteration:
- raise NotGovernmentEmailDomain()
-
def unicode_truncate(s, length):
encoded = s.encode('utf-8')[:length]
diff --git a/tests/app/test_utils.py b/tests/app/test_utils.py
index c7fb087a8..cb5a85b1c 100644
--- a/tests/app/test_utils.py
+++ b/tests/app/test_utils.py
@@ -1,16 +1,13 @@
-from collections import Counter, OrderedDict
+from collections import OrderedDict
from csv import DictReader
from io import StringIO
from pathlib import Path
import pytest
from freezegun import freeze_time
-from notifications_utils.recipients import validate_email_address
from app import format_datetime_relative
from app.utils import (
- AgreementInfo,
- GovernmentEmailDomain,
Spreadsheet,
email_safe,
generate_next_dict,
@@ -292,159 +289,6 @@ def test_get_cdn_domain_on_non_localhost(client, mocker):
assert domain == 'static-logos.admintest.com'
-@pytest.mark.parametrize("domain_or_email_address", (
- "test@dclgdatamart.co.uk", "test@communities.gsi.gov.uk", "test@communities.gov.uk",
-))
-def test_get_valid_agreement_info_known_details(domain_or_email_address):
- agreement_info = AgreementInfo(domain_or_email_address)
- assert agreement_info.crown_status is None
- assert agreement_info.owner == "Ministry of Housing, Communities & Local Government"
- assert agreement_info.agreement_signed is True
- assert agreement_info.as_human_readable == (
- 'Yes, on behalf of Ministry of Housing, Communities & Local Government'
- )
-
-
-@pytest.mark.parametrize("domain_or_email_address", (
- "test@dwp.gov.uk", "test@dwp.gsi.gov.uk",
-))
-def test_dwp_go_live_requests_are_flagged(domain_or_email_address):
- agreement_info = AgreementInfo(domain_or_email_address)
- assert agreement_info.owner == "Department for Work and Pensions"
- assert agreement_info.agreement_signed is True
- assert agreement_info.as_human_readable == (
- 'DWP - Requires OED approval'
- )
-
-
-@pytest.mark.parametrize("domain_or_email_address, is_canonical", (
- ("test@dclgdatamart.co.uk", False),
- ("test@communities.gsi.gov.uk", False),
- ("test@communities.gov.uk", True),
-))
-def test_get_canonical_domain(domain_or_email_address, is_canonical):
- assert AgreementInfo(domain_or_email_address).canonical_domain == 'communities.gov.uk'
- assert AgreementInfo(domain_or_email_address).is_canonical == is_canonical
-
-
-def test_get_canonical_domain_passes_through_unknown_domain():
- assert AgreementInfo('example.com').canonical_domain is None
- assert AgreementInfo('example.com').is_canonical is False
-
-
-@pytest.mark.parametrize("domain_or_email_address", (
- "test@police.gov.uk", "police.gov.uk",
-))
-def test_get_valid_agreement_info_unknown_details(domain_or_email_address):
- government_domain = AgreementInfo(domain_or_email_address)
- assert government_domain.crown_status is None
- assert government_domain.owner is None
- assert government_domain.agreement_signed is None
- assert government_domain.as_human_readable == 'Can’t tell (domain is police.gov.uk)'
-
-
-def test_get_valid_agreement_info_only_org_known():
- agreement_info = AgreementInfo('nhs.net')
- # Some parts of the NHS are Crown, some aren’t
- assert agreement_info.crown_status is None
- assert agreement_info.owner == 'NHS'
- assert agreement_info.agreement_signed is None
- assert agreement_info.as_human_readable == 'Can’t tell (organisation is NHS, crown status unknown)'
-
-
-def test_get_valid_agreement_info_some_known_details():
- agreement_info = AgreementInfo("marinemanagement.org.uk")
- assert agreement_info.crown_status is None
- assert agreement_info.owner == "Marine Management Organisation"
- assert agreement_info.agreement_signed is True
- assert agreement_info.as_human_readable == (
- 'Yes, on behalf of Marine Management Organisation'
- )
-
-
-def test_get_valid_local_agreement_info_some_known_details():
- # This example may need to be updated to use a different council if
- # Babergh every sign the agreement
- agreement_info = AgreementInfo("babergh.gov.uk")
- assert agreement_info.crown_status is False
- assert agreement_info.owner == "Babergh District Council"
- assert agreement_info.agreement_signed is False
- assert agreement_info.as_human_readable == (
- 'No (organisation is Babergh District Council, a non-crown body)'
- )
-
-
-def test_get_valid_government_domain_gets_most_specific_first():
-
- generic = AgreementInfo("gov.uk")
- assert generic.crown_status is None
- assert generic.owner is None
- assert generic.agreement_signed is None
- assert generic.as_human_readable == (
- 'Can’t tell (domain is gov.uk)'
- )
-
- specific = AgreementInfo("dacorum.gov.uk")
- assert specific.crown_status is False
- assert specific.owner == 'Dacorum Borough Council'
- assert specific.agreement_signed is True
- assert specific.as_human_readable == (
- 'Yes, on behalf of Dacorum Borough Council'
- )
-
-
-def test_get_domain_info_for_branding_request():
-
- assert AgreementInfo("gov.uk").as_info_for_branding_request == (
- 'Can’t tell (domain is gov.uk)'
- )
- assert AgreementInfo("dacorum.gov.uk").as_info_for_branding_request == (
- 'Dacorum Borough Council'
- )
-
-
-def test_domains_are_lowercased():
- for domain in AgreementInfo.domains.keys():
- assert domain == domain.lower()
-
-
-def test_validate_government_domain_data():
-
- for domain in AgreementInfo.domains.keys():
-
- validate_email_address('test@{}'.format(domain))
-
- agreement_info = AgreementInfo(domain)
-
- assert agreement_info.crown_status in {
- True, False, None
- }
-
- assert isinstance(agreement_info.owner, str) and agreement_info.owner.strip()
-
- assert agreement_info.agreement_signed in {
- True, False, None
- }
-
-
-def test_domain_data_is_canonicalized():
- for owner, count in Counter(
- AgreementInfo(domain).owner
- for domain in AgreementInfo.domains.keys()
- if AgreementInfo(domain).is_canonical
- ).most_common():
- if count > 1:
- raise ValueError(
- '{} entries in domains.yml for {}'.format(count, owner)
- )
-
-
-def test_validate_email_domain_data():
-
- for domain in GovernmentEmailDomain.domains.keys():
- validate_email_address('test@{}'.format(domain))
-
-
@pytest.mark.parametrize('time, human_readable_datetime', [
('2018-03-14 09:00', '14 March at 9:00am'),
('2018-03-14 15:00', '14 March at 3:00pm'),