Browse files

Finished implementing account recovery, with unit tests

  • Loading branch information...
1 parent 37ff232 commit 924647bf7c3622d656a07bb458b6d1b27b0fd031 Simon Willison committed May 25, 2009
Showing with 60 additions and 7 deletions.
  1. +8 −3 django_openid/auth.py
  2. +1 −1 django_openid/registration.py
  3. +51 −3 django_openid/tests/auth_tests.py
View
11 django_openid/auth.py
@@ -29,6 +29,7 @@ class AuthConsumer(consumer.SessionConsumer):
recovery_complete_template = 'django_openid/recovery_complete.html'
recovery_email_from = None
+ recovery_email_subject = 'Recover your account'
password_logins_enabled = True
account_recovery_enabled = True
@@ -43,6 +44,8 @@ class AuthConsumer(consumer.SessionConsumer):
bad_password_message = 'Incorrect username or password'
invalid_token_message = 'Invalid token'
recovery_email_sent_message = 'Check your mail for further instructions'
+ recovery_not_found_message = 'No matching user was found'
+ recovery_multiple_found_message = 'Try entering your username instead'
r_user_not_found_message = 'That user account does not exist'
account_recovery_url = None
@@ -303,7 +306,7 @@ def do_recover(self, request, extra_message = None):
users = self.lookup_users_by_email(submitted)
if users:
if len(users) > 1:
- extra_message = 'Try entering your username instead'
+ extra_message = self.recovery_multiple_found_message
user = None
else:
user = users[0]
@@ -312,6 +315,8 @@ def do_recover(self, request, extra_message = None):
return self.show_message(
request, 'E-mail sent', self.recovery_email_sent_message
)
+ else:
+ extra_message = self.recovery_not_found_message
return self.render(request, self.recover_template, {
'action': request.path,
'message': extra_message,
@@ -371,7 +376,7 @@ def do_r(self, request, token = ''):
'associate_url': urljoin(request.path, '../../associations/'),
'user': user,
})
- do_r.urlregex = '^r/([\w.]+)/$'
+ do_r.urlregex = '^r/([^/]+)/$'
def generate_recovery_code(self, user):
# Code is {hex-days}.{hex-userid}.{signature}
@@ -392,7 +397,7 @@ def send_recovery_email(self, request, user):
'code': code,
'user': user,
}).content
- send_email(
+ send_mail(
subject = self.recovery_email_subject,
message = email_body,
from_email = self.recovery_email_from or \
View
2 django_openid/registration.py
@@ -235,7 +235,7 @@ def do_c(self, request, token = ''):
else:
return self.show_error(request, c_already_confirmed_message)
- do_c.urlregex = '^c/([\w.]+)/$'
+ do_c.urlregex = '^c/([^/]+)/$'
def create_user(self, request, data, openid=None):
from django.contrib.auth.models import User
View
54 django_openid/tests/auth_tests.py
@@ -30,7 +30,10 @@ def setUp(self):
)
# Create user accounts associated with OpenIDs
- self.no_openids = User.objects.create(username = 'noopenids')
+ self.no_openids = User.objects.create(
+ username = 'noopenids',
+ email = 'noopenids@example.com'
+ )
self.no_openids.set_password('password')
self.no_openids.save()
self.one_openid = User.objects.create(username = 'oneopenid')
@@ -99,9 +102,10 @@ def testRegisterWithPassword(self):
self.assertEqual(len(mail.outbox), 1)
# Now extract and click that link
- body = mail.outbox[0].body
+ msg = mail.outbox[0]
+ self.assertEqual(msg.to, [u'test@example.com'])
link = [
- l.strip() for l in body.splitlines()
+ l.strip() for l in msg.body.splitlines()
if l.startswith('http://testserver/')
][0]
response = self.client.get(link)
@@ -114,3 +118,47 @@ def testRegisterWithPassword(self):
self.assertEqual(
user.groups.filter(name = 'Unconfirmed users').count(), 0
)
+
+class AccountRecoveryTest(AuthTestBase):
+
+ def testRecoverAccountBadUsername(self):
+ response = self.client.get('/openid/recover/')
+ self.assertEqual(
+ response.template_name, 'django_openid/recover.html'
+ )
+ response = self.client.post('/openid/recover/', {
+ 'recover': 'does-not-exist'
+ })
+ self.assertEqual(
+ response.template_context['message'],
+ RegistrationConsumer.recovery_not_found_message
+ )
+
+ def testRecoverAccountByUsername(self):
+ self.assertEqual(len(mail.outbox), 0)
+ response = self.client.post('/openid/recover/', {
+ 'recover': 'noopenids'
+ })
+ self.assertEqual(len(mail.outbox), 1)
+ msg = mail.outbox[0]
+ self.assertEqual(msg.to, [u'noopenids@example.com'])
+ link = [
+ l.strip() for l in msg.body.splitlines()
+ if l.startswith('http://testserver/')
+ ][0]
+
+ # Tampering with the link should cause it to fail
+ bits = link.split('.')
+ bits[-1] = 'X' + bits[-1]
+ tampered = '.'.join(bits)
+ response = self.client.get(tampered)
+ self.assert_('Invalid token' in str(response))
+ self.assertNotEqual(
+ response.template_name, 'django_openid/recovery_complete.html'
+ )
+ # Following that link should log us in
+ response = self.client.get(link)
+ self.assertEqual(
+ response.template_name, 'django_openid/recovery_complete.html'
+ )
+

0 comments on commit 924647b

Please sign in to comment.