Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / forms.py @ 262c2717

History | View | Annotate | Download (17.1 kB)

1 aba1e498 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 18ffbee1 Sofia Papagiannaki
#
3 64cd4730 Antony Chazapis
# Redistribution and use in source and binary forms, with or
4 64cd4730 Antony Chazapis
# without modification, are permitted provided that the following
5 64cd4730 Antony Chazapis
# conditions are met:
6 18ffbee1 Sofia Papagiannaki
#
7 64cd4730 Antony Chazapis
#   1. Redistributions of source code must retain the above
8 64cd4730 Antony Chazapis
#      copyright notice, this list of conditions and the following
9 64cd4730 Antony Chazapis
#      disclaimer.
10 18ffbee1 Sofia Papagiannaki
#
11 64cd4730 Antony Chazapis
#   2. Redistributions in binary form must reproduce the above
12 64cd4730 Antony Chazapis
#      copyright notice, this list of conditions and the following
13 64cd4730 Antony Chazapis
#      disclaimer in the documentation and/or other materials
14 64cd4730 Antony Chazapis
#      provided with the distribution.
15 18ffbee1 Sofia Papagiannaki
#
16 64cd4730 Antony Chazapis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 64cd4730 Antony Chazapis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 64cd4730 Antony Chazapis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 64cd4730 Antony Chazapis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 64cd4730 Antony Chazapis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 64cd4730 Antony Chazapis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 64cd4730 Antony Chazapis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 64cd4730 Antony Chazapis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 64cd4730 Antony Chazapis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 64cd4730 Antony Chazapis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 64cd4730 Antony Chazapis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 64cd4730 Antony Chazapis
# POSSIBILITY OF SUCH DAMAGE.
28 18ffbee1 Sofia Papagiannaki
#
29 64cd4730 Antony Chazapis
# The views and conclusions contained in the software and
30 64cd4730 Antony Chazapis
# documentation are those of the authors and should not be
31 64cd4730 Antony Chazapis
# interpreted as representing official policies, either expressed
32 64cd4730 Antony Chazapis
# or implied, of GRNET S.A.
33 8f378756 Sofia Papagiannaki
from urlparse import urljoin
34 270dd48d Sofia Papagiannaki
from datetime import datetime
35 64cd4730 Antony Chazapis
36 64cd4730 Antony Chazapis
from django import forms
37 64cd4730 Antony Chazapis
from django.utils.translation import ugettext as _
38 e2125441 Sofia Papagiannaki
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, PasswordResetForm
39 e2125441 Sofia Papagiannaki
from django.core.mail import send_mail
40 e2125441 Sofia Papagiannaki
from django.contrib.auth.tokens import default_token_generator
41 e2125441 Sofia Papagiannaki
from django.template import Context, loader
42 e2125441 Sofia Papagiannaki
from django.utils.http import int_to_base36
43 374611bc Sofia Papagiannaki
from django.core.urlresolvers import reverse
44 270dd48d Sofia Papagiannaki
from django.utils.functional import lazy
45 18ffbee1 Sofia Papagiannaki
from django.utils.safestring import mark_safe
46 0a569195 Sofia Papagiannaki
from django.contrib import messages
47 5ed6816e Sofia Papagiannaki
48 09e7393c Sofia Papagiannaki
from astakos.im.models import AstakosUser, Invitation, get_latest_terms
49 a53b19da Sofia Papagiannaki
from astakos.im.settings import INVITATIONS_PER_LEVEL, DEFAULT_FROM_EMAIL, BASEURL, SITENAME, RECAPTCHA_PRIVATE_KEY, DEFAULT_CONTACT_EMAIL, RECAPTCHA_ENABLED
50 45f8d9ff Sofia Papagiannaki
from astakos.im.widgets import DummyWidget, RecaptchaWidget
51 270dd48d Sofia Papagiannaki
52 270dd48d Sofia Papagiannaki
# since Django 1.4 use django.core.urlresolvers.reverse_lazy instead
53 09e7393c Sofia Papagiannaki
from astakos.im.util import reverse_lazy, reserved_email, get_query
54 64cd4730 Antony Chazapis
55 3bf924ec Sofia Papagiannaki
import logging
56 db7fecd9 Sofia Papagiannaki
import recaptcha.client.captcha as captcha
57 64cd4730 Antony Chazapis
58 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
59 e015e9e6 Sofia Papagiannaki
60 15efc749 Sofia Papagiannaki
class LocalUserCreationForm(UserCreationForm):
61 890b0eaf Sofia Papagiannaki
    """
62 890b0eaf Sofia Papagiannaki
    Extends the built in UserCreationForm in several ways:
63 18ffbee1 Sofia Papagiannaki

64 8316698a Sofia Papagiannaki
    * Adds email, first_name, last_name, recaptcha_challenge_field, recaptcha_response_field field.
65 5ed6816e Sofia Papagiannaki
    * The username field isn't visible and it is assigned a generated id.
66 18ffbee1 Sofia Papagiannaki
    * User created is not active.
67 890b0eaf Sofia Papagiannaki
    """
