-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfields.py
132 lines (98 loc) · 4.74 KB
/
fields.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import string
from django import forms
from django.core.validators import validate_email
from django.forms.widgets import CheckboxInput
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from .conf import settings
class LengthValidator(object):
code = 'length'
def __init__(self, min_length=None, max_length=None):
self.min_length = min_length or settings.USERS_PASSWORD_MIN_LENGTH
self.max_length = max_length or settings.USERS_PASSWORD_MAX_LENGTH
def __call__(self, value):
if self.min_length and len(value) < self.min_length:
raise forms.ValidationError(
_('Password too short (must be %s characters or more)') % self.min_length,
code=self.code)
elif self.max_length and len(value) > self.max_length:
raise forms.ValidationError(
_('Password too long (must be %s characters or less)') % self.max_length,
code=self.code)
length_validator = LengthValidator()
class ComplexityValidator(object):
code = 'complexity'
message = _('Weak password, %s')
def __init__(self):
self.password_policy = settings.USERS_PASSWORD_POLICY
def __call__(self, value):
if not settings.USERS_CHECK_PASSWORD_COMPLEXITY: # pragma: no cover
return
uppercase, lowercase, digits, non_ascii, punctuation = set(), set(), set(), set(), set()
for char in value:
if char.isupper():
uppercase.add(char)
elif char.islower():
lowercase.add(char)
elif char.isdigit():
digits.add(char)
elif char in string.punctuation:
punctuation.add(char)
else:
non_ascii.add(char)
if len(uppercase) < self.password_policy.get('UPPER', 0):
raise forms.ValidationError(
self.message % _('must contain %(UPPER)s or '
'more uppercase characters (A-Z)') % self.password_policy,
code=self.code)
elif len(lowercase) < self.password_policy.get('LOWER', 0):
raise forms.ValidationError(
self.message % _('Must contain %(LOWER)s or '
'more lowercase characters (a-z)') % self.password_policy,
code=self.code)
elif len(digits) < self.password_policy.get('DIGITS', 0):
raise forms.ValidationError(
self.message % _('must contain %(DIGITS)s or '
'more numbers (0-9)') % self.password_policy,
code=self.code)
elif len(punctuation) < self.password_policy.get('PUNCTUATION', 0):
raise forms.ValidationError(
self.message % _('must contain %(PUNCTUATION)s or more '
'symbols') % self.password_policy,
code=self.code)
complexity_validator = ComplexityValidator()
class PasswordField(forms.CharField):
widget = forms.PasswordInput()
default_validators = [length_validator, complexity_validator, ]
class HoneyPotField(forms.BooleanField):
widget = CheckboxInput
def __init__(self, *args, **kwargs):
super(HoneyPotField, self).__init__(*args, **kwargs)
self.required = False
if not self.label:
self.label = _('Are you human? (Sorry, we have to ask!)')
if not self.help_text:
self.help_text = _('Please don\'t check this box if you are a human.')
def validate(self, value):
if value:
raise forms.ValidationError(_('Doh! You are a robot!'))
class EmailDomainValidator(object):
message = _('Sorry, %s emails are not allowed. Please use a different email address.')
code = 'invalid'
def __init__(self, ):
self.domain_blacklist = settings.USERS_EMAIL_DOMAINS_BLACKLIST
self.domain_whitelist = settings.USERS_EMAIL_DOMAINS_WHITELIST
def __call__(self, value):
if not settings.USERS_VALIDATE_EMAIL_DOMAIN: # pragma: no cover
return
if not value or '@' not in value:
raise forms.ValidationError(_('Enter a valid email address.'), code=self.code)
value = force_text(value)
user_part, domain_part = value.rsplit('@', 1)
if self.domain_blacklist and domain_part in self.domain_blacklist:
raise forms.ValidationError(self.message % domain_part, code=self.code)
if self.domain_whitelist and domain_part not in self.domain_whitelist:
raise forms.ValidationError(self.message % domain_part, code=self.code)
validate_email_domain = EmailDomainValidator()
class UsersEmailField(forms.EmailField):
default_validators = [validate_email, validate_email_domain]