1. Daniel Lindsley
  2. django-registration

Commits

Daniel Lindsley  committed a9231fc

Moved the deletion of expired users to the backend, which allows for customization.

  • Participants
  • Parent commits d36a382
  • Branches default

Comments (0)

Files changed (8)

File docs/backend-api.rst

View file
 
 For workflows which do not require a separate activation step, this
 method can and should raise ``NotImplementedError``.
+
+
+delete_expired_users()
+~~~~~~~~~~~~~~~~~~~~~~
+
+Removes expired instances of :class:`RegistrationProfile`, and
+their associated user accounts, from the database. This is
+useful as a periodic maintenance task to clean out accounts
+which registered but never activated.
+
+Accounts to be deleted are identified by searching for instances
+of :class:`RegistrationProfile` with expired activation keys and
+with associated user accounts which are inactive (have their
+``is_active`` field set to ``False``). To disable a user account
+without having it deleted, simply delete its associated
+:class:`RegistrationProfile`; any ``User`` which does not have
+an associated :class:`RegistrationProfile` will not be deleted.
+
+A custom management command is provided which will execute this
+method, suitable for use in cron jobs or other scheduled
+maintenance tasks: ``manage.py cleanupregistration``.

File docs/default-backend.rst

View file
       :type activation_key: string, a 40-character SHA1 hexdigest
       :rtype: ``User`` or bool
 
-   .. method:: delete_expired_users
-
-      Removes expired instances of :class:`RegistrationProfile`, and
-      their associated user accounts, from the database. This is
-      useful as a periodic maintenance task to clean out accounts
-      which registered but never activated.
-
-      Accounts to be deleted are identified by searching for instances
-      of :class:`RegistrationProfile` with expired activation keys and
-      with associated user accounts which are inactive (have their
-      ``is_active`` field set to ``False``). To disable a user account
-      without having it deleted, simply delete its associated
-      :class:`RegistrationProfile`; any ``User`` which does not have
-      an associated :class:`RegistrationProfile` will not be deleted.
-
-      A custom management command is provided which will execute this
-      method, suitable for use in cron jobs or other scheduled
-      maintenance tasks: ``manage.py cleanupregistration``.
-
-      :rtype: ``None``
-
    .. method:: create_inactive_user(username, email, password, site[, send_email])
 
       Creates a new, inactive user account and an associated instance

File registration/backends/default/__init__.py

View file
         
         """
         return ('registration_activation_complete', (), {})
+
+    def delete_expired_users(self):
+        """
+        Remove expired instances of ``RegistrationProfile`` and their
+        associated ``User``s.
+        
+        Accounts to be deleted are identified by searching for
+        instances of ``RegistrationProfile`` with expired activation
+        keys, and then checking to see if their associated ``User``
+        instances have the field ``is_active`` set to ``False``; any
+        ``User`` who is both inactive and has an expired activation
+        key will be deleted.
+        
+        It is recommended that this method be executed regularly as
+        part of your routine site maintenance; this application
+        provides a custom management command which will call this
+        method, accessible as ``manage.py cleanupregistration``.
+        
+        Regularly clearing out accounts which have never been
+        activated serves two useful purposes:
+        
+        1. It alleviates the ocasional need to reset a
+           ``RegistrationProfile`` and/or re-send an activation email
+           when a user does not receive or does not act upon the
+           initial activation email; since the account will be
+           deleted, the user will be able to simply re-register and
+           receive a new activation key.
+        
+        2. It prevents the possibility of a malicious user registering
+           one or more accounts and never activating them (thus
+           denying the use of those usernames to anyone else); since
+           those accounts will be deleted, the usernames will become
+           available for use again.
+        
+        This method respects inactive ``User``s whose associated
+        ``RegistrationProfile`` has been marked as activated. In this case,
+        only the ``RegistrationProfile`` will be deleted, leaving the inactive
+        ``User`` (and related data) in place.
+        
+        """
+        for profile in RegistrationProfile.objects.all():
+            if profile.is_activated():
+                profile.delete()
+            elif profile.activation_key_expired():
+                user = profile.user
+                if not user.is_active:
+                    user.delete()

File registration/backends/simple/__init__.py

View file
 from django.contrib.auth.models import User
 
 from registration import signals
+from registration.backends.default import DefaultBackend
 from registration.forms import RegistrationForm
 
 
-class SimpleBackend(object):
+class SimpleBackend(DefaultBackend):
     """
     A registration backend which implements the simplest possible
     workflow: a user supplies a username, email address and password

File registration/management/commands/cleanupregistration.py

View file
 A management command which deletes expired accounts (e.g.,
 accounts which signed up but never activated) from the database.
 
