Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / forms.py @ 213ba781

History | View | Annotate | Download (28.4 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 caf70869 Sofia Papagiannaki
from random import random
35 64cd4730 Antony Chazapis
36 64cd4730 Antony Chazapis
from django import forms
37 64cd4730 Antony Chazapis
from django.utils.translation import ugettext as _
38 e1a80257 Sofia Papagiannaki
from django.contrib.auth.forms import (
39 e1a80257 Sofia Papagiannaki
    UserCreationForm, AuthenticationForm,
40 e1a80257 Sofia Papagiannaki
    PasswordResetForm, PasswordChangeForm,
41 73fbaec4 Sofia Papagiannaki
    SetPasswordForm)
42 e2125441 Sofia Papagiannaki
from django.core.mail import send_mail
43 e2125441 Sofia Papagiannaki
from django.contrib.auth.tokens import default_token_generator
44 e2125441 Sofia Papagiannaki
from django.template import Context, loader
45 e2125441 Sofia Papagiannaki
from django.utils.http import int_to_base36
46 374611bc Sofia Papagiannaki
from django.core.urlresolvers import reverse
47 18ffbee1 Sofia Papagiannaki
from django.utils.safestring import mark_safe
48 49790d9d Sofia Papagiannaki
from django.utils.encoding import smart_str
49 1cbce16f Sofia Papagiannaki
from django.conf import settings
50 678b2236 Sofia Papagiannaki
from django.forms.models import fields_for_model
51 d2633501 Kostas Papadimitriou
from django.db import transaction
52 caf70869 Sofia Papagiannaki
from django.utils.encoding import smart_unicode
53 caf70869 Sofia Papagiannaki
from django.core import validators
54 e1a80257 Sofia Papagiannaki
from django.contrib.auth.models import AnonymousUser
55 5ed6816e Sofia Papagiannaki
56 678b2236 Sofia Papagiannaki
from astakos.im.models import (
57 73fbaec4 Sofia Papagiannaki
    AstakosUser, EmailChange, Invitation,
58 e1a80257 Sofia Papagiannaki
    Resource, PendingThirdPartyUser, get_latest_terms, RESOURCE_SEPARATOR,
59 213ba781 Sofia Papagiannaki
    ProjectApplication, MemberJoinPolicy, MemberLeavePolicy)
60 c0b26605 Sofia Papagiannaki
from astakos.im.settings import (
61 c0b26605 Sofia Papagiannaki
    INVITATIONS_PER_LEVEL, BASEURL, SITENAME, RECAPTCHA_PRIVATE_KEY,
62 c0b26605 Sofia Papagiannaki
    RECAPTCHA_ENABLED, DEFAULT_CONTACT_EMAIL, LOGGING_LEVEL,
63 2e90e3ec Kostas Papadimitriou
    PASSWORD_RESET_EMAIL_SUBJECT, NEWPASSWD_INVALIDATE_TOKEN,
64 73fbaec4 Sofia Papagiannaki
    MODERATION_ENABLED)
65 45f8d9ff Sofia Papagiannaki
from astakos.im.widgets import DummyWidget, RecaptchaWidget
66 73fbaec4 Sofia Papagiannaki
from astakos.im.functions import send_change_email, submit_application
67 270dd48d Sofia Papagiannaki
68 6556e514 Sofia Papagiannaki
from astakos.im.util import reserved_email, get_query, model_to_dict
69 c4b1a172 Kostas Papadimitriou
from astakos.im import auth_providers
70 64cd4730 Antony Chazapis
71 ae497612 Olga Brani
import astakos.im.messages as astakos_messages
72 64cd4730 Antony Chazapis
73 3bf924ec Sofia Papagiannaki
import logging
74 49790d9d Sofia Papagiannaki
import hashlib
75 db7fecd9 Sofia Papagiannaki
import recaptcha.client.captcha as captcha
76 caf70869 Sofia Papagiannaki
import re
77 64cd4730 Antony Chazapis
78 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
79 e015e9e6 Sofia Papagiannaki
80 caf70869 Sofia Papagiannaki
DOMAIN_VALUE_REGEX = re.compile(
81 892410d3 Sofia Papagiannaki
    r'^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$',
82 73fbaec4 Sofia Papagiannaki
    re.IGNORECASE)
83 d2633501 Kostas Papadimitriou
84 caf70869 Sofia Papagiannaki
class StoreUserMixin(object):
85 e5966bd9 Kostas Papadimitriou
86 d2633501 Kostas Papadimitriou
    @transaction.commit_on_success
87 d2633501 Kostas Papadimitriou
    def store_user(self, user, request):
88 d2633501 Kostas Papadimitriou
        user.save()
89 d2633501 Kostas Papadimitriou
        self.post_store_user(user, request)
90 d2633501 Kostas Papadimitriou
        return user
91 d2633501 Kostas Papadimitriou
92 d2633501 Kostas Papadimitriou
    def post_store_user(self, user, request):
93 d2633501 Kostas Papadimitriou
        """
94 d2633501 Kostas Papadimitriou
        Interface method for descendant backends to be able to do stuff within
95 d2633501 Kostas Papadimitriou
        the transaction enabled by store_user.
96 d2633501 Kostas Papadimitriou
        """
97 d2633501 Kostas Papadimitriou
        pass
98 d2633501 Kostas Papadimitriou
99 d2633501 Kostas Papadimitriou
100 d2633501 Kostas Papadimitriou
class LocalUserCreationForm(UserCreationForm, StoreUserMixin):
101 890b0eaf Sofia Papagiannaki
    """
102 890b0eaf Sofia Papagiannaki
    Extends the built in UserCreationForm in several ways:
103 18ffbee1 Sofia Papagiannaki

104 8316698a Sofia Papagiannaki
    * Adds email, first_name, last_name, recaptcha_challenge_field, recaptcha_response_field field.
105 5ed6816e Sofia Papagiannaki
    * The username field isn't visible and it is assigned a generated id.
106 18ffbee1 Sofia Papagiannaki
    * User created is not active.
107 890b0eaf Sofia Papagiannaki
    """
108 db7fecd9 Sofia Papagiannaki
    recaptcha_challenge_field = forms.CharField(widget=DummyWidget)
109 5ce3ce4f Sofia Papagiannaki
    recaptcha_response_field = forms.CharField(
110 5ce3ce4f Sofia Papagiannaki
        widget=RecaptchaWidget, label='')
111 18ffbee1 Sofia Papagiannaki
112 794852f2 Sofia Papagiannaki
    class Meta:
113 794852f2 Sofia Papagiannaki
        model = AstakosUser
114 5ce3ce4f Sofia Papagiannaki
        fields = ("email", "first_name", "last_name",
115 5ce3ce4f Sofia Papagiannaki
                  "has_signed_terms", "has_signed_terms")
116 18ffbee1 Sofia Papagiannaki
117 64cd4730 Antony Chazapis
    def __init__(self, *args, **kwargs):
118 64cd4730 Antony Chazapis
        """
119 890b0eaf Sofia Papagiannaki
        Changes the order of fields, and removes the username field.
120 64cd4730 Antony Chazapis
        """
121 bf0c6de5 Sofia Papagiannaki
        request = kwargs.pop('request', None)
122 672d445a Sofia Papagiannaki
        if request:
123 672d445a Sofia Papagiannaki
            self.ip = request.META.get('REMOTE_ADDR',
124 672d445a Sofia Papagiannaki
                                       request.META.get('HTTP_X_REAL_IP', None))
125 ab8bfb29 Kostas Papadimitriou
126 15efc749 Sofia Papagiannaki
        super(LocalUserCreationForm, self).__init__(*args, **kwargs)
127 890b0eaf Sofia Papagiannaki
        self.fields.keyOrder = ['email', 'first_name', 'last_name',
128 d8f63346 Sofia Papagiannaki
                                'password1', 'password2']
129 1b3398a0 Olga Brani
130 53bf2659 Sofia Papagiannaki
        if RECAPTCHA_ENABLED:
131 53bf2659 Sofia Papagiannaki
            self.fields.keyOrder.extend(['recaptcha_challenge_field',
132 5ce3ce4f Sofia Papagiannaki
                                         'recaptcha_response_field', ])
133 1b3398a0 Olga Brani
        if get_latest_terms():
134 1b3398a0 Olga Brani
            self.fields.keyOrder.append('has_signed_terms')
135 18ffbee1 Sofia Papagiannaki
136 18ffbee1 Sofia Papagiannaki
        if 'has_signed_terms' in self.fields:
137 18ffbee1 Sofia Papagiannaki
            # Overriding field label since we need to apply a link
138 18ffbee1 Sofia Papagiannaki
            # to the terms within the label
139 18ffbee1 Sofia Papagiannaki
            terms_link_html = '<a href="%s" target="_blank">%s</a>' \
140 5ce3ce4f Sofia Papagiannaki
                % (reverse('latest_terms'), _("the terms"))
141 18ffbee1 Sofia Papagiannaki
            self.fields['has_signed_terms'].label = \
142 5ce3ce4f Sofia Papagiannaki
                mark_safe("I agree with %s" % terms_link_html)
143 18ffbee1 Sofia Papagiannaki
144 af4eb974 Sofia Papagiannaki
    def clean_email(self):
145 e5966bd9 Kostas Papadimitriou
        email = self.cleaned_data['email']
146 881c856c Sofia Papagiannaki
        if not email:
147 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.REQUIRED_FIELD))
148 0a569195 Sofia Papagiannaki
        if reserved_email(email):
