]> git.ozlabs.org Git - patchwork/commitdiff
registration: use EmailConfimation rather than separate registration app
authorJeremy Kerr <jk@ozlabs.org>
Sun, 31 Oct 2010 23:29:29 +0000 (19:29 -0400)
committerJeremy Kerr <jk@ozlabs.org>
Thu, 14 Apr 2011 09:21:04 +0000 (17:21 +0800)
Since we have infrastructure for email confirmations, we no longer need
the separate registration app.

Requires a migration script, which will delete all inactive users,
including those newly added and pending confirmation. Use carefully.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
30 files changed:
apps/patchwork/forms.py
apps/patchwork/models.py
apps/patchwork/tests/__init__.py
apps/patchwork/tests/registration.py [new file with mode: 0644]
apps/patchwork/tests/user.py
apps/patchwork/tests/utils.py
apps/patchwork/urls.py
apps/patchwork/views/base.py
apps/patchwork/views/user.py
apps/settings.py
apps/urls.py
docs/INSTALL
lib/sql/grant-all.mysql.sql
lib/sql/grant-all.postgres.sql
lib/sql/migration/009-drop-registrationprofile.sql [new file with mode: 0644]
templates/base.html
templates/patchwork/activation_email.txt [new file with mode: 0644]
templates/patchwork/activation_email_subject.txt [new file with mode: 0644]
templates/patchwork/help/about.html
templates/patchwork/login.html [new file with mode: 0644]
templates/patchwork/logout.html [new file with mode: 0644]
templates/patchwork/registration-confirm.html [new file with mode: 0644]
templates/patchwork/registration_form.html [new file with mode: 0644]
templates/registration/activate.html [deleted file]
templates/registration/activation_email.txt [deleted file]
templates/registration/activation_email_subject.txt [deleted file]
templates/registration/login.html [deleted file]
templates/registration/logout.html [deleted file]
templates/registration/registration_complete.html [deleted file]
templates/registration/registration_form.html [deleted file]

index 1ff2bd0088c765711a26c176f652337409bc4d56..f83c27ae75c3e45fc3298e844cdbc0c75a691af8 100644 (file)
@@ -22,34 +22,33 @@ from django.contrib.auth.models import User
 from django import forms
 
 from patchwork.models import Patch, State, Bundle, UserProfile
-from registration.forms import RegistrationFormUniqueEmail
-from registration.models import RegistrationProfile
 
-class RegistrationForm(RegistrationFormUniqueEmail):
+class RegistrationForm(forms.Form):
     first_name = forms.CharField(max_length = 30, required = False)
     last_name = forms.CharField(max_length = 30, required = False)
-    username = forms.CharField(max_length=30, label=u'Username')
+    username = forms.RegexField(regex = r'^\w+$', max_length=30,
+                                label=u'Username')
     email = forms.EmailField(max_length=100, label=u'Email address')
     password = forms.CharField(widget=forms.PasswordInput(),
                                 label='Password')
-    password1 = forms.BooleanField(required = False)
-    password2 = forms.BooleanField(required = False)
-
-    def save(self, profile_callback = None):
-        user = RegistrationProfile.objects.create_inactive_user( \
-                username = self.cleaned_data['username'],
-                password = self.cleaned_data['password'],
-                email = self.cleaned_data['email'],
-                profile_callback = profile_callback)
-        user.first_name = self.cleaned_data.get('first_name', '')
-        user.last_name = self.cleaned_data.get('last_name', '')
-        user.save()
-
-        # saving the userprofile causes the firstname/lastname to propagate
-        # to the person objects.
-        user.get_profile().save()
-
-        return user
+
+    def clean_username(self):
+        value = self.cleaned_data['username']
+        try:
+            user = User.objects.get(username__iexact = value)
+        except User.DoesNotExist:
+            return self.cleaned_data['username']
+        raise forms.ValidationError('This username is already taken. ' + \
+                                    'Please choose another.')
+
+    def clean_email(self):
+        value = self.cleaned_data['email']
+        try:
+            user = User.objects.get(email__iexact = value)
+        except User.DoesNotExist:
+            return self.cleaned_data['email']
+        raise forms.ValidationError('This email address is already in use ' + \
+                                    'for the account "%s".\n' % user.username)
 
     def clean(self):
         return self.cleaned_data
index ee6748fa44c835cc9110c7c4710f2f79c75f8dc2..806875bb00009eb911e84e0f50cf71d5063dc41e 100644 (file)
@@ -21,6 +21,7 @@ from django.db import models
 from django.contrib.auth.models import User
 from django.core.urlresolvers import reverse
 from django.contrib.sites.models import Site
