[Registration] check usernames when registering
[mygpo.git] / mygpo / users / views / registration.py
blob8f222eabbc8d051706c4a7294e305f07d78fa566
1 import uuid
2 import re
4 from django import forms
5 from django.core.validators import RegexValidator
6 from django.db import IntegrityError, transaction
7 from django.http import HttpResponseRedirect
8 from django.views.generic.edit import FormView
9 from django.utils.translation import ugettext as _
10 from django.template.loader import render_to_string
11 from django.core.urlresolvers import reverse, reverse_lazy
12 from django.views.generic import TemplateView
13 from django.views.generic.base import View
14 from django.contrib import messages
15 from django.contrib.auth import get_user_model
16 from django.contrib.sites.shortcuts import get_current_site
18 from mygpo.utils import random_token
19 from mygpo.users.models import UserProxy
22 USERNAME_MAXLEN = get_user_model()._meta.get_field('username').max_length
24 USERNAME_REGEX = re.compile(r'\w[\w.-]{2,}')
27 class UsernameValidator(RegexValidator):
28 """ Validates that a username uses only allowed characters """
29 regex = USERNAME_REGEX
30 message = 'Invalid Username'
31 code='invalid-username'
34 class RegistrationForm(forms.Form):
35 """ Form that is used to register a new user """
36 username = forms.CharField(max_length=USERNAME_MAXLEN,
37 validators=[UsernameValidator()],
39 email = forms.EmailField()
40 password1 = forms.CharField(widget=forms.PasswordInput())
41 password2 = forms.CharField(widget=forms.PasswordInput())
43 def clean(self):
44 cleaned_data = super(RegistrationForm, self).clean()
45 password1 = cleaned_data.get('password1')
46 password2 = cleaned_data.get('password2')
48 if not password1 or password1 != password2:
49 raise forms.ValidationError('Passwords do not match')
52 class RegistrationView(FormView):
53 """ View to register a new user """
54 template_name = 'registration/registration_form.html'
55 form_class = RegistrationForm
56 success_url = reverse_lazy('registration-complete')
58 def form_valid(self, form):
59 """ called whene the form was POSTed and its contents were valid """
61 try:
62 user = self.create_user(form)
64 except IntegrityError:
65 messages.error(self.request,
66 _('Username or email address already in use'))
67 return HttpResponseRedirect(reverse('register'))
69 send_activation_email(user, self.request)
70 return super(RegistrationView, self).form_valid(form)
72 @transaction.atomic
73 def create_user(self, form):
74 User = get_user_model()
75 user = User()
76 user.username = form.cleaned_data['username']
77 user.email = form.cleaned_data['email']
78 user.set_password(form.cleaned_data['password1'])
79 user.is_active = False
80 user.save()
82 user.profile.uuid == uuid.uuid1()
83 user.profile.activation_key = random_token()
84 user.profile.save()
86 return user
89 class ActivationView(TemplateView):
90 """ Activates an already registered user """
92 template_name = 'registration/activation_failed.html'
94 def get(self, request, activation_key):
95 User = get_user_model()
97 try:
98 user = UserProxy.objects.get(
99 profile__activation_key=activation_key,
100 is_active=False,
102 except UserProxy.DoesNotExist:
103 messages.error(request, _('The activation link is either not '
104 'valid or has already expired.'))
105 return super(ActivationView, self).get(request, activation_key)
107 user.activate()
108 messages.success(request, _('Your user has been activated. '
109 'You can log in now.'))
110 return HttpResponseRedirect(reverse('login'))
113 class ResendActivationForm(forms.Form):
114 """ Form for resending the activation email """
116 username = forms.CharField(max_length=USERNAME_MAXLEN, required=False)
117 email = forms.EmailField(required=False)
119 def clean(self):
120 cleaned_data = super(ResendActivationForm, self).clean()
121 username = cleaned_data.get('username')
122 email = cleaned_data.get('email')
124 if not username and not email:
125 raise forms.ValidationError(_('Either username or email address '
126 'are required.'))
129 class ResendActivationView(FormView):
130 """ View to resend the activation email """
131 template_name = 'registration/resend_activation.html'
132 form_class = ResendActivationForm
133 success_url = reverse_lazy('resent-activation')
135 def form_valid(self, form):
136 """ called whene the form was POSTed and its contents were valid """
138 try:
139 user = UserProxy.objects.all().by_username_or_email(
140 form.cleaned_data['username'],
141 form.cleaned_data['email'],
144 except UserProxy.DoesNotExist:
145 messages.error(self.request, _('User does not exist.'))
146 return HttpResponseRedirect(reverse('resend-activation'))
148 if user.profile.activation_key is None:
149 messages.success(self.request, _('Your account already has been '
150 'activated. Go ahead and log in.'))
152 send_activation_email(user, self.request)
153 return super(ResendActivationView, self).form_valid(form)
156 class ResentActivationView(TemplateView):
157 template_name = 'registration/resent_activation.html'
160 def send_activation_email(user, request):
161 """ Sends the activation email for the given user """
163 subj = render_to_string('registration/activation_email_subject.txt')
164 # remove trailing newline added by render_to_string
165 subj = subj.strip()
167 msg = render_to_string('registration/activation_email.txt', {
168 'site': get_current_site(request),
169 'activation_key': user.profile.activation_key,
171 user.email_user(subj, msg)