Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / forms.py @ b22de10a

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

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

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

477 e2125441 Sofia Papagiannaki
    Since Django 1.3 this is useless since ``django.contrib.auth.views.reset_password``
478 e2125441 Sofia Papagiannaki
    accepts a from_email argument.
479 e2125441 Sofia Papagiannaki
    """
480 23c271b3 Sofia Papagiannaki
    def clean_email(self):
481 23c271b3 Sofia Papagiannaki
        email = super(ExtendedPasswordResetForm, self).clean_email()
482 23c271b3 Sofia Papagiannaki
        try:
483 789a5951 Sofia Papagiannaki
            user = AstakosUser.objects.get(email__iexact=email, is_active=True)
484 23c271b3 Sofia Papagiannaki
            if not user.has_usable_password():
485 ae497612 Olga Brani
                raise forms.ValidationError(_(astakos_messages.UNUSABLE_PASSWORD))
486 d2633501 Kostas Papadimitriou
487 d2633501 Kostas Papadimitriou
            if not user.can_change_password():
488 d2633501 Kostas Papadimitriou
                raise forms.ValidationError(_('Password change for this account'
489 d2633501 Kostas Papadimitriou
                                              ' is not supported.'))
490 d2633501 Kostas Papadimitriou
491 23c271b3 Sofia Papagiannaki
        except AstakosUser.DoesNotExist, e:
492 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.EMAIL_UNKNOWN))
493 23c271b3 Sofia Papagiannaki
        return email
494 ab8bfb29 Kostas Papadimitriou
495 5ce3ce4f Sofia Papagiannaki
    def save(
496 5ce3ce4f Sofia Papagiannaki
        self, domain_override=None, email_template_name='registration/password_reset_email.html',
497 5ce3ce4f Sofia Papagiannaki
            use_https=False, token_generator=default_token_generator, request=None):
498 e2125441 Sofia Papagiannaki
        """
499 e2125441 Sofia Papagiannaki
        Generates a one-use only link for resetting password and sends to the user.
