[Users] handle ValidationError during registration
[mygpo.git] / mygpo / users / views / registration.py
blobcf960da233e38e074e16dfb6785e5bfc1b4e2b39
1 import uuid
2 import re
4 from django import forms
5 from django.core.validators import RegexValidator
6 from django.core.exceptions import ValidationError
7 from django.db import IntegrityError, transaction
8 from django.http import HttpResponseRedirect
9 from django.views.generic.edit import FormView
10 from django.utils.translation import ugettext as _
11 from django.template.loader import render_to_string
12 from django.core.urlresolvers import reverse, reverse_lazy
13 from django.views.generic import TemplateView
14 from django.views.generic.base import View
15 from django.contrib import messages
16 from django.contrib.auth import get_user_model
17 from django.contrib.sites.shortcuts import get_current_site
19 from mygpo.utils import random_token
20 from mygpo.users.models import UserProxy
23 USERNAME_MAXLEN = get_user_model()._meta.get_field('username').max_length
25 USERNAME_REGEX = re.compile(r'^\w[\w.+-]*$')
28 class UsernameValidator(RegexValidator):
29 """ Validates that a username uses only allowed characters """
30 regex = USERNAME_REGEX
31 message = 'Invalid Username'
32 code='invalid-username'
35 class RegistrationForm(forms.Form):
36 """ Form that is used to register a new user """
37 username = forms.CharField(max_length=USERNAME_MAXLEN,
38 validators=[UsernameValidator()],
40 email = forms.EmailField()
41 password1 = forms.CharField(widget=forms.PasswordInput())
42 password2 = forms.CharField(widget=forms.PasswordInput())
44 def clean(self):
45 cleaned_data = super(RegistrationForm, self).clean()
46 password1 = cleaned_data.get('password1')
47 password2 = cleaned_data.get('password2')
49 if not password1 or password1 != password2:
50 raise forms.ValidationError('Passwords do not match')
53 class RegistrationView(FormView):
54 """ View to register a new user """
55 template_name = 'registration/registration_form.html'
56 form_class = RegistrationForm
57 success_url = reverse_lazy('registration-complete')
59 def form_valid(self, form):
60 """ called whene the form was POSTed and its contents were valid """
62 try:
63 user = self.create_user(form)
65 except ValidationError as e:
66 messages.error(self.request, '; '.join(e.messages))
67 return HttpResponseRedirect(reverse('register'))
69 except IntegrityError:
70 messages.error(self.request,
71 _('Username or email address already in use'))
72 return HttpResponseRedirect(reverse('register'))
74 send_activation_email(user, self.request)
75 return super(RegistrationView, self).form_valid(form)
77 @transaction.atomic
78 def create_user(self, form):
79 User = get_user_model()
80 user = User()
81 user.username = form.cleaned_data['username']
82 user.email = form.cleaned_data['email']
83 user.set_password(form.cleaned_data['password1'])
84 user.is_active = False
85 user.full_clean()
86 user.save()
88 user.profile.uuid == uuid.uuid1()
89 user.profile.activation_key = random_token()
90 user.profile.save()
92 return user
95 class ActivationView(TemplateView):
96 """ Activates an already registered user """
98 template_name = 'registration/activation_failed.html'
100 def get(self, request, activation_key):
101 User = get_user_model()
103 try:
104 user = UserProxy.objects.get(
105 profile__activation_key=activation_key,
106 is_active=False,
108 except UserProxy.DoesNotExist:
109 messages.error(request, _('The activation link is either not '
110 'valid or has already expired.'))
111 return super(ActivationView, self).get(request, activation_key)
113 user.activate()
114 messages.success(request, _('Your user has been activated. '
115 'You can log in now.'))
116 return HttpResponseRedirect(reverse('login'))
119 class ResendActivationForm(forms.Form):
120 """ Form for resending the activation email """
122 username = forms.CharField(max_length=USERNAME_MAXLEN, required=False)
123 email = forms.EmailField(required=False)
125 def clean(self):
126 cleaned_data = super(ResendActivationForm, self).clean()
127 username = cleaned_data.get('username')
128 email = cleaned_data.get('email')
130 if not username and not email:
131 raise forms.ValidationError(_('Either username or email address '
132 'are required.'))
135 class ResendActivationView(FormView):
136 """ View to resend the activation email """
137 template_name = 'registration/resend_activation.html'
138 form_class = ResendActivationForm
139 success_url = reverse_lazy('resent-activation')
141 def form_valid(self, form):
142 """ called whene the form was POSTed and its contents were valid """
144 try:
145 user = UserProxy.objects.all().by_username_or_email(
146 form.cleaned_data['username'],
147 form.cleaned_data['email'],
150 except UserProxy.DoesNotExist:
151 messages.error(self.request, _('User does not exist.'))
152 return HttpResponseRedirect(reverse('resend-activation'))
154 if user.profile.activation_key is None:
155 messages.success(self.request, _('Your account already has been '
156 'activated. Go ahead and log in.'))
158 send_activation_email(user, self.request)
159 return super(ResendActivationView, self).form_valid(form)
162 class ResentActivationView(TemplateView):
163 template_name = 'registration/resent_activation.html'
166 def send_activation_email(user, request):
167 """ Sends the activation email for the given user """
169 subj = render_to_string('registration/activation_email_subject.txt')
170 # remove trailing newline added by render_to_string
171 subj = subj.strip()
173 msg = render_to_string('registration/activation_email.txt', {
174 'site': get_current_site(request),
175 'activation_key': user.profile.activation_key,
177 user.email_user(subj, msg)