Commit 3e13bc798b277823e4bb3ab0992fbb6fa5eb99ec
1 parent
dab8f064
Exists in
master
and in
39 other branches
Refactorign signup process
Showing
8 changed files
with
87 additions
and
177 deletions
Show diff stats
src/accounts/forms.py
1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
2 | 2 | ||
3 | from django import forms | 3 | from django import forms |
4 | -from django.contrib.auth.models import User | 4 | +from django.contrib.auth import get_user_model |
5 | from django.contrib.auth.forms import UserCreationForm as UserCreationForm_ | 5 | from django.contrib.auth.forms import UserCreationForm as UserCreationForm_ |
6 | from django.utils.translation import ugettext_lazy as _ | 6 | from django.utils.translation import ugettext_lazy as _ |
7 | 7 | ||
8 | from super_archives.models import MailingList | 8 | from super_archives.models import MailingList |
9 | -from super_archives.validators import UniqueValidator | ||
10 | 9 | ||
11 | 10 | ||
12 | -LISTS_NAMES = [] | ||
13 | -for list_ in MailingList.objects.iterator(): | ||
14 | - choice = (list_.name, list_.name) | ||
15 | - LISTS_NAMES.append(choice) | 11 | +User = get_user_model() |
16 | 12 | ||
17 | 13 | ||
18 | -class UserCreationForm(UserCreationForm_): | ||
19 | - first_name = forms.CharField(max_length=30, label=_(u'Name'), | ||
20 | - widget=forms.TextInput(attrs={'class':'form-control'})) | ||
21 | - last_name = forms.CharField(max_length=30, label=_(u'Last name'), | ||
22 | - widget=forms.TextInput(attrs={'class':'form-control'})) | ||
23 | - email = forms.EmailField(validators=[UniqueValidator(User, 'email')], | ||
24 | - widget=forms.TextInput(attrs={'class':'form-control'})) | ||
25 | - lists = forms.MultipleChoiceField(label=u'Listas', | ||
26 | - required=False, | ||
27 | - widget=forms.CheckboxSelectMultiple, | ||
28 | - choices=LISTS_NAMES) | ||
29 | - | 14 | +class NewUserForm(forms.ModelForm): |
15 | + class Meta: | ||
16 | + model = User | ||
17 | + fields = ('first_name', 'last_name', 'email', 'username') | ||
30 | 18 | ||
31 | def __init__(self, *args, **kwargs): | 19 | def __init__(self, *args, **kwargs): |
32 | - super(UserCreationForm, self).__init__(*args, **kwargs) | ||
33 | - self.fields.pop('password1') | ||
34 | - self.fields.pop('password2') | ||
35 | - | ||
36 | - | ||
37 | -class UserUpdateForm(UserCreationForm): | ||
38 | - institution= forms.CharField(max_length=120, label=_(u'Institution'), required=False, | ||
39 | - widget=forms.TextInput(attrs={'class':'form-control'})) | ||
40 | - role = forms.CharField(max_length=60, label=_(u'Role'), required=False, | ||
41 | - widget=forms.TextInput(attrs={'class':'form-control'})) | ||
42 | - twitter = forms.URLField(label=_(u'Twitter'), required=False, | ||
43 | - widget=forms.TextInput(attrs={'class':'form-control'})) | ||
44 | - facebook = forms.URLField(label=_(u'Facebook'), required=False, | ||
45 | - widget=forms.TextInput(attrs={'class':'form-control'})) | ||
46 | - google_talk = forms.EmailField(label=_(u'Google Talk'), required=False, | ||
47 | - widget=forms.TextInput(attrs={'class':'form-control'})) | ||
48 | - webpage = forms.URLField(label=_(u'Personal Website/Blog'), required=False, | ||
49 | - widget=forms.TextInput(attrs={'class':'form-control'})) | 20 | + super(NewUserForm, self).__init__(*args, **kwargs) |
21 | + for field in self.fields.values(): | ||
22 | + field.widget.attrs.update({'class': 'form-control'}) | ||
23 | + field.required = True | ||
50 | 24 | ||
51 | - def __init__(self, *args, **kwargs): | ||
52 | - super(UserUpdateForm, self).__init__(*args, **kwargs) | ||
53 | - self.fields.pop('username') | ||
54 | - self.fields.pop('first_name') | ||
55 | - self.fields.pop('last_name') | ||
56 | - self.fields.pop('email') | ||
57 | - self.fields.pop('lists') | 25 | + |
26 | +class ListsForm(forms.Form): | ||
27 | + LISTS_NAMES = ((list.name, list.name) for list in MailingList.objects.all()) | ||
28 | + lists = forms.MultipleChoiceField(label=_(u'Mailing lists'), | ||
29 | + required=False, | ||
30 | + widget=forms.CheckboxSelectMultiple, | ||
31 | + choices=LISTS_NAMES) |
src/accounts/models.py
@@ -4,13 +4,13 @@ from django.contrib.auth.models import AbstractUser | @@ -4,13 +4,13 @@ from django.contrib.auth.models import AbstractUser | ||
4 | 4 | ||
5 | 5 | ||
6 | class User(AbstractUser): | 6 | class User(AbstractUser): |
7 | - institution = models.CharField(max_length=128, null=True) | ||
8 | - role = models.CharField(max_length=128, null=True) | ||
9 | - twitter = models.CharField(max_length=128, null=True) | ||
10 | - facebook = models.CharField(max_length=128, null=True) | ||
11 | - google_talk = models.EmailField(null=True) | ||
12 | - webpage = models.CharField(max_length=256, null=True) | ||
13 | - verification_hash = models.CharField(max_length=32, null=True) | 7 | + institution = models.CharField(max_length=128, null=True, blank=True) |
8 | + role = models.CharField(max_length=128, null=True, blank=True) | ||
9 | + twitter = models.CharField(max_length=128, null=True, blank=True) | ||
10 | + facebook = models.CharField(max_length=128, null=True, blank=True) | ||
11 | + google_talk = models.EmailField(null=True, blank=True) | ||
12 | + webpage = models.CharField(max_length=256, null=True, blank=True) | ||
13 | + verification_hash = models.CharField(max_length=32, null=True, blank=True) | ||
14 | 14 | ||
15 | # We need to have `email` field set as unique but Django does not | 15 | # We need to have `email` field set as unique but Django does not |
16 | # support field overriding (at least not until 1.6). | 16 | # support field overriding (at least not until 1.6). |
src/accounts/templates/accounts/account_message.html
src/accounts/templates/accounts/email_signup-email-confirmation.html
@@ -1,9 +0,0 @@ | @@ -1,9 +0,0 @@ | ||
1 | -{% load i18n %} | ||
2 | - | ||
3 | -{% trans "Welcome to the Colab!" %} | ||
4 | - | ||
5 | -{% trans "To activate your account, please confirm your mail's activation by accessing the following link:" %} | ||
6 | - | ||
7 | -<a href="http://{{ server_name }}{% url 'email_verification' hash %}"> | ||
8 | - http://{{ server_name }}{% url 'email_verification' hash %} | ||
9 | -</a> |
src/accounts/urls.py
@@ -5,10 +5,9 @@ from .views import UserProfileDetailView | @@ -5,10 +5,9 @@ from .views import UserProfileDetailView | ||
5 | 5 | ||
6 | 6 | ||
7 | urlpatterns = patterns('', | 7 | urlpatterns = patterns('', |
8 | - url(r'^$', 'accounts.views.signup', name='signup'), | 8 | + #url(r'^$', 'accounts.views.signup', name='signup'), |
9 | 9 | ||
10 | - url(r'^verify/(?P<hash>[\w]{32})/$', | ||
11 | - 'accounts.views.verify_email', name='email_verification'), | 10 | + url(r'^register/$', 'accounts.views.signup', name='signup'), |
12 | 11 | ||
13 | url(r'^(?P<username>[\w@+.-]+)/?$', | 12 | url(r'^(?P<username>[\w@+.-]+)/?$', |
14 | UserProfileDetailView.as_view(), name='user_profile'), | 13 | UserProfileDetailView.as_view(), name='user_profile'), |
src/accounts/views.py
1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
2 | # encoding: utf-8 | 2 | # encoding: utf-8 |
3 | 3 | ||
4 | -import uuid | ||
5 | -from colab.deprecated import signup as signup_ | 4 | +from django.contrib import messages |
6 | 5 | ||
7 | -from django.template import RequestContext | ||
8 | from django.contrib.auth import get_user_model | 6 | from django.contrib.auth import get_user_model |
9 | from django.views.generic import DetailView | 7 | from django.views.generic import DetailView |
10 | from django.utils.translation import ugettext as _ | 8 | from django.utils.translation import ugettext as _ |
11 | -from django.shortcuts import render, get_object_or_404 | 9 | +from django.shortcuts import render, redirect |
12 | 10 | ||
13 | from colab.deprecated import solrutils | 11 | from colab.deprecated import solrutils |
12 | +from colab.deprecated import signup as signup_ | ||
14 | 13 | ||
15 | -from .forms import UserCreationForm | ||
16 | from super_archives.models import EmailAddress, Message | 14 | from super_archives.models import EmailAddress, Message |
17 | - | ||
18 | - | ||
19 | -# helper | ||
20 | -def get_field_set(form): | ||
21 | - fieldsets = ( | ||
22 | - (_('Personal Information'), ( | ||
23 | - form['first_name'], | ||
24 | - form['last_name'], | ||
25 | - form['email'], | ||
26 | - form['username'], | ||
27 | - ) | ||
28 | - ), | ||
29 | - (_('Subscribe to mail lists'), ( | ||
30 | - form['lists'], | ||
31 | - ) | ||
32 | - ), | ||
33 | - ) | ||
34 | - return fieldsets | ||
35 | - | ||
36 | - | ||
37 | -def signup(request): | ||
38 | - | ||
39 | - # If the request method is GET just return the form | ||
40 | - if request.method == 'GET': | ||
41 | - form = UserCreationForm() | ||
42 | - return render(request, 'accounts/signup-form.html', | ||
43 | - {'form': form, 'fieldsets': get_field_set(form)}) | ||
44 | - | ||
45 | - # If the request method is POST try to store data | ||
46 | - form = UserCreationForm(request.POST) | ||
47 | - | ||
48 | - # If there is validation errors give the form back to the user | ||
49 | - if not form.is_valid(): | ||
50 | - return render(request, 'accounts/signup-form.html', | ||
51 | - {'form': form, 'fieldsets': get_field_set(form)}) | ||
52 | - | ||
53 | - user = User( | ||
54 | - username=form.cleaned_data.get('username'), | ||
55 | - email=form.cleaned_data.get('email'), | ||
56 | - first_name=form.cleaned_data.get('first_name'), | ||
57 | - last_name=form.cleaned_data.get('last_name'), | ||
58 | - is_active=False, | ||
59 | - ) | ||
60 | - user.set_password(form.cleaned_data.get('password1')) | ||
61 | - user.save() | ||
62 | - | ||
63 | - profile = UserProfile( | ||
64 | - user=user, | ||
65 | - institution=form.cleaned_data.get('institution'), | ||
66 | - role=form.cleaned_data.get('role'), | ||
67 | - twitter=form.cleaned_data.get('twitter'), | ||
68 | - facebook=form.cleaned_data.get('facebook'), | ||
69 | - google_talk=form.cleaned_data.get('google_talk'), | ||
70 | - webpage=form.cleaned_data.get('webpage'), | ||
71 | - verification_hash=uuid.uuid4().get_hex(), | ||
72 | - ) | ||
73 | - profile.save() | ||
74 | - | ||
75 | - signup_.send_verification_email(request, user) | ||
76 | - | ||
77 | - mailing_lists = form.cleaned_data.get('lists') | ||
78 | - if mailing_lists: | ||
79 | - signup_.send_email_lists(user, mailing_lists) | ||
80 | - | ||
81 | - | ||
82 | - # Check if the user's email have been used previously | ||
83 | - # in the mainling lists to link the user to old messages | ||
84 | - email_addr, created = EmailAddress.objects.get_or_create(address=user.email) | ||
85 | - if created: | ||
86 | - email_addr.real_name = user.get_full_name() | ||
87 | - | ||
88 | - email_addr.user = user | ||
89 | - email_addr.save() | ||
90 | - | ||
91 | - template_data = { | ||
92 | - 'msg': _(u'Registration completed successfully. Please visit your email address to validate it.'), | ||
93 | - 'msg_css_class': 'alert-success', | ||
94 | - } | ||
95 | - | ||
96 | - return render(request, 'accounts/account_message.html', template_data) | ||
97 | - | ||
98 | - | ||
99 | -def verify_email(request, hash): | ||
100 | - """Verify hash and activate user's account""" | ||
101 | - | ||
102 | - profile = get_object_or_404(UserProfile, verification_hash=hash) | ||
103 | - | ||
104 | - profile.verification_hash = 'verified' | ||
105 | - profile.save() | ||
106 | - | ||
107 | - profile.user.is_active = True | ||
108 | - profile.user.save() | ||
109 | - | ||
110 | - template_data = { | ||
111 | - 'msg': _(u'E-mail validated correctly.'), | ||
112 | - 'msg_css_class': 'alert-success', | ||
113 | - } | ||
114 | - | ||
115 | - return render(request, 'accounts/account_message.html', template_data) | 15 | +from .forms import NewUserForm, ListsForm |
116 | 16 | ||
117 | 17 | ||
118 | class UserProfileDetailView(DetailView): | 18 | class UserProfileDetailView(DetailView): |
@@ -141,5 +41,43 @@ class UserProfileDetailView(DetailView): | @@ -141,5 +41,43 @@ class UserProfileDetailView(DetailView): | ||
141 | query = query.order_by('-received_time') | 41 | query = query.order_by('-received_time') |
142 | context['emails'] = query[:10] | 42 | context['emails'] = query[:10] |
143 | 43 | ||
44 | + context.update(kwargs) | ||
144 | return super(UserProfileDetailView, self).get_context_data(**context) | 45 | return super(UserProfileDetailView, self).get_context_data(**context) |
145 | 46 | ||
47 | + | ||
48 | +def signup(request): | ||
49 | + # If the request method is GET just return the form | ||
50 | + if request.method == 'GET': | ||
51 | + user_form = NewUserForm() | ||
52 | + lists_form = ListsForm() | ||
53 | + return render(request, 'registration/registration_form.html', | ||
54 | + {'user_form': user_form, 'lists_form': lists_form}) | ||
55 | + | ||
56 | + user_form = NewUserForm(request.POST) | ||
57 | + lists_form = ListsForm(request.POST) | ||
58 | + | ||
59 | + if not user_form.is_valid() or not lists_form.is_valid(): | ||
60 | + return render(request, 'registration/registration_form.html', | ||
61 | + {'user_form': user_form, 'lists_form': lists_form}) | ||
62 | + | ||
63 | + user = user_form.save() | ||
64 | + | ||
65 | + mailing_lists = lists_form.cleaned_data.get('lists') | ||
66 | + if mailing_lists: | ||
67 | + signup_.send_email_lists(user, mailing_lists) | ||
68 | + | ||
69 | + # Check if the user's email have been used previously | ||
70 | + # in the mainling lists to link the user to old messages | ||
71 | + email_addr, created = EmailAddress.objects.get_or_create(address=user.email) | ||
72 | + if created: | ||
73 | + email_addr.real_name = user.get_full_name() | ||
74 | + | ||
75 | + email_addr.user = user | ||
76 | + email_addr.save() | ||
77 | + | ||
78 | + messages.success(request, _('Your profile has been created!')) | ||
79 | + messages.warning(request, _('You must login to validated your profile. ' | ||
80 | + 'Profiles not validated are deleted in 24h.')) | ||
81 | + | ||
82 | + return redirect('user_profile', username=user.username) | ||
83 | + |
src/colab/custom_settings.py
@@ -23,7 +23,6 @@ INSTALLED_APPS = INSTALLED_APPS + ( | @@ -23,7 +23,6 @@ INSTALLED_APPS = INSTALLED_APPS + ( | ||
23 | 'cliauth', | 23 | 'cliauth', |
24 | 'django_browserid', | 24 | 'django_browserid', |
25 | 'conversejs', | 25 | 'conversejs', |
26 | - 'registration', | ||
27 | 26 | ||
28 | # Own apps | 27 | # Own apps |
29 | 'super_archives', | 28 | 'super_archives', |
@@ -145,6 +144,14 @@ STATIC_ROOT = os.path.join(BASE_DIR, '..', 'www', 'static') | @@ -145,6 +144,14 @@ STATIC_ROOT = os.path.join(BASE_DIR, '..', 'www', 'static') | ||
145 | 144 | ||
146 | AUTH_USER_MODEL = 'accounts.User' | 145 | AUTH_USER_MODEL = 'accounts.User' |
147 | 146 | ||
147 | +from django.contrib.messages import constants as messages | ||
148 | +MESSAGE_TAGS = { | ||
149 | + messages.INFO: 'alert-info', | ||
150 | + messages.SUCCESS: 'alert-success', | ||
151 | + messages.WARNING: 'alert-warning', | ||
152 | + messages.ERROR: 'alert-danger', | ||
153 | +} | ||
154 | + | ||
148 | 155 | ||
149 | ### Proxy configuration | 156 | ### Proxy configuration |
150 | SOCKS_SERVER = None | 157 | SOCKS_SERVER = None |
src/colab/deprecated/templates/base.html
@@ -47,8 +47,6 @@ | @@ -47,8 +47,6 @@ | ||
47 | <div class="row"> | 47 | <div class="row"> |
48 | </div> | 48 | </div> |
49 | 49 | ||
50 | - {% block header %}{% endblock %} | ||
51 | - | ||
52 | <nav class="navbar navbar-default navbar-fixed-top" role="navigation"> | 50 | <nav class="navbar navbar-default navbar-fixed-top" role="navigation"> |
53 | <div class="navbar-header"> | 51 | <div class="navbar-header"> |
54 | <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-main"> | 52 | <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-main"> |
@@ -119,6 +117,17 @@ | @@ -119,6 +117,17 @@ | ||
119 | </div> | 117 | </div> |
120 | </nav> | 118 | </nav> |
121 | 119 | ||
120 | + {% block messages %} | ||
121 | + {% for message in messages %} | ||
122 | + <div class="alert alert-dismissable {{ message.tags }}"> | ||
123 | + <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> | ||
124 | + {{ message }} | ||
125 | + </div> | ||
126 | + {% endfor %} | ||
127 | + {% endblock %} | ||
128 | + | ||
129 | + {% block header %}{% endblock %} | ||
130 | + | ||
122 | <div> | 131 | <div> |
123 | {% block main-content %} {% endblock %} | 132 | {% block main-content %} {% endblock %} |
124 | </div> | 133 | </div> |