500 e2125441 Sofia Papagiannaki
        """
501 e2125441 Sofia Papagiannaki
        for user in self.users_cache:
502 d2633501 Kostas Papadimitriou
            url = user.astakosuser.get_password_reset_url(token_generator)
503 a53b19da Sofia Papagiannaki
            url = urljoin(BASEURL, url)
504 e2125441 Sofia Papagiannaki
            t = loader.get_template(email_template_name)
505 e2125441 Sofia Papagiannaki
            c = {
506 e2125441 Sofia Papagiannaki
                'email': user.email,
507 8f378756 Sofia Papagiannaki
                'url': url,
508 374611bc Sofia Papagiannaki
                'site_name': SITENAME,
509 e2125441 Sofia Papagiannaki
                'user': user,
510 a53b19da Sofia Papagiannaki
                'baseurl': BASEURL,
511 09122dd8 Sofia Papagiannaki
                'support': DEFAULT_CONTACT_EMAIL
512 e2125441 Sofia Papagiannaki
            }
513 1cbce16f Sofia Papagiannaki
            from_email = settings.SERVER_EMAIL
514 1fcf4a99 Kostas Papadimitriou
            send_mail(_(PASSWORD_RESET_EMAIL_SUBJECT),
515 5ce3ce4f Sofia Papagiannaki
                      t.render(Context(c)), from_email, [user.email])
516 5ce3ce4f Sofia Papagiannaki
517 270dd48d Sofia Papagiannaki
518 49790d9d Sofia Papagiannaki
class EmailChangeForm(forms.ModelForm):
519 49790d9d Sofia Papagiannaki
    class Meta:
520 49790d9d Sofia Papagiannaki
        model = EmailChange
521 49790d9d Sofia Papagiannaki
        fields = ('new_email_address',)
522 ab8bfb29 Kostas Papadimitriou
523 49790d9d Sofia Papagiannaki
    def clean_new_email_address(self):
524 49790d9d Sofia Papagiannaki
        addr = self.cleaned_data['new_email_address']
525 49790d9d Sofia Papagiannaki
        if AstakosUser.objects.filter(email__iexact=addr):
526 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.EMAIL_USED))
527 49790d9d Sofia Papagiannaki
        return addr
528 ab8bfb29 Kostas Papadimitriou
529 49790d9d Sofia Papagiannaki
    def save(self, email_template_name, request, commit=True):
530 49790d9d Sofia Papagiannaki
        ec = super(EmailChangeForm, self).save(commit=False)
531 49790d9d Sofia Papagiannaki
        ec.user = request.user
532 5ce3ce4f Sofia Papagiannaki
        activation_key = hashlib.sha1(
533 5ce3ce4f Sofia Papagiannaki
            str(random()) + smart_str(ec.new_email_address))
534 5ce3ce4f Sofia Papagiannaki
        ec.activation_key = activation_key.hexdigest()
535 49790d9d Sofia Papagiannaki
        if commit:
536 49790d9d Sofia Papagiannaki
            ec.save()
537 49790d9d Sofia Papagiannaki
        send_change_email(ec, request, email_template_name=email_template_name)
538 49790d9d Sofia Papagiannaki
539 5ce3ce4f Sofia Papagiannaki
540 270dd48d Sofia Papagiannaki
class SignApprovalTermsForm(forms.ModelForm):
541 270dd48d Sofia Papagiannaki
    class Meta:
542 270dd48d Sofia Papagiannaki
        model = AstakosUser
543 270dd48d Sofia Papagiannaki
        fields = ("has_signed_terms",)
544 18ffbee1 Sofia Papagiannaki
545 270dd48d Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
546 270dd48d Sofia Papagiannaki
        super(SignApprovalTermsForm, self).__init__(*args, **kwargs)
547 18ffbee1 Sofia Papagiannaki
548 270dd48d Sofia Papagiannaki
    def clean_has_signed_terms(self):
549 270dd48d Sofia Papagiannaki
        has_signed_terms = self.cleaned_data['has_signed_terms']
550 270dd48d Sofia Papagiannaki
        if not has_signed_terms:
551 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.SIGN_TERMS))
552 270dd48d Sofia Papagiannaki
        return has_signed_terms
553 8f5a3a06 Sofia Papagiannaki
554 5ce3ce4f Sofia Papagiannaki
555 8f5a3a06 Sofia Papagiannaki
class InvitationForm(forms.ModelForm):
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 5ce3ce4f Sofia Papagiannaki
600 0f4fa26d Sofia Papagiannaki
class AstakosGroupCreationForm(forms.ModelForm):
601 0f4fa26d Sofia Papagiannaki
    kind = forms.ModelChoiceField(
602 0f4fa26d Sofia Papagiannaki
        queryset=GroupKind.objects.all(),
603 0f4fa26d Sofia Papagiannaki
        label="",
604 0f4fa26d Sofia Papagiannaki
        widget=forms.HiddenInput()
605 0f4fa26d Sofia Papagiannaki
    )
606 caf70869 Sofia Papagiannaki
    name = forms.CharField(
607 caf70869 Sofia Papagiannaki
        validators=[validators.RegexValidator(
608 caf70869 Sofia Papagiannaki
            DOMAIN_VALUE_REGEX,
609 caf70869 Sofia Papagiannaki
            _(astakos_messages.DOMAIN_VALUE_ERR), 'invalid'
610 caf70869 Sofia Papagiannaki
        )],
611 67be1883 Olga Brani
        widget=forms.TextInput(attrs={'placeholder': 'myproject.mylab.ntua.gr'}),
612 67be1883 Olga Brani
        help_text=" The Project's name should be in a domain format. The domain shouldn't neccessarily exist in the real world but is helpful to imply a structure. e.g.: myproject.mylab.ntua.gr or myservice.myteam.myorganization "
613 67be1883 Olga Brani
    )
614 67be1883 Olga Brani
    homepage = forms.URLField(
615 67be1883 Olga Brani
        label= 'Homepage Url',
616 67be1883 Olga Brani
        widget=forms.TextInput(attrs={'placeholder': 'http://myproject.com'}),
617 67be1883 Olga Brani
        help_text="This should be a URL pointing at your project's site. e.g.: http://myproject.com ",
618 67be1883 Olga Brani
        required=False
619 67be1883 Olga Brani
    )
620 67be1883 Olga Brani
    desc = forms.CharField(
621 67be1883 Olga Brani
        label= 'Description',
622 67be1883 Olga Brani
        widget=forms.Textarea, 
623 67be1883 Olga Brani
        help_text= "Please provide a short but descriptive abstract of your Project, so that anyone searching can quickly understand what this Project is about. "
624 67be1883 Olga Brani
    )
625 67be1883 Olga Brani
    issue_date = forms.DateTimeField(
626 67be1883 Olga Brani
        label= 'Start date',
627 67be1883 Olga Brani
        help_text= "Here you specify the date you want your Project to start granting its resources. Its members will get the resources coming from this Project on this exact date."
628 67be1883 Olga Brani
    )
629 67be1883 Olga Brani
    expiration_date = forms.DateTimeField(
630 67be1883 Olga Brani
        label= 'End date',
631 67be1883 Olga Brani
        help_text= "Here you specify the date you want your Project to cease. This means that after this date all members will no longer be able to allocate resources from this Project.  "
632 caf70869 Sofia Papagiannaki
    )
633 1831a0fe Olga Brani
    moderation_enabled = forms.BooleanField(
634 67be1883 Olga Brani
        label= 'Moderated',
635 67be1883 Olga Brani
        help_text="Select this to approve each member manually, before they become a part of your Project (default). Be sure you know what you are doing, if you uncheck this option. ",
636 8c804c12 Sofia Papagiannaki
        required=False,
637 8c804c12 Sofia Papagiannaki
        initial=True
638 1831a0fe Olga Brani
    )
639 9a06d96f Olga Brani
    max_participants = forms.IntegerField(
640 67be1883 Olga Brani
        label='Total number of members',
641 67be1883 Olga Brani
        required=True, min_value=1,
642 67be1883 Olga Brani
        help_text="Here you specify the number of members this Project is going to have. This means that this number of people will be granted the resources you will specify in the next step. This can be '1' if you are the only one wanting to get resources. "
643 9a06d96f Olga Brani
    )
644 9a06d96f Olga Brani
645 0f4fa26d Sofia Papagiannaki
    class Meta:
646 0f4fa26d Sofia Papagiannaki
        model = AstakosGroup
647 5ce3ce4f Sofia Papagiannaki
648 0f4fa26d Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
649 9a06d96f Olga Brani
        #update QueryDict
650 9a06d96f Olga Brani
        args = list(args)
651 9a06d96f Olga Brani
        qd = args.pop(0).copy()
652 9a06d96f Olga Brani
        members_unlimited = qd.pop('members_unlimited', False)
653 9a06d96f Olga Brani
        members_uplimit = qd.pop('members_uplimit', None)
654 2e90e3ec Kostas Papadimitriou
655 9a06d96f Olga Brani
        #substitue QueryDict
656 9a06d96f Olga Brani
        args.insert(0, qd)
657 2e90e3ec Kostas Papadimitriou
658 0f4fa26d Sofia Papagiannaki
        super(AstakosGroupCreationForm, self).__init__(*args, **kwargs)
659 caf70869 Sofia Papagiannaki
        
660 9a06d96f Olga Brani
        self.fields.keyOrder = ['kind', 'name', 'homepage', 'desc',
661 9a06d96f Olga Brani
                                'issue_date', 'expiration_date',
662 9a06d96f Olga Brani
                                'moderation_enabled', 'max_participants']
663 8c804c12 Sofia Papagiannaki
        def add_fields((k, v)):
664 dcd1c383 Olga Brani
            k = k.partition('_proxy')[0]
665 9a06d96f Olga Brani
            self.fields[k] = forms.IntegerField(
666 0f4fa26d Sofia Papagiannaki
                required=False,
667 c3a905e7 Olga Brani
                widget=forms.HiddenInput(),
668 29b87e7c Sofia Papagiannaki
                min_value=1
669 0f4fa26d Sofia Papagiannaki
            )
670 8c804c12 Sofia Papagiannaki
        map(add_fields,
671 6abd262c Olga Brani
            ((k, v) for k,v in qd.iteritems() if k.endswith('_uplimit'))
672 9a06d96f Olga Brani
        )
673 2e90e3ec Kostas Papadimitriou
674 8c804c12 Sofia Papagiannaki
        def add_fields((k, v)):
675 8c804c12 Sofia Papagiannaki
            self.fields[k] = forms.BooleanField(
676 8c804c12 Sofia Papagiannaki
                required=False,
677 6abd262c Olga Brani
                #widget=forms.HiddenInput()
678 8c804c12 Sofia Papagiannaki
            )
679 8c804c12 Sofia Papagiannaki
        map(add_fields,
680 8c804c12 Sofia Papagiannaki
            ((k, v) for k,v in qd.iteritems() if k.startswith('is_selected_'))
681 8c804c12 Sofia Papagiannaki
        )
682 2e90e3ec Kostas Papadimitriou
683 29b87e7c Sofia Papagiannaki
    def policies(self):
684 29b87e7c Sofia Papagiannaki
        self.clean()
685 29b87e7c Sofia Papagiannaki
        policies = []
686 29b87e7c Sofia Papagiannaki
        append = policies.append
687 29b87e7c Sofia Papagiannaki
        for name, uplimit in self.cleaned_data.iteritems():
688 2e90e3ec Kostas Papadimitriou
689 29b87e7c Sofia Papagiannaki
            subs = name.split('_uplimit')
690 29b87e7c Sofia Papagiannaki
            if len(subs) == 2:
691 29b87e7c Sofia Papagiannaki
                prefix, suffix = subs
692 930f09ba Sofia Papagiannaki
                s, sep, r = prefix.partition(RESOURCE_SEPARATOR)
693 29b87e7c Sofia Papagiannaki
                resource = Resource.objects.get(service__name=s, name=r)
694 2e90e3ec Kostas Papadimitriou
695 29b87e7c Sofia Papagiannaki
                # keep only resource limits for selected resource groups
696 29b87e7c Sofia Papagiannaki
                if self.cleaned_data.get(
697 c3a905e7 Olga Brani
                    'is_selected_%s' % resource.group, False
698 29b87e7c Sofia Papagiannaki
                ):
699 29b87e7c Sofia Papagiannaki
                    append(dict(service=s, resource=r, uplimit=uplimit))
700 29b87e7c Sofia Papagiannaki
        return policies
701 29b87e7c Sofia Papagiannaki
702 29b87e7c Sofia Papagiannaki
class AstakosGroupCreationSummaryForm(forms.ModelForm):
703 29b87e7c Sofia Papagiannaki
    kind = forms.ModelChoiceField(
704 29b87e7c Sofia Papagiannaki
        queryset=GroupKind.objects.all(),
705 29b87e7c Sofia Papagiannaki
        label="",
706 29b87e7c Sofia Papagiannaki
        widget=forms.HiddenInput()
707 29b87e7c Sofia Papagiannaki
    )
708 caf70869 Sofia Papagiannaki
    name = forms.CharField(
709 caf70869 Sofia Papagiannaki
        widget=forms.TextInput(attrs={'placeholder': 'eg. foo.ece.ntua.gr'}),
710 caf70869 Sofia Papagiannaki
        help_text="Name should be in the form of dns"
711 caf70869 Sofia Papagiannaki
    )
712 29b87e7c Sofia Papagiannaki
    moderation_enabled = forms.BooleanField(
713 29b87e7c Sofia Papagiannaki
        help_text="Check if you want to approve members participation manually",
714 29b87e7c Sofia Papagiannaki
        required=False,
715 29b87e7c Sofia Papagiannaki
        initial=True
716 29b87e7c Sofia Papagiannaki
    )
717 29b87e7c Sofia Papagiannaki
    max_participants = forms.IntegerField(
718 29b87e7c Sofia Papagiannaki
        required=False, min_value=1
719 29b87e7c Sofia Papagiannaki
    )
720 29b87e7c Sofia Papagiannaki
721 29b87e7c Sofia Papagiannaki
    class Meta:
722 29b87e7c Sofia Papagiannaki
        model = AstakosGroup
723 29b87e7c Sofia Papagiannaki
724 29b87e7c Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
725 29b87e7c Sofia Papagiannaki
        #update QueryDict
726 29b87e7c Sofia Papagiannaki
        args = list(args)
727 29b87e7c Sofia Papagiannaki
        qd = args.pop(0).copy()
728 29b87e7c Sofia Papagiannaki
        members_unlimited = qd.pop('members_unlimited', False)
729 29b87e7c Sofia Papagiannaki
        members_uplimit = qd.pop('members_uplimit', None)
730 2e90e3ec Kostas Papadimitriou
731 29b87e7c Sofia Papagiannaki
        #substitue QueryDict
732 29b87e7c Sofia Papagiannaki
        args.insert(0, qd)
733 2e90e3ec Kostas Papadimitriou
734 29b87e7c Sofia Papagiannaki
        super(AstakosGroupCreationSummaryForm, self).__init__(*args, **kwargs)
735 29b87e7c Sofia Papagiannaki
        self.fields.keyOrder = ['kind', 'name', 'homepage', 'desc',
736 29b87e7c Sofia Papagiannaki
                                'issue_date', 'expiration_date',
737 29b87e7c Sofia Papagiannaki
                                'moderation_enabled', 'max_participants']
738 29b87e7c Sofia Papagiannaki
        def add_fields((k, v)):
739 29b87e7c Sofia Papagiannaki
            self.fields[k] = forms.IntegerField(
740 29b87e7c Sofia Papagiannaki
                required=False,
741 c3a905e7 Olga Brani
                widget=forms.TextInput(),
742 29b87e7c Sofia Papagiannaki
                min_value=1
743 29b87e7c Sofia Papagiannaki
            )
744 29b87e7c Sofia Papagiannaki
        map(add_fields,
745 29b87e7c Sofia Papagiannaki
            ((k, v) for k,v in qd.iteritems() if k.endswith('_uplimit'))
746 29b87e7c Sofia Papagiannaki
        )
747 2e90e3ec Kostas Papadimitriou
748 29b87e7c Sofia Papagiannaki
        def add_fields((k, v)):
749 29b87e7c Sofia Papagiannaki
            self.fields[k] = forms.BooleanField(
750 29b87e7c Sofia Papagiannaki
                required=False,
751 c3a905e7 Olga Brani
                widget=forms.HiddenInput()
752 29b87e7c Sofia Papagiannaki
            )
753 29b87e7c Sofia Papagiannaki
        map(add_fields,
754 29b87e7c Sofia Papagiannaki
            ((k, v) for k,v in qd.iteritems() if k.startswith('is_selected_'))
755 29b87e7c Sofia Papagiannaki
        )
756 29b87e7c Sofia Papagiannaki
        for f in self.fields.values():
757 29b87e7c Sofia Papagiannaki
            f.widget = forms.HiddenInput()
758 29b87e7c Sofia Papagiannaki
759 820b18e0 Sofia Papagiannaki
    def clean(self):
760 29b87e7c Sofia Papagiannaki
        super(AstakosGroupCreationSummaryForm, self).clean()
761 820b18e0 Sofia Papagiannaki
        self.cleaned_data['policies'] = []
762 820b18e0 Sofia Papagiannaki
        append = self.cleaned_data['policies'].append
763 c3a905e7 Olga Brani
        #tbd = [f for f in self.fields if (f.startswith('is_selected_') and (not f.endswith('_proxy')))]
764 8c804c12 Sofia Papagiannaki
        tbd = [f for f in self.fields if f.startswith('is_selected_')]
765 9a06d96f Olga Brani
        for name, uplimit in self.cleaned_data.iteritems():
766 9a06d96f Olga Brani
            subs = name.split('_uplimit')
767 9a06d96f Olga Brani
            if len(subs) == 2:
768 820b18e0 Sofia Papagiannaki
                tbd.append(name)
769 9a06d96f Olga Brani
                prefix, suffix = subs
770 930f09ba Sofia Papagiannaki
                s, sep, r = prefix.partition(RESOURCE_SEPARATOR)
771 8c804c12 Sofia Papagiannaki
                resource = Resource.objects.get(service__name=s, name=r)
772 2e90e3ec Kostas Papadimitriou
773 8c804c12 Sofia Papagiannaki
                # keep only resource limits for selected resource groups
774 8c804c12 Sofia Papagiannaki
                if self.cleaned_data.get(
775 3cbd5e47 Olga Brani
                    'is_selected_%s' % resource.group, False
776 8c804c12 Sofia Papagiannaki
                ):
777 8c804c12 Sofia Papagiannaki
                    append(dict(service=s, resource=r, uplimit=uplimit))
778 29b87e7c Sofia Papagiannaki
        for name in tbd:
779 29b87e7c Sofia Papagiannaki
            self.cleaned_data.pop(name, None)
780 820b18e0 Sofia Papagiannaki
        return self.cleaned_data
781 01ac12d5 Sofia Papagiannaki
782 51c57c9c Sofia Papagiannaki
class AstakosGroupUpdateForm(forms.ModelForm):
783 51c57c9c Sofia Papagiannaki
    class Meta:
784 51c57c9c Sofia Papagiannaki
        model = AstakosGroup
785 463a973c Sofia Papagiannaki
        fields = ( 'desc','homepage', 'moderation_enabled')
786 5ce3ce4f Sofia Papagiannaki
787 9a06d96f Olga Brani
788 a4233484 Sofia Papagiannaki
class AddGroupMembersForm(forms.Form):
789 9a06d96f Olga Brani
    q = forms.CharField(
790 c3a905e7 Olga Brani
        max_length=800, widget=forms.Textarea, label=_('Add members'),
791 ae497612 Olga Brani
        help_text=_(astakos_messages.ADD_GROUP_MEMBERS_Q_HELP),
792 9a06d96f Olga Brani
        required=True)
793 9a06d96f Olga Brani
794 a4233484 Sofia Papagiannaki
    def clean(self):
795 a4233484 Sofia Papagiannaki
        q = self.cleaned_data.get('q') or ''
796 a4233484 Sofia Papagiannaki
        users = q.split(',')
797 a4233484 Sofia Papagiannaki
        users = list(u.strip() for u in users if u)
798 a4233484 Sofia Papagiannaki
        db_entries = AstakosUser.objects.filter(email__in=users)
799 a4233484 Sofia Papagiannaki
        unknown = list(set(users) - set(u.email for u in db_entries))
800 a4233484 Sofia Papagiannaki
        if unknown:
801 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.UNKNOWN_USERS) % ','.join(unknown))
802 a4233484 Sofia Papagiannaki
        self.valid_users = db_entries
803 a4233484 Sofia Papagiannaki
        return self.cleaned_data
804 9a06d96f Olga Brani
805 a4233484 Sofia Papagiannaki
    def get_valid_users(self):
806 a4233484 Sofia Papagiannaki
        """Should be called after form cleaning"""
807 a4233484 Sofia Papagiannaki
        try:
808 a4233484 Sofia Papagiannaki
            return self.valid_users
809 a4233484 Sofia Papagiannaki
        except:
810 a4233484 Sofia Papagiannaki
            return ()
811 a4233484 Sofia Papagiannaki
812 a4233484 Sofia Papagiannaki
813 01ac12d5 Sofia Papagiannaki
class AstakosGroupSearchForm(forms.Form):
814 59728d4e Olga Brani
    q = forms.CharField(max_length=200, label='Search project')
815 789bcaf9 Sofia Papagiannaki
816 9a06d96f Olga Brani
817 54213d7a Sofia Papagiannaki
class TimelineForm(forms.Form):
818 88305cf0 root
    entity = forms.ModelChoiceField(
819 9a06d96f Olga Brani
        queryset=AstakosUser.objects.filter(is_active=True)
820 88305cf0 root
    )
821 54213d7a Sofia Papagiannaki
    resource = forms.ModelChoiceField(
822 6e52912b Sofia Papagiannaki
        queryset=Resource.objects.all()
823 54213d7a Sofia Papagiannaki
    )
824 54213d7a Sofia Papagiannaki
    start_date = forms.DateTimeField()
825 54213d7a Sofia Papagiannaki
    end_date = forms.DateTimeField()
826 82b05401 root
    details = forms.BooleanField(required=False, label="Detailed Listing")
827 82b05401 root
    operation = forms.ChoiceField(
828 9a06d96f Olga Brani
        label='Charge Method',
829 9a06d96f Olga Brani
        choices=(('', '-------------'),
830 9a06d96f Olga Brani
                 ('charge_usage', 'Charge Usage'),
831 9a06d96f Olga Brani
                 ('charge_traffic', 'Charge Traffic'), )
832 9a06d96f Olga Brani
    )
833 9a06d96f Olga Brani
834 6e52912b Sofia Papagiannaki
    def clean(self):
835 6e52912b Sofia Papagiannaki
        super(TimelineForm, self).clean()
836 6e52912b Sofia Papagiannaki
        d = self.cleaned_data
837 6e52912b Sofia Papagiannaki
        if 'resource' in d:
838 6e52912b Sofia Papagiannaki
            d['resource'] = str(d['resource'])
839 6e52912b Sofia Papagiannaki
        if 'start_date' in d:
840 9a06d96f Olga Brani
            d['start_date'] = d['start_date'].strftime(
841 9a06d96f Olga Brani
                "%Y-%m-%dT%H:%M:%S.%f")[:24]
842 6e52912b Sofia Papagiannaki
        if 'end_date' in d:
843 c3f6cdf1 root
            d['end_date'] = d['end_date'].strftime("%Y-%m-%dT%H:%M:%S.%f")[:24]
844 9a06d96f Olga Brani
        if 'entity' in d:
845 c9015cf6 Sofia Papagiannaki
            d['entity'] = d['entity'].email
846 c3f6cdf1 root
        return d
847 c3f6cdf1 root
848 9a06d96f Olga Brani
849 789bcaf9 Sofia Papagiannaki
class AstakosGroupSortForm(forms.Form):
850 098f333b Sofia Papagiannaki
    sorting = forms.ChoiceField(
851 098f333b Sofia Papagiannaki
        label='Sort by',
852 098f333b Sofia Papagiannaki
        choices=(
853 098f333b Sofia Papagiannaki
            ('groupname', 'Name'),
854 098f333b Sofia Papagiannaki
            ('issue_date', 'Issue Date'),
855 098f333b Sofia Papagiannaki
            ('expiration_date', 'Expiration Date'),
856 098f333b Sofia Papagiannaki
            ('approved_members_num', 'Participants'),
857 098f333b Sofia Papagiannaki
            ('moderation_enabled', 'Moderation'),
858 098f333b Sofia Papagiannaki
            ('membership_status', 'Enrollment Status')
859 098f333b Sofia Papagiannaki
        ),
860 098f333b Sofia Papagiannaki
        required=True
861 098f333b Sofia Papagiannaki
    )
862 9a06d96f Olga Brani
863 801be7a3 Sofia Papagiannaki
class MembersSortForm(forms.Form):
864 bfaeedb6 Sofia Papagiannaki
    sorting = forms.ChoiceField(
865 bfaeedb6 Sofia Papagiannaki
        label='Sort by',
866 bfaeedb6 Sofia Papagiannaki
        choices=(('person__email', 'User Id'),
867 bfaeedb6 Sofia Papagiannaki
                 ('person__first_name', 'Name'),
868 bfaeedb6 Sofia Papagiannaki
                 ('date_joined', 'Status')
869 bfaeedb6 Sofia Papagiannaki
        ),
870 bfaeedb6 Sofia Papagiannaki
        required=True
871 bfaeedb6 Sofia Papagiannaki
    )
872 9eafaa32 Sofia Papagiannaki
873 9eafaa32 Sofia Papagiannaki
class PickResourceForm(forms.Form):
874 9eafaa32 Sofia Papagiannaki
    resource = forms.ModelChoiceField(
875 9eafaa32 Sofia Papagiannaki
        queryset=Resource.objects.select_related().all()
876 9eafaa32 Sofia Papagiannaki
    )
877 9a06d96f Olga Brani
    resource.widget.attrs["onchange"] = "this.form.submit()"
878 9a06d96f Olga Brani
879 9a06d96f Olga Brani
880 48e9f076 Sofia Papagiannaki
class ExtendedSetPasswordForm(SetPasswordForm):
881 48e9f076 Sofia Papagiannaki
    """
