from django.contrib.auth.models import User
from django import forms
-from patchwork.models import RegistrationRequest, Patch, State, Bundle, \
- UserProfile
-
-class RegisterForm(forms.ModelForm):
- password = forms.CharField(widget = forms.PasswordInput)
- email = forms.EmailField(max_length = 200)
-
- class Meta:
- model = RegistrationRequest
- exclude = ['key', 'active', 'date']
-
- def clean_email(self):
- value = self.cleaned_data['email']
- try:
- User.objects.get(email = value)
- raise forms.ValidationError(('The email address %s has ' +
- 'has already been registered') % value)
- except User.DoesNotExist:
- pass
- try:
- RegistrationRequest.objects.get(email = value)
- raise forms.ValidationError(('The email address %s has ' +
- 'has already been registered') % value)
- except RegistrationRequest.DoesNotExist:
- pass
- return value
-
- def clean_username(self):
- value = self.cleaned_data['username']
- try:
- User.objects.get(username = value)
- raise forms.ValidationError(('The username %s has ' +
- 'has already been registered') % value)
- except User.DoesNotExist:
- pass
- try:
- RegistrationRequest.objects.get(username = value)
- raise forms.ValidationError(('The username %s has ' +
- 'has already been registered') % value)
- except RegistrationRequest.DoesNotExist:
- pass
- return value
+from patchwork.models import Patch, State, Bundle, UserProfile
+from registration.forms import RegistrationFormUniqueEmail
+from registration.models import RegistrationProfile
+
+class RegistrationForm(RegistrationFormUniqueEmail):
+ 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')
+ 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()
+ return user
+
+ def clean(self):
+ return self.cleaned_data
class LoginForm(forms.Form):
username = forms.CharField(max_length = 30)
str += random.choice(allowedchars)
return str;
-class RegistrationRequest(models.Model):
- username = models.CharField(max_length = 30, unique = True)
- first_name = models.CharField(max_length = 50)
- last_name = models.CharField(max_length = 50)
- email = models.CharField(max_length = 200, unique = True)
- password = models.CharField(max_length = 200)
- key = models.CharField(max_length = 32, default = _confirm_key)
- date = models.DateTimeField(default=datetime.datetime.now)
- active = models.BooleanField(default = True)
-
- def create_user(self):
- if not self.active:
- return
- user = User.objects.create_user(self.username,
- self.email, self.password)
- user.first_name = self.first_name
- user.last_name = self.last_name
- user.save()
- profile = UserProfile(user = user)
- profile.save()
- self.active = False
- self.save()
-
- # link a person to this user. if none exists, create.
- person = None
- try:
- person = Person.objects.get(email = user.email)
- except Exception:
- pass
- if not person:
- person = Person(email = user.email)
-
- person.link_to_user(user)
- person.save()
-
- return user
-
class UserPersonConfirmation(models.Model):
user = models.ForeignKey(User)
email = models.CharField(max_length = 200)
(r'^patch/(?P<patch_id>\d+)/raw/$', 'patchwork.views.patch.content'),
(r'^patch/(?P<patch_id>\d+)/mbox/$', 'patchwork.views.patch.mbox'),
- # registration process
- (r'^register/$', 'patchwork.views.user.register'),
- (r'^register/confirm/(?P<key>[^/]+)/$',
- 'patchwork.views.user.register_confirm'),
-
- (r'^login/$', 'patchwork.views.user.login'),
- (r'^logout/$', 'patchwork.views.user.logout'),
-
# logged-in user stuff
(r'^user/$', 'patchwork.views.user.profile'),
(r'^user/todo/$', 'patchwork.views.user.todo_lists'),
from patchwork.forms import MultiplePatchForm
-from patchwork.models import Bundle, Project, State
+from patchwork.models import Bundle, Project, State, UserProfile
from django.conf import settings
from django.shortcuts import render_to_response, get_object_or_404
context.add_message(str)
return (errors, form)
+
+def userprofile_register_callback(user):
+ profile = UserProfile(user = user)
+ profile.save()
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-from patchwork.models import Patch, Project, Person, RegistrationRequest
+from patchwork.models import Patch, Project, Person
from patchwork.filters import Filters
-from patchwork.forms import RegisterForm, LoginForm, PatchForm
+from patchwork.forms import LoginForm, PatchForm
from django.shortcuts import render_to_response, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.db import transaction
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-from patchwork.models import Patch, Project, Person, RegistrationRequest, Bundle
+from patchwork.models import Patch, Project, Person, Bundle
from patchwork.filters import Filters
-from patchwork.forms import RegisterForm, LoginForm, PatchForm, MultiplePatchForm, CreateBundleForm
+from patchwork.forms import PatchForm, MultiplePatchForm, CreateBundleForm
from patchwork.utils import get_patch_ids, set_patches, Order
from patchwork.requestcontext import PatchworkRequestContext
from django.shortcuts import render_to_response, get_object_or_404
from django.shortcuts import render_to_response, get_object_or_404
from django.contrib import auth
from django.http import HttpResponse, HttpResponseRedirect
-from patchwork.models import Project, Patch, Bundle, Person, \
- RegistrationRequest, UserProfile, UserPersonConfirmation, State
-from patchwork.forms import RegisterForm, LoginForm, MultiplePatchForm, \
- UserProfileForm, UserPersonLinkForm
+from patchwork.models import Project, Patch, Bundle, Person, UserProfile, \
+ UserPersonConfirmation, State
+from patchwork.forms import MultiplePatchForm, UserProfileForm, \
+ UserPersonLinkForm
from patchwork.utils import Order, get_patch_ids
from patchwork.filters import DelegateFilter
from patchwork.paginator import Paginator
from django.core.mail import send_mail
import django.core.urlresolvers
-def register(request):
- context = PatchworkRequestContext(request)
- template = 'patchwork/register.html'
-
- if request.method != 'POST':
- form = RegisterForm()
- context['form'] = form
- return render_to_response(template, context)
-
- reg_req = RegistrationRequest()
- form = RegisterForm(instance = reg_req, data = request.POST)
-
- if form.is_valid():
- form.save()
- try:
- context['request'] = reg_req
- send_mail('Patchwork account confirmation',
- render_to_string('patchwork/register.mail', context),
- settings.PATCHWORK_FROM_EMAIL,
- [form.cleaned_data['email']])
-
- except Exception, ex:
- context['request'] = None
- context['error'] = 'An error occurred during registration. ' + \
- 'Please try again later'
-
- context['form'] = form
-
- return render_to_response(template, context)
-
-def register_confirm(request, key):
- context = PatchworkRequestContext(request)
- req = get_object_or_404(RegistrationRequest, key = key)
- req.create_user()
- user = auth.authenticate(username = req.username, password = req.password)
- auth.login(request, user)
-
- return render_to_response('patchwork/register-confirm.html', context)
-
-def login(request):
- context = PatchworkRequestContext(request)
- template = 'patchwork/login.html'
- error = None
-
- if request.method == 'POST':
- form = LoginForm(request.POST)
- context['form'] = form
-
- if not form.is_valid():
- return render_to_response(template, context)
-
- data = form.cleaned_data
- user = auth.authenticate(username = data['username'],
- password = data['password'])
-
- if user is not None and user.is_active:
- auth.login(request, user)
- url = request.POST.get('next', None) or \
- django.core.urlresolvers.reverse( \
- 'patchwork.views.user.profile')
- return HttpResponseRedirect(url)
-
- context['error'] = 'Invalid username or password'
-
- else:
- context['form'] = LoginForm()
-
- return render_to_response(template, context)
-
-def logout(request):
- auth.logout(request)
- return render_to_response('patchwork/logout.html')
-
@login_required
def profile(request):
context = PatchworkRequestContext(request)
--- /dev/null
+../lib/packages/django-registration
\ No newline at end of file
ROOT_URLCONF = 'apps.urls'
-LOGIN_URL = '/patchwork/login'
+LOGIN_URL = '/accounts/login'
+LOGIN_REDIRECT_URL = '/user/'
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
'django.contrib.sites',
'django.contrib.admin',
'patchwork',
+ 'registration',
)
DEFAULT_PATCHES_PER_PAGE = 100
PATCHWORK_FROM_EMAIL = 'Patchwork <patchwork@patchwork.example.com>'
+
+ACCOUNT_ACTIVATION_DAYS = 7
from django.conf.urls.defaults import *
from patchwork.admin import admin_site
+from registration.views import register
+from patchwork.forms import RegistrationForm
+from patchwork.utils import userprofile_register_callback
+
urlpatterns = patterns('',
# Example:
(r'^', include('patchwork.urls')),
+ # override the default registration form
+ url(r'^accounts/register/$',
+ register,
+ {'form_class': RegistrationForm,
+ 'profile_callback': userprofile_register_callback},
+ name='registration_register'),
+
+ (r'^accounts/', include('registration.urls')),
+
# Uncomment this for admin:
(r'^admin/(.*)', admin_site.root),
(r'^css/(?P<path>.*)$', 'django.views.static.serve',
- {'document_root': '/home/jk/devel/patchwork/pwsite/htdocs/css'}),
+ {'document_root': '/srv/patchwork/htdocs/css'}),
(r'^js/(?P<path>.*)$', 'django.views.static.serve',
- {'document_root': '/home/jk/devel/patchwork/pwsite/htdocs/js'}),
+ {'document_root': '/srv/patchwork/htdocs/js'}),
(r'^images/(?P<path>.*)$', 'django.views.static.serve',
- {'document_root': '/home/jk/devel/patchwork/pwsite/htdocs/images'}),
+ {'document_root': '/srv/patchwork/htdocs/images'}),
)
--- /dev/null
+{% load pwurl %}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <title>{% block title %}Patchwork{% endblock %} - Patchwork</title>
+ <link rel="stylesheet" type="text/css" href="/css/style.css"/>
+{% block headers %}{% endblock %}
+ </head>
+ <body>
+ <div id="title">
+ <h1 style="float: left;">
+ <a
+ href="{% url patchwork.views.projects %}">Patchwork</a><span
+ class="beta">β</span>
+ {% block heading %}{% endblock %}</h1>
+ <div id="auth">
+{% if user.is_authenticated %}
+ Logged in as
+ <a href="{% url patchwork.views.user.profile %}"
+ ><strong>{{ user.username }}</strong></a>
+ <br/>
+ <a href="{% url patchwork.views.user.profile %}">profile</a> ::
+ <a href="{% url patchwork.views.user.todo_lists %}">todo
+ ({{ user.get_profile.n_todo_patches }})</a><br/>
+ <a href="{% url auth_logout %}">logout</a><!-- ::
+ <a href="/help/">help</a> -->
+{% else %}
+ <a href="{% url auth_login %}">login</a>
+ <br/>
+ <a href="{% url registration_register %}">register</a>
+ <!--
+ <br/>
+ <a href="/help/">help</a>
+ -->
+{% endif %}
+ </div>
+ <div style="clear: both;"></div>
+ </div>
+ <div id="nav">
+ {% if project %}
+ <strong>Project</strong>: {{ project.linkname }}
+ :
+ <a href="{% url patchwork.views.patch.list project_id=project.linkname %}"
+ >patches</a>
+ :
+ <a href="{% url patchwork.views.project project_id=project.linkname %}"
+ >project info</a>
+ {% if other_projects %}
+ :
+ <a href="{% url patchwork.views.projects %}"
+ >other projects</a>
+ {% endif %}
+ {% else %}
+ <a href="{% url patchwork.views.projects %}"
+ >project list</a>
+ {% endif %}
+ </div>
+{% if messages %}
+ <div id="messages">
+ {% for message in messages %}
+ <div class="message">{{ message }}</div>
+ {% endfor %}
+ </div>
+{% endif %}
+ <div id="content">
+{% block body %}
+{% endblock %}
+ </div>
+ <div id="footer">
+ <a href="http://ozlabs.org/~jk/projects/patchwork">patchwork</a>
+ patch tracking system
+ </div>
+ </body>
+</html>
+
+
+
+++ /dev/null
-{% load pwurl %}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
- <title>{% block title %}Patchwork{% endblock %} - Patchwork</title>
- <link rel="stylesheet" type="text/css" href="/css/style.css"/>
-{% block headers %}{% endblock %}
- </head>
- <body>
- <div id="title">
- <h1 style="float: left;">
- <a
- href="{% url patchwork.views.projects %}">Patchwork</a><span
- class="beta">β</span>
- {% block heading %}{% endblock %}</h1>
- <div id="auth">
-{% if user.is_authenticated %}
- Logged in as
- <a href="{% url patchwork.views.user.profile %}"
- ><strong>{{ user.username }}</strong></a>
- <br/>
- <a href="{% url patchwork.views.user.profile %}">profile</a> ::
- <a href="{% url patchwork.views.user.todo_lists %}">todo
- ({{ user.get_profile.n_todo_patches }})</a><br/>
- <a href="{% url patchwork.views.user.logout %}">logout</a><!-- ::
- <a href="/help/">help</a> -->
-{% else %}
- <a href="{% url patchwork.views.user.login %}">login</a>
- <br/>
- <a href="{% url patchwork.views.user.register %}">register</a>
- <!--
- <br/>
- <a href="/help/">help</a>
- -->
-{% endif %}
- </div>
- <div style="clear: both;"></div>
- </div>
- <div id="nav">
- {% if project %}
- <strong>Project</strong>: {{ project.linkname }}
- :
- <a href="{% url patchwork.views.patch.list project_id=project.linkname %}"
- >patches</a>
- :
- <a href="{% url patchwork.views.project project_id=project.linkname %}"
- >project info</a>
- {% if other_projects %}
- :
- <a href="{% url patchwork.views.projects %}"
- >other projects</a>
- {% endif %}
- {% else %}
- <a href="{% url patchwork.views.projects %}"
- >project list</a>
- {% endif %}
- </div>
-{% if messages %}
- <div id="messages">
- {% for message in messages %}
- <div class="message">{{ message }}</div>
- {% endfor %}
- </div>
-{% endif %}
- <div id="content">
-{% block body %}
-{% endblock %}
- </div>
- <div id="footer">
- <a href="http://ozlabs.org/~jk/projects/patchwork">patchwork</a>
- patch tracking system
- </div>
- </body>
-</html>
-
-
-
-{% extends "patchwork/base.html" %}
+{% extends "base.html" %}
{% load person %}
-{% extends "patchwork/base.html" %}
+{% extends "base.html" %}
{% load person %}
-{% extends "patchwork/base.html" %}
+{% extends "base.html" %}
{% load person %}
+++ /dev/null
-{% extends "patchwork/base.html" %}
-
-{% block title %}Patchwork Login{% endblock %}
-{% block heading %}Patchwork Login{% endblock %}
-
-
-{% block body %}
-<form method="post">
-<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 %}
+++ /dev/null
-{% extends "patchwork/base.html" %}
-
-{% block title %}Patchwork{% endblock %}
-{% block heading %}Patchwork{% endblock %}
-
-{% block body %}
-<p>Logged out</p>
-{% endblock %}
-{% extends "patchwork/base.html" %}
+{% extends "base.html" %}
{% load syntax %}
{% load person %}
-{% extends "patchwork/base.html" %}
+{% extends "base.html" %}
{% block title %}User Profile: {{ user.username }}{% endblock %}
{% block heading %}User Profile: {{ user.username }}{% endblock %}
-{% extends "patchwork/base.html" %}
+{% extends "base.html" %}
{% block title %}{{ project.name }}{% endblock %}
{% block heading %}{{ project.name }}{% endblock %}
-{% extends "patchwork/base.html" %}
+{% extends "base.html" %}
{% block title %}Project List{% endblock %}
{% block heading %}Project List{% endblock %}
+++ /dev/null
-{% extends "patchwork/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 %}
+++ /dev/null
-{% extends "patchwork/base.html" %}
-
-{% block title %}Patchwork Registration{% endblock %}
-{% block heading %}Patchwork 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">
-<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 %}
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.user.register_confirm key=request.key %}
+ http://{{site.domain}}{% url registration_activateactivation_key=request.key %}
If you didn't request a user account on patchwork, then you can ignore
this mail.
-{% extends "patchwork/base.html" %}
+{% extends "base.html" %}
{% load person %}
-{% extends "patchwork/base.html" %}
+{% extends "base.html" %}
{% block title %}{{ user }}'s todo lists{% endblock %}
{% block heading %}{{ user }}'s todo lists{% endblock %}
-{% extends "patchwork/base.html" %}
+{% extends "base.html" %}
{% block title %}{{ user.username }}{% endblock %}
{% block heading %}link accounts for {{ user.username }}{% endblock %}
-{% extends "patchwork/base.html" %}
+{% extends "base.html" %}
{% block title %}{{ user.username }}{% endblock %}
{% block heading %}link accounts for {{ user.username }}{% endblock %}
--- /dev/null
+{% 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 %}
--- /dev/null
+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.
--- /dev/null
+Patchwork account confirmation
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}Patchwork Login{% endblock %}
+{% block heading %}Patchwork Login{% endblock %}
+
+
+{% block body %}
+<form method="post">
+<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 %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}Patchwork{% endblock %}
+{% block heading %}Patchwork{% endblock %}
+
+{% block body %}
+<p>Logged out</p>
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}Patchwork Registration{% endblock %}
+{% block heading %}Patchwork 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 actiavate your
+ patchwork account.</p>
+
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}Patchwork Registration{% endblock %}
+{% block heading %}Patchwork 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">
+<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 %}