149 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.EMAIL_USED))
150 0a569195 Sofia Papagiannaki
        return email
151 18ffbee1 Sofia Papagiannaki
152 270dd48d Sofia Papagiannaki
    def clean_has_signed_terms(self):
153 270dd48d Sofia Papagiannaki
        has_signed_terms = self.cleaned_data['has_signed_terms']
154 270dd48d Sofia Papagiannaki
        if not has_signed_terms:
155 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.SIGN_TERMS))
156 270dd48d Sofia Papagiannaki
        return has_signed_terms
157 18ffbee1 Sofia Papagiannaki
158 db7fecd9 Sofia Papagiannaki
    def clean_recaptcha_response_field(self):
159 db7fecd9 Sofia Papagiannaki
        if 'recaptcha_challenge_field' in self.cleaned_data:
160 db7fecd9 Sofia Papagiannaki
            self.validate_captcha()
161 db7fecd9 Sofia Papagiannaki
        return self.cleaned_data['recaptcha_response_field']
162 db7fecd9 Sofia Papagiannaki
163 db7fecd9 Sofia Papagiannaki
    def clean_recaptcha_challenge_field(self):
164 db7fecd9 Sofia Papagiannaki
        if 'recaptcha_response_field' in self.cleaned_data:
165 db7fecd9 Sofia Papagiannaki
            self.validate_captcha()
166 db7fecd9 Sofia Papagiannaki
        return self.cleaned_data['recaptcha_challenge_field']
167 db7fecd9 Sofia Papagiannaki
168 db7fecd9 Sofia Papagiannaki
    def validate_captcha(self):
169 db7fecd9 Sofia Papagiannaki
        rcf = self.cleaned_data['recaptcha_challenge_field']
170 db7fecd9 Sofia Papagiannaki
        rrf = self.cleaned_data['recaptcha_response_field']
171 db7fecd9 Sofia Papagiannaki
        check = captcha.submit(rcf, rrf, RECAPTCHA_PRIVATE_KEY, self.ip)
172 db7fecd9 Sofia Papagiannaki
        if not check.is_valid:
173 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.CAPTCHA_VALIDATION_ERR))
174 18ffbee1 Sofia Papagiannaki
175 d2633501 Kostas Papadimitriou
    def post_store_user(self, user, request):
176 d2633501 Kostas Papadimitriou
        """
177 d2633501 Kostas Papadimitriou
        Interface method for descendant backends to be able to do stuff within
178 d2633501 Kostas Papadimitriou
        the transaction enabled by store_user.
179 d2633501 Kostas Papadimitriou
        """
180 d2633501 Kostas Papadimitriou
        user.add_auth_provider('local', auth_backend='astakos')
181 d2633501 Kostas Papadimitriou
        user.set_password(self.cleaned_data['password1'])
182 d2633501 Kostas Papadimitriou
183 890b0eaf Sofia Papagiannaki
    def save(self, commit=True):
184 64cd4730 Antony Chazapis
        """
185 890b0eaf Sofia Papagiannaki
        Saves the email, first_name and last_name properties, after the normal
186 890b0eaf Sofia Papagiannaki
        save behavior is complete.
187 890b0eaf Sofia Papagiannaki
        """
188 15efc749 Sofia Papagiannaki
        user = super(LocalUserCreationForm, self).save(commit=False)
189 d2633501 Kostas Papadimitriou
        user.renew_token()
190 9fb8e808 Sofia Papagiannaki
        if commit:
191 9fb8e808 Sofia Papagiannaki
            user.save()
192 aab4d540 Sofia Papagiannaki
            logger.log(LOGGING_LEVEL, 'Created user %s' % user.email)
193 890b0eaf Sofia Papagiannaki
        return user
194 64cd4730 Antony Chazapis
195 5ce3ce4f Sofia Papagiannaki
196 15efc749 Sofia Papagiannaki
class InvitedLocalUserCreationForm(LocalUserCreationForm):
197 890b0eaf Sofia Papagiannaki
    """
198 062c970c Sofia Papagiannaki
    Extends the LocalUserCreationForm: email is readonly.
199 890b0eaf Sofia Papagiannaki
    """
200 794852f2 Sofia Papagiannaki
    class Meta:
201 794852f2 Sofia Papagiannaki
        model = AstakosUser
202 270dd48d Sofia Papagiannaki
        fields = ("email", "first_name", "last_name", "has_signed_terms")
203 18ffbee1 Sofia Papagiannaki
204 64cd4730 Antony Chazapis
    def __init__(self, *args, **kwargs):
205 64cd4730 Antony Chazapis
        """
206 3bf924ec Sofia Papagiannaki
        Changes the order of fields, and removes the username field.
207 64cd4730 Antony Chazapis
        """
208 15efc749 Sofia Papagiannaki
        super(InvitedLocalUserCreationForm, self).__init__(*args, **kwargs)
209 18ffbee1 Sofia Papagiannaki
210 64cd4730 Antony Chazapis
        #set readonly form fields
211 062c970c Sofia Papagiannaki
        ro = ('email', 'username',)
212 4e30244e Sofia Papagiannaki
        for f in ro:
213 4e30244e Sofia Papagiannaki
            self.fields[f].widget.attrs['readonly'] = True
214 ab8bfb29 Kostas Papadimitriou
215 9fb8e808 Sofia Papagiannaki
    def save(self, commit=True):
216 15efc749 Sofia Papagiannaki
        user = super(InvitedLocalUserCreationForm, self).save(commit=False)
217 74836e50 Sofia Papagiannaki
        user.set_invitations_level()
218 8316698a Sofia Papagiannaki
        user.email_verified = True
219 9fb8e808 Sofia Papagiannaki
        if commit:
220 9fb8e808 Sofia Papagiannaki
            user.save()
221 9fb8e808 Sofia Papagiannaki
        return user
222 5ed6816e Sofia Papagiannaki
223 d2633501 Kostas Papadimitriou
224 d2633501 Kostas Papadimitriou
class ThirdPartyUserCreationForm(forms.ModelForm, StoreUserMixin):
225 6c8a3f7c Sofia Papagiannaki
    id = forms.CharField(
226 6c8a3f7c Sofia Papagiannaki
        widget=forms.HiddenInput(),
227 6c8a3f7c Sofia Papagiannaki
        label='',
228 6c8a3f7c Sofia Papagiannaki
        required=False
229 6c8a3f7c Sofia Papagiannaki
    )
230 ef20ea07 Sofia Papagiannaki
    third_party_identifier = forms.CharField(
231 ef20ea07 Sofia Papagiannaki
        widget=forms.HiddenInput(),
232 ef20ea07 Sofia Papagiannaki
        label=''
233 ef20ea07 Sofia Papagiannaki
    )
234 8f5a3a06 Sofia Papagiannaki
    class Meta:
235 8f5a3a06 Sofia Papagiannaki
        model = AstakosUser
236 6c8a3f7c Sofia Papagiannaki
        fields = ['id', 'email', 'third_party_identifier', 'first_name', 'last_name']
237 ab8bfb29 Kostas Papadimitriou
238 8f5a3a06 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
239 8f5a3a06 Sofia Papagiannaki
        """
240 8f5a3a06 Sofia Papagiannaki
        Changes the order of fields, and removes the username field.
241 8f5a3a06 Sofia Papagiannaki
        """
242 0a569195 Sofia Papagiannaki
        self.request = kwargs.get('request', None)
243 0a569195 Sofia Papagiannaki
        if self.request:
244 0a569195 Sofia Papagiannaki
            kwargs.pop('request')
245 2e90e3ec Kostas Papadimitriou
246 ef20ea07 Sofia Papagiannaki
        latest_terms = get_latest_terms()
247 ef20ea07 Sofia Papagiannaki
        if latest_terms:
248 ef20ea07 Sofia Papagiannaki
            self._meta.fields.append('has_signed_terms')
249 2e90e3ec Kostas Papadimitriou
250 8f5a3a06 Sofia Papagiannaki
        super(ThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
251 2e90e3ec Kostas Papadimitriou
252 ef20ea07 Sofia Papagiannaki
        if latest_terms:
253 8f5a3a06 Sofia Papagiannaki
            self.fields.keyOrder.append('has_signed_terms')
254 2e90e3ec Kostas Papadimitriou
255 18ffbee1 Sofia Papagiannaki
        if 'has_signed_terms' in self.fields:
256 18ffbee1 Sofia Papagiannaki
            # Overriding field label since we need to apply a link
257 18ffbee1 Sofia Papagiannaki
            # to the terms within the label
258 18ffbee1 Sofia Papagiannaki
            terms_link_html = '<a href="%s" target="_blank">%s</a>' \
259 5ce3ce4f Sofia Papagiannaki
                % (reverse('latest_terms'), _("the terms"))
260 18ffbee1 Sofia Papagiannaki
            self.fields['has_signed_terms'].label = \
261 18ffbee1 Sofia Papagiannaki
                    mark_safe("I agree with %s" % terms_link_html)
262 2e90e3ec Kostas Papadimitriou
263 18ffbee1 Sofia Papagiannaki
    def clean_email(self):
264 e5966bd9 Kostas Papadimitriou
        email = self.cleaned_data['email']
265 18ffbee1 Sofia Papagiannaki
        if not email:
266 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.REQUIRED_FIELD))
267 c630fee6 Kostas Papadimitriou
        if reserved_email(email):
268 c630fee6 Kostas Papadimitriou
            raise forms.ValidationError(_(astakos_messages.EMAIL_USED))
269 0a569195 Sofia Papagiannaki
        return email
270 ab8bfb29 Kostas Papadimitriou
271 18ffbee1 Sofia Papagiannaki
    def clean_has_signed_terms(self):
272 18ffbee1 Sofia Papagiannaki
        has_signed_terms = self.cleaned_data['has_signed_terms']
273 18ffbee1 Sofia Papagiannaki
        if not has_signed_terms:
274 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.SIGN_TERMS))
275 18ffbee1 Sofia Papagiannaki
        return has_signed_terms
276 ab8bfb29 Kostas Papadimitriou
277 d2633501 Kostas Papadimitriou
    def post_store_user(self, user, request):
278 d2633501 Kostas Papadimitriou
        pending = PendingThirdPartyUser.objects.get(
279 d2633501 Kostas Papadimitriou
                                token=request.POST.get('third_party_token'),
280 d2633501 Kostas Papadimitriou
                                third_party_identifier= \
281 d2633501 Kostas Papadimitriou
            self.cleaned_data.get('third_party_identifier'))
282 d2633501 Kostas Papadimitriou
        return user.add_pending_auth_provider(pending)
283 d2633501 Kostas Papadimitriou
284 d2633501 Kostas Papadimitriou
285 8f5a3a06 Sofia Papagiannaki
    def save(self, commit=True):
286 8f5a3a06 Sofia Papagiannaki
        user = super(ThirdPartyUserCreationForm, self).save(commit=False)
287 8f5a3a06 Sofia Papagiannaki
        user.set_unusable_password()
288 d2633501 Kostas Papadimitriou
        user.renew_token()
289 8f5a3a06 Sofia Papagiannaki
        if commit:
290 8f5a3a06 Sofia Papagiannaki
            user.save()
291 aab4d540 Sofia Papagiannaki
            logger.log(LOGGING_LEVEL, 'Created user %s' % user.email)
292 8f5a3a06 Sofia Papagiannaki
        return user
293 8f5a3a06 Sofia Papagiannaki
294 5ce3ce4f Sofia Papagiannaki
295 8f5a3a06 Sofia Papagiannaki
class InvitedThirdPartyUserCreationForm(ThirdPartyUserCreationForm):
296 4e30244e Sofia Papagiannaki
    """
297 062c970c Sofia Papagiannaki
    Extends the ThirdPartyUserCreationForm: email is readonly.
298 4e30244e Sofia Papagiannaki
    """
299 8f5a3a06 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
300 4e30244e Sofia Papagiannaki
        """
301 4e30244e Sofia Papagiannaki
        Changes the order of fields, and removes the username field.
302 4e30244e Sofia Papagiannaki
        """