+from django.conf import settings
 from patchwork.parser import hash_patch
 
 import re
@@ -374,9 +375,10 @@ class BundlePatch(models.Model):
         ordering = ['order']
 
 class EmailConfirmation(models.Model):
-    validity = datetime.timedelta(days = 30)
+    validity = datetime.timedelta(days = settings.CONFIRMATION_VALIDITY_DAYS)
     type = models.CharField(max_length = 20, choices = [
                                 ('userperson', 'User-Person association'),
+                                ('registration', 'Registration'),
                             ])
     email = models.CharField(max_length = 200)
     user = models.ForeignKey(User, null = True)
index 9618d1fa472116f464719705e5b38445bdb482e4..db096d80b0b9862f169daa6171e2ebd3c7e9c603 100644 (file)
@@ -24,3 +24,5 @@ from patchwork.tests.mboxviews import *
 from patchwork.tests.updates import *
 from patchwork.tests.filters import *
 from patchwork.tests.confirm import *
+from patchwork.tests.registration import *
+from patchwork.tests.user import *
diff --git a/apps/patchwork/tests/registration.py b/apps/patchwork/tests/registration.py
new file mode 100644 (file)
index 0000000..18b781f
--- /dev/null
@@ -0,0 +1,150 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2010 Jeremy Kerr <jk@ozlabs.org>
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import unittest
+from django.test import TestCase
+from django.test.client import Client
+from django.core import mail
+from django.core.urlresolvers import reverse
+from django.contrib.auth.models import User
+from patchwork.models import EmailConfirmation, Person
+from patchwork.tests.utils import create_user
+
+def _confirmation_url(conf):
+    return reverse('patchwork.views.confirm', kwargs = {'key': conf.key})
+
+class TestUser(object):
+    firstname = 'Test'
+    lastname = 'User'
+    username = 'testuser'
+    email = 'test@example.com'
+    password = 'foobar'
+
+class RegistrationTest(TestCase):
+    def setUp(self):
+        self.user = TestUser()
+        self.client = Client()
+        self.default_data = {'username': self.user.username,
+                             'first_name': self.user.firstname,
+                             'last_name': self.user.lastname,
+                             'email': self.user.email,
+                             'password': self.user.password}
+        self.required_error = 'This field is required.'
+        self.invalid_error = 'Enter a valid value.'
+
+    def testRegistrationForm(self):
+        response = self.client.get('/register/')
+        self.assertEquals(response.status_code, 200)
+        self.assertTemplateUsed(response, 'patchwork/registration_form.html')
+
+    def testBlankFields(self):
+        for field in ['username', 'email', 'password']:
+            data = self.default_data.copy()
+            del data[field]
+            response = self.client.post('/register/', data)
+            self.assertEquals(response.status_code, 200)
+            self.assertFormError(response, 'form', field, self.required_error)
+
+    def testInvalidUsername(self):
+        data = self.default_data.copy()
+        data['username'] = 'invalid user'
+        response = self.client.post('/register/', data)
+        self.assertEquals(response.status_code, 200)
+        self.assertFormError(response, 'form', 'username', self.invalid_error)
+
+    def testExistingUsername(self):
+        user = create_user()
+        data = self.default_data.copy()
+        data['username'] = user.username
+        response = self.client.post('/register/', data)
+        self.assertEquals(response.status_code, 200)
+        self.assertFormError(response, 'form', 'username',
+                'This username is already taken. Please choose another.')
+
+    def testExistingEmail(self):
+        user = create_user()
+        data = self.default_data.copy()
+        data['email'] = user.email
+        response = self.client.post('/register/', data)
+        self.assertEquals(response.status_code, 200)
+        self.assertFormError(response, 'form', 'email',
+                'This email address is already in use ' + \
+                'for the account "%s".\n' % user.username)
+
+    def testValidRegistration(self):
+        response = self.client.post('/register/', self.default_data)
+        self.assertEquals(response.status_code, 200)
+        self.assertContains(response, 'confirmation email has been sent')
+
+        # check for presence of an inactive user object
+        users = User.objects.filter(username = self.user.username)
+        self.assertEquals(users.count(), 1)
+        user = users[0]
+        self.assertEquals(user.username, self.user.username)
+        self.assertEquals(user.email, self.user.email)
+        self.assertEquals(user.is_active, False)
+
+        # check for confirmation object
+        confs = EmailConfirmation.objects.filter(user = user,
+                                                 type = 'registration')
+        self.assertEquals(len(confs), 1)
+        conf = confs[0]
+        self.assertEquals(conf.email, self.user.email)
+
+        # check for a sent mail
+        self.assertEquals(len(mail.outbox), 1)
+        msg = mail.outbox[0]
+        self.assertEquals(msg.subject, 'Patchwork account confirmation')
+        self.assertTrue(self.user.email in msg.to)
+        self.assertTrue(_confirmation_url(conf) in msg.body)
+
+        # ...and that the URL is valid
+        response = self.client.get(_confirmation_url(conf))
+        self.assertEquals(response.status_code, 200)
+
+class RegistrationConfirmationTest(TestCase):
+
+    def setUp(self):
+        self.user = TestUser()
+        self.default_data = {'username': self.user.username,
+                             'first_name': self.user.firstname,
+                             'last_name': self.user.lastname,
+                             'email': self.user.email,
+                             'password': self.user.password}
+
+    def testRegistrationConfirmation(self):
+        self.assertEqual(EmailConfirmation.objects.count(), 0)
+        response = self.client.post('/register/', self.default_data)
+        self.assertEquals(response.status_code, 200)
+        self.assertContains(response, 'confirmation email has been sent')
+
+        self.assertEqual(EmailConfirmation.objects.count(), 1)
+        conf = EmailConfirmation.objects.filter()[0]
+        self.assertFalse(conf.user.is_active)
+        self.assertTrue(conf.active)
+
+        response = self.client.get(_confirmation_url(conf))
+        self.assertEquals(response.status_code, 200)
+        self.assertTemplateUsed(response, 'patchwork/registration-confirm.html')
+
+        conf = EmailConfirmation.objects.get(pk = conf.pk)
+        self.assertTrue(conf.user.is_active)
+        self.assertFalse(conf.active)
+
+
index c9e5be3feb2d549a03f5ae4728483c017d2cfea2..e96e6c537f4fce0e4b4e80d2056bf8b6d24ce0d3 100644 (file)
@@ -22,9 +22,9 @@ from django.test import TestCase
 from django.test.client import Client
 from django.core import mail
 from django.core.urlresolvers import reverse
