Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / forms.py @ 672d445a

History | View | Annotate | Download (17.8 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 5ed6816e Sofia Papagiannaki
47 8f5a3a06 Sofia Papagiannaki
from astakos.im.models import AstakosUser, Invitation
48 4e30244e Sofia Papagiannaki
from astakos.im.settings import INVITATIONS_PER_LEVEL, DEFAULT_FROM_EMAIL, SITENAME, RECAPTCHA_PRIVATE_KEY, DEFAULT_CONTACT_EMAIL, RECAPTCHA_ENABLED
49 270dd48d Sofia Papagiannaki
from astakos.im.widgets import DummyWidget, RecaptchaWidget, ApprovalTermsWidget
50 270dd48d Sofia Papagiannaki
51 270dd48d Sofia Papagiannaki
# since Django 1.4 use django.core.urlresolvers.reverse_lazy instead
52 d8f63346 Sofia Papagiannaki
from astakos.im.util import reverse_lazy, get_latest_terms
53 64cd4730 Antony Chazapis
54 3bf924ec Sofia Papagiannaki
import logging
55 db7fecd9 Sofia Papagiannaki
import recaptcha.client.captcha as captcha
56 64cd4730 Antony Chazapis
57 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
58 e015e9e6 Sofia Papagiannaki
59 15efc749 Sofia Papagiannaki
class LocalUserCreationForm(UserCreationForm):
60 890b0eaf Sofia Papagiannaki
    """
61 890b0eaf Sofia Papagiannaki
    Extends the built in UserCreationForm in several ways:
62 18ffbee1 Sofia Papagiannaki

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

331 890b0eaf Sofia Papagiannaki
    The class defines a save method which sets ``is_verified`` to True so as the user
332 890b0eaf Sofia Papagiannaki
    during the next login will not to be redirected to profile page.
333 890b0eaf Sofia Papagiannaki
    """
334 c301698f Sofia Papagiannaki
    renew = forms.BooleanField(label='Renew token', required=False)
335 18ffbee1 Sofia Papagiannaki
336 890b0eaf Sofia Papagiannaki
    class Meta:
337 890b0eaf Sofia Papagiannaki
        model = AstakosUser
338 18ffbee1 Sofia Papagiannaki
        fields = ('email', 'first_name', 'last_name', 'auth_token', 'auth_token_expires', 'groups')
339 18ffbee1 Sofia Papagiannaki
340 64cd4730 Antony Chazapis
    def __init__(self, *args, **kwargs):
341 890b0eaf Sofia Papagiannaki
        super(ProfileForm, self).__init__(*args, **kwargs)
342 890b0eaf Sofia Papagiannaki
        instance = getattr(self, 'instance', None)
343 18ffbee1 Sofia Papagiannaki
        ro_fields = ('auth_token', 'auth_token_expires', 'groups')
344 890b0eaf Sofia Papagiannaki
        if instance and instance.id:
345 890b0eaf Sofia Papagiannaki
            for field in ro_fields:
346 890b0eaf Sofia Papagiannaki
                self.fields[field].widget.attrs['readonly'] = True
347 18ffbee1 Sofia Papagiannaki
348 890b0eaf Sofia Papagiannaki
    def save(self, commit=True):
349 890b0eaf Sofia Papagiannaki
        user = super(ProfileForm, self).save(commit=False)
350 890b0eaf Sofia Papagiannaki
        user.is_verified = True
351 c301698f Sofia Papagiannaki
        if self.cleaned_data.get('renew'):
352 c301698f Sofia Papagiannaki
            user.renew_token()
353 890b0eaf Sofia Papagiannaki
        if commit:
354 890b0eaf Sofia Papagiannaki
            user.save()
355 890b0eaf Sofia Papagiannaki
        return user
356 64cd4730 Antony Chazapis
357 890b0eaf Sofia Papagiannaki
class FeedbackForm(forms.Form):
358 890b0eaf Sofia Papagiannaki
    """
359 890b0eaf Sofia Papagiannaki
    Form for writing feedback.
360 890b0eaf Sofia Papagiannaki
    """
361 8f5a3a06 Sofia Papagiannaki
    feedback_msg = forms.CharField(widget=forms.TextInput(), label=u'Message')
362 8f5a3a06 Sofia Papagiannaki
    feedback_data = forms.CharField(widget=forms.HiddenInput(), label='',
363 8f5a3a06 Sofia Papagiannaki
                                    required=False)
364 5ed6816e Sofia Papagiannaki
365 5ed6816e Sofia Papagiannaki
class SendInvitationForm(forms.Form):
366 5ed6816e Sofia Papagiannaki
    """
367 5ed6816e Sofia Papagiannaki
    Form for sending an invitations
368 5ed6816e Sofia Papagiannaki
    """
369 18ffbee1 Sofia Papagiannaki
370 5ed6816e Sofia Papagiannaki
    email = forms.EmailField(required = True, label = 'Email address')
371 5ed6816e Sofia Papagiannaki
    first_name = forms.EmailField(label = 'First name')
372 5ed6816e Sofia Papagiannaki
    last_name = forms.EmailField(label = 'Last name')
373 e2125441 Sofia Papagiannaki
374 e2125441 Sofia Papagiannaki
class ExtendedPasswordResetForm(PasswordResetForm):
375 e2125441 Sofia Papagiannaki
    """
376 e2125441 Sofia Papagiannaki
    Extends PasswordResetForm by overriding save method:
377 e2125441 Sofia Papagiannaki
    passes a custom from_email in send_mail.
378 18ffbee1 Sofia Papagiannaki

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