303 5ce3ce4f Sofia Papagiannaki
        super(
304 5ce3ce4f Sofia Papagiannaki
            InvitedThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
305 4e30244e Sofia Papagiannaki
306 8f5a3a06 Sofia Papagiannaki
        #set readonly form fields
307 062c970c Sofia Papagiannaki
        ro = ('email',)
308 4e30244e Sofia Papagiannaki
        for f in ro:
309 4e30244e Sofia Papagiannaki
            self.fields[f].widget.attrs['readonly'] = True
310 ab8bfb29 Kostas Papadimitriou
311 4e30244e Sofia Papagiannaki
    def save(self, commit=True):
312 4e30244e Sofia Papagiannaki
        user = super(InvitedThirdPartyUserCreationForm, self).save(commit=False)
313 d2633501 Kostas Papadimitriou
        user.set_invitation_level()
314 4e30244e Sofia Papagiannaki
        user.email_verified = True
315 4e30244e Sofia Papagiannaki
        if commit:
316 4e30244e Sofia Papagiannaki
            user.save()
317 4e30244e Sofia Papagiannaki
        return user
318 8f5a3a06 Sofia Papagiannaki
319 5ce3ce4f Sofia Papagiannaki
320 18ffbee1 Sofia Papagiannaki
class ShibbolethUserCreationForm(ThirdPartyUserCreationForm):
321 5ce3ce4f Sofia Papagiannaki
    additional_email = forms.CharField(
322 5ce3ce4f Sofia Papagiannaki
        widget=forms.HiddenInput(), label='', required=False)
323 ab8bfb29 Kostas Papadimitriou
324 ca828a10 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
325 ca828a10 Sofia Papagiannaki
        super(ShibbolethUserCreationForm, self).__init__(*args, **kwargs)
326 ca828a10 Sofia Papagiannaki
        # copy email value to additional_mail in case user will change it
327 ca828a10 Sofia Papagiannaki
        name = 'email'
328 ca828a10 Sofia Papagiannaki
        field = self.fields[name]
329 ca828a10 Sofia Papagiannaki
        self.initial['additional_email'] = self.initial.get(name, field.initial)
330 ef20ea07 Sofia Papagiannaki
        self.initial['email'] = None
331 d2633501 Kostas Papadimitriou
332 4e30244e Sofia Papagiannaki
333 9a06d96f Olga Brani
class InvitedShibbolethUserCreationForm(ShibbolethUserCreationForm,
334 9a06d96f Olga Brani
                                        InvitedThirdPartyUserCreationForm):
335 4e30244e Sofia Papagiannaki
    pass
336 ab8bfb29 Kostas Papadimitriou
337 5ce3ce4f Sofia Papagiannaki
338 5ed6816e Sofia Papagiannaki
class LoginForm(AuthenticationForm):
339 5ed6816e Sofia Papagiannaki
    username = forms.EmailField(label=_("Email"))
340 672d445a Sofia Papagiannaki
    recaptcha_challenge_field = forms.CharField(widget=DummyWidget)
341 5ce3ce4f Sofia Papagiannaki
    recaptcha_response_field = forms.CharField(
342 5ce3ce4f Sofia Papagiannaki
        widget=RecaptchaWidget, label='')
343 ab8bfb29 Kostas Papadimitriou
344 672d445a Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
345 672d445a Sofia Papagiannaki
        was_limited = kwargs.get('was_limited', False)
346 672d445a Sofia Papagiannaki
        request = kwargs.get('request', None)
347 672d445a Sofia Papagiannaki
        if request:
348 672d445a Sofia Papagiannaki
            self.ip = request.META.get('REMOTE_ADDR',
349 672d445a Sofia Papagiannaki
                                       request.META.get('HTTP_X_REAL_IP', None))
350 ab8bfb29 Kostas Papadimitriou
351 672d445a Sofia Papagiannaki
        t = ('request', 'was_limited')
352 672d445a Sofia Papagiannaki
        for elem in t:
353 672d445a Sofia Papagiannaki
            if elem in kwargs.keys():
354 672d445a Sofia Papagiannaki
                kwargs.pop(elem)
355 672d445a Sofia Papagiannaki
        super(LoginForm, self).__init__(*args, **kwargs)
356 ab8bfb29 Kostas Papadimitriou
357 672d445a Sofia Papagiannaki
        self.fields.keyOrder = ['username', 'password']
358 672d445a Sofia Papagiannaki
        if was_limited and RECAPTCHA_ENABLED:
359 672d445a Sofia Papagiannaki
            self.fields.keyOrder.extend(['recaptcha_challenge_field',
360 5ce3ce4f Sofia Papagiannaki
                                         'recaptcha_response_field', ])
361 9a06d96f Olga Brani
362 9a06d96f Olga Brani
    def clean_username(self):
363 4bdd7e3d Kostas Papadimitriou
        return self.cleaned_data['username'].lower()
364 ab8bfb29 Kostas Papadimitriou
365 672d445a Sofia Papagiannaki
    def clean_recaptcha_response_field(self):
366 672d445a Sofia Papagiannaki
        if 'recaptcha_challenge_field' in self.cleaned_data:
367 672d445a Sofia Papagiannaki
            self.validate_captcha()
368 672d445a Sofia Papagiannaki
        return self.cleaned_data['recaptcha_response_field']
369 672d445a Sofia Papagiannaki
370 672d445a Sofia Papagiannaki
    def clean_recaptcha_challenge_field(self):
371 672d445a Sofia Papagiannaki
        if 'recaptcha_response_field' in self.cleaned_data:
372 672d445a Sofia Papagiannaki
            self.validate_captcha()
373 672d445a Sofia Papagiannaki
        return self.cleaned_data['recaptcha_challenge_field']
374 672d445a Sofia Papagiannaki
375 672d445a Sofia Papagiannaki
    def validate_captcha(self):
376 672d445a Sofia Papagiannaki
        rcf = self.cleaned_data['recaptcha_challenge_field']
377 672d445a Sofia Papagiannaki
        rrf = self.cleaned_data['recaptcha_response_field']
378 672d445a Sofia Papagiannaki
        check = captcha.submit(rcf, rrf, RECAPTCHA_PRIVATE_KEY, self.ip)
379 672d445a Sofia Papagiannaki
        if not check.is_valid:
380 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.CAPTCHA_VALIDATION_ERR))
381 2e90e3ec Kostas Papadimitriou
382 eedb3923 Sofia Papagiannaki
    def clean(self):
383 1f3b4b39 Sofia Papagiannaki
        """
384 1f3b4b39 Sofia Papagiannaki
        Override default behavior in order to check user's activation later
385 1f3b4b39 Sofia Papagiannaki
        """
386 c4b1a172 Kostas Papadimitriou
        username = self.cleaned_data.get('username')
387 c4b1a172 Kostas Papadimitriou
388 bea8a810 Kostas Papadimitriou
        if username:
389 bea8a810 Kostas Papadimitriou
            try:
390 bea8a810 Kostas Papadimitriou
                user = AstakosUser.objects.get_by_identifier(username)
391 bea8a810 Kostas Papadimitriou
                if not user.has_auth_provider('local'):
392 bea8a810 Kostas Papadimitriou
                    provider = auth_providers.get_provider('local')
393 bea8a810 Kostas Papadimitriou
                    raise forms.ValidationError(
394 bea8a810 Kostas Papadimitriou
                        _(provider.get_message('NOT_ACTIVE_FOR_USER')))
395 bea8a810 Kostas Papadimitriou
            except AstakosUser.DoesNotExist:
396 bea8a810 Kostas Papadimitriou
                pass
397 c4b1a172 Kostas Papadimitriou
398 1f3b4b39 Sofia Papagiannaki
        try:
399 1f3b4b39 Sofia Papagiannaki
            super(LoginForm, self).clean()
400 1f3b4b39 Sofia Papagiannaki
        except forms.ValidationError, e:
401 c4b1a172 Kostas Papadimitriou
            if self.user_cache is None:
402 c4b1a172 Kostas Papadimitriou
                raise
403 c4b1a172 Kostas Papadimitriou
            if not self.user_cache.is_active:
404 c4b1a172 Kostas Papadimitriou
                raise forms.ValidationError(self.user_cache.get_inactive_message())
405 1f3b4b39 Sofia Papagiannaki
            if self.request:
406 1f3b4b39 Sofia Papagiannaki
                if not self.request.session.test_cookie_worked():
407 1f3b4b39 Sofia Papagiannaki
                    raise
408 eedb3923 Sofia Papagiannaki
        return self.cleaned_data
