annotate accounts/forms.py @ 708:a6c664e04649

Update production requirements.txt.
author Brian Neal <bgneal@gmail.com>
date Sun, 15 Sep 2013 17:00:52 -0500
parents 988782c6ce6c
children 9133b4626a4b
rev   line source
gremmie@1 1 """forms for the accounts application"""
gremmie@1 2
bgneal@74 3 import logging
bgneal@74 4
gremmie@1 5 from django import forms
gremmie@1 6 from django.contrib.auth.models import User
gremmie@1 7 from django.core.urlresolvers import reverse
gremmie@1 8 from django.template.loader import render_to_string
gremmie@1 9 from django.contrib.sites.models import Site
bgneal@6 10 from django.conf import settings
gremmie@1 11
gremmie@1 12 from core.functions import send_mail
gremmie@1 13 from accounts.models import PendingUser
gremmie@1 14 from accounts.models import IllegalUsername
gremmie@1 15 from accounts.models import IllegalEmail
bgneal@690 16
bgneal@690 17
bgneal@690 18 logger = logging.getLogger('auth')
gremmie@1 19
gremmie@1 20
gremmie@1 21 class RegisterForm(forms.Form):
bgneal@74 22 """Form used to register with the website"""
bgneal@498 23 username = forms.RegexField(
bgneal@498 24 max_length=30,
bgneal@498 25 regex=r'^\w+$',
bgneal@498 26 error_messages={'invalid': ('Your username must be 30 characters or'
bgneal@498 27 ' less and contain only letters, numbers and underscores.')},
bgneal@498 28 widget=forms.TextInput(attrs={'class': 'text'}),
bgneal@498 29 )
bgneal@498 30 email = forms.EmailField(widget=forms.TextInput(attrs={'class': 'text'}))
bgneal@498 31 password1 = forms.CharField(label="Password",
bgneal@498 32 widget=forms.PasswordInput(attrs={'class': 'text'}))
bgneal@498 33 password2 = forms.CharField(label="Password confirmation",
bgneal@498 34 widget=forms.PasswordInput(attrs={'class': 'text'}))
bgneal@316 35 agree_age = forms.BooleanField(required=True,
bgneal@155 36 label='I certify that I am over the age of 13',
bgneal@155 37 error_messages={
bgneal@347 38 'required': 'Sorry, but you must be over the age of 13 to '
bgneal@155 39 'register at our site.',
bgneal@155 40 })
bgneal@316 41 agree_tos = forms.BooleanField(required=True,
bgneal@155 42 label='I agree to the Terms of Service',
bgneal@155 43 error_messages={
bgneal@155 44 'required': 'You have not agreed to our Terms of Service.',
bgneal@155 45 })
bgneal@155 46 agree_privacy = forms.BooleanField(required=True,
bgneal@155 47 label='I agree to the Privacy Policy',
bgneal@155 48 error_messages={
bgneal@155 49 'required': 'You have not agreed to our Privacy Policy.',
bgneal@155 50 })
bgneal@498 51 question1 = forms.CharField(label="What number appears in the site name?",
bgneal@498 52 widget=forms.TextInput(attrs={'class': 'text'}))
bgneal@347 53 question2 = forms.CharField(label='', required=False,
bgneal@347 54 widget=forms.TextInput(attrs={'style': 'display: none;'}))
gremmie@1 55
bgneal@74 56 def __init__(self, *args, **kwargs):
bgneal@74 57 self.ip = kwargs.pop('ip', '?')
bgneal@74 58 super(RegisterForm, self).__init__(*args, **kwargs)
bgneal@74 59
bgneal@74 60 def clean_username(self):
bgneal@74 61 username = self.cleaned_data['username']
bgneal@74 62 try:
bgneal@565 63 User.objects.get(username=username)
bgneal@74 64 except User.DoesNotExist:
gremmie@1 65 try:
bgneal@565 66 PendingUser.objects.get(username=username)
bgneal@74 67 except PendingUser.DoesNotExist:
bgneal@74 68 try:
bgneal@565 69 IllegalUsername.objects.get(username=username)
bgneal@74 70 except IllegalUsername.DoesNotExist:
bgneal@74 71 return username
bgneal@74 72 self._validation_error("That username is not allowed.", username)
bgneal@74 73 self._validation_error("A pending user with that username already exists.", username)
bgneal@74 74 self._validation_error("A user with that username already exists.", username)
gremmie@1 75
bgneal@74 76 def clean_email(self):
bgneal@74 77 email = self.cleaned_data['email']
bgneal@565 78
bgneal@565 79 if User.objects.filter(email=email).count():
bgneal@565 80 self._validation_error("A user with that email address already exists.", email)
bgneal@565 81 elif PendingUser.objects.filter(email=email).count():
bgneal@74 82 self._validation_error("A pending user with that email address already exists.", email)
bgneal@565 83 elif IllegalEmail.objects.filter(email=email).count():
bgneal@565 84 self._validation_error("That email address is not allowed.", email)
bgneal@659 85
bgneal@565 86 # email is ok
bgneal@565 87 return email
gremmie@1 88
bgneal@74 89 def clean_password2(self):
bgneal@74 90 password1 = self.cleaned_data.get("password1", "")
bgneal@74 91 password2 = self.cleaned_data["password2"]
bgneal@74 92 if password1 != password2:
bgneal@74 93 self._validation_error("The two password fields didn't match.")
bgneal@155 94 if len(password1) < 6:
bgneal@155 95 self._validation_error("Please choose a password of 6 characters or more.")
bgneal@74 96 return password2
gremmie@1 97
bgneal@346 98 def clean_question1(self):
bgneal@346 99 answer = self.cleaned_data.get('question1')
bgneal@346 100 success = False
bgneal@346 101 if answer:
bgneal@346 102 try:
bgneal@346 103 val = int(answer)
bgneal@346 104 except ValueError:
bgneal@346 105 pass
bgneal@346 106 else:
bgneal@346 107 success = val == 101
bgneal@346 108 if not success:
bgneal@346 109 self._validation_error("Incorrect answer to our anti-spam question.", answer)
bgneal@346 110 return answer
bgneal@346 111
bgneal@347 112 def clean_question2(self):
bgneal@347 113 """
bgneal@347 114 Honeypot field should be empty.
bgneal@347 115 """
bgneal@347 116 answer = self.cleaned_data.get('question2')
bgneal@347 117 if answer:
bgneal@690 118 logger.critical('Accounts/registration: Honeypot filled [%s]', self.ip)
bgneal@690 119 self._validation_error('Wrong answer #2', answer)
bgneal@347 120 return answer
bgneal@347 121
bgneal@74 122 def save(self):
bgneal@74 123 pending_user = PendingUser.objects.create_pending_user(self.cleaned_data['username'],
bgneal@74 124 self.cleaned_data['email'],
bgneal@74 125 self.cleaned_data['password1'])
gremmie@1 126
bgneal@74 127 # Send the confirmation email
gremmie@1 128
bgneal@74 129 site = Site.objects.get_current()
bgneal@74 130 admin_email = settings.ADMINS[0][1]
gremmie@1 131
bgneal@316 132 activation_link = 'http://%s%s' % (site.domain, reverse('accounts.views.register_confirm',
bgneal@74 133 kwargs = {'username' : pending_user.username, 'key' : pending_user.key}))
gremmie@1 134
bgneal@74 135 msg = render_to_string('accounts/registration_email.txt',
bgneal@74 136 {
bgneal@74 137 'site_name' : site.name,
bgneal@74 138 'site_domain' : site.domain,
bgneal@74 139 'user_email' : pending_user.email,
bgneal@74 140 'activation_link' : activation_link,
bgneal@74 141 'username' : pending_user.username,
bgneal@74 142 'admin_email' : admin_email,
bgneal@74 143 })
gremmie@1 144
bgneal@74 145 subject = 'Registration Confirmation for ' + site.name
bgneal@659 146 send_mail(subject, msg, admin_email, [self.cleaned_data['email']],
bgneal@659 147 defer=False)
bgneal@690 148 logger.info('Accounts/registration conf. email sent to %s for user %s; IP = %s',
bgneal@316 149 self.cleaned_data['email'], pending_user.username, self.ip)
gremmie@1 150
bgneal@74 151 return pending_user
gremmie@1 152
bgneal@74 153 def _validation_error(self, msg, param=None):
bgneal@690 154 logger.error('Accounts/registration [%s]: %s (%s)', self.ip, msg, param)
bgneal@74 155 raise forms.ValidationError(msg)
bgneal@659 156
bgneal@659 157
bgneal@659 158 class ForgotUsernameForm(forms.Form):
bgneal@659 159 """Form used to recover lost username"""
bgneal@659 160 email = forms.EmailField(widget=forms.TextInput(attrs={'class': 'text'}))
bgneal@659 161
bgneal@659 162 def save(self):
bgneal@659 163 """Email the username associated with the email address to the user."""
bgneal@659 164 email = self.cleaned_data['email']
bgneal@659 165 try:
bgneal@659 166 user = User.objects.get(email=email)
bgneal@659 167 except User.DoesNotExist:
bgneal@659 168 # nothing to do; we don't tell the user as this gives away info
bgneal@659 169 # about our database
bgneal@659 170 return
bgneal@659 171
bgneal@659 172 site = Site.objects.get_current()
bgneal@659 173 admin_email = settings.ADMINS[0][1]
bgneal@659 174
bgneal@659 175 subject = 'Forgotten username for %s' % site.name
bgneal@659 176 msg = render_to_string('accounts/forgot_user_email.txt', {
bgneal@659 177 'user': user,
bgneal@659 178 'site': site,
bgneal@659 179 'admin_email': admin_email,
bgneal@659 180 })
bgneal@659 181 send_mail(subject, msg, admin_email, [email], defer=False)
bgneal@659 182
bgneal@690 183 logger.info('Forgotten username email sent to {} <{}>'.format(
bgneal@659 184 user.username, email))