annotate accounts/forms.py @ 661:15dbe0ccda95

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