409 64cd4730 Antony Chazapis
410 5ce3ce4f Sofia Papagiannaki
411 890b0eaf Sofia Papagiannaki
class ProfileForm(forms.ModelForm):
412 890b0eaf Sofia Papagiannaki
    """
413 890b0eaf Sofia Papagiannaki
    Subclass of ``ModelForm`` for permiting user to edit his/her profile.
414 9a06d96f Olga Brani
    Most of the fields are readonly since the user is not allowed to change
415 9a06d96f Olga Brani
    them.
416 18ffbee1 Sofia Papagiannaki

417 9a06d96f Olga Brani
    The class defines a save method which sets ``is_verified`` to True so as the
418 9a06d96f Olga Brani
    user during the next login will not to be redirected to profile page.
419 890b0eaf Sofia Papagiannaki
    """
420 c301698f Sofia Papagiannaki
    renew = forms.BooleanField(label='Renew token', required=False)
421 18ffbee1 Sofia Papagiannaki
422 890b0eaf Sofia Papagiannaki
    class Meta:
423 890b0eaf Sofia Papagiannaki
        model = AstakosUser
424 5ce3ce4f Sofia Papagiannaki
        fields = ('email', 'first_name', 'last_name', 'auth_token',
425 5ce3ce4f Sofia Papagiannaki
                  'auth_token_expires')
426 18ffbee1 Sofia Papagiannaki
427 64cd4730 Antony Chazapis
    def __init__(self, *args, **kwargs):
428 bf0c6de5 Sofia Papagiannaki
        self.session_key = kwargs.pop('session_key', None)
429 890b0eaf Sofia Papagiannaki
        super(ProfileForm, self).__init__(*args, **kwargs)
430 890b0eaf Sofia Papagiannaki
        instance = getattr(self, 'instance', None)
431 0a569195 Sofia Papagiannaki
        ro_fields = ('email', 'auth_token', 'auth_token_expires')
432 890b0eaf Sofia Papagiannaki
        if instance and instance.id:
433 890b0eaf Sofia Papagiannaki
            for field in ro_fields:
434 890b0eaf Sofia Papagiannaki
                self.fields[field].widget.attrs['readonly'] = True
435 18ffbee1 Sofia Papagiannaki
436 890b0eaf Sofia Papagiannaki
    def save(self, commit=True):
437 890b0eaf Sofia Papagiannaki
        user = super(ProfileForm, self).save(commit=False)
438 890b0eaf Sofia Papagiannaki
        user.is_verified = True
439 c301698f Sofia Papagiannaki
        if self.cleaned_data.get('renew'):
440 bf0c6de5 Sofia Papagiannaki
            user.renew_token(
441 bf0c6de5 Sofia Papagiannaki
                flush_sessions=True,
442 bf0c6de5 Sofia Papagiannaki
                current_key=self.session_key
443 bf0c6de5 Sofia Papagiannaki
            )
444 890b0eaf Sofia Papagiannaki
        if commit:
445 890b0eaf Sofia Papagiannaki
            user.save()
446 890b0eaf Sofia Papagiannaki
        return user
447 64cd4730 Antony Chazapis
448 5ce3ce4f Sofia Papagiannaki
449 890b0eaf Sofia Papagiannaki
class FeedbackForm(forms.Form):
450 890b0eaf Sofia Papagiannaki
    """
451 890b0eaf Sofia Papagiannaki
    Form for writing feedback.
452 890b0eaf Sofia Papagiannaki
    """
453 0a569195 Sofia Papagiannaki
    feedback_msg = forms.CharField(widget=forms.Textarea, label=u'Message')
454 8f5a3a06 Sofia Papagiannaki
    feedback_data = forms.CharField(widget=forms.HiddenInput(), label='',
455 8f5a3a06 Sofia Papagiannaki
                                    required=False)
456 5ed6816e Sofia Papagiannaki
457 5ce3ce4f Sofia Papagiannaki
458 5ed6816e Sofia Papagiannaki
class SendInvitationForm(forms.Form):
459 5ed6816e Sofia Papagiannaki
    """
460 5ed6816e Sofia Papagiannaki
    Form for sending an invitations
461 5ed6816e Sofia Papagiannaki
    """
462 18ffbee1 Sofia Papagiannaki
463 5ce3ce4f Sofia Papagiannaki
    email = forms.EmailField(required=True, label='Email address')
464 5ce3ce4f Sofia Papagiannaki
    first_name = forms.EmailField(label='First name')
465 5ce3ce4f Sofia Papagiannaki
    last_name = forms.EmailField(label='Last name')
466 5ce3ce4f Sofia Papagiannaki
467 e2125441 Sofia Papagiannaki
468 e2125441 Sofia Papagiannaki
class ExtendedPasswordResetForm(PasswordResetForm):
469 e2125441 Sofia Papagiannaki
    """
470 dd5f8f4d Kostas Papadimitriou
    Extends PasswordResetForm by overriding
471 18ffbee1 Sofia Papagiannaki

472 dd5f8f4d Kostas Papadimitriou
    save method: to pass a custom from_email in send_mail.
473 dd5f8f4d Kostas Papadimitriou
    clean_email: to handle local auth provider checks
474 e2125441 Sofia Papagiannaki
    """
475 23c271b3 Sofia Papagiannaki
    def clean_email(self):
476 23c271b3 Sofia Papagiannaki
        email = super(ExtendedPasswordResetForm, self).clean_email()
477 23c271b3 Sofia Papagiannaki
        try:
478 dd5f8f4d Kostas Papadimitriou
            user = AstakosUser.objects.get_by_identifier(email)
479 dd5f8f4d Kostas Papadimitriou
480 dd5f8f4d Kostas Papadimitriou
            if not user.is_active:
481 dd5f8f4d Kostas Papadimitriou
                raise forms.ValidationError(_(astakos_messages.ACCOUNT_INACTIVE))
482 dd5f8f4d Kostas Papadimitriou
483 23c271b3 Sofia Papagiannaki
            if not user.has_usable_password():
484 ae497612 Olga Brani
                raise forms.ValidationError(_(astakos_messages.UNUSABLE_PASSWORD))
485 d2633501 Kostas Papadimitriou
486 d2633501 Kostas Papadimitriou
            if not user.can_change_password():
487 dd5f8f4d Kostas Papadimitriou
                raise forms.ValidationError(_(astakos_messages.AUTH_PROVIDER_CANNOT_CHANGE_PASSWORD))
488 23c271b3 Sofia Papagiannaki
        except AstakosUser.DoesNotExist, e:
489 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.EMAIL_UNKNOWN))
490 23c271b3 Sofia Papagiannaki
        return email
491 ab8bfb29 Kostas Papadimitriou
492 5ce3ce4f Sofia Papagiannaki
    def save(
493 5ce3ce4f Sofia Papagiannaki
        self, domain_override=None, email_template_name='registration/password_reset_email.html',
494 5ce3ce4f Sofia Papagiannaki
            use_https=False, token_generator=default_token_generator, request=None):
495 e2125441 Sofia Papagiannaki
        """
496 e2125441 Sofia Papagiannaki
        Generates a one-use only link for resetting password and sends to the user.
497 e2125441 Sofia Papagiannaki
        """
498 e2125441 Sofia Papagiannaki
        for user in self.users_cache:
499 d2633501 Kostas Papadimitriou
            url = user.astakosuser.get_password_reset_url(token_generator)
500 a53b19da Sofia Papagiannaki
            url = urljoin(BASEURL, url)
501 e2125441 Sofia Papagiannaki
            t = loader.get_template(email_template_name)