+from django.conf import settings
 from django.contrib.auth.models import User
 from patchwork.models import EmailConfirmation, Person
-from patchwork.utils import userprofile_register_callback
 
 def _confirmation_url(conf):
     return reverse('patchwork.views.confirm', kwargs = {'key': conf.key})
@@ -39,7 +39,6 @@ class TestUser(object):
         self.password = User.objects.make_random_password()
         self.user = User.objects.create_user(self.username,
                             self.email, self.password)
-        userprofile_register_callback(self.user)
 
 class UserPersonRequestTest(TestCase):
     def setUp(self):
@@ -119,3 +118,11 @@ class UserPersonConfirmTest(TestCase):
         # need to reload the confirmation to check this.
         conf = EmailConfirmation.objects.get(pk = self.conf.pk)
         self.assertEquals(conf.active, False)
+
+class UserLoginRedirectTest(TestCase):
+    
+    def testUserLoginRedirect(self):
+        url = '/user/'
+        response = self.client.get(url)
+        self.assertRedirects(response, settings.LOGIN_URL + '?next=' + url)
+
index f1c95e8a8d274054bdcc927dc2c8ed2e18259a14..1cb5dfb95d529375b980d4629b7855790384ae55 100644 (file)
@@ -59,7 +59,7 @@ class defaults(object):
 _user_idx = 1
 def create_user():
     global _user_idx
-    userid = 'test-%d' % _user_idx
+    userid = 'test%d' % _user_idx
     email = '%s@example.com' % userid
     _user_idx += 1
 
index 27c79fd57075d51f201c10a1f4d37543b5cfc577..6810e3efb4770765f7e280fb4393da7254987581 100644 (file)
@@ -19,6 +19,7 @@
 
 from django.conf.urls.defaults import *
 from django.conf import settings