882 48e9f076 Sofia Papagiannaki
    Extends SetPasswordForm by enabling user
883 48e9f076 Sofia Papagiannaki
    to optionally renew also the token.
884 48e9f076 Sofia Papagiannaki
    """
885 ee210d1d Sofia Papagiannaki
    if not NEWPASSWD_INVALIDATE_TOKEN:
886 bf0c6de5 Sofia Papagiannaki
        renew = forms.BooleanField(
887 bf0c6de5 Sofia Papagiannaki
            label='Renew token',
888 bf0c6de5 Sofia Papagiannaki
            required=False,
889 bf0c6de5 Sofia Papagiannaki
            initial=True,
890 bf0c6de5 Sofia Papagiannaki
            help_text='Unsetting this may result in security risk.'
891 bf0c6de5 Sofia Papagiannaki
        )
892 2e90e3ec Kostas Papadimitriou
893 48e9f076 Sofia Papagiannaki
    def __init__(self, user, *args, **kwargs):
894 48e9f076 Sofia Papagiannaki
        super(ExtendedSetPasswordForm, self).__init__(user, *args, **kwargs)
895 d2633501 Kostas Papadimitriou
896 d2633501 Kostas Papadimitriou
    @transaction.commit_on_success()
897 48e9f076 Sofia Papagiannaki
    def save(self, commit=True):
898 bf0c6de5 Sofia Papagiannaki
        try:
899 bf0c6de5 Sofia Papagiannaki
            self.user = AstakosUser.objects.get(id=self.user.id)
900 bf0c6de5 Sofia Papagiannaki
            if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
901 53161dd8 Sofia Papagiannaki
                self.user.renew_token()
902 d2633501 Kostas Papadimitriou
            #self.user.flush_sessions()
903 d2633501 Kostas Papadimitriou
            if not self.user.has_auth_provider('local'):
904 d2633501 Kostas Papadimitriou
                self.user.add_auth_provider('local', auth_backend='astakos')
905 d2633501 Kostas Papadimitriou
906 bf0c6de5 Sofia Papagiannaki
        except BaseException, e:
907 bf0c6de5 Sofia Papagiannaki
            logger.exception(e)
908 53161dd8 Sofia Papagiannaki
        return super(ExtendedSetPasswordForm, self).save(commit=commit)
909 e1a80257 Sofia Papagiannaki
910 e1a80257 Sofia Papagiannaki
911 e1a80257 Sofia Papagiannaki
class ProjectApplicationForm(forms.ModelForm):
912 e1a80257 Sofia Papagiannaki
    name = forms.CharField(
913 e1a80257 Sofia Papagiannaki
        validators=[validators.RegexValidator(
914 e1a80257 Sofia Papagiannaki
            DOMAIN_VALUE_REGEX,
915 e1a80257 Sofia Papagiannaki
            _(astakos_messages.DOMAIN_VALUE_ERR),
916 e1a80257 Sofia Papagiannaki
            'invalid'
917 e1a80257 Sofia Papagiannaki
        )],
918 e1a80257 Sofia Papagiannaki
        widget=forms.TextInput(attrs={'placeholder': 'eg. foo.ece.ntua.gr'}),
919 e1a80257 Sofia Papagiannaki
        help_text="Name should be in the form of dns"
920 e1a80257 Sofia Papagiannaki
    )
921 e1a80257 Sofia Papagiannaki
    comments = forms.CharField(widget=forms.Textarea, required=False)
922 e1a80257 Sofia Papagiannaki
    
923 e1a80257 Sofia Papagiannaki
    class Meta:
924 e1a80257 Sofia Papagiannaki
        model = ProjectDefinition
925 e1a80257 Sofia Papagiannaki
        exclude = ('resource_grants')
926 e1a80257 Sofia Papagiannaki
    
927 f3342849 Sofia Papagiannaki
    
928 e1a80257 Sofia Papagiannaki
    def clean(self):
929 e1a80257 Sofia Papagiannaki
        userid = self.data.get('user', None)[0]
930 e1a80257 Sofia Papagiannaki
        self.user = None
931 e1a80257 Sofia Papagiannaki
        if userid:
932 e1a80257 Sofia Papagiannaki
            try:
933 e1a80257 Sofia Papagiannaki
                self.user = AstakosUser.objects.get(id=userid)
934 e1a80257 Sofia Papagiannaki
            except AstakosUser.DoesNotExist:
935 e1a80257 Sofia Papagiannaki
                pass
936 e1a80257 Sofia Papagiannaki
        if not self.user:
937 e1a80257 Sofia Papagiannaki
            raise forms.ValidationError(_(astakos_messages.NO_APPLICANT))
938 e1a80257 Sofia Papagiannaki
        super(ProjectApplicationForm, self).clean()
939 e1a80257 Sofia Papagiannaki
        return self.cleaned_data
940 e1a80257 Sofia Papagiannaki
    
941 f3342849 Sofia Papagiannaki
    @property
942 f3342849 Sofia Papagiannaki
    def resource_policies(self):
943 e1a80257 Sofia Papagiannaki
        policies = []
944 e1a80257 Sofia Papagiannaki
        append = policies.append
945 f3342849 Sofia Papagiannaki
        for name, value in self.data.iteritems():
946 f3342849 Sofia Papagiannaki
            if not value:
947 f3342849 Sofia Papagiannaki
                continue
948 f3342849 Sofia Papagiannaki
            uplimit = value[0]
949 e1a80257 Sofia Papagiannaki
            subs = name.split('_uplimit')
950 e1a80257 Sofia Papagiannaki
            if len(subs) == 2:
951 e1a80257 Sofia Papagiannaki
                prefix, suffix = subs
952 e1a80257 Sofia Papagiannaki
                s, sep, r = prefix.partition(RESOURCE_SEPARATOR)
953 e1a80257 Sofia Papagiannaki
                resource = Resource.objects.get(service__name=s, name=r)
954 e1a80257 Sofia Papagiannaki
955 e1a80257 Sofia Papagiannaki
                # keep only resource limits for selected resource groups
956 f3342849 Sofia Papagiannaki
#                 if self.data.get(
957 f3342849 Sofia Papagiannaki
#                     'is_selected_%s' % resource.group, False
958 f3342849 Sofia Papagiannaki
#                 ):
959 f3342849 Sofia Papagiannaki
                if uplimit:
960 e1a80257 Sofia Papagiannaki
                    append(dict(service=s, resource=r, uplimit=uplimit))
961 e1a80257 Sofia Papagiannaki
        return policies
962 e1a80257 Sofia Papagiannaki
963 e1a80257 Sofia Papagiannaki
    def save(self, commit=True):
964 e1a80257 Sofia Papagiannaki
        definition = super(ProjectApplicationForm, self).save(commit=commit)
965 f3342849 Sofia Papagiannaki
        definition.resource_policies=self.resource_policies
966 e1a80257 Sofia Papagiannaki
        applicant = self.user
967 e1a80257 Sofia Papagiannaki
        comments = self.cleaned_data.pop('comments', None)
968 e1a80257 Sofia Papagiannaki
        try:
969 e1a80257 Sofia Papagiannaki
            precursor_application = self.instance.projectapplication
970 e1a80257 Sofia Papagiannaki
        except:
971 e1a80257 Sofia Papagiannaki
            precursor_application = None
972 f3342849 Sofia Papagiannaki
        return submit_application(
973 e1a80257 Sofia Papagiannaki
            definition,
974 e1a80257 Sofia Papagiannaki
            applicant,
975 e1a80257 Sofia Papagiannaki
            comments,
976 e1a80257 Sofia Papagiannaki
            precursor_application,
977 e1a80257 Sofia Papagiannaki
            commit
978 e1a80257 Sofia Papagiannaki
        )