502 e2125441 Sofia Papagiannaki
            c = {
503 e2125441 Sofia Papagiannaki
                'email': user.email,
504 8f378756 Sofia Papagiannaki
                'url': url,
505 374611bc Sofia Papagiannaki
                'site_name': SITENAME,
506 e2125441 Sofia Papagiannaki
                'user': user,
507 a53b19da Sofia Papagiannaki
                'baseurl': BASEURL,
508 09122dd8 Sofia Papagiannaki
                'support': DEFAULT_CONTACT_EMAIL
509 e2125441 Sofia Papagiannaki
            }
510 1cbce16f Sofia Papagiannaki
            from_email = settings.SERVER_EMAIL
511 1fcf4a99 Kostas Papadimitriou
            send_mail(_(PASSWORD_RESET_EMAIL_SUBJECT),
512 5ce3ce4f Sofia Papagiannaki
                      t.render(Context(c)), from_email, [user.email])
513 5ce3ce4f Sofia Papagiannaki
514 270dd48d Sofia Papagiannaki
515 49790d9d Sofia Papagiannaki
class EmailChangeForm(forms.ModelForm):
516 34a76cdb Kostas Papadimitriou
517 49790d9d Sofia Papagiannaki
    class Meta:
518 49790d9d Sofia Papagiannaki
        model = EmailChange
519 49790d9d Sofia Papagiannaki
        fields = ('new_email_address',)
520 ab8bfb29 Kostas Papadimitriou
521 49790d9d Sofia Papagiannaki
    def clean_new_email_address(self):
522 49790d9d Sofia Papagiannaki
        addr = self.cleaned_data['new_email_address']
523 49790d9d Sofia Papagiannaki
        if AstakosUser.objects.filter(email__iexact=addr):
524 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.EMAIL_USED))
525 49790d9d Sofia Papagiannaki
        return addr
526 ab8bfb29 Kostas Papadimitriou
527 49790d9d Sofia Papagiannaki
    def save(self, email_template_name, request, commit=True):
528 49790d9d Sofia Papagiannaki
        ec = super(EmailChangeForm, self).save(commit=False)
529 49790d9d Sofia Papagiannaki
        ec.user = request.user
530 5ce3ce4f Sofia Papagiannaki
        activation_key = hashlib.sha1(
531 5ce3ce4f Sofia Papagiannaki
            str(random()) + smart_str(ec.new_email_address))
532 5ce3ce4f Sofia Papagiannaki
        ec.activation_key = activation_key.hexdigest()
533 49790d9d Sofia Papagiannaki
        if commit:
534 49790d9d Sofia Papagiannaki
            ec.save()
535 49790d9d Sofia Papagiannaki
        send_change_email(ec, request, email_template_name=email_template_name)
536 49790d9d Sofia Papagiannaki
537 5ce3ce4f Sofia Papagiannaki
538 270dd48d Sofia Papagiannaki
class SignApprovalTermsForm(forms.ModelForm):
539 34a76cdb Kostas Papadimitriou
540 270dd48d Sofia Papagiannaki
    class Meta:
541 270dd48d Sofia Papagiannaki
        model = AstakosUser
542 270dd48d Sofia Papagiannaki
        fields = ("has_signed_terms",)
543 18ffbee1 Sofia Papagiannaki
544 270dd48d Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
545 270dd48d Sofia Papagiannaki
        super(SignApprovalTermsForm, self).__init__(*args, **kwargs)
546 18ffbee1 Sofia Papagiannaki
547 270dd48d Sofia Papagiannaki
    def clean_has_signed_terms(self):
548 270dd48d Sofia Papagiannaki
        has_signed_terms = self.cleaned_data['has_signed_terms']
549 270dd48d Sofia Papagiannaki
        if not has_signed_terms:
550 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.SIGN_TERMS))
551 270dd48d Sofia Papagiannaki
        return has_signed_terms
552 8f5a3a06 Sofia Papagiannaki
553 5ce3ce4f Sofia Papagiannaki
554 8f5a3a06 Sofia Papagiannaki
class InvitationForm(forms.ModelForm):
555 34a76cdb Kostas Papadimitriou
556 8f5a3a06 Sofia Papagiannaki
    username = forms.EmailField(label=_("Email"))
557 ab8bfb29 Kostas Papadimitriou
558 18ffbee1 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
559 18ffbee1 Sofia Papagiannaki
        super(InvitationForm, self).__init__(*args, **kwargs)
560 ab8bfb29 Kostas Papadimitriou
561 8f5a3a06 Sofia Papagiannaki
    class Meta:
562 8f5a3a06 Sofia Papagiannaki
        model = Invitation
563 8f5a3a06 Sofia Papagiannaki
        fields = ('username', 'realname')
564 ab8bfb29 Kostas Papadimitriou
565 8f5a3a06 Sofia Papagiannaki
    def clean_username(self):
566 8f5a3a06 Sofia Papagiannaki
        username = self.cleaned_data['username']
567 8f5a3a06 Sofia Papagiannaki
        try:
568 5ce3ce4f Sofia Papagiannaki
            Invitation.objects.get(username=username)
569 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.INVITATION_EMAIL_EXISTS))
570 8f5a3a06 Sofia Papagiannaki
        except Invitation.DoesNotExist:
571 8f5a3a06 Sofia Papagiannaki
            pass
572 18ffbee1 Sofia Papagiannaki
        return username
573 1039bab1 Sofia Papagiannaki
574 5ce3ce4f Sofia Papagiannaki
575 1039bab1 Sofia Papagiannaki
class ExtendedPasswordChangeForm(PasswordChangeForm):
576 1039bab1 Sofia Papagiannaki
    """
577 1039bab1 Sofia Papagiannaki
    Extends PasswordChangeForm by enabling user
578 1039bab1 Sofia Papagiannaki
    to optionally renew also the token.
579 1039bab1 Sofia Papagiannaki
    """
580 ee210d1d Sofia Papagiannaki
    if not NEWPASSWD_INVALIDATE_TOKEN:
581 48e9f076 Sofia Papagiannaki
        renew = forms.BooleanField(label='Renew token', required=False,
582 48e9f076 Sofia Papagiannaki
                                   initial=True,
583 48e9f076 Sofia Papagiannaki
                                   help_text='Unsetting this may result in security risk.')
584 ab8bfb29 Kostas Papadimitriou
585 1039bab1 Sofia Papagiannaki
    def __init__(self, user, *args, **kwargs):
586 bf0c6de5 Sofia Papagiannaki
        self.session_key = kwargs.pop('session_key', None)
587 1039bab1 Sofia Papagiannaki
        super(ExtendedPasswordChangeForm, self).__init__(user, *args, **kwargs)
588 ab8bfb29 Kostas Papadimitriou
589 1039bab1 Sofia Papagiannaki
    def save(self, commit=True):
590 bf0c6de5 Sofia Papagiannaki
        try:
591 bf0c6de5 Sofia Papagiannaki
            if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
592 bf0c6de5 Sofia Papagiannaki
                self.user.renew_token()
593 bf0c6de5 Sofia Papagiannaki
            self.user.flush_sessions(current_key=self.session_key)
594 bf0c6de5 Sofia Papagiannaki
        except AttributeError:
595 bf0c6de5 Sofia Papagiannaki
            # if user model does has not such methods
596 bf0c6de5 Sofia Papagiannaki
            pass
597 53161dd8 Sofia Papagiannaki
        return super(ExtendedPasswordChangeForm, self).save(commit=commit)
598 48e9f076 Sofia Papagiannaki
599 48e9f076 Sofia Papagiannaki
class ExtendedSetPasswordForm(SetPasswordForm):
600 48e9f076 Sofia Papagiannaki
    """
601 48e9f076 Sofia Papagiannaki
    Extends SetPasswordForm by enabling user
602 48e9f076 Sofia Papagiannaki
    to optionally renew also the token.
603 48e9f076 Sofia Papagiannaki
    """
