# HG changeset patch # User Brian Neal # Date 1400028288 18000 # Node ID 9133b4626a4bde4d833009da38a258cfd4a5cebd # Parent b6d6c9e37faeed665bc6bf5dbcec16d59619d1c3 Added additional security questions on the registration page. diff -r b6d6c9e37fae -r 9133b4626a4b accounts/forms.py --- a/accounts/forms.py Sun May 04 15:37:56 2014 -0500 +++ b/accounts/forms.py Tue May 13 19:44:48 2014 -0500 @@ -52,6 +52,31 @@ widget=forms.TextInput(attrs={'class': 'text'})) question2 = forms.CharField(label='', required=False, widget=forms.TextInput(attrs={'style': 'display: none;'})) + question3 = forms.CharField(label="Don't put anything in this box", + required=False, + widget=forms.TextInput(attrs={'class': 'text'})) + + SPAM_CHOICES = [(1, 'cat'), (2, '328'), (4, 'green'), (8, 'ocean')] + question4 = forms.ChoiceField(label="Pick the number", choices=SPAM_CHOICES) + question5 = forms.IntegerField(label="What number did you pick, above?", + widget=forms.TextInput(attrs={'class': 'text'})) + question6 = forms.ChoiceField(label="Pick the color", choices=SPAM_CHOICES) + + USER_QUALITIES = [ + (1, "I am the lowest form of life, a spammer"), + (2, "I'm a fan of surf music or I want to learn more"), + (3, "Someone is paying me to post links to this site"), + (4, "I am not going to spam this site"), + (5, "I understand my account may be removed if I post spam"), + (6, "I am going to spam the crap out of this site"), + (7, "Surf music is one of my interests, not spam"), + ] + question7 = forms.MultipleChoiceField( + label="Check all that apply", + choices=USER_QUALITIES, + required=False, + widget=forms.CheckboxSelectMultiple) + def __init__(self, *args, **kwargs): self.ip = kwargs.pop('ip', '?') @@ -119,6 +144,37 @@ self._validation_error('Wrong answer #2', answer) return answer + def clean_question3(self): + answer = self.cleaned_data.get('question3') + if answer: + self._validation_error('Oops, that should be blank', answer) + return answer + + def clean_question4(self): + answer = self.cleaned_data.get('question4') + if answer != u'2': + self._validation_error('Please pick the number', answer) + return answer + + def clean_question5(self): + answer = self.cleaned_data.get('question5') + if answer != 328: + self._validation_error('Please enter the correct number', answer) + return answer + + def clean_question6(self): + answer = self.cleaned_data.get('question6') + if answer != u'4': + self._validation_error('Please pick the color', answer) + return answer + + def clean_question7(self): + answer = self.cleaned_data.get('question7') + answer.sort() + if answer != [u'2', u'4', u'5', u'7']: + self._validation_error("Sorry, try again", answer) + return answer + def save(self): pending_user = PendingUser.objects.create_pending_user(self.cleaned_data['username'], self.cleaned_data['email'], diff -r b6d6c9e37fae -r 9133b4626a4b accounts/tests/test_views.py --- a/accounts/tests/test_views.py Sun May 04 15:37:56 2014 -0500 +++ b/accounts/tests/test_views.py Tue May 13 19:44:48 2014 -0500 @@ -35,6 +35,23 @@ IllegalUsername.objects.create(username='illegalusername') IllegalEmail.objects.create(email='illegal@example.com') + self.post_vals = { + 'username': 'a_new_user', + 'email': 'test@example.com', + 'password1': 'my_password', + 'password2': 'my_password', + 'agree_age': 'on', + 'agree_tos': 'on', + 'agree_privacy': 'on', + 'question1': '101', + 'question2': '', + 'question3': '', + 'question4': u'2', + 'question5': u'328', + 'question6': u'4', + 'question7': [u'2', u'4', u'5', u'7'], + } + def test_get_view(self): """ Test a simple get of the registration view @@ -68,18 +85,9 @@ Ensure we can't register with a pending username. """ - response = self.client.post(reverse('accounts-register'), { - 'username': 'pending_user', - 'email': 'test@example.com', - 'password1': 'my_password', - 'password2': 'my_password', - 'agree_age': 'on', - 'agree_tos': 'on', - 'agree_privacy': 'on', - 'question1': '101', - 'question2': '', - }) - + self.post_vals['username'] = 'pending_user' + response = self.client.post(reverse('accounts-register'), + self.post_vals) self.assertEqual(response.status_code, 200) self.assertContains(response, 'A pending user with that username already exists') @@ -88,18 +96,9 @@ Ensure we can't register with a banned username. """ - response = self.client.post(reverse('accounts-register'), { - 'username': 'illegalusername', - 'email': 'test@example.com', - 'password1': 'my_password', - 'password2': 'my_password', - 'agree_age': 'on', - 'agree_tos': 'on', - 'agree_privacy': 'on', - 'question1': '101', - 'question2': '', - }) - + self.post_vals['username'] = 'illegalusername' + response = self.client.post(reverse('accounts-register'), + self.post_vals) self.assertEqual(response.status_code, 200) self.assertContains(response, 'That username is not allowed') @@ -108,18 +107,9 @@ Ensure we can't register with a duplicate email address. """ - response = self.client.post(reverse('accounts-register'), { - 'username': 'a_new_user', - 'email': 'existing_user@example.com', - 'password1': 'my_password', - 'password2': 'my_password', - 'agree_age': 'on', - 'agree_tos': 'on', - 'agree_privacy': 'on', - 'question1': '101', - 'question2': '', - }) - + self.post_vals['email'] = 'existing_user@example.com' + response = self.client.post(reverse('accounts-register'), + self.post_vals) self.assertEqual(response.status_code, 200) self.assertContains(response, 'A user with that email address already exists') @@ -128,18 +118,9 @@ Ensure we can't register with a duplicate email address. """ - response = self.client.post(reverse('accounts-register'), { - 'username': 'a_new_user', - 'email': 'pending_user@example.com', - 'password1': 'my_password', - 'password2': 'my_password', - 'agree_age': 'on', - 'agree_tos': 'on', - 'agree_privacy': 'on', - 'question1': '101', - 'question2': '', - }) - + self.post_vals['email'] = 'pending_user@example.com' + response = self.client.post(reverse('accounts-register'), + self.post_vals) self.assertEqual(response.status_code, 200) self.assertContains(response, 'A pending user with that email address already exists') @@ -148,18 +129,9 @@ Ensure we can't register with a banned email address. """ - response = self.client.post(reverse('accounts-register'), { - 'username': 'a_new_user', - 'email': 'illegal@example.com', - 'password1': 'my_password', - 'password2': 'my_password', - 'agree_age': 'on', - 'agree_tos': 'on', - 'agree_privacy': 'on', - 'question1': '101', - 'question2': '', - }) - + self.post_vals['email'] = 'illegal@example.com' + response = self.client.post(reverse('accounts-register'), + self.post_vals) self.assertEqual(response.status_code, 200) self.assertContains(response, 'That email address is not allowed') @@ -168,18 +140,9 @@ Ensure the passwords match. """ - response = self.client.post(reverse('accounts-register'), { - 'username': 'a_new_user', - 'email': 'test@example.com', - 'password1': 'my_password', - 'password2': 'my_password_doesnt match', - 'agree_age': 'on', - 'agree_tos': 'on', - 'agree_privacy': 'on', - 'question1': '101', - 'question2': '', - }) - + self.post_vals['password2'] = "doesn't match" + response = self.client.post(reverse('accounts-register'), + self.post_vals) self.assertEqual(response.status_code, 200) self.assertContains(response, "The two password fields didn't match") @@ -188,18 +151,9 @@ Ensure our anti-spam question is answered. """ - response = self.client.post(reverse('accounts-register'), { - 'username': 'a_new_user', - 'email': 'test@example.com', - 'password1': 'my_password', - 'password2': 'my_password_doesnt match', - 'agree_age': 'on', - 'agree_tos': 'on', - 'agree_privacy': 'on', - 'question1': 'huh', - 'question2': '', - }) - + self.post_vals['question1'] = 'huh' + response = self.client.post(reverse('accounts-register'), + self.post_vals) self.assertEqual(response.status_code, 200) self.assertContains(response, "Incorrect answer to our anti-spam question") @@ -208,18 +162,102 @@ Ensure our honeypot question check works. """ - response = self.client.post(reverse('accounts-register'), { - 'username': 'a_new_user', - 'email': 'test@example.com', - 'password1': 'my_password', - 'password2': 'my_password_doesnt match', - 'agree_age': 'on', - 'agree_tos': 'on', - 'agree_privacy': 'on', - 'question1': '101', - 'question2': 'non blank', - }) + self.post_vals['question2'] = 'non blank' + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + def test_question3(self): + """ + Ensure our non-hidden honeypot question check works. + + """ + self.post_vals['question3'] = 'non blank' + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + def test_question4(self): + """ + Ensure our security question 4 works + + """ + self.post_vals['question4'] = u'1' + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + self.post_vals['question4'] = u'4' + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + self.post_vals['question4'] = u'8' + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + def test_question5(self): + """ + Ensure our security question 5 works + + """ + self.post_vals['question5'] = u'1' + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + self.post_vals['question5'] = u'X' + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + self.post_vals['question5'] = u'2983' + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + def test_question6(self): + """ + Ensure our security question 6 works + + """ + self.post_vals['question6'] = u'1' + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + self.post_vals['question6'] = u'2' + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + self.post_vals['question6'] = u'8' + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + def test_question7(self): + """Test security question 7""" + + self.post_vals['question7'] = [] + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + self.post_vals['question7'] = [u'1'] + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + self.post_vals['question7'] = [u'6', u'2', u'4', u'5', u'7'] + response = self.client.post(reverse('accounts-register'), + self.post_vals) + self.assertEqual(response.status_code, 200) + + self.post_vals['question7'] = [u'4', u'3', u'7'] + response = self.client.post(reverse('accounts-register'), + self.post_vals) self.assertEqual(response.status_code, 200) def test_success(self): @@ -227,18 +265,8 @@ Ensure we can successfully register. """ - response = self.client.post(reverse('accounts-register'), { - 'username': 'a_new_user', - 'email': 'test@example.com', - 'password1': 'my_password', - 'password2': 'my_password', - 'agree_age': 'on', - 'agree_tos': 'on', - 'agree_privacy': 'on', - 'question1': '101', - 'question2': '', - }) - + response = self.client.post(reverse('accounts-register'), + self.post_vals) self.assertEqual(response.status_code, 302) try: diff -r b6d6c9e37fae -r 9133b4626a4b sg101/templates/accounts/register.html --- a/sg101/templates/accounts/register.html Sun May 04 15:37:56 2014 -0500 +++ b/sg101/templates/accounts/register.html Tue May 13 19:44:48 2014 -0500 @@ -13,6 +13,14 @@
  • You must agree to our Terms of Service.
  • You must agree to our Privacy Policy.
  • +
    + We are really sorry about all the crazy questions in the registration form. + We are forced to do this to reduce the number of automated registrations by + spammers. Hopefully this will be a small inconvenience for you and you will + hold no hard feelings toward us. Hey at least we don't have one of those + annoying CAPTCHA things, right? Again, we are sorry for making you do + this... +
    {% csrf_token %} {{ form.as_table }}