68 db7fecd9 Sofia Papagiannaki
    recaptcha_challenge_field = forms.CharField(widget=DummyWidget)
69 db7fecd9 Sofia Papagiannaki
    recaptcha_response_field = forms.CharField(widget=RecaptchaWidget, label='')
70 18ffbee1 Sofia Papagiannaki
71 794852f2 Sofia Papagiannaki
    class Meta:
72 794852f2 Sofia Papagiannaki
        model = AstakosUser
73 45f8d9ff Sofia Papagiannaki
        fields = ("email", "first_name", "last_name", "has_signed_terms", "has_signed_terms")
74 18ffbee1 Sofia Papagiannaki
75 64cd4730 Antony Chazapis
    def __init__(self, *args, **kwargs):
76 64cd4730 Antony Chazapis
        """
77 890b0eaf Sofia Papagiannaki
        Changes the order of fields, and removes the username field.
78 64cd4730 Antony Chazapis
        """
79 672d445a Sofia Papagiannaki
        request = kwargs.get('request', None)
80 672d445a Sofia Papagiannaki
        if request:
81 672d445a Sofia Papagiannaki
            kwargs.pop('request')
82 672d445a Sofia Papagiannaki
            self.ip = request.META.get('REMOTE_ADDR',
83 672d445a Sofia Papagiannaki
                                       request.META.get('HTTP_X_REAL_IP', None))
84 672d445a Sofia Papagiannaki
        
85 15efc749 Sofia Papagiannaki
        super(LocalUserCreationForm, self).__init__(*args, **kwargs)
86 890b0eaf Sofia Papagiannaki
        self.fields.keyOrder = ['email', 'first_name', 'last_name',
87 d8f63346 Sofia Papagiannaki
                                'password1', 'password2']
88 d8f63346 Sofia Papagiannaki
        if get_latest_terms():
89 d8f63346 Sofia Papagiannaki
            self.fields.keyOrder.append('has_signed_terms')
90 53bf2659 Sofia Papagiannaki
        if RECAPTCHA_ENABLED:
91 53bf2659 Sofia Papagiannaki
            self.fields.keyOrder.extend(['recaptcha_challenge_field',
92 53bf2659 Sofia Papagiannaki
                                         'recaptcha_response_field',])
93 18ffbee1 Sofia Papagiannaki
94 18ffbee1 Sofia Papagiannaki
        if 'has_signed_terms' in self.fields:
95 18ffbee1 Sofia Papagiannaki
            # Overriding field label since we need to apply a link
96 18ffbee1 Sofia Papagiannaki
            # to the terms within the label
97 18ffbee1 Sofia Papagiannaki
            terms_link_html = '<a href="%s" target="_blank">%s</a>' \
98 18ffbee1 Sofia Papagiannaki
                    % (reverse('latest_terms'), _("the terms"))
99 18ffbee1 Sofia Papagiannaki
            self.fields['has_signed_terms'].label = \
100 18ffbee1 Sofia Papagiannaki
                    mark_safe("I agree with %s" % terms_link_html)
101 18ffbee1 Sofia Papagiannaki
102 af4eb974 Sofia Papagiannaki
    def clean_email(self):
103 af4eb974 Sofia Papagiannaki
        email = self.cleaned_data['email']
104 881c856c Sofia Papagiannaki
        if not email:
105 881c856c Sofia Papagiannaki
            raise forms.ValidationError(_("This field is required"))
106 0a569195 Sofia Papagiannaki
        if reserved_email(email):
107 c37263ea Sofia Papagiannaki
            raise forms.ValidationError(_("This email is already used"))
108 0a569195 Sofia Papagiannaki
        return email
109 18ffbee1 Sofia Papagiannaki
110 270dd48d Sofia Papagiannaki
    def clean_has_signed_terms(self):