604 ee210d1d Sofia Papagiannaki
    if not NEWPASSWD_INVALIDATE_TOKEN:
605 bf0c6de5 Sofia Papagiannaki
        renew = forms.BooleanField(
606 bf0c6de5 Sofia Papagiannaki
            label='Renew token',
607 bf0c6de5 Sofia Papagiannaki
            required=False,
608 bf0c6de5 Sofia Papagiannaki
            initial=True,
609 47b77c8b Sofia Papagiannaki
            help_text='Unsetting this may result in security risk.')
610 2e90e3ec Kostas Papadimitriou
611 48e9f076 Sofia Papagiannaki
    def __init__(self, user, *args, **kwargs):
612 48e9f076 Sofia Papagiannaki
        super(ExtendedSetPasswordForm, self).__init__(user, *args, **kwargs)
613 d2633501 Kostas Papadimitriou
614 d2633501 Kostas Papadimitriou
    @transaction.commit_on_success()
615 48e9f076 Sofia Papagiannaki
    def save(self, commit=True):
616 bf0c6de5 Sofia Papagiannaki
        try:
617 bf0c6de5 Sofia Papagiannaki
            self.user = AstakosUser.objects.get(id=self.user.id)
618 bf0c6de5 Sofia Papagiannaki
            if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
619 53161dd8 Sofia Papagiannaki
                self.user.renew_token()
620 d2633501 Kostas Papadimitriou
            #self.user.flush_sessions()
621 d2633501 Kostas Papadimitriou
            if not self.user.has_auth_provider('local'):
622 d2633501 Kostas Papadimitriou
                self.user.add_auth_provider('local', auth_backend='astakos')
623 d2633501 Kostas Papadimitriou
624 bf0c6de5 Sofia Papagiannaki
        except BaseException, e:
625 bf0c6de5 Sofia Papagiannaki
            logger.exception(e)
626 53161dd8 Sofia Papagiannaki
        return super(ExtendedSetPasswordForm, self).save(commit=commit)
627 e1a80257 Sofia Papagiannaki
628 e1a80257 Sofia Papagiannaki
629 e1a80257 Sofia Papagiannaki
class ProjectApplicationForm(forms.ModelForm):
630 e1a80257 Sofia Papagiannaki
    name = forms.CharField(
631 e1a80257 Sofia Papagiannaki
        validators=[validators.RegexValidator(
632 e1a80257 Sofia Papagiannaki
            DOMAIN_VALUE_REGEX,
633 e1a80257 Sofia Papagiannaki
            _(astakos_messages.DOMAIN_VALUE_ERR),
634 e1a80257 Sofia Papagiannaki
            'invalid'
635 e1a80257 Sofia Papagiannaki
        )],
636 213ba781 Sofia Papagiannaki
        widget=forms.TextInput(
637 213ba781 Sofia Papagiannaki
            attrs={'placeholder': 'myproject.mylab.ntua.gr'}),
638 213ba781 Sofia Papagiannaki
            help_text="""The Project's name should be in a domain format.
639 213ba781 Sofia Papagiannaki
                         The domain shouldn't neccessarily exist in the real
640 213ba781 Sofia Papagiannaki
                         world but is helpful to imply a structure.
641 213ba781 Sofia Papagiannaki
                         e.g.: myproject.mylab.ntua.gr or
642 213ba781 Sofia Papagiannaki
                         myservice.myteam.myorganization"""
643 e1a80257 Sofia Papagiannaki
    )
644 52784759 Olga Brani
    homepage = forms.URLField(
645 595dde70 Olga Brani
        label="Homepage Url",
646 213ba781 Sofia Papagiannaki
        help_text="""This should be a URL pointing at your project's site.
647 213ba781 Sofia Papagiannaki
                     e.g.: http://myproject.com""",
648 52784759 Olga Brani
        widget=forms.TextInput(attrs={'placeholder': 'http://myproject.com'}),
649 dd5f8f4d Kostas Papadimitriou
650 52784759 Olga Brani
        required=False
651 52784759 Olga Brani
     )
652 e1a80257 Sofia Papagiannaki
    comments = forms.CharField(widget=forms.Textarea, required=False)
653 213ba781 Sofia Papagiannaki
    member_join_policy = forms.ModelChoiceField(
654 213ba781 Sofia Papagiannaki
        queryset=MemberJoinPolicy.objects.all(),
655 213ba781 Sofia Papagiannaki
        empty_label=None)
656 213ba781 Sofia Papagiannaki
    member_leave_policy = forms.ModelChoiceField(
657 213ba781 Sofia Papagiannaki
        queryset=MemberLeavePolicy.objects.all(),
658 213ba781 Sofia Papagiannaki
        empty_label=None)
659 213ba781 Sofia Papagiannaki
660 dd5f8f4d Kostas Papadimitriou
661 e1a80257 Sofia Papagiannaki
    class Meta:
662 73fbaec4 Sofia Papagiannaki
        model = ProjectApplication
663 73fbaec4 Sofia Papagiannaki
        exclude = (
664 5200e864 Sofia Papagiannaki
            'project',
665 73fbaec4 Sofia Papagiannaki
            'resource_grants', 'id', 'applicant', 'owner',
666 73fbaec4 Sofia Papagiannaki
            'precursor_application', 'state', 'issue_date')
667 73fbaec4 Sofia Papagiannaki
668 40b52116 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
669 40b52116 Sofia Papagiannaki
        self.precursor_application = kwargs.get('instance')
670 40b52116 Sofia Papagiannaki
        super(ProjectApplicationForm, self).__init__(*args, **kwargs)
671 dd5f8f4d Kostas Papadimitriou
672 e1a80257 Sofia Papagiannaki
    def clean(self):
673 185b2190 Sofia Papagiannaki
        userid = self.data.get('user', None)
674 e1a80257 Sofia Papagiannaki
        self.user = None
675 e1a80257 Sofia Papagiannaki
        if userid:
676 e1a80257 Sofia Papagiannaki
            try:
677 e1a80257 Sofia Papagiannaki
                self.user = AstakosUser.objects.get(id=userid)
678 e1a80257 Sofia Papagiannaki
            except AstakosUser.DoesNotExist:
679 e1a80257 Sofia Papagiannaki
                pass
680 e1a80257 Sofia Papagiannaki
        if not self.user:
681 e1a80257 Sofia Papagiannaki
            raise forms.ValidationError(_(astakos_messages.NO_APPLICANT))
682 e1a80257 Sofia Papagiannaki
        super(ProjectApplicationForm, self).clean()
683 e1a80257 Sofia Papagiannaki
        return self.cleaned_data
684 dd5f8f4d Kostas Papadimitriou
685 f3342849 Sofia Papagiannaki
    @property
686 f3342849 Sofia Papagiannaki
    def resource_policies(self):
687 e1a80257 Sofia Papagiannaki
        policies = []
688 e1a80257 Sofia Papagiannaki
        append = policies.append
689 f3342849 Sofia Papagiannaki
        for name, value in self.data.iteritems():
690 f3342849 Sofia Papagiannaki
            if not value:
691 f3342849 Sofia Papagiannaki
                continue
692 56eb807c Sofia Papagiannaki
            uplimit = value
693 56eb807c Sofia Papagiannaki
            if name.endswith('_uplimit'):
694 56eb807c Sofia Papagiannaki
                subs = name.split('_uplimit')
695 e1a80257 Sofia Papagiannaki
                prefix, suffix = subs
