1 # Copyright 2011-2012 GRNET S.A. All rights reserved.
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
7 # 1. Redistributions of source code must retain the above
8 # copyright notice, this list of conditions and the following
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.
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.
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 from urlparse import urljoin
35 from django import forms
36 from django.utils.translation import ugettext as _
37 from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, PasswordResetForm
38 from django.core.mail import send_mail
39 from django.contrib.auth.tokens import default_token_generator
40 from django.template import Context, loader
41 from django.utils.http import int_to_base36
42 from django.core.urlresolvers import reverse
44 from astakos.im.models import AstakosUser
45 from astakos.im.settings import INVITATIONS_PER_LEVEL, DEFAULT_FROM_EMAIL, BASEURL, SITENAME
49 logger = logging.getLogger(__name__)
51 class LocalUserCreationForm(UserCreationForm):
53 Extends the built in UserCreationForm in several ways:
55 * Adds email, first_name and last_name field.
56 * The username field isn't visible and it is assigned a generated id.
57 * User created is not active.
62 fields = ("email", "first_name", "last_name")
64 def __init__(self, *args, **kwargs):
66 Changes the order of fields, and removes the username field.
68 super(LocalUserCreationForm, self).__init__(*args, **kwargs)
69 self.fields.keyOrder = ['email', 'first_name', 'last_name',
70 'password1', 'password2']
72 def clean_email(self):
73 email = self.cleaned_data['email']
75 raise forms.ValidationError(_("This field is required"))
77 AstakosUser.objects.get(email = email)
78 raise forms.ValidationError(_("Email is reserved"))
79 except AstakosUser.DoesNotExist:
82 def save(self, commit=True):
84 Saves the email, first_name and last_name properties, after the normal
85 save behavior is complete.
87 user = super(LocalUserCreationForm, self).save(commit=False)
91 logger.info('Created user %s', user)
94 class InvitedLocalUserCreationForm(LocalUserCreationForm):
96 Extends the LocalUserCreationForm: adds an inviter readonly field.
99 inviter = forms.CharField(widget=forms.TextInput(), label=_('Inviter Real Name'))
103 fields = ("email", "first_name", "last_name")
105 def __init__(self, *args, **kwargs):
107 Changes the order of fields, and removes the username field.
109 super(InvitedLocalUserCreationForm, self).__init__(*args, **kwargs)
110 self.fields.keyOrder = ['email', 'inviter', 'first_name',
111 'last_name', 'password1', 'password2']
112 #set readonly form fields
113 self.fields['inviter'].widget.attrs['readonly'] = True
114 self.fields['email'].widget.attrs['readonly'] = True
115 self.fields['username'].widget.attrs['readonly'] = True
117 def save(self, commit=True):
118 user = super(InvitedLocalUserCreationForm, self).save(commit=False)
119 level = user.invitation.inviter.level + 1
121 user.invitations = INVITATIONS_PER_LEVEL[level]
126 class LoginForm(AuthenticationForm):
127 username = forms.EmailField(label=_("Email"))
129 class ProfileForm(forms.ModelForm):
131 Subclass of ``ModelForm`` for permiting user to edit his/her profile.
132 Most of the fields are readonly since the user is not allowed to change them.
134 The class defines a save method which sets ``is_verified`` to True so as the user
135 during the next login will not to be redirected to profile page.
137 renew = forms.BooleanField(label='Renew token', required=False)
141 fields = ('email', 'first_name', 'last_name', 'auth_token', 'auth_token_expires')
143 def __init__(self, *args, **kwargs):
144 super(ProfileForm, self).__init__(*args, **kwargs)
145 instance = getattr(self, 'instance', None)
146 ro_fields = ('auth_token', 'auth_token_expires', 'email')
147 if instance and instance.id:
148 for field in ro_fields:
149 self.fields[field].widget.attrs['readonly'] = True
151 def save(self, commit=True):
152 user = super(ProfileForm, self).save(commit=False)
153 user.is_verified = True
154 if self.cleaned_data.get('renew'):
160 class ThirdPartyUserCreationForm(ProfileForm):
163 fields = ('email', 'last_name', 'first_name', 'affiliation', 'provider', 'third_party_identifier')
165 def __init__(self, *args, **kwargs):
166 super(ThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
167 self.fields.keyOrder = ['email']
169 def clean_email(self):
170 email = self.cleaned_data['email']
172 raise forms.ValidationError(_("This field is required"))
174 user = AstakosUser.objects.get(email = email)
175 raise forms.ValidationError(_("Email is reserved"))
176 except AstakosUser.DoesNotExist:
179 def save(self, commit=True):
180 user = super(ThirdPartyUserCreationForm, self).save(commit=False)
181 user.verified = False
185 logger.info('Created user %s', user)
188 class InvitedThirdPartyUserCreationForm(ThirdPartyUserCreationForm):
189 def __init__(self, *args, **kwargs):
190 super(InvitedThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
191 #set readonly form fields
192 self.fields['email'].widget.attrs['readonly'] = True
194 class FeedbackForm(forms.Form):
196 Form for writing feedback.
198 feedback_msg = forms.CharField(widget=forms.Textarea(),
199 label=u'Message', required=False)
200 feedback_data = forms.CharField(widget=forms.HiddenInput(),
201 label='', required=False)
203 class SendInvitationForm(forms.Form):
205 Form for sending an invitations
208 email = forms.EmailField(required = True, label = 'Email address')
209 first_name = forms.EmailField(label = 'First name')
210 last_name = forms.EmailField(label = 'Last name')
212 class ExtendedPasswordResetForm(PasswordResetForm):
214 Extends PasswordResetForm by overriding save method:
215 passes a custom from_email in send_mail.
217 Since Django 1.3 this is useless since ``django.contrib.auth.views.reset_password``
218 accepts a from_email argument.
220 def save(self, domain_override=None, email_template_name='registration/password_reset_email.html',
221 use_https=False, token_generator=default_token_generator, request=None):
223 Generates a one-use only link for resetting password and sends to the user.
225 for user in self.users_cache:
226 url = urljoin(BASEURL,
227 '/im/local/reset/confirm/%s-%s' %(int_to_base36(user.id),
228 token_generator.make_token(user)))
229 t = loader.get_template(email_template_name)
233 'site_name': SITENAME,
237 from_email = DEFAULT_FROM_EMAIL
238 send_mail(_("Password reset on %s") % SITENAME,
239 t.render(Context(c)), from_email, [user.email])