From a6f86e9506dd43da042e8f335a761ec336536ac8 Mon Sep 17 00:00:00 2001
From: Dave Dash
Date: Thu, 19 Aug 2010 10:42:01 -0700
Subject: [PATCH] bug 558507, adds recaptcha
---
apps/users/forms.py | 42 ++++++++++++++++--------
apps/users/models.py | 6 ++--
apps/users/templates/users/register.html | 7 ++++
apps/users/tests/test_forms.py | 9 +++--
apps/users/views.py | 6 ++--
requirements/prod.txt | 4 +++
settings.py | 5 ++-
7 files changed, 57 insertions(+), 22 deletions(-)
diff --git a/apps/users/forms.py b/apps/users/forms.py
index 2f064df9c5..db193a191e 100644
--- a/apps/users/forms.py
+++ b/apps/users/forms.py
@@ -4,7 +4,9 @@ from django import forms
from django.contrib.auth import forms as auth_forms
from django.forms.util import ErrorList
+import captcha.fields
import commonware.log
+import happyforms
from tower import ugettext as _
from .models import UserProfile, BlacklistedUsername
@@ -66,14 +68,19 @@ class UserDeleteForm(forms.Form):
super(UserDeleteForm, self).save(**kw)
-class UserRegisterForm(forms.ModelForm):
- """For registering users. We're not building off
+class UserRegisterForm(happyforms.ModelForm):
+ """
+ For registering users. We're not building off
d.contrib.auth.forms.UserCreationForm because it doesn't do a lot of the
- details here, so we'd have to rewrite most of it anyway."""
- password = forms.CharField(max_length=255, required=False,
- widget=forms.PasswordInput(render_value=False))
- password2 = forms.CharField(max_length=255, required=False,
- widget=forms.PasswordInput(render_value=False))
+ details here, so we'd have to rewrite most of it anyway.
+ """
+
+ password = forms.CharField(max_length=255,
+ widget=forms.PasswordInput(render_value=False))
+
+ password2 = forms.CharField(max_length=255,
+ widget=forms.PasswordInput(render_value=False))
+ recaptcha = captcha.fields.ReCaptchaField()
class Meta:
model = UserProfile
@@ -81,7 +88,7 @@ class UserRegisterForm(forms.ModelForm):
def clean_username(self):
name = self.cleaned_data['username']
if BlacklistedUsername.blocked(name):
- raise forms.ValidationError("This username is invalid.")
+ raise forms.ValidationError(_('This username is invalid.'))
return name
def clean(self):
@@ -90,13 +97,14 @@ class UserRegisterForm(forms.ModelForm):
data = self.cleaned_data
# Passwords
- p1 = data.get("password")
- p2 = data.get("password2")
+ p1 = data.get('password')
+ p2 = data.get('password2')
if p1 != p2:
- msg = _("The passwords did not match.")
- self._errors["password2"] = ErrorList([msg])
- del data["password2"]
+ msg = _('The passwords did not match.')
+ self._errors['password2'] = ErrorList([msg])
+ if p2:
+ del data['password2']
return data
@@ -104,11 +112,19 @@ class UserRegisterForm(forms.ModelForm):
class UserEditForm(UserRegisterForm):
oldpassword = forms.CharField(max_length=255, required=False,
widget=forms.PasswordInput(render_value=False))
+ password = forms.CharField(max_length=255, required=False,
+ widget=forms.PasswordInput(render_value=False))
+
+ password2 = forms.CharField(max_length=255, required=False,
+ widget=forms.PasswordInput(render_value=False))
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(UserEditForm, self).__init__(*args, **kwargs)
+ # TODO: We should inherit from a base form not UserRegisterForm
+ del self.fields['recaptcha']
+
class Meta:
model = UserProfile
exclude = ['password']
diff --git a/apps/users/models.py b/apps/users/models.py
index bb96821789..3d933791ae 100644
--- a/apps/users/models.py
+++ b/apps/users/models.py
@@ -49,10 +49,8 @@ class UserProfile(amo.models.ModelBase):
nickname = models.CharField(max_length=255, default='', null=True,
blank=True)
- firstname = models.CharField(max_length=255, default='', null=True,
- blank=True)
- lastname = models.CharField(max_length=255, default='', null=True,
- blank=True)
+ firstname = models.CharField(max_length=255, default='', blank=True)
+ lastname = models.CharField(max_length=255, default='', blank=True)
username = models.CharField(max_length=255, default='', unique=True)
display_name = models.CharField(max_length=255, default='', null=True,
diff --git a/apps/users/templates/users/register.html b/apps/users/templates/users/register.html
index 33d691d00e..9cbcc55cee 100644
--- a/apps/users/templates/users/register.html
+++ b/apps/users/templates/users/register.html
@@ -58,6 +58,13 @@
{{ form.password2|safe }}
{{ form.password2.errors|safe }}
+
+
+ {{ form.recaptcha|safe }}
+ {{ form.recaptcha.errors|safe }}
+
diff --git a/apps/users/tests/test_forms.py b/apps/users/tests/test_forms.py
index d6e0587036..939487a405 100644
--- a/apps/users/tests/test_forms.py
+++ b/apps/users/tests/test_forms.py
@@ -5,6 +5,7 @@ from django.utils.http import int_to_base36
import test_utils
from manage import settings
+from mock import patch
from nose.tools import eq_
import amo.test_utils
@@ -266,13 +267,17 @@ class TestUserRegisterForm(UserFormBase):
self.assertContains(r, "You are already logged in")
self.assertNotContains(r, '')
- def test_success(self):
+ @patch('captcha.fields.ReCaptchaField.clean')
+ def test_success(self, clean):
+ clean = lambda: ''
+
data = {'email': 'john.connor@sky.net',
'password': 'carebears',
'password2': 'carebears',
'username': 'BigJC',
'homepage': ''}
- r = self.client.post('/en-US/firefox/users/register', data)
+ r = self.client.post('/en-US/firefox/users/register', data,
+ follow=True)
self.assertContains(r, "Congratulations!")
u = User.objects.get(email='john.connor@sky.net').get_profile()
diff --git a/apps/users/views.py b/apps/users/views.py
index 17d691e2d5..3a402b365f 100644
--- a/apps/users/views.py
+++ b/apps/users/views.py
@@ -1,4 +1,3 @@
-import json
import random
import string
from django import http
@@ -27,11 +26,12 @@ from .utils import EmailResetCode
log = commonware.log.getLogger('z.users')
+
@login_required(redirect=False)
@json_view
def ajax(request):
"""Query for a user matching a given email."""
- email = request.GET.get('q','').strip()
+ email = request.GET.get('q', '').strip()
u = get_object_or_404(UserProfile, email=email)
return dict(id=u.id, name=u.display_name)
@@ -306,7 +306,9 @@ def register(request):
messages.info(request, _("You are already logged in to an account."))
form = None
elif request.method == 'POST':
+
form = forms.UserRegisterForm(request.POST)
+
if form.is_valid():
data = request.POST
u = UserProfile()
diff --git a/requirements/prod.txt b/requirements/prod.txt
index 9c6ff6ad7c..5cb23bbe58 100644
--- a/requirements/prod.txt
+++ b/requirements/prod.txt
@@ -31,3 +31,7 @@ importlib==1.0.2
# Better Forms
-e git://github.com/mozilla/happyforms.git#egg=happyforms
+
+# Recaptcha
+-e git://github.com/mozilla/django-recaptcha.git#egg=django-recaptcha
+
diff --git a/settings.py b/settings.py
index 8ce08a982e..40fbdcc380 100644
--- a/settings.py
+++ b/settings.py
@@ -534,8 +534,11 @@ def read_only_mode(env):
# Uploaded file limits
MAX_ICON_UPLOAD_SIZE = 4 * 1024 * 1024
-
## Feature switches
# Use this to keep collections compatible with remora before we're ready to
# switch to zamboni/bandwagon3.
NEW_COLLECTIONS = True
+
+# RECAPTCHA
+RECAPTCHA_PUBLIC_KEY = ''
+RECAPTCHA_PRIVATE_KEY = ''