James Bennett avatar James Bennett committed 04bc7d4

First draft of a simple one-step registration backend. Documentation in next commit.

Comments (0)

Files changed (3)

registration/backends/simple/__init__.py

+from django.conf import settings
+from django.contrib.auth import authenticate
+from django.contrib.auth import login
+from django.contrib.auth.models import User
+
+from registration import signals
+from registration.forms import RegistrationForm
+
+
+class SimpleBackend(object):
+    """
+    A registration backend which implements the simplest possible
+    workflow: a user supplies a username, email address and password
+    (the bare minimum for a useful account), and is immediately signed
+    up and logged in.
+    
+    """
+    def register(self, request, **kwargs):
+        """
+        Create and immediately log in a new user.
+        
+        """
+        username, email, password = kwargs['username'], kwargs['email'], kwargs['password1']
+        User.objects.create_user(username, email, password)
+        
+        # authenticate() always has to be called before login(), and
+        # will return the user we just created.
+        new_user = authenticate(username=username, password=password)
+        login(request, new_user)
+        signals.user_registered.send(sender=self.__class__,
+                                     user=new_user,
+                                     request=request)
+        return new_user
+
+    def activate(self, **kwargs):
+        raise NotImplementedError
+
+    def registration_allowed(self, request):
+        """
+        Indicate whether account registration is currently permitted,
+        based on the value of the setting ``REGISTRATION_OPEN``. This
+        is determined as follows:
+
+        * If ``REGISTRATION_OPEN`` is not specified in settings, or is
+          set to ``True``, registration is permitted.
+
+        * If ``REGISTRATION_OPEN`` is both specified and set to
+          ``False``, registration is not permitted.
+        
+        """
+        return getattr(settings, 'REGISTRATION_OPEN', True)
+
+    def get_form_class(self, request):
+        return RegistrationForm
+
+    def post_registration_redirect(self, request, user):
+        """
+        After registration, redirect to the user's account page.
+        
+        """
+        return (user.get_absolute_url(), (), {})
+
+    def post_activation_redirect(self, request, user):
+        raise NotImplementedError

registration/backends/simple/urls.py

+"""
+URLconf for registration and activation, using django-registration's
+default backend.
+
+If the default behavior of these views is acceptable to you, simply
+use a line like this in your root URLconf to set up the default URLs
+for registration::
+
+    (r'^accounts/', include('registration.backends.default.urls')),
+
+This will also automatically set up the views in
+``django.contrib.auth`` at sensible default locations.
+
+If you'd like to customize the behavior (e.g., by passing extra
+arguments to the various views) or split up the URLs, feel free to set
+up your own URL patterns for these views instead.
+
+"""
+
+
+from django.conf.urls.defaults import *
+from django.views.generic.simple import direct_to_template
+
+from registration.views import activate
+from registration.views import register
+
+
+urlpatterns = patterns('',
+                       url(r'^register/$',
+                           register,
+                           { 'backend': 'registration.backends.default.DefaultBackend' },
+                           name='registration_register'),
+                       url(r'^register/closed/$',
+                           direct_to_template,
+                           { 'template': 'registration/registration_closed.html' },
+                           name='registration_disallowed'),
+                       (r'', include('registration.auth_urls')),
+                       )

registration/tests/backends.py

 from django.conf import settings
 from django.contrib import admin
 from django.contrib.auth.models import User
+from django.contrib.sessions.middleware import SessionMiddleware
 from django.contrib.sites.models import Site
 from django.core import mail
 from django.core.exceptions import ImproperlyConfigured
 from registration.admin import RegistrationAdmin
 from registration.backends import get_backend
 from registration.backends.default import DefaultBackend
+from registration.backends.simple import SimpleBackend
 from registration.models import RegistrationProfile
 
 
             }
         environ.update(self.defaults)
         environ.update(request)
-        return WSGIRequest(environ)
+        request = WSGIRequest(environ)
+
+        # We have to manually add a session since we'll be bypassing
+        # the middleware chain.
+        session_middleware = SessionMiddleware()
+        session_middleware.process_request(request)
+        return request
 
 
 def _mock_request():
     the default backend.
 
     """
+    backend = DefaultBackend()
+    
     def setUp(self):
         """
         Create an instance of the default backend for use in testing,
         and set ``ACCOUNT_ACTIVATION_DAYS`` if it's not set already.
 
         """
-        from registration.backends.default import DefaultBackend
-        self.backend = DefaultBackend()
         self.old_activation = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', None)
         if self.old_activation is None:
             settings.ACCOUNT_ACTIVATION_DAYS = 7
         admin_class.activate_users(_mock_request(),
                                    RegistrationProfile.objects.all())
         self.failUnless(User.objects.get(username='alice').is_active)
+
+
+class SimpleRegistrationBackendTests(TestCase):
+    """
+    Test the simple registration backend, which does signup and
+    immediate activation.
+    
+    """
+    backend = SimpleBackend()
+    
+    def test_registration(self):
+        """
+        Test the registration process: registration creates a new
+        inactive account and a new profile with activation key,
+        populates the correct account data and sends an activation
+        email.
+
+        """
+        new_user = self.backend.register(_mock_request(),
+                                         username='bob',
+                                         email='bob@example.com',
+                                         password1='secret')
+
+        # Details of the returned user must match what went in.
+        self.assertEqual(new_user.username, 'bob')
+        self.failUnless(new_user.check_password('secret'))
+        self.assertEqual(new_user.email, 'bob@example.com')
+
+        # New user must not be active.
+        self.failUnless(new_user.is_active)
+
+    def test_allow(self):
+        """
+        Test that the setting ``REGISTRATION_OPEN`` appropriately
+        controls whether registration is permitted.
+
+        """
+        old_allowed = getattr(settings, 'REGISTRATION_OPEN', True)
+        settings.REGISTRATION_OPEN = True
+        self.failUnless(self.backend.registration_allowed(_mock_request()))
+
+        settings.REGISTRATION_OPEN = False
+        self.failIf(self.backend.registration_allowed(_mock_request()))
+        settings.REGISTRATION_OPEN = old_allowed
+
+    def test_form_class(self):
+        """
+        Test that the default form class returned is
+        ``registration.forms.RegistrationForm``.
+
+        """
+        self.failUnless(self.backend.get_form_class(_mock_request()) is forms.RegistrationForm)
+
+    def test_post_registration_redirect(self):
+        """
+        Test that the default post-registration redirect is the public
+        URL of the new user account.
+
+        """
+        new_user = self.backend.register(_mock_request(),
+                                         username='bob',
+                                         email='bob@example.com',
+                                         password1='secret')
+        
+        self.assertEqual(self.backend.post_registration_redirect(_mock_request(), new_user),
+                         (new_user.get_absolute_url(), (), {}))
+
+    def test_registration_signal(self):
+        """
+        Test that registering a user sends the ``user_registered``
+        signal.
+        
+        """
+        def receiver(sender, **kwargs):
+            self.failUnless('user' in kwargs)
+            self.assertEqual(kwargs['user'].username, 'bob')
+            self.failUnless('request' in kwargs)
+            self.failUnless(isinstance(kwargs['request'], WSGIRequest))
+            received_signals.append(kwargs.get('signal'))
+
+        received_signals = []
+        signals.user_registered.connect(receiver, sender=self.backend.__class__)
+
+        self.backend.register(_mock_request(),
+                              username='bob',
+                              email='bob@example.com',
+                              password1='secret')
+
+        self.assertEqual(len(received_signals), 1)
+        self.assertEqual(received_signals, [signals.user_registered])
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.