2018-01-31 10:26:37 +00:00
|
|
|
|
import re
|
2018-02-14 14:35:16 +00:00
|
|
|
|
|
2017-12-05 14:48:36 +00:00
|
|
|
|
from notifications_utils.field import Field
|
2020-01-21 16:50:44 +00:00
|
|
|
|
from notifications_utils.formatters import formatted_list
|
2018-02-20 11:22:17 +00:00
|
|
|
|
from notifications_utils.recipients import (
|
|
|
|
|
|
InvalidEmailError,
|
|
|
|
|
|
validate_email_address,
|
|
|
|
|
|
)
|
2019-05-03 15:13:39 +01:00
|
|
|
|
from notifications_utils.sanitise_text import SanitiseSMS
|
2018-02-20 11:22:17 +00:00
|
|
|
|
from wtforms import ValidationError
|
2017-02-13 13:11:29 +00:00
|
|
|
|
|
2020-06-16 18:04:29 +01:00
|
|
|
|
from app.main._commonly_used_passwords import commonly_used_passwords
|
2019-04-04 11:09:09 +01:00
|
|
|
|
from app.utils import Spreadsheet, is_gov_user
|
2015-12-01 15:51:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
2020-06-16 18:04:29 +01:00
|
|
|
|
class CommonlyUsedPassword:
|
2015-12-01 15:51:09 +00:00
|
|
|
|
def __init__(self, message=None):
|
|
|
|
|
|
if not message:
|
2020-06-16 18:04:29 +01:00
|
|
|
|
message = 'Password is in list of commonly used passwords.'
|
2015-12-01 15:51:09 +00:00
|
|
|
|
self.message = message
|
|
|
|
|
|
|
|
|
|
|
|
def __call__(self, form, field):
|
2020-06-16 18:04:29 +01:00
|
|
|
|
if field.data in commonly_used_passwords:
|
2015-12-01 15:51:09 +00:00
|
|
|
|
raise ValidationError(self.message)
|
2016-01-07 12:43:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
2017-02-13 13:11:29 +00:00
|
|
|
|
class CsvFileValidator:
|
2016-01-11 15:00:51 +00:00
|
|
|
|
|
|
|
|
|
|
def __init__(self, message='Not a csv file'):
|
|
|
|
|
|
self.message = message
|
|
|
|
|
|
|
|
|
|
|
|
def __call__(self, form, field):
|
2016-05-05 15:41:11 +01:00
|
|
|
|
if not Spreadsheet.can_handle(field.data.filename):
|
2019-09-13 11:55:21 +01:00
|
|
|
|
raise ValidationError("{} is not a spreadsheet that Notify can read".format(field.data.filename))
|
2016-03-18 12:05:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
2017-02-13 13:11:29 +00:00
|
|
|
|
class ValidGovEmail:
|
2016-03-18 12:05:50 +00:00
|
|
|
|
|
|
|
|
|
|
def __call__(self, form, field):
|
2018-12-07 12:23:12 +00:00
|
|
|
|
|
|
|
|
|
|
if field.data == '':
|
|
|
|
|
|
return
|
|
|
|
|
|
|
2016-10-28 10:45:05 +01:00
|
|
|
|
from flask import url_for
|
2020-03-26 12:41:46 +00:00
|
|
|
|
message = '''
|
|
|
|
|
|
Enter a public sector email address or
|
|
|
|
|
|
<a class="govuk-link govuk-link--no-visited-state" href="{}">find out who can use Notify</a>
|
2020-05-20 15:58:36 +01:00
|
|
|
|
'''.format(url_for('main.who_can_use_notify'))
|
2016-10-28 10:45:05 +01:00
|
|
|
|
if not is_gov_user(field.data.lower()):
|
2016-03-18 12:05:50 +00:00
|
|
|
|
raise ValidationError(message)
|
2016-04-07 16:02:06 +01:00
|
|
|
|
|
|
|
|
|
|
|
2020-04-22 17:49:03 +01:00
|
|
|
|
class ValidEmail:
|
2018-02-14 14:35:16 +00:00
|
|
|
|
|
2020-04-22 17:49:03 +01:00
|
|
|
|
message = 'Enter a valid email address'
|
2018-02-14 14:35:16 +00:00
|
|
|
|
|
|
|
|
|
|
def __call__(self, form, field):
|
2018-12-07 12:23:12 +00:00
|
|
|
|
|
|
|
|
|
|
if field.data == '':
|
|
|
|
|
|
return
|
|
|
|
|
|
|
2018-02-14 14:35:16 +00:00
|
|
|
|
try:
|
|
|
|
|
|
validate_email_address(field.data)
|
|
|
|
|
|
except InvalidEmailError:
|
|
|
|
|
|
raise ValidationError(self.message)
|
2018-12-07 12:23:12 +00:00
|
|
|
|
|
2018-02-14 14:35:16 +00:00
|
|
|
|
|
2017-02-13 13:11:29 +00:00
|
|
|
|
class NoCommasInPlaceHolders:
|
2016-04-07 16:02:06 +01:00
|
|
|
|
|
2019-09-13 16:00:56 +01:00
|
|
|
|
def __init__(self, message='You cannot put commas between double brackets'):
|
2016-04-07 16:02:06 +01:00
|
|
|
|
self.message = message
|
|
|
|
|
|
|
|
|
|
|
|
def __call__(self, form, field):
|
2017-12-05 14:48:36 +00:00
|
|
|
|
if ',' in ''.join(Field(field.data).placeholders):
|
2016-04-07 16:02:06 +01:00
|
|
|
|
raise ValidationError(self.message)
|
2017-02-13 13:11:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
2020-03-04 14:25:14 +00:00
|
|
|
|
class NoEmbeddedImagesInSVG:
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, message='This SVG has an embedded raster image in it and will not render well'):
|
|
|
|
|
|
self.message = message
|
|
|
|
|
|
|
|
|
|
|
|
def __call__(self, form, field):
|
2020-03-04 17:26:19 +00:00
|
|
|
|
is_image_embedded = '<image' in field.data.stream.read().decode("utf-8")
|
|
|
|
|
|
field.data.stream.seek(0)
|
|
|
|
|
|
if is_image_embedded:
|
2020-03-04 14:25:14 +00:00
|
|
|
|
raise ValidationError(self.message)
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-05-03 15:13:39 +01:00
|
|
|
|
class OnlySMSCharacters:
|
2020-07-03 15:46:00 +01:00
|
|
|
|
|
|
|
|
|
|
def __init__(self, *args, template_type, **kwargs):
|
|
|
|
|
|
self._template_type = template_type
|
|
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
|
|
2017-02-13 13:11:29 +00:00
|
|
|
|
def __call__(self, form, field):
|
2019-05-03 15:13:39 +01:00
|
|
|
|
non_sms_characters = sorted(list(SanitiseSMS.get_non_compatible_characters(field.data)))
|
|
|
|
|
|
if non_sms_characters:
|
2017-02-14 17:06:32 +00:00
|
|
|
|
raise ValidationError(
|
2020-07-03 15:46:00 +01:00
|
|
|
|
'You cannot use {} in {}. {} will not show up properly on everyone’s phones.'.format(
|
2019-05-03 15:13:39 +01:00
|
|
|
|
formatted_list(non_sms_characters, conjunction='or', before_each='', after_each=''),
|
2020-07-03 15:46:00 +01:00
|
|
|
|
{
|
|
|
|
|
|
'broadcast': 'broadcasts',
|
|
|
|
|
|
'sms': 'text messages',
|
|
|
|
|
|
}.get(self._template_type),
|
2019-05-03 15:13:39 +01:00
|
|
|
|
('It' if len(non_sms_characters) == 1 else 'They')
|
2017-02-14 17:06:32 +00:00
|
|
|
|
)
|
|
|
|
|
|
)
|
2018-01-31 10:26:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
2020-04-02 15:57:46 +01:00
|
|
|
|
class LettersNumbersFullStopsAndUnderscoresOnly:
|
2018-01-31 10:26:37 +00:00
|
|
|
|
|
2020-04-02 15:57:46 +01:00
|
|
|
|
regex = re.compile(r'^[a-zA-Z0-9\s\._]+$')
|
2018-01-31 10:26:37 +00:00
|
|
|
|
|
|
|
|
|
|
def __init__(self, message='Use letters and numbers only'):
|
|
|
|
|
|
self.message = message
|
|
|
|
|
|
|
|
|
|
|
|
def __call__(self, form, field):
|
|
|
|
|
|
if field.data and not re.match(self.regex, field.data):
|
|
|
|
|
|
raise ValidationError(self.message)
|
2018-02-28 11:50:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DoesNotStartWithDoubleZero:
|
|
|
|
|
|
|
2019-09-13 16:00:56 +01:00
|
|
|
|
def __init__(self, message="Cannot start with 00"):
|
2018-02-28 11:50:41 +00:00
|
|
|
|
self.message = message
|
|
|
|
|
|
|
|
|
|
|
|
def __call__(self, form, field):
|
|
|
|
|
|
if field.data and field.data.startswith("00"):
|
|
|
|
|
|
raise ValidationError(self.message)
|
2019-11-08 17:12:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MustContainAlphanumericCharacters:
|
|
|
|
|
|
|
|
|
|
|
|
regex = re.compile(r".*[a-zA-Z0-9].*[a-zA-Z0-9].*")
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
|
|
self,
|
|
|
|
|
|
message="Must include at least two alphanumeric characters"
|
|
|
|
|
|
):
|
|
|
|
|
|
self.message = message
|
|
|
|
|
|
|
|
|
|
|
|
def __call__(self, form, field):
|
|
|
|
|
|
if field.data and not re.match(self.regex, field.data):
|
|
|
|
|
|
raise ValidationError(self.message)
|