+from django.contrib.auth import views as auth_views
 
 urlpatterns = patterns('',
     # Example:
@@ -46,6 +47,23 @@ urlpatterns = patterns('',
     (r'^user/link/$', 'patchwork.views.user.link'),
     (r'^user/unlink/(?P<person_id>[^/]+)/$', 'patchwork.views.user.unlink'),
 
+    # password change
+    url(r'^user/password-change/$', auth_views.password_change,
+            name='auth_password_change'),
+    url(r'^user/password-change/done/$', auth_views.password_change_done,
+            name='auth_password_change_done'),
+
+    # login/logout
+    url(r'^user/login/$', auth_views.login,
+        {'template_name': 'patchwork/login.html'},
+        name = 'auth_login'),
+    url(r'^user/logout/$', auth_views.logout,
+        {'template_name': 'patchwork/logout.html'},
+        name = 'auth_logout'),
+
+    # registration
+    (r'^register/', 'patchwork.views.user.register'),
+
     # public view for bundles
     (r'^bundle/(?P<username>[^/]*)/(?P<bundlename>[^/]*)/$',
                                 'patchwork.views.bundle.public'),
index 1539472e06505a3d05eab6ed88572068e4289804..590a3b6dd96de2ec5510e84890c381b43ae4b909 100644 (file)
@@ -62,6 +62,7 @@ def confirm(request, key):
     import patchwork.views.user
     views = {
         'userperson': patchwork.views.user.link_confirm,
+        'registration': patchwork.views.user.register_confirm,
     }
 
     conf = get_object_or_404(EmailConfirmation, key = key)
index 759a6e392f1d6da1d8eb3d5d6ca14389d7bc7252..3d28f4b09b81efc1c80bfc8116487caa5bb2fe4a 100644 (file)
 from django.contrib.auth.decorators import login_required
 from patchwork.requestcontext import PatchworkRequestContext
 from django.shortcuts import render_to_response, get_object_or_404
+from django.contrib import auth
+from django.contrib.sites.models import Site
 from django.http import HttpResponseRedirect
 from patchwork.models import Project, Bundle, Person, EmailConfirmation, State
-from patchwork.forms import UserProfileForm, UserPersonLinkForm
+from patchwork.forms import UserProfileForm, UserPersonLinkForm, \
+         RegistrationForm
 from patchwork.filters import DelegateFilter
 from patchwork.views import generic_list
 from django.template.loader import render_to_string
@@ -31,6 +34,55 @@ from django.conf import settings
 from django.core.mail import send_mail
 import django.core.urlresolvers
 
+def register(request):
+    context = PatchworkRequestContext(request)
+    if request.method == 'POST':
+        form = RegistrationForm(request.POST)
+        if form.is_valid():
+            data = form.cleaned_data
+            # create inactive user
+            user = auth.models.User.objects.create_user(data['username'],
+                                                        data['email'],
+                                                        data['password'])
+            user.is_active = False;
+            user.first_name = data.get('first_name', '')
+            user.last_name = data.get('last_name', '')
+            user.save()
+
+            # create confirmation
+            conf = EmailConfirmation(type = 'registration', user = user,
+                                     email = user.email)
+            conf.save()
+
+            # send email
+            mail_ctx = {'site': Site.objects.get_current(),
+                        'confirmation': conf}
+
+            subject = render_to_string('patchwork/activation_email_subject.txt',
+                                mail_ctx).replace('\n', ' ').strip()
+            
+            message = render_to_string('patchwork/activation_email.txt',
+                                    mail_ctx)
+            
+            send_mail(subject, message, settings.DEFAULT_FROM_EMAIL,
+                            [conf.email])
+
+            # setting 'confirmation' in the template indicates success
+            context['confirmation'] = conf
+
+    else:
+        form = RegistrationForm()
+    
+    return render_to_response('patchwork/registration_form.html',
+                              { 'form': form },
+                              context_instance=context)
+
+def register_confirm(request, conf):
+    conf.user.is_active = True
+    conf.user.save()
+    conf.deactivate()
+    return render_to_response('patchwork/registration-confirm.html')
+
 @login_required
 def profile(request):
     context = PatchworkRequestContext(request)
index f56da70ea02b871ce84dc816283c430cbf3a3328..8f091d0c672bdb4e24f2959121e4fa71f0409b38 100644 (file)
@@ -64,7 +64,7 @@ MIDDLEWARE_CLASSES = (
 
 ROOT_URLCONF = 'apps.urls'
 
-LOGIN_URL = '/accounts/login'
+LOGIN_URL = '/user/login/'
 LOGIN_REDIRECT_URL = '/user/'
 
 # If you change the ROOT_DIR setting in your local_settings.py, you'll need to
@@ -96,13 +96,12 @@ INSTALLED_APPS = (
     'django.contrib.sites',
     'django.contrib.admin',
     'patchwork',
-    'registration',
 )
 
 DEFAULT_PATCHES_PER_PAGE = 100
 DEFAULT_FROM_EMAIL = 'Patchwork <patchwork@patchwork.example.com>'
 
-ACCOUNT_ACTIVATION_DAYS = 7
+CONFIRMATION_VALIDITY_DAYS = 7
 
 # Set to True to enable the Patchwork XML-RPC interface
 ENABLE_XMLRPC = False
index 3894708af605363d875a22f6ed70dbeb426e7c8b..4ddef9e15532e864a7cc2a963d60113fea10b45b 100644 (file)
@@ -23,9 +23,6 @@ from django.conf.urls.defaults import *
 from django.conf import settings
 from django.contrib import admin
 
-from registration.views import register
-from patchwork.forms import RegistrationForm
-
 admin.autodiscover()
 
 htdocs = os.path.join(settings.ROOT_DIR, 'htdocs')
@@ -34,13 +31,6 @@ urlpatterns = patterns('',
     # Example:
     (r'^', include('patchwork.urls')),
 
-    # override the default registration form
-    url(r'^accounts/register/$',
-        register, {'form_class': RegistrationForm},
-        name='registration_register'),
-
-    (r'^accounts/', include('registration.urls')),
-
     # Uncomment this for admin:
      (r'^admin/', include(admin.site.urls)),
 
index 4c178efe1c8dc9f7ef3c489d51c8edd08f1b0602..6a1a0bf6498ed46c9529bd902e41453c3e86dba8 100644 (file)
@@ -81,17 +81,6 @@ in brackets):
          cd ../python
          ln -s ../packages/django/django ./django
 
-        We also use the django-registration infrastructure from
-        http://bitbucket.org/ubernostrum/django-registration/. Your distro
-        may provide the django-registration python module (in Ubuntu/Debian it's
-        called 'python-django-registration'). If not, download the module
-        and symlink it to lib/python/ :
-
-         cd lib/packages/
-         hg clone http://bitbucket.org/ubernostrum/django-registration/
-         cd ../python
-         ln -s ../packages/django-registration/registration ./registration
-
         We also use some Javascript libraries:
 
          cd lib/packages
index f60c6b875d8e7b6fa01a799e9313ac3b658e6af9..a3d758c46f591faa5e5514c61f21c9d8db8adb62 100644 (file)
@@ -22,7 +22,6 @@ GRANT SELECT, UPDATE, INSERT, DELETE ON patchwork_project TO 'www-data'@localhos
 GRANT SELECT, UPDATE, INSERT, DELETE ON patchwork_bundle TO 'www-data'@localhost;
 GRANT SELECT, UPDATE, INSERT, DELETE ON patchwork_bundle_patches TO 'www-data'@localhost;
 GRANT SELECT, UPDATE, INSERT, DELETE ON patchwork_patch TO 'www-data'@localhost;
-GRANT SELECT, UPDATE, INSERT, DELETE ON registration_registrationprofile TO 'www-data'@localhost;
 
 -- allow the mail user (in this case, 'nobody') to add patches
 GRANT INSERT, SELECT ON patchwork_patch TO 'nobody'@localhost;
index 47c4ad3fcd0fe3bf7cd4b4c0c564bd12d7244102..591ffd0ecdcc0273245c0bc3dff81f516f94b952 100644 (file)
@@ -22,8 +22,7 @@ GRANT SELECT, UPDATE, INSERT, DELETE ON
        patchwork_project,
        patchwork_bundle,
        patchwork_bundlepatch,
-       patchwork_patch,
-       registration_registrationprofile
+       patchwork_patch
 TO "www-data";
 GRANT SELECT, UPDATE ON
        auth_group_id_seq,
@@ -45,8 +44,7 @@ GRANT SELECT, UPDATE ON
        patchwork_state_id_seq,
        patchwork_emailconfirmation_id_seq,
        patchwork_userprofile_id_seq,
-       patchwork_userprofile_maintainer_projects_id_seq,
-       registration_registrationprofile_id_seq
+       patchwork_userprofile_maintainer_projects_id_seq
 TO "www-data";
 
 -- allow the mail user (in this case, 'nobody') to add patches
diff --git a/lib/sql/migration/009-drop-registrationprofile.sql b/lib/sql/migration/009-drop-registrationprofile.sql
new file mode 100644 (file)
index 0000000..f1c2b43
--- /dev/null
@@ -0,0 +1,27 @@
+BEGIN;
+
+DELETE FROM registration_registrationprofile;
+
+-- unlink users who have contributed
+
+UPDATE patchwork_person SET user_id = NULL
+    WHERE user_id IN (SELECT id FROM auth_user WHERE is_active = False)
+           AND id IN (SELECT DISTINCT submitter_id FROM patchwork_comment);
+
+-- remove persons who only have a user linkage
+
+DELETE FROM patchwork_person WHERE user_id IN
+    (SELECT id FROM auth_user WHERE is_active = False);
+
+-- delete profiles
+
+DELETE FROM patchwork_userprofile WHERE user_id IN
+    (SELECT id FROM auth_user WHERE is_active = False);
+
+-- delete inactive users
+
+DELETE FROM auth_user WHERE is_active = False;
+
+DROP TABLE registration_registrationprofile;
+
+COMMIT;
index e14470e8c4c33feec0059de909777e6a89dcbd98..9e80dcad92e82e1b3b85c57b139780de2c622c61 100644 (file)
@@ -30,7 +30,7 @@
 {% else %}
      <a href="{% url auth_login %}">login</a>
      <br/>
-     <a href="{% url registration_register %}">register</a>
+     <a href="{% url patchwork.views.user.register %}">register</a>
 {% endif %}
    </div>
    <div style="clear: both;"></div>
diff --git a/templates/patchwork/activation_email.txt b/templates/patchwork/activation_email.txt
new file mode 100644 (file)
index 0000000..e918e5f
--- /dev/null
@@ -0,0 +1,11 @@
+Hi,
+
+This email is to confirm your account on the patchwork patch-tracking
+system. You can activate your account by visiting the url:
+
+ http://{{site.domain}}{% url patchwork.views.confirm key=confirmation.key %}
+
+If you didn't request a user account on patchwork, then you can ignore
+this mail.
+
+Happy patchworking.
diff --git a/templates/patchwork/activation_email_subject.txt b/templates/patchwork/activation_email_subject.txt
new file mode 100644 (file)
index 0000000..c409f38
--- /dev/null
@@ -0,0 +1 @@
+Patchwork account confirmation
index edc381ec4618ad6dde8943eec46227766525f4f7..0d784d7fcbd9d537705c3d88fe0d5966f9a216fa 100644 (file)
 <p>Patchwork is built on the <a href="http://djangoproject.com/">django</a>
 web framework.</p>
 
-<p>Patchwork includes the <a
-href="http://code.google.com/p/django-registration/">django-registration</a>
-application.</p>
-
 <p>Icons from the <a href="http://sweetie.sublink.ca/">Sweetie</a> icon set.</a>
 
 {% endblock %}
diff --git a/templates/patchwork/login.html b/templates/patchwork/login.html
new file mode 100644 (file)
index 0000000..2dfc2a7
--- /dev/null
@@ -0,0 +1,27 @@
+{% extends "base.html" %}
+
+{% block title %}Login{% endblock %}
+{% block heading %}Login{% endblock %}
+
+
+{% block body %}
+<form method="post">
+{% csrf_token %}
+<table class="form loginform">
+ <tr>
+  <th colspan="2" class="headerrow">login</th>
+ </tr>
+ {% if error %}
+  <tr>
+   <td colspan="2">{{ error }}</td>
+  </tr>
+ {% endif %}
+ {{ form }}
+ <tr>
+  <td colspan="2" class="submitrow">
+   <input type="submit" value="Login"/>
+  </td>
+ </tr>
+</table>
+</form>
+{% endblock %}
diff --git a/templates/patchwork/logout.html b/templates/patchwork/logout.html
new file mode 100644 (file)
index 0000000..f030aee
--- /dev/null
@@ -0,0 +1,8 @@
+{% extends "base.html" %}
+
+{% block title %}Logout{% endblock %}
+{% block heading %}Logout{% endblock %}
+
+{% block body %}
+<p>Logged out</p>
+{% endblock %}
diff --git a/templates/patchwork/registration-confirm.html b/templates/patchwork/registration-confirm.html
new file mode 100644 (file)
index 0000000..f0cc39f
--- /dev/null
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block title %}Registration{% endblock %}
+{% block heading %}Registration{% endblock %}
+
+{% block body %}
+<p>Registraton confirmed!</p>
+
+<p>Your patchwork registration is complete. Head over to your <a
+ href="{% url patchwork.views.user.profile %}">profile</a> to start using
+patchwork's extra features.</p>
+
+{% endblock %}
diff --git a/templates/patchwork/registration_form.html b/templates/patchwork/registration_form.html
new file mode 100644 (file)
index 0000000..3a314b8
--- /dev/null
@@ -0,0 +1,121 @@
+{% extends "base.html" %}
+
+{% block title %}Registration{% endblock %}
+{% block heading %}Registration{% endblock %}
+
+
+{% block body %}
+
+{% if confirmation and not error %}
+ <p>Registration successful!</p>
+ <p>A confirmation email has been sent to {{ confirmation.email }}. You'll
+ need to visit the link provided in that email to confirm your
+ registration.</p>
+</p>
+{% else %}
+<p>By creating a patchwork account, you can:<p>
+<ul>
+ <li>create "bundles" of patches</li>
+ <li>update the state of your own patches</li>
+</ul>
+<form method="post">
+{% csrf_token %}
+<table class="form registerform">
+ <tr>
+  <th colspan="2" class="headerrow">register</th>
+ </tr>
+ {% if error %}
+  <tr>
+   <td colspan="2">{{ error }}</td>
+  </tr>
+ {% endif %}
+
+  <tr>
+   <td>{{ form.first_name.label_tag }}</td>
+   <td>
+{% if form.first_name.errors %}
+    {{ form.first_name.errors }}
+{% endif %}
+    {{ form.first_name }}
+{% if form.first_name.help_text %}
+    <div class="help_text"/>{{ form.first_name.help_text }}</div>
+{% endif %}
+   </td>
+  </tr>
+   
+  <tr>
+   <td>{{ form.last_name.label_tag }}</td>
+   <td>
+{% if form.last_name.errors %}
+    {{ form.last_name.errors }}
+{% endif %}
+    {{ form.last_name }}
+{% if form.last_name.help_text %}
+    <div class="help_text"/>{{ form.last_name.help_text }}</div>
+{% endif %}
+   </td>
+  </tr>
+
+  <tr>
+   <td></td>
+   <td class="form-help">
+    Your name is used to identify you on the site
+   </td>
+  </tr>
+   
+  <tr>
+   <td>{{ form.email.label_tag }}</td>
+   <td>
+{% if form.email.errors %}
+    {{ form.email.errors }}
+{% endif %}
+    {{ form.email }}
+{% if form.email.help_text %}
+    <div class="help_text"/>{{ form.email.help_text }}</div>
+{% endif %}
+   </td>
+  </tr>
+   
+  <tr>
+   <td></td>
+   <td class="form-help">
+    Patchwork will send a confirmation email to this address
+   </td>
+  </tr>
+
+  <tr>
+   <td>{{ form.username.label_tag }}</td>
+   <td>
+{% if form.username.errors %}
+    {{ form.username.errors }}
+{% endif %}
+    {{ form.username }}
+{% if form.username.help_text %}
+    <div class="help_text"/>{{ form.username.help_text }}</div>
+{% endif %}
+   </td>
+  </tr>
+   
+  <tr>
+   <td>{{ form.password.label_tag }}</td>
+   <td>
+{% if form.password.errors %}
+    {{ form.password.errors }}
+{% endif %}
+    {{ form.password }}
+{% if form.password.help_text %}
+    <div class="help_text"/>{{ form.password.help_text }}</div>
+{% endif %}
+   </td>
+  </tr>
+
+   <tr>
+  <td colspan="2" class="submitrow">
+   <input type="submit" value="Register"/>
+  </td>
+ </tr>
+</table>
+</form>
+{% endif %}
+
+{% endblock %}
diff --git a/templates/registration/activate.html b/templates/registration/activate.html
deleted file mode 100644 (file)
index f0cc39f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Registration{% endblock %}
-{% block heading %}Registration{% endblock %}
-
-{% block body %}
-<p>Registraton confirmed!</p>
-
-<p>Your patchwork registration is complete. Head over to your <a
- href="{% url patchwork.views.user.profile %}">profile</a> to start using
-patchwork's extra features.</p>
-
-{% endblock %}
diff --git a/templates/registration/activation_email.txt b/templates/registration/activation_email.txt
deleted file mode 100644 (file)
index 6b1477d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-Hi,
-
-This email is to confirm your account on the patchwork patch-tracking
-system. You can activate your account by visiting the url:
-
- http://{{site.domain}}{% url registration_activate activation_key=activation_key %}
-
-If you didn't request a user account on patchwork, then you can ignore
-this mail.
-
-Happy patchworking.
diff --git a/templates/registration/activation_email_subject.txt b/templates/registration/activation_email_subject.txt
deleted file mode 100644 (file)
index c409f38..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Patchwork account confirmation
diff --git a/templates/registration/login.html b/templates/registration/login.html
deleted file mode 100644 (file)
index 2dfc2a7..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Login{% endblock %}
-{% block heading %}Login{% endblock %}
-
-
-{% block body %}
-<form method="post">
-{% csrf_token %}
-<table class="form loginform">
- <tr>
-  <th colspan="2" class="headerrow">login</th>
- </tr>
- {% if error %}
-  <tr>
-   <td colspan="2">{{ error }}</td>
-  </tr>
- {% endif %}
- {{ form }}
- <tr>
-  <td colspan="2" class="submitrow">
-   <input type="submit" value="Login"/>
-  </td>
- </tr>
-</table>
-</form>
-{% endblock %}
diff --git a/templates/registration/logout.html b/templates/registration/logout.html
deleted file mode 100644 (file)
index f030aee..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Logout{% endblock %}
-{% block heading %}Logout{% endblock %}
-
-{% block body %}
-<p>Logged out</p>
-{% endblock %}
diff --git a/templates/registration/registration_complete.html b/templates/registration/registration_complete.html
deleted file mode 100644 (file)
index a89c116..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Registration{% endblock %}
-{% block heading %}Registration{% endblock %}
-
-{% block body %}
-
- <p>Registration successful!</p>
- <p>A confirmation email has been sent to your email address. You'll
- need to visit the link provided in that email to activate your
- patchwork account.</p>
-
-{% endblock %}
diff --git a/templates/registration/registration_form.html b/templates/registration/registration_form.html
deleted file mode 100644 (file)
index e2b17c1..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Registration{% endblock %}
-{% block heading %}Registration{% endblock %}
-
-
-{% block body %}
-
-{% if request and not error %}
- <p>Registration successful!</p>
- <p>A confirmation email has been sent to {{ request.email }}. You'll
- need to visit the link provided in that email to confirm your
- registration.</p>
- <pre>{{email}}</pre>
-</p>
-{% else %}
-<p>By creating a patchwork account, you can:<p>
-<ul>
- <li>create "bundles" of patches</li>
- <li>update the state of your own patches</li>
-</ul>
-<form method="post">
-{% csrf_token %}
-<table class="form registerform">
- <tr>
-  <th colspan="2" class="headerrow">register</th>
- </tr>
- {% if error %}
-  <tr>
-   <td colspan="2">{{ error }}</td>
-  </tr>
- {% endif %}
-
-  <tr>
-   <td>{{ form.first_name.label_tag }}</td>
-   <td>
-{% if form.first_name.errors %}
-    {{ form.first_name.errors }}
-{% endif %}
-    {{ form.first_name }}
-{% if form.first_name.help_text %}
-    <div class="help_text"/>{{ form.first_name.help_text }}</div>
-{% endif %}
-   </td>
-  </tr>
-   
-  <tr>
-   <td>{{ form.last_name.label_tag }}</td>
-   <td>
-{% if form.last_name.errors %}
-    {{ form.last_name.errors }}
-{% endif %}
-    {{ form.last_name }}
-{% if form.last_name.help_text %}
-    <div class="help_text"/>{{ form.last_name.help_text }}</div>
-{% endif %}
-   </td>
-  </tr>
-
-  <tr>
-   <td></td>
-   <td class="form-help">
-    Your name is used to identify you on the site
-   </td>
-  </tr>
-   
-  <tr>
-   <td>{{ form.email.label_tag }}</td>
-   <td>
-{% if form.email.errors %}
-    {{ form.email.errors }}
-{% endif %}
-    {{ form.email }}
-{% if form.email.help_text %}
-    <div class="help_text"/>{{ form.email.help_text }}</div>
-{% endif %}
-   </td>
-  </tr>
-   
-  <tr>
-   <td></td>
-   <td class="form-help">
-    Patchwork will send a confirmation email to this address
-   </td>
-  </tr>
-
-  <tr>
-   <td>{{ form.username.label_tag }}</td>
-   <td>
-{% if form.username.errors %}
-    {{ form.username.errors }}
-{% endif %}
-    {{ form.username }}
-{% if form.username.help_text %}
-    <div class="help_text"/>{{ form.username.help_text }}</div>
-{% endif %}
-   </td>
-  </tr>
-   
-  <tr>
-   <td>{{ form.password.label_tag }}</td>
-   <td>
-{% if form.password.errors %}
-    {{ form.password.errors }}
-{% endif %}
-    {{ form.password }}
-{% if form.password.help_text %}
-    <div class="help_text"/>{{ form.password.help_text }}</div>
-{% endif %}
-   </td>
-  </tr>
-
-   <tr>
-  <td colspan="2" class="submitrow">
-   <input type="submit" value="Register"/>
-  </td>
- </tr>
-</table>
-</form>
-{% endif %}
-
-{% endblock %}