-Calls ``RegistrationProfile.objects.delete_expired_users()``, which
-contains the actual logic for determining which accounts are deleted.
+Calls ``backend.delete_expired_users()``, which contains the actual
+logic for determining which accounts are deleted.
+
+You can supply a custom backend using the ``--backend`` flag, which
+takes a dotted import path to the appropriate class.
 
 """
 
+from optparse import make_option
+
 from django.core.management.base import NoArgsCommand
 
-from registration.models import RegistrationProfile
+from registration.backends import get_backend
 
 
 class Command(NoArgsCommand):
     help = "Delete expired user registrations from the database"
+    option_list = NoArgsCommand.option_list + (
+            make_option('--backend',
+                action='store',
+                dest='backend',
+                default='registration.backends.default.DefaultBackend',
+                help='Specifies the backend to use when removing expired accounts'),
+            )
 
-    def handle_noargs(self, **options):
-        RegistrationProfile.objects.delete_expired_users()
+    def handle(self, **options):
+        backend = get_backend(options['backend'])
+        backend.delete_expired_users()

File registration/models.py

View file
                            activation_key=activation_key)
         
     def delete_expired_users(self):
-        """
-        Remove expired instances of ``RegistrationProfile`` and their
-        associated ``User``s.
-        
-        Accounts to be deleted are identified by searching for
-        instances of ``RegistrationProfile`` with expired activation
-        keys, and then checking to see if their associated ``User``
-        instances have the field ``is_active`` set to ``False``; any
-        ``User`` who is both inactive and has an expired activation
-        key will be deleted.
-        
-        It is recommended that this method be executed regularly as
-        part of your routine site maintenance; this application
-        provides a custom management command which will call this
-        method, accessible as ``manage.py cleanupregistration``.
-        
-        Regularly clearing out accounts which have never been
-        activated serves two useful purposes:
-        
-        1. It alleviates the ocasional need to reset a
-           ``RegistrationProfile`` and/or re-send an activation email
-           when a user does not receive or does not act upon the
-           initial activation email; since the account will be
-           deleted, the user will be able to simply re-register and
-           receive a new activation key.
-        
-        2. It prevents the possibility of a malicious user registering
-           one or more accounts and never activating them (thus
-           denying the use of those usernames to anyone else); since
-           those accounts will be deleted, the usernames will become
-           available for use again.
-        
-        If you have a troublesome ``User`` and wish to disable their
-        account while keeping it in the database, simply delete the
-        associated ``RegistrationProfile``; an inactive ``User`` which
-        does not have an associated ``RegistrationProfile`` will not
-        be deleted.
-        
-        """
-        for profile in self.all():
-            if profile.activation_key_expired():
-                user = profile.user
-                if not user.is_active:
-                    user.delete()
+        raise DeprecationWarning("This method has been removed. Please use the 'delete_expired_users' on the correct backend.")
 
 
 class RegistrationProfile(models.Model):
     def __unicode__(self):
         return u"Registration information for %s" % self.user
     
+    def is_activated(self):
+        return self.activation_key == self.ACTIVATED
+    
     def activation_key_expired(self):
         """
         Determine whether this ``RegistrationProfile``'s activation
         
         """
         expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
-        return self.activation_key == self.ACTIVATED or \
+        return self.is_activated() or \
                (self.user.date_joined + expiration_date <= datetime.datetime.now())
     activation_key_expired.boolean = True
 

File registration/tests/backends.py

View file
         admin_class.activate_users(_mock_request(),
                                    RegistrationProfile.objects.all())
         self.failUnless(User.objects.get(username='alice').is_active)
+    
+    def test_expired_user_deletion(self):
+        """
+        ``DefaultBackend.delete_expired_users()`` only
+        deletes inactive users whose activation window has expired.
+        
+        """
+        new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+                                                                    username='alice',
+                                                                    password='swordfish',
+                                                                    email='alice@example.com')
+        expired_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+                                                                        username='bob',
+                                                                        password='secret',
+                                                                        email='bob@example.com')
+        expired_user.date_joined -= datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS + 1)
+        expired_user.save()
+        disabled_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+                                                                         username='disabled',
+                                                                         password='password',
+                                                                         email='disabled@example.com')
+        disabled_user.activation_key = RegistrationProfile.ACTIVATED
+        disabled_user.save()
+
+        self.assertRaises(DeprecationWarning, RegistrationProfile.objects.delete_expired_users)
+        self.assertEqual(RegistrationProfile.objects.count(), 3)
+        self.backend.delete_expired_users()
+        self.assertEqual(RegistrationProfile.objects.count(), 2)
+        self.assertRaises(User.DoesNotExist, User.objects.get, username='bob')
 
 
 class SimpleRegistrationBackendTests(TestCase):

File registration/tests/models.py

View file
         invalid_key = sha_constructor('foo').hexdigest()
         self.failIf(RegistrationProfile.objects.activate_user(invalid_key))
 
-    def test_expired_user_deletion(self):
-        """
-        ``RegistrationProfile.objects.delete_expired_users()`` only
-        deletes inactive users whose activation window has expired.
-        
-        """
-        new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
-                                                                    **self.user_info)
-        expired_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
-                                                                        username='bob',
-                                                                        password='secret',
-                                                                        email='bob@example.com')
-        expired_user.date_joined -= datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS + 1)
-        expired_user.save()
-
-        RegistrationProfile.objects.delete_expired_users()
-        self.assertEqual(RegistrationProfile.objects.count(), 1)
-        self.assertRaises(User.DoesNotExist, User.objects.get, username='bob')
-
     def test_management_command(self):
         """
         The ``cleanupregistration`` management command properly