111 270dd48d Sofia Papagiannaki
        has_signed_terms = self.cleaned_data['has_signed_terms']
112 270dd48d Sofia Papagiannaki
        if not has_signed_terms:
113 270dd48d Sofia Papagiannaki
            raise forms.ValidationError(_('You have to agree with the terms'))
114 270dd48d Sofia Papagiannaki
        return has_signed_terms
115 18ffbee1 Sofia Papagiannaki
116 db7fecd9 Sofia Papagiannaki
    def clean_recaptcha_response_field(self):
117 db7fecd9 Sofia Papagiannaki
        if 'recaptcha_challenge_field' in self.cleaned_data:
118 db7fecd9 Sofia Papagiannaki
            self.validate_captcha()
119 db7fecd9 Sofia Papagiannaki
        return self.cleaned_data['recaptcha_response_field']
120 db7fecd9 Sofia Papagiannaki
121 db7fecd9 Sofia Papagiannaki
    def clean_recaptcha_challenge_field(self):
122 db7fecd9 Sofia Papagiannaki
        if 'recaptcha_response_field' in self.cleaned_data:
123 db7fecd9 Sofia Papagiannaki
            self.validate_captcha()
124 db7fecd9 Sofia Papagiannaki
        return self.cleaned_data['recaptcha_challenge_field']
125 db7fecd9 Sofia Papagiannaki
126 db7fecd9 Sofia Papagiannaki
    def validate_captcha(self):
127 db7fecd9 Sofia Papagiannaki
        rcf = self.cleaned_data['recaptcha_challenge_field']
128 db7fecd9 Sofia Papagiannaki
        rrf = self.cleaned_data['recaptcha_response_field']
129 db7fecd9 Sofia Papagiannaki
        check = captcha.submit(rcf, rrf, RECAPTCHA_PRIVATE_KEY, self.ip)
130 db7fecd9 Sofia Papagiannaki
        if not check.is_valid:
131 db7fecd9 Sofia Papagiannaki
            raise forms.ValidationError(_('You have not entered the correct words'))
132 18ffbee1 Sofia Papagiannaki
133 890b0eaf Sofia Papagiannaki
    def save(self, commit=True):
134 64cd4730 Antony Chazapis
        """
135 890b0eaf Sofia Papagiannaki
        Saves the email, first_name and last_name properties, after the normal
136 890b0eaf Sofia Papagiannaki
        save behavior is complete.
137 890b0eaf Sofia Papagiannaki
        """
138 15efc749 Sofia Papagiannaki
        user = super(LocalUserCreationForm, self).save(commit=False)
139 3bf924ec Sofia Papagiannaki
        user.renew_token()
140 9fb8e808 Sofia Papagiannaki
        if commit:
141 9fb8e808 Sofia Papagiannaki
            user.save()
142 262c2717 Sofia Papagiannaki
            logger.info('Created user %s', user)
143 890b0eaf Sofia Papagiannaki
        return user
144 64cd4730 Antony Chazapis
145 15efc749 Sofia Papagiannaki
class InvitedLocalUserCreationForm(LocalUserCreationForm):
146 890b0eaf Sofia Papagiannaki
    """
147 062c970c Sofia Papagiannaki
    Extends the LocalUserCreationForm: email is readonly.
148 890b0eaf Sofia Papagiannaki
    """
149 794852f2 Sofia Papagiannaki
    class Meta:
150 794852f2 Sofia Papagiannaki
        model = AstakosUser
151 270dd48d Sofia Papagiannaki
        fields = ("email", "first_name", "last_name", "has_signed_terms")
152 18ffbee1 Sofia Papagiannaki
153 64cd4730 Antony Chazapis
    def __init__(self, *args, **kwargs):
154 64cd4730 Antony Chazapis
        """
155 3bf924ec Sofia Papagiannaki
        Changes the order of fields, and removes the username field.
156 64cd4730 Antony Chazapis
        """
157 15efc749 Sofia Papagiannaki
        super(InvitedLocalUserCreationForm, self).__init__(*args, **kwargs)
158 18ffbee1 Sofia Papagiannaki
159 64cd4730 Antony Chazapis
        #set readonly form fields
160 062c970c Sofia Papagiannaki
        ro = ('email', 'username',)
161 4e30244e Sofia Papagiannaki
        for f in ro:
162 4e30244e Sofia Papagiannaki
            self.fields[f].widget.attrs['readonly'] = True
163 4e30244e Sofia Papagiannaki
        