696 e1a80257 Sofia Papagiannaki
                s, sep, r = prefix.partition(RESOURCE_SEPARATOR)
697 e1a80257 Sofia Papagiannaki
                resource = Resource.objects.get(service__name=s, name=r)
698 e1a80257 Sofia Papagiannaki
699 e1a80257 Sofia Papagiannaki
                # keep only resource limits for selected resource groups
700 30dd9e0e Olga Brani
                if self.data.get(
701 30dd9e0e Olga Brani
                    'is_selected_%s' % resource.group, "0"
702 30dd9e0e Olga Brani
                 ) == "1":
703 6556e514 Sofia Papagiannaki
                    d = model_to_dict(resource)
704 30dd9e0e Olga Brani
                    if uplimit:
705 6556e514 Sofia Papagiannaki
                        d.update(dict(service=s, resource=r, uplimit=uplimit))
706 30dd9e0e Olga Brani
                    else:
707 6556e514 Sofia Papagiannaki
                        d.update(dict(service=s, resource=r, uplimit=None))
708 6556e514 Sofia Papagiannaki
                    append(d)
709 dd5f8f4d Kostas Papadimitriou
710 e1a80257 Sofia Papagiannaki
        return policies
711 dd5f8f4d Kostas Papadimitriou
712 e1a80257 Sofia Papagiannaki
713 e1a80257 Sofia Papagiannaki
    def save(self, commit=True):
714 73fbaec4 Sofia Papagiannaki
        application = super(ProjectApplicationForm, self).save(commit=False)
715 e1a80257 Sofia Papagiannaki
        applicant = self.user
716 e1a80257 Sofia Papagiannaki
        comments = self.cleaned_data.pop('comments', None)
717 73fbaec4 Sofia Papagiannaki
        return submit_application(
718 73fbaec4 Sofia Papagiannaki
            application,
719 ccab6eb5 Sofia Papagiannaki
            self.resource_policies,
720 e1a80257 Sofia Papagiannaki
            applicant,
721 e1a80257 Sofia Papagiannaki
            comments,
722 40b52116 Sofia Papagiannaki
            self.precursor_application
723 e1a80257 Sofia Papagiannaki
        )
724 8327782d Sofia Papagiannaki
725 8327782d Sofia Papagiannaki
class ProjectSortForm(forms.Form):
726 8327782d Sofia Papagiannaki
    sorting = forms.ChoiceField(
727 8327782d Sofia Papagiannaki
        label='Sort by',
728 73fbaec4 Sofia Papagiannaki
        choices=(('name', 'Sort by Name'),
729 8327782d Sofia Papagiannaki
                 ('issue_date', 'Sort by Issue date'),
730 73fbaec4 Sofia Papagiannaki
                 ('start_date', 'Sort by Start Date'),
731 73fbaec4 Sofia Papagiannaki
                 ('end_date', 'Sort by End Date'),
732 8327782d Sofia Papagiannaki
#                  ('approved_members_num', 'Sort by Participants'),
733 d6a162d3 Sofia Papagiannaki
                 ('state', 'Sort by Status'),
734 73fbaec4 Sofia Papagiannaki
                 ('member_join_policy__description', 'Sort by Member Join Policy'),
735 7592e3e2 Sofia Papagiannaki
                 ('member_leave_policy__description', 'Sort by Member Leave Policy'),
736 7592e3e2 Sofia Papagiannaki
                 ('-name', 'Sort by Name'),
737 7592e3e2 Sofia Papagiannaki
                 ('-issue_date', 'Sort by Issue date'),
738 7592e3e2 Sofia Papagiannaki
                 ('-start_date', 'Sort by Start Date'),
739 7592e3e2 Sofia Papagiannaki
                 ('-end_date', 'Sort by End Date'),
740 7592e3e2 Sofia Papagiannaki
#                  ('-approved_members_num', 'Sort by Participants'),
741 7592e3e2 Sofia Papagiannaki
                 ('-state', 'Sort by Status'),
742 7592e3e2 Sofia Papagiannaki
                 ('-member_join_policy__description', 'Sort by Member Join Policy'),
743 7592e3e2 Sofia Papagiannaki
                 ('-member_leave_policy__description', 'Sort by Member Leave Policy')
744 8327782d Sofia Papagiannaki
        ),
745 8327782d Sofia Papagiannaki
        required=True
746 ccab6eb5 Sofia Papagiannaki
    )
747 ccab6eb5 Sofia Papagiannaki
748 ccab6eb5 Sofia Papagiannaki
class AddProjectMembersForm(forms.Form):
749 ccab6eb5 Sofia Papagiannaki
    q = forms.CharField(
750 ccab6eb5 Sofia Papagiannaki
        max_length=800, widget=forms.Textarea, label=_('Add members'),
751 ccab6eb5 Sofia Papagiannaki
        help_text=_(astakos_messages.ADD_PROJECT_MEMBERS_Q_HELP),
752 ccab6eb5 Sofia Papagiannaki
        required=True)
753 ccab6eb5 Sofia Papagiannaki
754 ccab6eb5 Sofia Papagiannaki
    def clean(self):
755 ccab6eb5 Sofia Papagiannaki
        q = self.cleaned_data.get('q') or ''
756 ccab6eb5 Sofia Papagiannaki
        users = q.split(',')
757 ccab6eb5 Sofia Papagiannaki
        users = list(u.strip() for u in users if u)
758 ccab6eb5 Sofia Papagiannaki
        db_entries = AstakosUser.objects.filter(email__in=users)
759 ccab6eb5 Sofia Papagiannaki
        unknown = list(set(users) - set(u.email for u in db_entries))
760 ccab6eb5 Sofia Papagiannaki
        if unknown:
761 ccab6eb5 Sofia Papagiannaki
            raise forms.ValidationError(_(astakos_messages.UNKNOWN_USERS) % ','.join(unknown))
762 ccab6eb5 Sofia Papagiannaki
        self.valid_users = db_entries
763 ccab6eb5 Sofia Papagiannaki
        return self.cleaned_data
764 ccab6eb5 Sofia Papagiannaki
765 ccab6eb5 Sofia Papagiannaki
    def get_valid_users(self):
766 ccab6eb5 Sofia Papagiannaki
        """Should be called after form cleaning"""
767 ccab6eb5 Sofia Papagiannaki
        try:
768 ccab6eb5 Sofia Papagiannaki
            return self.valid_users
769 ccab6eb5 Sofia Papagiannaki
        except:
770 bfe23b13 Sofia Papagiannaki
            return ()
771 bfe23b13 Sofia Papagiannaki
772 bfe23b13 Sofia Papagiannaki
class ProjectMembersSortForm(forms.Form):
773 bfe23b13 Sofia Papagiannaki
    sorting = forms.ChoiceField(
774 bfe23b13 Sofia Papagiannaki
        label='Sort by',
775 bfe23b13 Sofia Papagiannaki
        choices=(('person__email', 'User Id'),
776 bfe23b13 Sofia Papagiannaki
                 ('person__first_name', 'Name'),
777 bfe23b13 Sofia Papagiannaki
                 ('acceptance_date', 'Acceptance date')
778 bfe23b13 Sofia Papagiannaki
        ),
779 bfe23b13 Sofia Papagiannaki
        required=True
780 bfe23b13 Sofia Papagiannaki
    )
781 bfe23b13 Sofia Papagiannaki
782 6dadd24a Sofia Papagiannaki
class ProjectSearchForm(forms.Form):
783 85d444db Sofia Papagiannaki
    q = forms.CharField(max_length=200, label='Search project', required=False)