user registration form checks whether the email is reserved
[astakos] / astakos / im / forms.py
1 # Copyright 2011-2012 GRNET S.A. All rights reserved.
2
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
5 # conditions are met:
6
7 #   1. Redistributions of source code must retain the above
8 #      copyright notice, this list of conditions and the following
9 #      disclaimer.
10
11 #   2. Redistributions in binary form must reproduce the above
12 #      copyright notice, this list of conditions and the following
13 #      disclaimer in the documentation and/or other materials
14 #      provided with the distribution.
15
16 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
28
29 # The views and conclusions contained in the software and
30 # documentation are those of the authors and should not be
31 # interpreted as representing official policies, either expressed
32 # or implied, of GRNET S.A.
33
34 from django import forms
35 from django.utils.translation import ugettext as _
36 from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
37 from django.conf import settings
38 from django.core.validators import email_re
39 from django.conf import settings
40
41 from hashlib import new as newhasher
42
43 from astakos.im.models import AstakosUser
44 from astakos.im.util import get_or_create_user
45
46 import logging
47 import uuid
48
49 class ExtendedUserCreationForm(UserCreationForm):
50     """
51     Extends the built in UserCreationForm in several ways:
52     
53     * Adds email, first_name and last_name field.
54     * The username field isn't visible and it is assigned a generated id.
55     * User created is not active. 
56     """
57     
58     class Meta:
59         model = AstakosUser
60         fields = ("email", "first_name", "last_name")
61     
62     def __init__(self, *args, **kwargs):
63         """
64         Changes the order of fields, and removes the username field.
65         """
66         super(ExtendedUserCreationForm, self).__init__(*args, **kwargs)
67         self.fields.keyOrder = ['email', 'first_name', 'last_name',
68                                 'password1', 'password2']
69     
70     def clean_email(self):
71         email = self.cleaned_data['email']
72         try:
73             AstakosUser.objects.get(email = email)
74             raise forms.ValidationError(_("Email is reserved"))
75         except AstakosUser.DoesNotExist:
76             return email
77     
78     def save(self, commit=True):
79         """
80         Saves the email, first_name and last_name properties, after the normal
81         save behavior is complete.
82         """
83         user = super(ExtendedUserCreationForm, self).save(commit=False)
84         user.username = uuid.uuid4().hex[:30]
85         user.is_active = False
86         user.renew_token()
87         if commit:
88             user.save()
89         logging.info('Created user %s', user)
90         return user
91
92 class InvitedExtendedUserCreationForm(ExtendedUserCreationForm):
93     """
94     Extends the ExtendedUserCreationForm: adds an inviter readonly field.
95     """
96     
97     inviter = forms.CharField(widget=forms.TextInput(), label=_('Inviter Real Name'))
98     
99     class Meta:
100         model = AstakosUser
101         fields = ("email", "first_name", "last_name")
102     
103     def __init__(self, *args, **kwargs):
104         """
105         Changes the order of fields, and removes the username field.
106         """
107         super(InvitedExtendedUserCreationForm, self).__init__(*args, **kwargs)
108         self.fields.keyOrder = ['email', 'inviter', 'first_name',
109                                 'last_name', 'password1', 'password2']
110         #set readonly form fields
111         self.fields['inviter'].widget.attrs['readonly'] = True
112         self.fields['email'].widget.attrs['readonly'] = True
113         self.fields['username'].widget.attrs['readonly'] = True
114     
115     def save(self, commit=True):
116         user = super(InvitedExtendedUserCreationForm, self).save(commit=False)
117         level = user.invitation.inviter.level
118         user.level = level + 1
119         user.invitations = settings.INVITATIONS_PER_LEVEL[level]
120         if commit:
121             user.save()
122         return user
123
124 class LoginForm(AuthenticationForm):
125     username = forms.EmailField(label=_("Email"))
126
127 class ProfileForm(forms.ModelForm):
128     """
129     Subclass of ``ModelForm`` for permiting user to edit his/her profile.
130     Most of the fields are readonly since the user is not allowed to change them.
131     
132     The class defines a save method which sets ``is_verified`` to True so as the user
133     during the next login will not to be redirected to profile page.
134     """
135     class Meta:
136         model = AstakosUser
137         exclude = ('is_active', 'is_superuser', 'is_staff', 'is_verified', 'groups', 'user_permissions')
138     
139     def __init__(self, *args, **kwargs):
140         super(ProfileForm, self).__init__(*args, **kwargs)
141         instance = getattr(self, 'instance', None)
142         ro_fields = ('username','date_joined', 'updated', 'auth_token',
143                      'auth_token_created', 'auth_token_expires', 'invitations',
144                      'level', 'last_login', 'email', )
145         if instance and instance.id:
146             for field in ro_fields:
147                 if isinstance(self.fields[field].widget, forms.CheckboxInput):
148                     self.fields[field].widget.attrs['disabled'] = True
149                 self.fields[field].widget.attrs['readonly'] = True
150     
151     def save(self, commit=True):
152         user = super(ProfileForm, self).save(commit=False)
153         user.is_verified = True
154         if commit:
155             user.save()
156         return user
157
158
159 class FeedbackForm(forms.Form):
160     """
161     Form for writing feedback.
162     """
163     feedback_msg = forms.CharField(widget=forms.Textarea(),
164                                 label=u'Message', required=False)
165     feedback_data = forms.CharField(widget=forms.Textarea(),
166                                 label=u'Data', required=False)
167
168 class SendInvitationForm(forms.Form):
169     """
170     Form for sending an invitations
171     """
172     
173     email = forms.EmailField(required = True, label = 'Email address')
174     first_name = forms.EmailField(label = 'First name')
175     last_name = forms.EmailField(label = 'Last name')
176