164 18ffbee1 Sofia Papagiannaki
165 9fb8e808 Sofia Papagiannaki
    def save(self, commit=True):
166 15efc749 Sofia Papagiannaki
        user = super(InvitedLocalUserCreationForm, self).save(commit=False)
167 881c856c Sofia Papagiannaki
        level = user.invitation.inviter.level + 1
168 881c856c Sofia Papagiannaki
        user.level = level
169 8316698a Sofia Papagiannaki
        user.invitations = INVITATIONS_PER_LEVEL.get(level, 0)
170 8316698a Sofia Papagiannaki
        user.email_verified = True
171 9fb8e808 Sofia Papagiannaki
        if commit:
172 9fb8e808 Sofia Papagiannaki
            user.save()
173 9fb8e808 Sofia Papagiannaki
        return user
174 5ed6816e Sofia Papagiannaki
175 18ffbee1 Sofia Papagiannaki
class ThirdPartyUserCreationForm(forms.ModelForm):
176 8f5a3a06 Sofia Papagiannaki
    class Meta:
177 8f5a3a06 Sofia Papagiannaki
        model = AstakosUser
178 45f8d9ff Sofia Papagiannaki
        fields = ("email", "first_name", "last_name", "third_party_identifier", "has_signed_terms")
179 8f5a3a06 Sofia Papagiannaki
    
180 8f5a3a06 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
181 8f5a3a06 Sofia Papagiannaki
        """
182 8f5a3a06 Sofia Papagiannaki
        Changes the order of fields, and removes the username field.
183 8f5a3a06 Sofia Papagiannaki
        """
184 0a569195 Sofia Papagiannaki
        self.request = kwargs.get('request', None)
185 0a569195 Sofia Papagiannaki
        if self.request:
186 0a569195 Sofia Papagiannaki
            kwargs.pop('request')
