Remove code that reads domains.yml

Since we’ve removed calls to this code from the rest of the app, it can
safely be removed now.
This commit is contained in:
Chris Hill-Scott
2019-04-04 11:13:41 +01:00
parent 470b8a2912
commit 9d99c78c3a
2 changed files with 16 additions and 339 deletions

View File

@@ -13,15 +13,7 @@ import ago
import dateutil import dateutil
import pyexcel import pyexcel
import yaml import yaml
from flask import ( from flask import abort, current_app, redirect, request, session, url_for
Markup,
abort,
current_app,
redirect,
request,
session,
url_for,
)
from flask_login import current_user from flask_login import current_user
from notifications_utils.field import Field from notifications_utils.field import Field
from notifications_utils.formatters import make_quotes_smart 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__)) _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) class GovernmentEmailDomain():
domain_names = sorted(domains.keys(), key=len, reverse=True)
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): def __init__(self, email_address_or_domain):
try:
self._match = next(filter( self._match = next(filter(
self.get_matching_function(email_address_or_domain), self.get_matching_function(email_address_or_domain),
self.domain_names, self.domain_names,
), None) ))
except StopIteration:
self._domain = email_address_or_domain.split('@')[-1] raise NotGovernmentEmailDomain()
(
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: 'Cant 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 'Cant tell (domain is {})'.format(self._domain)
@property
def as_info_for_branding_request(self):
return self.owner or 'Cant 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 ((
'{} <a href="{}">Sign in</a> 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 ((
'{} <a href="{}">Download the agreement</a> or '
'<a href="{}">contact us</a> 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 ((
'{} <a href="{}">Download a copy</a>.'
).format(self._acceptance_required, download_link))
return (
'Your organisation ({}) has already accepted the '
'GOV.UK&nbsp;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 ((
'<a href="{}">Sign in</a> 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 ((
'<a href="{}">Download the agreement</a> or '
'<a href="{}">contact us</a> to find out if we already '
'have one in place with your organisation.'
).format(download_link, support_link))
return (
'<a href="{}">Download the agreement</a> '
'({} {}).'.format(
download_link,
self.owner,
{
True: 'has already accepted it',
False: 'hasnt 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
@staticmethod @staticmethod
def get_matching_function(email_address_or_domain): def get_matching_function(email_address_or_domain):
@@ -564,45 +436,6 @@ class AgreementInfo:
return fn 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): def unicode_truncate(s, length):
encoded = s.encode('utf-8')[:length] encoded = s.encode('utf-8')[:length]

View File

@@ -1,16 +1,13 @@
from collections import Counter, OrderedDict from collections import OrderedDict
from csv import DictReader from csv import DictReader
from io import StringIO from io import StringIO
from pathlib import Path from pathlib import Path
import pytest import pytest
from freezegun import freeze_time from freezegun import freeze_time
from notifications_utils.recipients import validate_email_address
from app import format_datetime_relative from app import format_datetime_relative
from app.utils import ( from app.utils import (
AgreementInfo,
GovernmentEmailDomain,
Spreadsheet, Spreadsheet,
email_safe, email_safe,
generate_next_dict, generate_next_dict,
@@ -292,159 +289,6 @@ def test_get_cdn_domain_on_non_localhost(client, mocker):
assert domain == 'static-logos.admintest.com' 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 == 'Cant 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 arent
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 == 'Cant 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 == (
'Cant 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 == (
'Cant 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', [ @pytest.mark.parametrize('time, human_readable_datetime', [
('2018-03-14 09:00', '14 March at 9:00am'), ('2018-03-14 09:00', '14 March at 9:00am'),
('2018-03-14 15:00', '14 March at 3:00pm'), ('2018-03-14 15:00', '14 March at 3:00pm'),