Commits

Marko Mrdjenovic committed 6b5acc0

decoupling of RegistrationProfile to EmailValidation

Comments (0)

Files changed (14)

+The primary author of django-registration-plus is Marko Mrdjenovic
+<m@mmm.si>, who may be found online at 
+<http://friedcellcollective.net/>.
+
+django-registration-plus was forked from django-registration. Its 
+authors listed below:
 The primary author of django-registration is James Bennett
 <james@b-list.org>, who may be found online at
 <http://www.b-list.org/>.
 If you have the Python ``easy_install`` utility available, you can
 also type the following to download and install in one step::
 
-   easy_install -Z django-registration
+   easy_install -Z django-registration-plus
 
 (the ``-Z`` flag is required to force ``easy_install`` to do a normal
 source install rather than a zipped egg; django-registration cannot be
 
 Or if you're using ``pip``::
 
-    pip install django-registration
+    pip install django-registration-plus
 
 Or if you'd prefer you can simply place the included ``registration``
 directory somewhere on your Python path, or symlink to it from
 Mercurial checkout.
 
 Note that this application requires Python 2.3 or later, and a
-functional installation of Django 1.` or newer. You can obtain Python
+functional installation of Django 1.1 or newer. You can obtain Python
 from http://www.python.org/ and Django from
 http://www.djangoproject.com/.
+Copyright (c) 2011, Marko Mrdjenovic
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of the author nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+License of django-registration from which this project was forked:
+
 Copyright (c) 2007-2011, James Bennett
 All rights reserved.
 

registration/__init__.py

-VERSION = (0, 8, 0, 'alpha', 1)
+VERSION = (0, 9, 0, 'alpha', 1)
 
 def get_version():
     version = '%s.%s' % (VERSION[0], VERSION[1])

registration/admin.py

 from django.contrib.sites.models import Site
 from django.utils.translation import ugettext_lazy as _
 
-from registration.models import RegistrationProfile
+from registration.models import EmailValidation
 
 
 class RegistrationAdmin(admin.ModelAdmin):
         
         """
         for profile in queryset:
-            RegistrationProfile.objects.activate_user(profile.activation_key)
+            EmailValidation.objects.activate_user(profile.activation_key)
     activate_users.short_description = _("Activate users")
 
     def resend_activation_email(self, request, queryset):
     resend_activation_email.short_description = _("Re-send activation emails")
 
 
-admin.site.register(RegistrationProfile, RegistrationAdmin)
+admin.site.register(EmailValidation, RegistrationAdmin)

registration/backends/default/__init__.py

 
 from registration import signals
 from registration.forms import RegistrationForm
-from registration.models import RegistrationProfile
+from registration.models import EmailValidation
 
 
 class DefaultBackend(object):
       (since this backend makes use of models defined in this
       application).
 
-    * The setting ``ACCOUNT_ACTIVATION_DAYS`` be supplied, specifying
+    * The setting ``EMAIL_ACTIVATION_DAYS`` be supplied, specifying
       (as an integer) the number of days from registration during
       which a user may activate their account (after that period
       expires, activation will be disallowed).
     permitted.
 
     Internally, this is accomplished via storing an activation key in
-    an instance of ``registration.models.RegistrationProfile``. See
+    an instance of ``registration.models.EmailValidation``. See
     that model and its custom manager for full documentation of its
     fields and supported operations.
     
         user account, which will initially be inactive.
 
         Along with the new ``User`` object, a new
-        ``registration.models.RegistrationProfile`` will be created,
+        ``registration.models.EmailValidation`` will be created,
         tied to that ``User``, containing the activation key which
         will be used for this account.
 
         An email will be sent to the supplied email address; this
         email should contain an activation link. The email will be
         rendered using two templates. See the documentation for
-        ``RegistrationProfile.send_activation_email()`` for
+        ``EmailValidation.send_activation_email()`` for
         information about these templates and the contexts provided to
         them.
 
-        After the ``User`` and ``RegistrationProfile`` are created and
+        After the ``User`` and ``EmailValidation`` are created and
         the activation email is sent, the signal
         ``registration.signals.user_registered`` will be sent, with
         the new ``User`` as the keyword argument ``user`` and the
             site = Site.objects.get_current()
         else:
             site = RequestSite(request)
-        new_user = RegistrationProfile.objects.create_inactive_user(username, email,
-                                                                    password, site)
+        new_user = EmailValidation.objects.create_inactive_user(username, email,
+                                                                password, site)
         signals.user_registered.send(sender=self.__class__,
                                      user=new_user,
                                      request=request)
         the class of this backend as the sender.
         
         """
-        activated = RegistrationProfile.objects.activate_user(activation_key)
+        activated = EmailValidation.objects.activate_user(activation_key)
         if activated:
             signals.user_activated.send(sender=self.__class__,
                                         user=activated,

registration/locale/sl/LC_MESSAGES/django.mo

Binary file modified.

registration/locale/sl/LC_MESSAGES/django.po

 "Project-Id-Version: 0.8.1beta\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2009-10-12 14:09-0500\n"
-"PO-Revision-Date: 2009-10-23 15:49+0100\n"
-"Last-Translator: Domen Kožar <domen@dev.si>\n"
+"PO-Revision-Date: 2011-11-05 21:20+0100\n"
+"Last-Translator: Marko Mrdjenovic <m@mmm.si>\n"
 "Language-Team: Slovenian <domen@dev.si>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 
 #: admin.py:43
 msgid "Re-send activation emails"
-msgstr "Ponovno pošlju aktivacijske emaile"
+msgstr "Ponovno pošlji aktivacijsko e-pošto"
 
 #: forms.py:35
 msgid "username"
 
 #: forms.py:39
 msgid "Email address"
-msgstr "Elektronska pošta"
+msgstr "E-naslov"
 
 #: forms.py:41
 msgid "Password"
 
 #: forms.py:55
 msgid "A user with that username already exists."
-msgstr "Uporabnik z tem uporabniškim imenom že obstaja."
+msgstr "Uporabnik s tem uporabniškim imenom že obstaja."
 
 #: forms.py:67
 msgid "The two password fields didn't match."
 
 #: forms.py:78
 msgid "I have read and agree to the Terms of Service"
-msgstr "Strinjam se z pogoji uporable"
+msgstr "Strinjam se s pogoji uporabe"
 
 #: forms.py:79
 msgid "You must agree to the terms to register"
-msgstr "Za registracijo se morate strinjati z pogoji uporabe"
+msgstr "Za registracijo se morate strinjati s pogoji uporabe"
 
 #: forms.py:95
 msgid "This email address is already in use. Please supply a different email address."
-msgstr "Email je že v uporabi, prosimo vnesite drugega."
+msgstr "E-naslov je že v uporabi, prosimo vnesite drugega."
 
 #: forms.py:122
 msgid "Registration using free email addresses is prohibited. Please supply a different email address."
-msgstr "Registracija ni mogoča z brezplačnimi email naslovi. Prosimo vnesite drug email naslov."
+msgstr "Registracija ni mogoča z brezplačnimi e-naslovi. Prosimo vnesite drug e-naslov."
 
 #: models.py:165
 msgid "user"

registration/management/commands/cleanupregistration.py

 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
+Calls ``EmailValidation.objects.delete_expired_users()``, which
 contains the actual logic for determining which accounts are deleted.
 
 """
 
 from django.core.management.base import NoArgsCommand
 
-from registration.models import RegistrationProfile
+from registration.models import EmailValidation
 
 
 class Command(NoArgsCommand):
     help = "Delete expired user registrations from the database"
 
     def handle_noargs(self, **options):
-        RegistrationProfile.objects.delete_expired_users()
+        EmailValidation.objects.delete_expired_users()

registration/models.py

 
 from django.conf import settings
 from django.contrib.auth.models import User
+from django.core.mail import EmailMultiAlternatives
+from django.core.mail import get_connection
 from django.db import models
 from django.db import transaction
+from django.template.base import TemplateDoesNotExist
 from django.template.loader import render_to_string
 from django.utils.hashcompat import sha_constructor
 from django.utils.translation import ugettext_lazy as _
 SHA1_RE = re.compile('^[a-f0-9]{40}$')
 
 
-class RegistrationManager(models.Manager):
+class EmailValidationManager(models.Manager):
     """
-    Custom manager for the ``RegistrationProfile`` model.
+    Custom manager for the ``EmailValidation`` model.
     
     The methods defined here provide shortcuts for account creation
     and activation (including generation and emailing of activation
         
         To prevent reactivation of an account which has been
         deactivated by site administrators, the activation key is
-        reset to the string constant ``RegistrationProfile.ACTIVATED``
+        reset to the string constant ``EmailValidation.ACTIVATED``
         after successful activation.
 
         """
                 return False
             if not profile.activation_key_expired():
                 user = profile.user
-                user.is_active = True
-                user.save()
+                if not user.is_active:
+                    user.is_active = True
+                    user.save()
                 profile.activation_key = self.model.ACTIVATED
+                profile.activated = datetime.datetime.now()
                 profile.save()
                 return user
         return False
                              site, send_email=True):
         """
         Create a new, inactive ``User``, generate a
-        ``RegistrationProfile`` and email its activation key to the
+        ``EmailValidation`` and email its activation key to the
+        ``User``, returning the new ``User``.
+
+        By default, an activation email will be sent to the new
+        user. To disable this, pass ``send_email=False``.
+        
+        """
+    	return self.create_user(username, email, password, site,
+                                send_email, False)
+    
+    def create_user(self, username, email, password, site,
+                    send_email=True, active=False):
+        """
+        Create a new ``User``, generate a ``EmailValidation`` 
+        and email its activation key to the
         ``User``, returning the new ``User``.
 
         By default, an activation email will be sent to the new
         
         """
         new_user = User.objects.create_user(username, email, password)
-        new_user.is_active = False
-        new_user.save()
+        if not active:
+            new_user.is_active = False
+            new_user.save()
 
-        registration_profile = self.create_profile(new_user)
+        email_activation = self.create_validation(new_user)
 
         if send_email:
-            registration_profile.send_activation_email(site)
+            email_activation.send_activation_email(site)
 
         return new_user
-    create_inactive_user = transaction.commit_on_success(create_inactive_user)
+    create_user = transaction.commit_on_success(create_user)
 
-    def create_profile(self, user):
+    def create_validation(self, user):
         """
-        Create a ``RegistrationProfile`` for a given
-        ``User``, and return the ``RegistrationProfile``.
+        Create a ``EmailValidation`` for a given
+        ``User``, and return the ``EmailValidation``.
         
-        The activation key for the ``RegistrationProfile`` will be a
+        The activation key for the ``EmailValidation`` will be a
         SHA1 hash, generated from a combination of the ``User``'s
         username and a random salt.
         
         if isinstance(username, unicode):
             username = username.encode('utf-8')
         activation_key = sha_constructor(salt+username).hexdigest()
-        return self.create(user=user,
+        return self.create(user=user, email=user.email,
                            activation_key=activation_key)
         
     def delete_expired_users(self):
         """
-        Remove expired instances of ``RegistrationProfile`` and their
-        associated ``User``s.
+        Remove expired instances of ``EmailValidation`` and their
+        associated ``User``s (if not is_active).
         
         Accounts to be deleted are identified by searching for
-        instances of ``RegistrationProfile`` with expired activation
+        instances of ``EmailValidation`` 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
         activated serves two useful purposes:
         
         1. It alleviates the ocasional need to reset a
-           ``RegistrationProfile`` and/or re-send an activation email
+           ``EmailValidation`` 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
         
         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
+        associated ``EmailValidation``; an inactive ``User`` which
+        does not have an associated ``EmailValidation`` will not
         be deleted.
         
         """
                     user.delete()
 
 
-class RegistrationProfile(models.Model):
+class EmailValidation(models.Model):
     """
     A simple profile which stores an activation key for use during
     user account registration.
     ACTIVATED = u"ALREADY_ACTIVATED"
     
     user = models.ForeignKey(User, unique=True, verbose_name=_('user'))
+    email = models.EmailField(max_length=255)
     activation_key = models.CharField(_('activation key'), max_length=40)
+    created = models.DateTimeField(auto_now_add=True)
+    activated = models.DateTimeField(null=True, blank=True)
     
-    objects = RegistrationManager()
+    objects = EmailValidationManager()
     
     class Meta:
-        verbose_name = _('registration profile')
-        verbose_name_plural = _('registration profiles')
+        verbose_name = _('email activation')
+        verbose_name_plural = _('email activations')
     
     def __unicode__(self):
-        return u"Registration information for %s" % self.user
+        return u"Email activation for %s/%s" % (self.user, self.email)
     
     def activation_key_expired(self):
         """
-        Determine whether this ``RegistrationProfile``'s activation
+        Determine whether this ``EmailValidation``'s activation
         key has expired, returning a boolean -- ``True`` if the key
         has expired.
         
            is not permitted, and so this method returns ``True`` in
            this case.
 
-        2. Otherwise, the date the user signed up is incremented by
-           the number of days specified in the setting
-           ``ACCOUNT_ACTIVATION_DAYS`` (which should be the number of
-           days after signup during which a user is allowed to
-           activate their account); if the result is less than or
+        2. Otherwise, the date the activation was created is 
+           incremented by the number of days specified in the setting
+           ``EMAIL_ACTIVATION_DAYS`` (which should be the number of
+           days after activation during which a user is allowed to
+           activate their email); if the result is less than or
            equal to the current date, the key has expired and this
            method returns ``True``.
         
         """
-        expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
+        expiration_date = datetime.timedelta(days=settings.EMAIL_ACTIVATION_DAYS)
         return self.activation_key == self.ACTIVATED or \
-               (self.user.date_joined + expiration_date <= datetime.datetime.now())
+               (self.created + expiration_date <= datetime.datetime.now())
     activation_key_expired.boolean = True
 
     def send_activation_email(self, site):
         """
         Send an activation email to the user associated with this
-        ``RegistrationProfile``.
+        ``EmailValidation``.
         
-        The activation email will make use of two templates:
+        The activation email will make use of three templates:
 
         ``registration/activation_email_subject.txt``
             This template will be used for the subject line of the
             into only a single line.
 
         ``registration/activation_email.txt``
-            This template will be used for the body of the email.
+            This template will be used for the text body of the email.
+
+        ``registration/activation_email.html``
+            This template will be used for the HTML body of the email.
 
         These templates will each receive the following context
         variables:
             The number of days remaining during which the account may
             be activated.
 
+        ``user``
+            The User that this activation is tied to.
+
         ``site``
             An object representing the site on which the user
             registered; depending on whether ``django.contrib.sites``
 
         """
         ctx_dict = {'activation_key': self.activation_key,
-                    'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
+                    'expiration_days': settings.EMAIL_ACTIVATION_DAYS,
+                    'user': self.user,
                     'site': site}
         subject = render_to_string('registration/activation_email_subject.txt',
                                    ctx_dict)
         # Email subject *must not* contain newlines
         subject = ''.join(subject.splitlines())
         
-        message = render_to_string('registration/activation_email.txt',
-                                   ctx_dict)
+        txt_message = render_to_string('registration/activation_email.txt',
+                                       ctx_dict)
+
+        message = EmailMultiAlternatives(subject, txt_message,
+                                  settings.DEFAULT_FROM_EMAIL,
+                                  [self.user.email],
+                                  connection=get_connection())
+
+        try:
+            html_message = render_to_string('registration/activation_email.html',
+                                        ctx_dict)
+            message.attach_alternative(html_message, 'text/html')
+        except TemplateDoesNotExist:
+            pass
         
-        self.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
+        return message.send()
+
     

registration/tests/backends.py

 from registration.backends import get_backend
 from registration.backends.default import DefaultBackend
 from registration.backends.simple import SimpleBackend
-from registration.models import RegistrationProfile
+from registration.models import EmailValidation
 
 
 class _MockRequestClient(Client):
     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.
+        and set ``EMAIL_ACTIVATION_DAYS`` if it's not set already.
 
         """
-        self.old_activation = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', None)
+        self.old_activation = getattr(settings, 'EMAIL_ACTIVATION_DAYS', None)
         if self.old_activation is None:
-            settings.ACCOUNT_ACTIVATION_DAYS = 7 # pragma: no cover
+            settings.EMAIL_ACTIVATION_DAYS = 7 # pragma: no cover
 
     def tearDown(self):
         """
-        Yank out ``ACCOUNT_ACTIVATION_DAYS`` back out if it wasn't
+        Yank out ``EMAIL_ACTIVATION_DAYS`` back out if it wasn't
         originally set.
 
         """
         if self.old_activation is None:
-            settings.ACCOUNT_ACTIVATION_DAYS = self.old_activation # pragma: no cover
+            settings.EMAIL_ACTIVATION_DAYS = self.old_activation # pragma: no cover
 
     def test_registration(self):
         """
         Test the registration process: registration creates a new
-        inactive account and a new profile with activation key,
+        inactive account and a new validation with activation key,
         populates the correct account data and sends an activation
         email.
 
         # New user must not be active.
         self.failIf(new_user.is_active)
 
-        # A registration profile was created, and an activation email
+        # A registration validation was created, and an activation email
         # was sent.
-        self.assertEqual(RegistrationProfile.objects.count(), 1)
+        self.assertEqual(EmailValidation.objects.count(), 1)
         self.assertEqual(len(mail.outbox), 1)
 
     def test_registration_no_sites(self):
 
         self.failIf(new_user.is_active)
 
-        self.assertEqual(RegistrationProfile.objects.count(), 1)
+        self.assertEqual(EmailValidation.objects.count(), 1)
         self.assertEqual(len(mail.outbox), 1)
         
         Site._meta.installed = True
                                            email='alice@example.com',
                                            password1='swordfish')
 
-        valid_profile = RegistrationProfile.objects.get(user=valid_user)
+        valid_activation = EmailValidation.objects.get(user=valid_user)
         activated = self.backend.activate(_mock_request(),
-                                          valid_profile.activation_key)
+                                          valid_activation.activation_key)
         self.assertEqual(activated.username, valid_user.username)
         self.failUnless(activated.is_active)
 
-        # Fetch the profile again to verify its activation key has
+        # Fetch the activation again to verify its activation key has
         # been reset.
-        valid_profile = RegistrationProfile.objects.get(user=valid_user)
-        self.assertEqual(valid_profile.activation_key,
-                         RegistrationProfile.ACTIVATED)
+        valid_activation = EmailValidation.objects.get(user=valid_user)
+        self.assertEqual(valid_activation.activation_key,
+                         EmailValidation.ACTIVATED)
 
     def test_invalid_activation(self):
         """
                                              username='bob',
                                              email='bob@example.com',
                                              password1='secret')
-
-        expired_user.date_joined = expired_user.date_joined - datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
-        expired_user.save()
-        expired_profile = RegistrationProfile.objects.get(user=expired_user)
+        expired_activation = EmailValidation.objects.get(user=expired_user)
+        expired_activation.created -= datetime.timedelta(days=settings.EMAIL_ACTIVATION_DAYS + 1)
+        expired_activation.save()
         self.failIf(self.backend.activate(_mock_request(),
-                                          expired_profile.activation_key))
-        self.failUnless(expired_profile.activation_key_expired())
+                                          expired_activation.activation_key))
+        self.failUnless(expired_activation.activation_key_expired())
 
     def test_allow(self):
         """
                                          username='bob',
                                          email='bob@example.com',
                                          password1='secret')
-        profile = RegistrationProfile.objects.get(user=new_user)
-        self.backend.activate(_mock_request(), profile.activation_key)
+        validation = EmailValidation.objects.get(user=new_user)
+        self.backend.activate(_mock_request(), validation.activation_key)
 
         self.assertEqual(len(received_signals), 1)
         self.assertEqual(received_signals, [signals.user_activated])
                                          username='bob',
                                          email='bob@example.com',
                                          password1='secret')
-        new_user.date_joined -= datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS + 1)
-        new_user.save()
-        profile = RegistrationProfile.objects.get(user=new_user)
-        self.backend.activate(_mock_request(), profile.activation_key)
+        validation = EmailValidation.objects.get(user=new_user)
+        validation.created -= datetime.timedelta(days=settings.EMAIL_ACTIVATION_DAYS + 1)
+        validation.save()
+        self.backend.activate(_mock_request(), validation.activation_key)
 
         self.assertEqual(len(received_signals), 0)
 
         Test re-sending of activation emails via admin action.
         
         """
-        admin_class = RegistrationAdmin(RegistrationProfile, admin.site)
+        admin_class = RegistrationAdmin(EmailValidation, admin.site)
         
         alice = self.backend.register(_mock_request(),
                                       username='alice',
                                       password1='swordfish')
         
         admin_class.resend_activation_email(_mock_request(),
-                                            RegistrationProfile.objects.all())
+                                            EmailValidation.objects.all())
         self.assertEqual(len(mail.outbox), 2) # One on registering, one more on the resend.
         
-        RegistrationProfile.objects.filter(user=alice).update(activation_key=RegistrationProfile.ACTIVATED)
+        EmailValidation.objects.filter(user=alice).update(activation_key=EmailValidation.ACTIVATED)
         admin_class.resend_activation_email(_mock_request(),
-                                            RegistrationProfile.objects.all())
+                                            EmailValidation.objects.all())
         self.assertEqual(len(mail.outbox), 2) # No additional email because the account has activated.
 
     def test_email_send_action_no_sites(self):
         
         """
         Site._meta.installed = False
-        admin_class = RegistrationAdmin(RegistrationProfile, admin.site)
+        admin_class = RegistrationAdmin(EmailValidation, admin.site)
         
         alice = self.backend.register(_mock_request(),
                                       username='alice',
                                       password1='swordfish')
         
         admin_class.resend_activation_email(_mock_request(),
-                                            RegistrationProfile.objects.all())
+                                            EmailValidation.objects.all())
         self.assertEqual(len(mail.outbox), 2) # One on registering, one more on the resend.
         
-        RegistrationProfile.objects.filter(user=alice).update(activation_key=RegistrationProfile.ACTIVATED)
+        EmailValidation.objects.filter(user=alice).update(activation_key=EmailValidation.ACTIVATED)
         admin_class.resend_activation_email(_mock_request(),
-                                            RegistrationProfile.objects.all())
+                                            EmailValidation.objects.all())
         self.assertEqual(len(mail.outbox), 2) # No additional email because the account has activated.
         Site._meta.installed = True
 
         Test manual activation of users view admin action.
         
         """
-        admin_class = RegistrationAdmin(RegistrationProfile, admin.site)
+        admin_class = RegistrationAdmin(EmailValidation, admin.site)
 
         alice = self.backend.register(_mock_request(),
                                       username='alice',
                                       password1='swordfish')
 
         admin_class.activate_users(_mock_request(),
-                                   RegistrationProfile.objects.all())
+                                   EmailValidation.objects.all())
         self.failUnless(User.objects.get(username='alice').is_active)
 
 
     def test_registration(self):
         """
         Test the registration process: registration creates a new
-        inactive account and a new profile with activation key,
+        inactive account and a new validation with activation key,
         populates the correct account data and sends an activation
         email.
 

registration/tests/models.py

 from django.test import TestCase
 from django.utils.hashcompat import sha_constructor
 
-from registration.models import RegistrationProfile
+from registration.models import EmailValidation
 
 
 class RegistrationModelTests(TestCase):
                  'email': 'alice@example.com'}
     
     def setUp(self):
-        self.old_activation = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', None)
-        settings.ACCOUNT_ACTIVATION_DAYS = 7
+        self.old_activation = getattr(settings, 'EMAIL_ACTIVATION_DAYS', None)
+        settings.EMAIL_ACTIVATION_DAYS = 7
 
     def tearDown(self):
-        settings.ACCOUNT_ACTIVATION_DAYS = self.old_activation
+        settings.EMAIL_ACTIVATION_DAYS = self.old_activation
 
-    def test_profile_creation(self):
+    def test_validation_creation(self):
         """
-        Creating a registration profile for a user populates the
-        profile with the correct user and a SHA1 hash to use as
+        Creating a registration validation for a user populates the
+        validation with the correct user and a SHA1 hash to use as
         activation key.
         
         """
         new_user = User.objects.create_user(**self.user_info)
-        profile = RegistrationProfile.objects.create_profile(new_user)
+        validation = EmailValidation.objects.create_validation(new_user)
 
-        self.assertEqual(RegistrationProfile.objects.count(), 1)
-        self.assertEqual(profile.user.id, new_user.id)
-        self.failUnless(re.match('^[a-f0-9]{40}$', profile.activation_key))
-        self.assertEqual(unicode(profile),
-                         "Registration information for alice")
+        self.assertEqual(EmailValidation.objects.count(), 1)
+        self.assertEqual(validation.user.id, new_user.id)
+        self.failUnless(re.match('^[a-f0-9]{40}$', validation.activation_key))
+        self.assertEqual(unicode(validation),
+                         "Email activation for alice/alice@example.com")
 
     def test_activation_email(self):
         """
-        ``RegistrationProfile.send_activation_email`` sends an
+        ``EmailValidation.send_activation_email`` sends an
         email.
         
         """
         new_user = User.objects.create_user(**self.user_info)
-        profile = RegistrationProfile.objects.create_profile(new_user)
-        profile.send_activation_email(Site.objects.get_current())
+        validation = EmailValidation.objects.create_validation(new_user)
+        validation.send_activation_email(Site.objects.get_current())
         self.assertEqual(len(mail.outbox), 1)
         self.assertEqual(mail.outbox[0].to, [self.user_info['email']])
 
         user's account inactive.
         
         """
-        new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+        new_user = EmailValidation.objects.create_inactive_user(site=Site.objects.get_current(),
                                                                     **self.user_info)
         self.assertEqual(new_user.username, 'alice')
         self.assertEqual(new_user.email, 'alice@example.com')
         By default, creating a new user sends an activation email.
         
         """
-        new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+        new_user = EmailValidation.objects.create_inactive_user(site=Site.objects.get_current(),
                                                                     **self.user_info)
         self.assertEqual(len(mail.outbox), 1)
 
         send an activation email.
         
         """
-        new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+        new_user = EmailValidation.objects.create_inactive_user(site=Site.objects.get_current(),
                                                                     send_email=False,
                                                                     **self.user_info)
         self.assertEqual(len(mail.outbox), 0)
 
     def test_unexpired_account(self):
         """
-        ``RegistrationProfile.activation_key_expired()`` is ``False``
+        ``EmailValidation.activation_key_expired()`` is ``False``
         within the activation window.
         
         """
-        new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+        new_user = EmailValidation.objects.create_inactive_user(site=Site.objects.get_current(),
                                                                     **self.user_info)
-        profile = RegistrationProfile.objects.get(user=new_user)
-        self.failIf(profile.activation_key_expired())
+        validation = EmailValidation.objects.get(user=new_user)
+        self.failIf(validation.activation_key_expired())
 
     def test_expired_account(self):
         """
-        ``RegistrationProfile.activation_key_expired()`` is ``True``
+        ``EmailValidation.activation_key_expired()`` is ``True``
         outside the activation window.
         
         """
-        new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+        new_user = EmailValidation.objects.create_inactive_user(site=Site.objects.get_current(),
                                                                     **self.user_info)
-        new_user.date_joined -= datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS + 1)
-        new_user.save()
-        profile = RegistrationProfile.objects.get(user=new_user)
-        self.failUnless(profile.activation_key_expired())
+        validation = EmailValidation.objects.get(user=new_user)
+        validation.created -= datetime.timedelta(days=settings.EMAIL_ACTIVATION_DAYS + 1)
+        validation.save()
+        self.failUnless(validation.activation_key_expired())
 
     def test_valid_activation(self):
         """
         account active, and resets the activation key.
         
         """
-        new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+        new_user = EmailValidation.objects.create_inactive_user(site=Site.objects.get_current(),
                                                                     **self.user_info)
-        profile = RegistrationProfile.objects.get(user=new_user)
-        activated = RegistrationProfile.objects.activate_user(profile.activation_key)
+        validation = EmailValidation.objects.get(user=new_user)
+        activated = EmailValidation.objects.activate_user(validation.activation_key)
 
         self.failUnless(isinstance(activated, User))
         self.assertEqual(activated.id, new_user.id)
         self.failUnless(activated.is_active)
 
-        profile = RegistrationProfile.objects.get(user=new_user)
-        self.assertEqual(profile.activation_key, RegistrationProfile.ACTIVATED)
+        validation = EmailValidation.objects.get(user=new_user)
+        self.assertEqual(validation.activation_key, EmailValidation.ACTIVATED)
 
     def test_expired_activation(self):
         """
         activate the account.
         
         """
-        new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+        new_user = EmailValidation.objects.create_inactive_user(site=Site.objects.get_current(),
                                                                     **self.user_info)
-        new_user.date_joined -= datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS + 1)
-        new_user.save()
-
-        profile = RegistrationProfile.objects.get(user=new_user)
-        activated = RegistrationProfile.objects.activate_user(profile.activation_key)
+        validation = EmailValidation.objects.get(user=new_user)
+        validation.created -= datetime.timedelta(days=settings.EMAIL_ACTIVATION_DAYS + 1)
+        validation.save()
+        
+        activated = EmailValidation.objects.activate_user(validation.activation_key)
 
         self.failIf(isinstance(activated, User))
         self.failIf(activated)
         new_user = User.objects.get(username='alice')
         self.failIf(new_user.is_active)
 
-        profile = RegistrationProfile.objects.get(user=new_user)
-        self.assertNotEqual(profile.activation_key, RegistrationProfile.ACTIVATED)
+        validation = EmailValidation.objects.get(user=new_user)
+        self.assertNotEqual(validation.activation_key, EmailValidation.ACTIVATED)
 
     def test_activation_invalid_key(self):
         """
         fails.
         
         """
-        self.failIf(RegistrationProfile.objects.activate_user('foo'))
+        self.failIf(EmailValidation.objects.activate_user('foo'))
 
     def test_activation_already_activated(self):
         """
         Attempting to re-activate an already-activated account fails.
         
         """
-        new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+        new_user = EmailValidation.objects.create_inactive_user(site=Site.objects.get_current(),
                                                                     **self.user_info)
-        profile = RegistrationProfile.objects.get(user=new_user)
-        RegistrationProfile.objects.activate_user(profile.activation_key)
+        validation = EmailValidation.objects.get(user=new_user)
+        EmailValidation.objects.activate_user(validation.activation_key)
 
-        profile = RegistrationProfile.objects.get(user=new_user)
-        self.failIf(RegistrationProfile.objects.activate_user(profile.activation_key))
+        validation = EmailValidation.objects.get(user=new_user)
+        self.failIf(EmailValidation.objects.activate_user(validation.activation_key))
 
     def test_activation_nonexistent_key(self):
         """
         # Due to the way activation keys are constructed during
         # registration, this will never be a valid key.
         invalid_key = sha_constructor('foo').hexdigest()
-        self.failIf(RegistrationProfile.objects.activate_user(invalid_key))
+        self.failIf(EmailValidation.objects.activate_user(invalid_key))
 
     def test_expired_user_deletion(self):
         """
-        ``RegistrationProfile.objects.delete_expired_users()`` only
+        ``EmailValidation.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(),
+        new_user = EmailValidation.objects.create_inactive_user(site=Site.objects.get_current(),
                                                                     **self.user_info)
-        expired_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+        expired_user = EmailValidation.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()
+        expired_validation = EmailValidation.objects.get(user=expired_user)
+        expired_validation.created -= datetime.timedelta(days=settings.EMAIL_ACTIVATION_DAYS + 1)
+        expired_validation.save()
 
-        RegistrationProfile.objects.delete_expired_users()
-        self.assertEqual(RegistrationProfile.objects.count(), 1)
+        EmailValidation.objects.delete_expired_users()
+        self.assertEqual(EmailValidation.objects.count(), 1)
         self.assertRaises(User.DoesNotExist, User.objects.get, username='bob')
 
     def test_management_command(self):
         deletes expired accounts.
         
         """
-        new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+        new_user = EmailValidation.objects.create_inactive_user(site=Site.objects.get_current(),
                                                                     **self.user_info)
-        expired_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(),
+        expired_user = EmailValidation.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()
+        expired_validation = EmailValidation.objects.get(user=expired_user)
+        expired_validation.created -= datetime.timedelta(days=settings.EMAIL_ACTIVATION_DAYS + 1)
+        expired_validation.save()
 
         management.call_command('cleanupregistration')
-        self.assertEqual(RegistrationProfile.objects.count(), 1)
+        self.assertEqual(EmailValidation.objects.count(), 1)
         self.assertRaises(User.DoesNotExist, User.objects.get, username='bob')

registration/tests/views.py

 from django.test import TestCase
 
 from registration import forms
-from registration.models import RegistrationProfile
+from registration.models import EmailValidation
 
 
 class RegistrationViewTests(TestCase):
     def setUp(self):
         """
         These tests use the default backend, since we know it's
-        available; that needs to have ``ACCOUNT_ACTIVATION_DAYS`` set.
+        available; that needs to have ``EMAIL_ACTIVATION_DAYS`` set.
 
         """
-        self.old_activation = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', None)
+        self.old_activation = getattr(settings, 'EMAIL_ACTIVATION_DAYS', None)
         if self.old_activation is None:
-            settings.ACCOUNT_ACTIVATION_DAYS = 7 # pragma: no cover
+            settings.EMAIL_ACTIVATION_DAYS = 7 # pragma: no cover
 
     def tearDown(self):
         """
-        Yank ``ACCOUNT_ACTIVATION_DAYS`` back out if it wasn't
+        Yank ``EMAIL_ACTIVATION_DAYS`` back out if it wasn't
         originally set.
 
         """
         if self.old_activation is None:
-            settings.ACCOUNT_ACTIVATION_DAYS = self.old_activation # pragma: no cover
+            settings.EMAIL_ACTIVATION_DAYS = self.old_activation # pragma: no cover
 
     def test_registration_view_initial(self):
         """
                                           'password2': 'swordfish'})
         self.assertRedirects(response,
                              'http://testserver%s' % reverse('registration_complete'))
-        self.assertEqual(RegistrationProfile.objects.count(), 1)
+        self.assertEqual(EmailValidation.objects.count(), 1)
         self.assertEqual(len(mail.outbox), 1)
 
     def test_registration_view_failure(self):
                                           'password1': 'swordfish',
                                           'password2': 'swordfish'})
         self.assertRedirects(response, closed_redirect)
-        self.assertEqual(RegistrationProfile.objects.count(), 0)
+        self.assertEqual(EmailValidation.objects.count(), 0)
 
         settings.REGISTRATION_OPEN = old_allowed
 
                                'email': 'alice@example.com',
                                'password1': 'swordfish',
                                'password2': 'swordfish'})
-        profile = RegistrationProfile.objects.get(user__username='alice')
+        validation = EmailValidation.objects.get(user__username='alice')
         response = self.client.get(reverse('registration_activate',
-                                           kwargs={'activation_key': profile.activation_key}))
+                                           kwargs={'activation_key': validation.activation_key}))
         self.assertRedirects(response, success_redirect)
         self.failUnless(User.objects.get(username='alice').is_active)
 
                                'password1': 'secret',
                                'password2': 'secret'})
         expired_user = User.objects.get(username='bob')
-        expired_user.date_joined = expired_user.date_joined - datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
-        expired_user.save()
+        expired_validation = EmailValidation.objects.get(user=expired_user)
+        expired_validation.created -= datetime.timedelta(days=settings.EMAIL_ACTIVATION_DAYS + 1)
+        expired_validation.save()
 
-        expired_profile = RegistrationProfile.objects.get(user=expired_user)
         response = self.client.get(reverse('registration_activate',
-                                           kwargs={'activation_key': expired_profile.activation_key}))
+                                           kwargs={'activation_key': expired_validation.activation_key}))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.context['activation_key'],
-                         expired_profile.activation_key)
+                         expired_validation.activation_key)
         self.failIf(User.objects.get(username='bob').is_active)
 
     def test_activation_success_url(self):
                                'email': 'alice@example.com',
                                'password1': 'swordfish',
                                'password2': 'swordfish'})
-        profile = RegistrationProfile.objects.get(user__username='alice')
+        validation = EmailValidation.objects.get(user__username='alice')
         response = self.client.get(reverse('registration_test_activate_success_url',
-                                           kwargs={'activation_key': profile.activation_key}))
+                                           kwargs={'activation_key': validation.activation_key}))
         self.assertRedirects(response, success_redirect)
         
     def test_activation_template_name(self):
             data_files.append(os.path.join(prefix, f))
 
 
-setup(name='django-registration',
+setup(name='django-registration-plus',
       version=get_version().replace(' ', '-'),
       description='An extensible user-registration application for Django',
-      author='James Bennett',
-      author_email='james@b-list.org',
-      url='http://www.bitbucket.org/ubernostrum/django-registration/wiki/',
-      download_url='http://www.bitbucket.org/ubernostrum/django-registration/get/v0.7.gz',
+      author='Marko Mrdjenovic',
+      author_email='m@mmm.si',
+      url='http://www.bitbucket.org/friedcell/django-registration-plus/wiki/',
+      download_url='http://www.bitbucket.org/friedcell/django-registration-plus/get/tip.gz',
       package_dir={'registration': 'registration'},
       packages=packages,
       package_data={'registration': data_files},