187 8f5a3a06 Sofia Papagiannaki
        super(ThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
188 0a569195 Sofia Papagiannaki
        self.fields.keyOrder = ['email', 'first_name', 'last_name', 'third_party_identifier']
189 8f5a3a06 Sofia Papagiannaki
        if get_latest_terms():
190 8f5a3a06 Sofia Papagiannaki
            self.fields.keyOrder.append('has_signed_terms')
191 18ffbee1 Sofia Papagiannaki
        #set readonly form fields
192 0a569195 Sofia Papagiannaki
        ro = ["third_party_identifier", "first_name", "last_name"]
193 18ffbee1 Sofia Papagiannaki
        for f in ro:
194 18ffbee1 Sofia Papagiannaki
            self.fields[f].widget.attrs['readonly'] = True
195 18ffbee1 Sofia Papagiannaki
        
196 18ffbee1 Sofia Papagiannaki
        if 'has_signed_terms' in self.fields:
197 18ffbee1 Sofia Papagiannaki
            # Overriding field label since we need to apply a link
198 18ffbee1 Sofia Papagiannaki
            # to the terms within the label
199 18ffbee1 Sofia Papagiannaki
            terms_link_html = '<a href="%s" target="_blank">%s</a>' \
200 18ffbee1 Sofia Papagiannaki
                    % (reverse('latest_terms'), _("the terms"))
201 18ffbee1 Sofia Papagiannaki
            self.fields['has_signed_terms'].label = \
202 18ffbee1 Sofia Papagiannaki
                    mark_safe("I agree with %s" % terms_link_html)
203 18ffbee1 Sofia Papagiannaki
    
204 18ffbee1 Sofia Papagiannaki
    def clean_email(self):
205 18ffbee1 Sofia Papagiannaki
        email = self.cleaned_data['email']
206 18ffbee1 Sofia Papagiannaki
        if not email:
207 18ffbee1 Sofia Papagiannaki
            raise forms.ValidationError(_("This field is required"))
208 0a569195 Sofia Papagiannaki
        return email
209 18ffbee1 Sofia Papagiannaki
    
210 18ffbee1 Sofia Papagiannaki
    def clean_has_signed_terms(self):
211 18ffbee1 Sofia Papagiannaki
        has_signed_terms = self.cleaned_data['has_signed_terms']
212 18ffbee1 Sofia Papagiannaki
        if not has_signed_terms:
213 18ffbee1 Sofia Papagiannaki
            raise forms.ValidationError(_('You have to agree with the terms'))
214 18ffbee1 Sofia Papagiannaki
        return has_signed_terms
215 8f5a3a06 Sofia Papagiannaki
    
216 8f5a3a06 Sofia Papagiannaki
    def save(self, commit=True):
217 8f5a3a06 Sofia Papagiannaki
        user = super(ThirdPartyUserCreationForm, self).save(commit=False)
218 8f5a3a06 Sofia Papagiannaki
        user.set_unusable_password()
219 18ffbee1 Sofia Papagiannaki
        user.renew_token()
220 0a569195 Sofia Papagiannaki
        user.provider = get_query(self.request).get('provider')
221 8f5a3a06 Sofia Papagiannaki
        if commit:
222 8f5a3a06 Sofia Papagiannaki
            user.save()
223 262c2717 Sofia Papagiannaki
            logger.info('Created user %s', user)
224 8f5a3a06 Sofia Papagiannaki
        return user
225 8f5a3a06 Sofia Papagiannaki
226 8f5a3a06 Sofia Papagiannaki
class InvitedThirdPartyUserCreationForm(ThirdPartyUserCreationForm):
227 4e30244e Sofia Papagiannaki
    """
228 062c970c Sofia Papagiannaki
    Extends the ThirdPartyUserCreationForm: email is readonly.
229 4e30244e Sofia Papagiannaki
    """
230 8f5a3a06 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
231 4e30244e Sofia Papagiannaki
        """
232 4e30244e Sofia Papagiannaki
        Changes the order of fields, and removes the username field.
233 4e30244e Sofia Papagiannaki
        """
234 8f5a3a06 Sofia Papagiannaki
        super(InvitedThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
235 4e30244e Sofia Papagiannaki
236 8f5a3a06 Sofia Papagiannaki
        #set readonly form fields
237 062c970c Sofia Papagiannaki
        ro = ('email',)
238 4e30244e Sofia Papagiannaki
        for f in ro:
239 4e30244e Sofia Papagiannaki
            self.fields[f].widget.attrs['readonly'] = True
240 4e30244e Sofia Papagiannaki
    
241 4e30244e Sofia Papagiannaki
    def save(self, commit=True):
242 4e30244e Sofia Papagiannaki
        user = super(InvitedThirdPartyUserCreationForm, self).save(commit=False)
243 4e30244e Sofia Papagiannaki
        level = user.invitation.inviter.level + 1
244 4e30244e Sofia Papagiannaki
        user.level = level
245 4e30244e Sofia Papagiannaki
        user.invitations = INVITATIONS_PER_LEVEL.get(level, 0)
246 4e30244e Sofia Papagiannaki
        user.email_verified = True
247 4e30244e Sofia Papagiannaki
        if commit:
248 4e30244e Sofia Papagiannaki
            user.save()
249 4e30244e Sofia Papagiannaki
        return user
250 8f5a3a06 Sofia Papagiannaki
251 18ffbee1 Sofia Papagiannaki
class ShibbolethUserCreationForm(ThirdPartyUserCreationForm):
252 18ffbee1 Sofia Papagiannaki
    def clean_email(self):
253 18ffbee1 Sofia Papagiannaki
        email = self.cleaned_data['email']
254 0a569195 Sofia Papagiannaki
        for user in AstakosUser.objects.filter(email = email):
255 0a569195 Sofia Papagiannaki
            if user.provider == 'shibboleth':
256 18ffbee1 Sofia Papagiannaki
                raise forms.ValidationError(_("This email is already associated with another shibboleth account."))
257 591d0505 Sofia Papagiannaki
            elif not user.is_active:
258 591d0505 Sofia Papagiannaki
                raise forms.ValidationError(_("This email is already associated with an inactive account. \
259 591d0505 Sofia Papagiannaki
                                              You need to wait to be activated before being able to switch to a shibboleth account."))
260 ab8f7956 Sofia Papagiannaki
        super(ShibbolethUserCreationForm, self).clean_email()
261 0a569195 Sofia Papagiannaki
        return email
262 4e30244e Sofia Papagiannaki
263 0a569195 Sofia Papagiannaki
class InvitedShibbolethUserCreationForm(ShibbolethUserCreationForm, InvitedThirdPartyUserCreationForm):
264 4e30244e Sofia Papagiannaki
    pass
265 18ffbee1 Sofia Papagiannaki
    
266 5ed6816e Sofia Papagiannaki
class LoginForm(AuthenticationForm):
267 5ed6816e Sofia Papagiannaki
    username = forms.EmailField(label=_("Email"))
268 672d445a Sofia Papagiannaki
    recaptcha_challenge_field = forms.CharField(widget=DummyWidget)
269 672d445a Sofia Papagiannaki
    recaptcha_response_field = forms.CharField(widget=RecaptchaWidget, label='')
270 672d445a Sofia Papagiannaki
    
271 672d445a Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
272 672d445a Sofia Papagiannaki
        was_limited = kwargs.get('was_limited', False)
273 672d445a Sofia Papagiannaki
        request = kwargs.get('request', None)
274 672d445a Sofia Papagiannaki
        if request:
275 672d445a Sofia Papagiannaki
            self.ip = request.META.get('REMOTE_ADDR',
276 672d445a Sofia Papagiannaki
                                       request.META.get('HTTP_X_REAL_IP', None))
277 672d445a Sofia Papagiannaki
        
278 672d445a Sofia Papagiannaki
        t = ('request', 'was_limited')
279 672d445a Sofia Papagiannaki
        for elem in t:
280 672d445a Sofia Papagiannaki
            if elem in kwargs.keys():
281 672d445a Sofia Papagiannaki
                kwargs.pop(elem)
282 672d445a Sofia Papagiannaki
        super(LoginForm, self).__init__(*args, **kwargs)
283 672d445a Sofia Papagiannaki
        
284 672d445a Sofia Papagiannaki
        self.fields.keyOrder = ['username', 'password']
285 672d445a Sofia Papagiannaki
        if was_limited and RECAPTCHA_ENABLED:
286 672d445a Sofia Papagiannaki
            self.fields.keyOrder.extend(['recaptcha_challenge_field',
287 672d445a Sofia Papagiannaki
                                         'recaptcha_response_field',])
288 672d445a Sofia Papagiannaki
    
289 672d445a Sofia Papagiannaki
    def clean_recaptcha_response_field(self):
290 672d445a Sofia Papagiannaki
        if 'recaptcha_challenge_field' in self.cleaned_data:
291 672d445a Sofia Papagiannaki
            self.validate_captcha()
292 672d445a Sofia Papagiannaki
        return self.cleaned_data['recaptcha_response_field']
293 672d445a Sofia Papagiannaki
294 672d445a Sofia Papagiannaki
    def clean_recaptcha_challenge_field(self):
295 672d445a Sofia Papagiannaki
        if 'recaptcha_response_field' in self.cleaned_data:
296 672d445a Sofia Papagiannaki
            self.validate_captcha()
297 672d445a Sofia Papagiannaki
        return self.cleaned_data['recaptcha_challenge_field']
298 672d445a Sofia Papagiannaki
299 672d445a Sofia Papagiannaki
    def validate_captcha(self):
300 672d445a Sofia Papagiannaki
        rcf = self.cleaned_data['recaptcha_challenge_field']
301 672d445a Sofia Papagiannaki
        rrf = self.cleaned_data['recaptcha_response_field']
302 672d445a Sofia Papagiannaki
        check = captcha.submit(rcf, rrf, RECAPTCHA_PRIVATE_KEY, self.ip)
303 672d445a Sofia Papagiannaki
        if not check.is_valid:
304 672d445a Sofia Papagiannaki
            raise forms.ValidationError(_('You have not entered the correct words'))
305 64cd4730 Antony Chazapis
306 890b0eaf Sofia Papagiannaki
class ProfileForm(forms.ModelForm):
307 890b0eaf Sofia Papagiannaki
    """
308 890b0eaf Sofia Papagiannaki
    Subclass of ``ModelForm`` for permiting user to edit his/her profile.
309 890b0eaf Sofia Papagiannaki
    Most of the fields are readonly since the user is not allowed to change them.
310 18ffbee1 Sofia Papagiannaki

311 890b0eaf Sofia Papagiannaki
    The class defines a save method which sets ``is_verified`` to True so as the user
312 890b0eaf Sofia Papagiannaki
    during the next login will not to be redirected to profile page.
313 890b0eaf Sofia Papagiannaki
    """
314 c301698f Sofia Papagiannaki
    renew = forms.BooleanField(label='Renew token', required=False)
315 18ffbee1 Sofia Papagiannaki
316 890b0eaf Sofia Papagiannaki
    class Meta:
317 890b0eaf Sofia Papagiannaki
        model = AstakosUser
318 0a569195 Sofia Papagiannaki
        fields = ('email', 'first_name', 'last_name', 'auth_token', 'auth_token_expires')
319 18ffbee1 Sofia Papagiannaki
320 64cd4730 Antony Chazapis
    def __init__(self, *args, **kwargs):
321 890b0eaf Sofia Papagiannaki
        super(ProfileForm, self).__init__(*args, **kwargs)
322 890b0eaf Sofia Papagiannaki
        instance = getattr(self, 'instance', None)
323 0a569195 Sofia Papagiannaki
        ro_fields = ('email', 'auth_token', 'auth_token_expires')
324 890b0eaf Sofia Papagiannaki
        if instance and instance.id:
325 890b0eaf Sofia Papagiannaki
            for field in ro_fields:
326 890b0eaf Sofia Papagiannaki
                self.fields[field].widget.attrs['readonly'] = True
327 18ffbee1 Sofia Papagiannaki
328 890b0eaf Sofia Papagiannaki
    def save(self, commit=True):
329 890b0eaf Sofia Papagiannaki
        user = super(ProfileForm, self).save(commit=False)
330 890b0eaf Sofia Papagiannaki
        user.is_verified = True
331 c301698f Sofia Papagiannaki
        if self.cleaned_data.get('renew'):
332 c301698f Sofia Papagiannaki
            user.renew_token()
333 890b0eaf Sofia Papagiannaki
        if commit:
334 890b0eaf Sofia Papagiannaki
            user.save()
335 890b0eaf Sofia Papagiannaki
        return user
336 64cd4730 Antony Chazapis
337 890b0eaf Sofia Papagiannaki
class FeedbackForm(forms.Form):
338 890b0eaf Sofia Papagiannaki
    """
339 890b0eaf Sofia Papagiannaki
    Form for writing feedback.
340 890b0eaf Sofia Papagiannaki
    """
341 0a569195 Sofia Papagiannaki
    feedback_msg = forms.CharField(widget=forms.Textarea, label=u'Message')
342 8f5a3a06 Sofia Papagiannaki
    feedback_data = forms.CharField(widget=forms.HiddenInput(), label='',
343 8f5a3a06 Sofia Papagiannaki
                                    required=False)
344 5ed6816e Sofia Papagiannaki
345 5ed6816e Sofia Papagiannaki
class SendInvitationForm(forms.Form):
346 5ed6816e Sofia Papagiannaki
    """
347 5ed6816e Sofia Papagiannaki
    Form for sending an invitations
348 5ed6816e Sofia Papagiannaki
    """
349 18ffbee1 Sofia Papagiannaki
350 5ed6816e Sofia Papagiannaki
    email = forms.EmailField(required = True, label = 'Email address')
351 5ed6816e Sofia Papagiannaki
    first_name = forms.EmailField(label = 'First name')
352 5ed6816e Sofia Papagiannaki
    last_name = forms.EmailField(label = 'Last name')
353 e2125441 Sofia Papagiannaki
354 e2125441 Sofia Papagiannaki
class ExtendedPasswordResetForm(PasswordResetForm):
355 e2125441 Sofia Papagiannaki
    """
356 e2125441 Sofia Papagiannaki
    Extends PasswordResetForm by overriding save method:
357 e2125441 Sofia Papagiannaki
    passes a custom from_email in send_mail.
358 18ffbee1 Sofia Papagiannaki

359 e2125441 Sofia Papagiannaki
    Since Django 1.3 this is useless since ``django.contrib.auth.views.reset_password``
360 e2125441 Sofia Papagiannaki
    accepts a from_email argument.
361 e2125441 Sofia Papagiannaki
    """
362 23c271b3 Sofia Papagiannaki
    def clean_email(self):
363 23c271b3 Sofia Papagiannaki
        email = super(ExtendedPasswordResetForm, self).clean_email()
364 23c271b3 Sofia Papagiannaki
        try:
365 0a569195 Sofia Papagiannaki
            user = AstakosUser.objects.get(email=email, is_active=True)
366 23c271b3 Sofia Papagiannaki
            if not user.has_usable_password():
367 23c271b3 Sofia Papagiannaki
                raise forms.ValidationError(_("This account has not a usable password."))
368 23c271b3 Sofia Papagiannaki
        except AstakosUser.DoesNotExist, e:
369 23c271b3 Sofia Papagiannaki
            raise forms.ValidationError(_('That e-mail address doesn\'t have an associated user account. Are you sure you\'ve registered?'))
370 23c271b3 Sofia Papagiannaki
        return email
371 23c271b3 Sofia Papagiannaki
    
372 e2125441 Sofia Papagiannaki
    def save(self, domain_override=None, email_template_name='registration/password_reset_email.html',
373 e2125441 Sofia Papagiannaki
             use_https=False, token_generator=default_token_generator, request=None):
374 e2125441 Sofia Papagiannaki
        """
375 e2125441 Sofia Papagiannaki
        Generates a one-use only link for resetting password and sends to the user.
376 e2125441 Sofia Papagiannaki
        """
377 e2125441 Sofia Papagiannaki
        for user in self.users_cache:
378 18ffbee1 Sofia Papagiannaki
            url = reverse('django.contrib.auth.views.password_reset_confirm',
379 18ffbee1 Sofia Papagiannaki
                          kwargs={'uidb36':int_to_base36(user.id),
380 18ffbee1 Sofia Papagiannaki
                                  'token':token_generator.make_token(user)})
381 a53b19da Sofia Papagiannaki
            url = urljoin(BASEURL, url)
382 e2125441 Sofia Papagiannaki
            t = loader.get_template(email_template_name)
383 e2125441 Sofia Papagiannaki
            c = {
384 e2125441 Sofia Papagiannaki
                'email': user.email,
385 8f378756 Sofia Papagiannaki
                'url': url,
386 374611bc Sofia Papagiannaki
                'site_name': SITENAME,
387 e2125441 Sofia Papagiannaki
                'user': user,
388 a53b19da Sofia Papagiannaki
                'baseurl': BASEURL,
389 09122dd8 Sofia Papagiannaki
                'support': DEFAULT_CONTACT_EMAIL
390 e2125441 Sofia Papagiannaki
            }
391 d552ecb7 Antony Chazapis
            from_email = DEFAULT_FROM_EMAIL
392 4abc7b29 Sofia Papagiannaki
            send_mail(_("Password reset on %s alpha2 testing") % SITENAME,
393 e2125441 Sofia Papagiannaki
                t.render(Context(c)), from_email, [user.email])
394 270dd48d Sofia Papagiannaki
395 270dd48d Sofia Papagiannaki
class SignApprovalTermsForm(forms.ModelForm):
396 270dd48d Sofia Papagiannaki
    class Meta:
397 270dd48d Sofia Papagiannaki
        model = AstakosUser
398 270dd48d Sofia Papagiannaki
        fields = ("has_signed_terms",)
399 18ffbee1 Sofia Papagiannaki
400 270dd48d Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
401 270dd48d Sofia Papagiannaki
        super(SignApprovalTermsForm, self).__init__(*args, **kwargs)
402 18ffbee1 Sofia Papagiannaki
403 270dd48d Sofia Papagiannaki
    def clean_has_signed_terms(self):
404 270dd48d Sofia Papagiannaki
        has_signed_terms = self.cleaned_data['has_signed_terms']
405 270dd48d Sofia Papagiannaki
        if not has_signed_terms:
406 270dd48d Sofia Papagiannaki
            raise forms.ValidationError(_('You have to agree with the terms'))
407 270dd48d Sofia Papagiannaki
        return has_signed_terms
408 8f5a3a06 Sofia Papagiannaki
409 8f5a3a06 Sofia Papagiannaki
class InvitationForm(forms.ModelForm):
410 8f5a3a06 Sofia Papagiannaki
    username = forms.EmailField(label=_("Email"))
411 8f5a3a06 Sofia Papagiannaki
    
412 18ffbee1 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
413 18ffbee1 Sofia Papagiannaki
        super(InvitationForm, self).__init__(*args, **kwargs)
414 18ffbee1 Sofia Papagiannaki
    
415 8f5a3a06 Sofia Papagiannaki
    class Meta:
416 8f5a3a06 Sofia Papagiannaki
        model = Invitation
417 8f5a3a06 Sofia Papagiannaki
        fields = ('username', 'realname')
418 8f5a3a06 Sofia Papagiannaki
    
419 8f5a3a06 Sofia Papagiannaki
    def clean_username(self):
420 8f5a3a06 Sofia Papagiannaki
        username = self.cleaned_data['username']
421 8f5a3a06 Sofia Papagiannaki
        try:
422 8f5a3a06 Sofia Papagiannaki
            Invitation.objects.get(username = username)
423 8f5a3a06 Sofia Papagiannaki
            raise forms.ValidationError(_('There is already invitation for this email.'))
424 8f5a3a06 Sofia Papagiannaki
        except Invitation.DoesNotExist:
425 8f5a3a06 Sofia Papagiannaki
            pass
426 18ffbee1 Sofia Papagiannaki
        return username