Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / forms.py @ 7233d542

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

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

473 e2125441 Sofia Papagiannaki
    Since Django 1.3 this is useless since ``django.contrib.auth.views.reset_password``
474 e2125441 Sofia Papagiannaki
    accepts a from_email argument.
475 e2125441 Sofia Papagiannaki
    """
476 23c271b3 Sofia Papagiannaki
    def clean_email(self):
477 23c271b3 Sofia Papagiannaki
        email = super(ExtendedPasswordResetForm, self).clean_email()
478 23c271b3 Sofia Papagiannaki
        try:
479 789a5951 Sofia Papagiannaki
            user = AstakosUser.objects.get(email__iexact=email, is_active=True)
480 23c271b3 Sofia Papagiannaki
            if not user.has_usable_password():
481 ae497612 Olga Brani
                raise forms.ValidationError(_(astakos_messages.UNUSABLE_PASSWORD))
482 d2633501 Kostas Papadimitriou
483 d2633501 Kostas Papadimitriou
            if not user.can_change_password():
484 d2633501 Kostas Papadimitriou
                raise forms.ValidationError(_('Password change for this account'
485 d2633501 Kostas Papadimitriou
                                              ' is not supported.'))
486 d2633501 Kostas Papadimitriou
487 23c271b3 Sofia Papagiannaki
        except AstakosUser.DoesNotExist, e:
488 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.EMAIL_UNKNOWN))
489 23c271b3 Sofia Papagiannaki
        return email
490 ab8bfb29 Kostas Papadimitriou
491 5ce3ce4f Sofia Papagiannaki
    def save(
492 5ce3ce4f Sofia Papagiannaki
        self, domain_override=None, email_template_name='registration/password_reset_email.html',
493 5ce3ce4f Sofia Papagiannaki
            use_https=False, token_generator=default_token_generator, request=None):
494 e2125441 Sofia Papagiannaki
        """
495 e2125441 Sofia Papagiannaki
        Generates a one-use only link for resetting password and sends to the user.
496 e2125441 Sofia Papagiannaki
        """
497 e2125441 Sofia Papagiannaki
        for user in self.users_cache:
498 d2633501 Kostas Papadimitriou
            url = user.astakosuser.get_password_reset_url(token_generator)
499 a53b19da Sofia Papagiannaki
            url = urljoin(BASEURL, url)
500 e2125441 Sofia Papagiannaki
            t = loader.get_template(email_template_name)
501 e2125441 Sofia Papagiannaki
            c = {
502 e2125441 Sofia Papagiannaki
                'email': user.email,
503 8f378756 Sofia Papagiannaki
                'url': url,
504 374611bc Sofia Papagiannaki
                'site_name': SITENAME,
505 e2125441 Sofia Papagiannaki
                'user': user,
506 a53b19da Sofia Papagiannaki
                'baseurl': BASEURL,
507 09122dd8 Sofia Papagiannaki
                'support': DEFAULT_CONTACT_EMAIL
508 e2125441 Sofia Papagiannaki
            }
509 1cbce16f Sofia Papagiannaki
            from_email = settings.SERVER_EMAIL
510 1fcf4a99 Kostas Papadimitriou
            send_mail(_(PASSWORD_RESET_EMAIL_SUBJECT),
511 5ce3ce4f Sofia Papagiannaki
                      t.render(Context(c)), from_email, [user.email])
512 5ce3ce4f Sofia Papagiannaki
513 270dd48d Sofia Papagiannaki
514 49790d9d Sofia Papagiannaki
class EmailChangeForm(forms.ModelForm):
515 49790d9d Sofia Papagiannaki
    class Meta:
516 49790d9d Sofia Papagiannaki
        model = EmailChange
517 49790d9d Sofia Papagiannaki
        fields = ('new_email_address',)
518 ab8bfb29 Kostas Papadimitriou
519 49790d9d Sofia Papagiannaki
    def clean_new_email_address(self):
520 49790d9d Sofia Papagiannaki
        addr = self.cleaned_data['new_email_address']
521 49790d9d Sofia Papagiannaki
        if AstakosUser.objects.filter(email__iexact=addr):
522 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.EMAIL_USED))
523 49790d9d Sofia Papagiannaki
        return addr
524 ab8bfb29 Kostas Papadimitriou
525 49790d9d Sofia Papagiannaki
    def save(self, email_template_name, request, commit=True):
526 49790d9d Sofia Papagiannaki
        ec = super(EmailChangeForm, self).save(commit=False)
527 49790d9d Sofia Papagiannaki
        ec.user = request.user
528 5ce3ce4f Sofia Papagiannaki
        activation_key = hashlib.sha1(
529 5ce3ce4f Sofia Papagiannaki
            str(random()) + smart_str(ec.new_email_address))
530 5ce3ce4f Sofia Papagiannaki
        ec.activation_key = activation_key.hexdigest()
531 49790d9d Sofia Papagiannaki
        if commit:
532 49790d9d Sofia Papagiannaki
            ec.save()
533 49790d9d Sofia Papagiannaki
        send_change_email(ec, request, email_template_name=email_template_name)
534 49790d9d Sofia Papagiannaki
535 5ce3ce4f Sofia Papagiannaki
536 270dd48d Sofia Papagiannaki
class SignApprovalTermsForm(forms.ModelForm):
537 270dd48d Sofia Papagiannaki
    class Meta:
538 270dd48d Sofia Papagiannaki
        model = AstakosUser
539 270dd48d Sofia Papagiannaki
        fields = ("has_signed_terms",)
540 18ffbee1 Sofia Papagiannaki
541 270dd48d Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
542 270dd48d Sofia Papagiannaki
        super(SignApprovalTermsForm, self).__init__(*args, **kwargs)
543 18ffbee1 Sofia Papagiannaki
544 270dd48d Sofia Papagiannaki
    def clean_has_signed_terms(self):
545 270dd48d Sofia Papagiannaki
        has_signed_terms = self.cleaned_data['has_signed_terms']
546 270dd48d Sofia Papagiannaki
        if not has_signed_terms:
547 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.SIGN_TERMS))
548 270dd48d Sofia Papagiannaki
        return has_signed_terms
549 8f5a3a06 Sofia Papagiannaki
550 5ce3ce4f Sofia Papagiannaki
551 8f5a3a06 Sofia Papagiannaki
class InvitationForm(forms.ModelForm):
552 8f5a3a06 Sofia Papagiannaki
    username = forms.EmailField(label=_("Email"))
553 ab8bfb29 Kostas Papadimitriou
554 18ffbee1 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
555 18ffbee1 Sofia Papagiannaki
        super(InvitationForm, self).__init__(*args, **kwargs)
556 ab8bfb29 Kostas Papadimitriou
557 8f5a3a06 Sofia Papagiannaki
    class Meta:
558 8f5a3a06 Sofia Papagiannaki
        model = Invitation
559 8f5a3a06 Sofia Papagiannaki
        fields = ('username', 'realname')
560 ab8bfb29 Kostas Papadimitriou
561 8f5a3a06 Sofia Papagiannaki
    def clean_username(self):
562 8f5a3a06 Sofia Papagiannaki
        username = self.cleaned_data['username']
563 8f5a3a06 Sofia Papagiannaki
        try:
564 5ce3ce4f Sofia Papagiannaki
            Invitation.objects.get(username=username)
565 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.INVITATION_EMAIL_EXISTS))
566 8f5a3a06 Sofia Papagiannaki
        except Invitation.DoesNotExist:
567 8f5a3a06 Sofia Papagiannaki
            pass
568 18ffbee1 Sofia Papagiannaki
        return username
569 1039bab1 Sofia Papagiannaki
570 5ce3ce4f Sofia Papagiannaki
571 1039bab1 Sofia Papagiannaki
class ExtendedPasswordChangeForm(PasswordChangeForm):
572 1039bab1 Sofia Papagiannaki
    """
573 1039bab1 Sofia Papagiannaki
    Extends PasswordChangeForm by enabling user
574 1039bab1 Sofia Papagiannaki
    to optionally renew also the token.
575 1039bab1 Sofia Papagiannaki
    """
576 ee210d1d Sofia Papagiannaki
    if not NEWPASSWD_INVALIDATE_TOKEN:
577 48e9f076 Sofia Papagiannaki
        renew = forms.BooleanField(label='Renew token', required=False,
578 48e9f076 Sofia Papagiannaki
                                   initial=True,
579 48e9f076 Sofia Papagiannaki
                                   help_text='Unsetting this may result in security risk.')
580 ab8bfb29 Kostas Papadimitriou
581 1039bab1 Sofia Papagiannaki
    def __init__(self, user, *args, **kwargs):
582 bf0c6de5 Sofia Papagiannaki
        self.session_key = kwargs.pop('session_key', None)
583 1039bab1 Sofia Papagiannaki
        super(ExtendedPasswordChangeForm, self).__init__(user, *args, **kwargs)
584 ab8bfb29 Kostas Papadimitriou
585 1039bab1 Sofia Papagiannaki
    def save(self, commit=True):
586 bf0c6de5 Sofia Papagiannaki
        try:
587 bf0c6de5 Sofia Papagiannaki
            if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
588 bf0c6de5 Sofia Papagiannaki
                self.user.renew_token()
589 bf0c6de5 Sofia Papagiannaki
            self.user.flush_sessions(current_key=self.session_key)
590 bf0c6de5 Sofia Papagiannaki
        except AttributeError:
591 bf0c6de5 Sofia Papagiannaki
            # if user model does has not such methods
592 bf0c6de5 Sofia Papagiannaki
            pass
593 53161dd8 Sofia Papagiannaki
        return super(ExtendedPasswordChangeForm, self).save(commit=commit)
594 48e9f076 Sofia Papagiannaki
595 5ce3ce4f Sofia Papagiannaki
596 0f4fa26d Sofia Papagiannaki
class AstakosGroupCreationForm(forms.ModelForm):
597 0f4fa26d Sofia Papagiannaki
    kind = forms.ModelChoiceField(
598 0f4fa26d Sofia Papagiannaki
        queryset=GroupKind.objects.all(),
599 0f4fa26d Sofia Papagiannaki
        label="",
600 0f4fa26d Sofia Papagiannaki
        widget=forms.HiddenInput()
601 0f4fa26d Sofia Papagiannaki
    )
602 caf70869 Sofia Papagiannaki
    name = forms.CharField(
603 caf70869 Sofia Papagiannaki
        validators=[validators.RegexValidator(
604 caf70869 Sofia Papagiannaki
            DOMAIN_VALUE_REGEX,
605 caf70869 Sofia Papagiannaki
            _(astakos_messages.DOMAIN_VALUE_ERR), 'invalid'
606 caf70869 Sofia Papagiannaki
        )],
607 caf70869 Sofia Papagiannaki
        widget=forms.TextInput(attrs={'placeholder': 'eg. foo.ece.ntua.gr'}),
608 caf70869 Sofia Papagiannaki
        help_text="Name should be in the form of dns"
609 caf70869 Sofia Papagiannaki
    )
610 1831a0fe Olga Brani
    moderation_enabled = forms.BooleanField(
611 1831a0fe Olga Brani
        help_text="Check if you want to approve members participation manually",
612 8c804c12 Sofia Papagiannaki
        required=False,
613 8c804c12 Sofia Papagiannaki
        initial=True
614 1831a0fe Olga Brani
    )
615 9a06d96f Olga Brani
    max_participants = forms.IntegerField(
616 3cbd5e47 Olga Brani
        required=True, min_value=1
617 9a06d96f Olga Brani
    )
618 9a06d96f Olga Brani
619 0f4fa26d Sofia Papagiannaki
    class Meta:
620 0f4fa26d Sofia Papagiannaki
        model = AstakosGroup
621 5ce3ce4f Sofia Papagiannaki
622 0f4fa26d Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
623 9a06d96f Olga Brani
        #update QueryDict
624 9a06d96f Olga Brani
        args = list(args)
625 9a06d96f Olga Brani
        qd = args.pop(0).copy()
626 9a06d96f Olga Brani
        members_unlimited = qd.pop('members_unlimited', False)
627 9a06d96f Olga Brani
        members_uplimit = qd.pop('members_uplimit', None)
628 2e90e3ec Kostas Papadimitriou
629 9a06d96f Olga Brani
        #substitue QueryDict
630 9a06d96f Olga Brani
        args.insert(0, qd)
631 2e90e3ec Kostas Papadimitriou
632 0f4fa26d Sofia Papagiannaki
        super(AstakosGroupCreationForm, self).__init__(*args, **kwargs)
633 caf70869 Sofia Papagiannaki
        
634 9a06d96f Olga Brani
        self.fields.keyOrder = ['kind', 'name', 'homepage', 'desc',
635 9a06d96f Olga Brani
                                'issue_date', 'expiration_date',
636 9a06d96f Olga Brani
                                'moderation_enabled', 'max_participants']
637 8c804c12 Sofia Papagiannaki
        def add_fields((k, v)):
638 dcd1c383 Olga Brani
            k = k.partition('_proxy')[0]
639 9a06d96f Olga Brani
            self.fields[k] = forms.IntegerField(
640 0f4fa26d Sofia Papagiannaki
                required=False,
641 c3a905e7 Olga Brani
                widget=forms.HiddenInput(),
642 29b87e7c Sofia Papagiannaki
                min_value=1
643 0f4fa26d Sofia Papagiannaki
            )
644 8c804c12 Sofia Papagiannaki
        map(add_fields,
645 6abd262c Olga Brani
            ((k, v) for k,v in qd.iteritems() if k.endswith('_uplimit'))
646 9a06d96f Olga Brani
        )
647 2e90e3ec Kostas Papadimitriou
648 8c804c12 Sofia Papagiannaki
        def add_fields((k, v)):
649 8c804c12 Sofia Papagiannaki
            self.fields[k] = forms.BooleanField(
650 8c804c12 Sofia Papagiannaki
                required=False,
651 6abd262c Olga Brani
                #widget=forms.HiddenInput()
652 8c804c12 Sofia Papagiannaki
            )
653 8c804c12 Sofia Papagiannaki
        map(add_fields,
654 8c804c12 Sofia Papagiannaki
            ((k, v) for k,v in qd.iteritems() if k.startswith('is_selected_'))
655 8c804c12 Sofia Papagiannaki
        )
656 2e90e3ec Kostas Papadimitriou
657 29b87e7c Sofia Papagiannaki
    def policies(self):
658 29b87e7c Sofia Papagiannaki
        self.clean()
659 29b87e7c Sofia Papagiannaki
        policies = []
660 29b87e7c Sofia Papagiannaki
        append = policies.append
661 29b87e7c Sofia Papagiannaki
        for name, uplimit in self.cleaned_data.iteritems():
662 2e90e3ec Kostas Papadimitriou
663 29b87e7c Sofia Papagiannaki
            subs = name.split('_uplimit')
664 29b87e7c Sofia Papagiannaki
            if len(subs) == 2:
665 29b87e7c Sofia Papagiannaki
                prefix, suffix = subs
666 930f09ba Sofia Papagiannaki
                s, sep, r = prefix.partition(RESOURCE_SEPARATOR)
667 29b87e7c Sofia Papagiannaki
                resource = Resource.objects.get(service__name=s, name=r)
668 2e90e3ec Kostas Papadimitriou
669 29b87e7c Sofia Papagiannaki
                # keep only resource limits for selected resource groups
670 29b87e7c Sofia Papagiannaki
                if self.cleaned_data.get(
671 c3a905e7 Olga Brani
                    'is_selected_%s' % resource.group, False
672 29b87e7c Sofia Papagiannaki
                ):
673 29b87e7c Sofia Papagiannaki
                    append(dict(service=s, resource=r, uplimit=uplimit))
674 29b87e7c Sofia Papagiannaki
        return policies
675 29b87e7c Sofia Papagiannaki
676 29b87e7c Sofia Papagiannaki
class AstakosGroupCreationSummaryForm(forms.ModelForm):
677 29b87e7c Sofia Papagiannaki
    kind = forms.ModelChoiceField(
678 29b87e7c Sofia Papagiannaki
        queryset=GroupKind.objects.all(),
679 29b87e7c Sofia Papagiannaki
        label="",
680 29b87e7c Sofia Papagiannaki
        widget=forms.HiddenInput()
681 29b87e7c Sofia Papagiannaki
    )
682 caf70869 Sofia Papagiannaki
    name = forms.CharField(
683 caf70869 Sofia Papagiannaki
        widget=forms.TextInput(attrs={'placeholder': 'eg. foo.ece.ntua.gr'}),
684 caf70869 Sofia Papagiannaki
        help_text="Name should be in the form of dns"
685 caf70869 Sofia Papagiannaki
    )
686 29b87e7c Sofia Papagiannaki
    moderation_enabled = forms.BooleanField(
687 29b87e7c Sofia Papagiannaki
        help_text="Check if you want to approve members participation manually",
688 29b87e7c Sofia Papagiannaki
        required=False,
689 29b87e7c Sofia Papagiannaki
        initial=True
690 29b87e7c Sofia Papagiannaki
    )
691 29b87e7c Sofia Papagiannaki
    max_participants = forms.IntegerField(
692 29b87e7c Sofia Papagiannaki
        required=False, min_value=1
693 29b87e7c Sofia Papagiannaki
    )
694 29b87e7c Sofia Papagiannaki
695 29b87e7c Sofia Papagiannaki
    class Meta:
696 29b87e7c Sofia Papagiannaki
        model = AstakosGroup
697 29b87e7c Sofia Papagiannaki
698 29b87e7c Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
699 29b87e7c Sofia Papagiannaki
        #update QueryDict
700 29b87e7c Sofia Papagiannaki
        args = list(args)
701 29b87e7c Sofia Papagiannaki
        qd = args.pop(0).copy()
702 29b87e7c Sofia Papagiannaki
        members_unlimited = qd.pop('members_unlimited', False)
703 29b87e7c Sofia Papagiannaki
        members_uplimit = qd.pop('members_uplimit', None)
704 2e90e3ec Kostas Papadimitriou
705 29b87e7c Sofia Papagiannaki
        #substitue QueryDict
706 29b87e7c Sofia Papagiannaki
        args.insert(0, qd)
707 2e90e3ec Kostas Papadimitriou
708 29b87e7c Sofia Papagiannaki
        super(AstakosGroupCreationSummaryForm, self).__init__(*args, **kwargs)
709 29b87e7c Sofia Papagiannaki
        self.fields.keyOrder = ['kind', 'name', 'homepage', 'desc',
710 29b87e7c Sofia Papagiannaki
                                'issue_date', 'expiration_date',
711 29b87e7c Sofia Papagiannaki
                                'moderation_enabled', 'max_participants']
712 29b87e7c Sofia Papagiannaki
        def add_fields((k, v)):
713 29b87e7c Sofia Papagiannaki
            self.fields[k] = forms.IntegerField(
714 29b87e7c Sofia Papagiannaki
                required=False,
715 c3a905e7 Olga Brani
                widget=forms.TextInput(),
716 29b87e7c Sofia Papagiannaki
                min_value=1
717 29b87e7c Sofia Papagiannaki
            )
718 29b87e7c Sofia Papagiannaki
        map(add_fields,
719 29b87e7c Sofia Papagiannaki
            ((k, v) for k,v in qd.iteritems() if k.endswith('_uplimit'))
720 29b87e7c Sofia Papagiannaki
        )
721 2e90e3ec Kostas Papadimitriou
722 29b87e7c Sofia Papagiannaki
        def add_fields((k, v)):
723 29b87e7c Sofia Papagiannaki
            self.fields[k] = forms.BooleanField(
724 29b87e7c Sofia Papagiannaki
                required=False,
725 c3a905e7 Olga Brani
                widget=forms.HiddenInput()
726 29b87e7c Sofia Papagiannaki
            )
727 29b87e7c Sofia Papagiannaki
        map(add_fields,
728 29b87e7c Sofia Papagiannaki
            ((k, v) for k,v in qd.iteritems() if k.startswith('is_selected_'))
729 29b87e7c Sofia Papagiannaki
        )
730 29b87e7c Sofia Papagiannaki
        for f in self.fields.values():
731 29b87e7c Sofia Papagiannaki
            f.widget = forms.HiddenInput()
732 29b87e7c Sofia Papagiannaki
733 820b18e0 Sofia Papagiannaki
    def clean(self):
734 29b87e7c Sofia Papagiannaki
        super(AstakosGroupCreationSummaryForm, self).clean()
735 820b18e0 Sofia Papagiannaki
        self.cleaned_data['policies'] = []
736 820b18e0 Sofia Papagiannaki
        append = self.cleaned_data['policies'].append
737 c3a905e7 Olga Brani
        #tbd = [f for f in self.fields if (f.startswith('is_selected_') and (not f.endswith('_proxy')))]
738 8c804c12 Sofia Papagiannaki
        tbd = [f for f in self.fields if f.startswith('is_selected_')]
739 9a06d96f Olga Brani
        for name, uplimit in self.cleaned_data.iteritems():
740 9a06d96f Olga Brani
            subs = name.split('_uplimit')
741 9a06d96f Olga Brani
            if len(subs) == 2:
742 820b18e0 Sofia Papagiannaki
                tbd.append(name)
743 9a06d96f Olga Brani
                prefix, suffix = subs
744 930f09ba Sofia Papagiannaki
                s, sep, r = prefix.partition(RESOURCE_SEPARATOR)
745 8c804c12 Sofia Papagiannaki
                resource = Resource.objects.get(service__name=s, name=r)
746 2e90e3ec Kostas Papadimitriou
747 8c804c12 Sofia Papagiannaki
                # keep only resource limits for selected resource groups
748 8c804c12 Sofia Papagiannaki
                if self.cleaned_data.get(
749 3cbd5e47 Olga Brani
                    'is_selected_%s' % resource.group, False
750 8c804c12 Sofia Papagiannaki
                ):
751 8c804c12 Sofia Papagiannaki
                    append(dict(service=s, resource=r, uplimit=uplimit))
752 29b87e7c Sofia Papagiannaki
        for name in tbd:
753 29b87e7c Sofia Papagiannaki
            self.cleaned_data.pop(name, None)
754 820b18e0 Sofia Papagiannaki
        return self.cleaned_data
755 01ac12d5 Sofia Papagiannaki
756 51c57c9c Sofia Papagiannaki
class AstakosGroupUpdateForm(forms.ModelForm):
757 51c57c9c Sofia Papagiannaki
    class Meta:
758 51c57c9c Sofia Papagiannaki
        model = AstakosGroup
759 463a973c Sofia Papagiannaki
        fields = ( 'desc','homepage', 'moderation_enabled')
760 5ce3ce4f Sofia Papagiannaki
761 9a06d96f Olga Brani
762 a4233484 Sofia Papagiannaki
class AddGroupMembersForm(forms.Form):
763 9a06d96f Olga Brani
    q = forms.CharField(
764 c3a905e7 Olga Brani
        max_length=800, widget=forms.Textarea, label=_('Add members'),
765 ae497612 Olga Brani
        help_text=_(astakos_messages.ADD_GROUP_MEMBERS_Q_HELP),
766 9a06d96f Olga Brani
        required=True)
767 9a06d96f Olga Brani
768 a4233484 Sofia Papagiannaki
    def clean(self):
769 a4233484 Sofia Papagiannaki
        q = self.cleaned_data.get('q') or ''
770 a4233484 Sofia Papagiannaki
        users = q.split(',')
771 a4233484 Sofia Papagiannaki
        users = list(u.strip() for u in users if u)
772 a4233484 Sofia Papagiannaki
        db_entries = AstakosUser.objects.filter(email__in=users)
773 a4233484 Sofia Papagiannaki
        unknown = list(set(users) - set(u.email for u in db_entries))
774 a4233484 Sofia Papagiannaki
        if unknown:
775 ae497612 Olga Brani
            raise forms.ValidationError(_(astakos_messages.UNKNOWN_USERS) % ','.join(unknown))
776 a4233484 Sofia Papagiannaki
        self.valid_users = db_entries
777 a4233484 Sofia Papagiannaki
        return self.cleaned_data
778 9a06d96f Olga Brani
779 a4233484 Sofia Papagiannaki
    def get_valid_users(self):
780 a4233484 Sofia Papagiannaki
        """Should be called after form cleaning"""
781 a4233484 Sofia Papagiannaki
        try:
782 a4233484 Sofia Papagiannaki
            return self.valid_users
783 a4233484 Sofia Papagiannaki
        except:
784 a4233484 Sofia Papagiannaki
            return ()
785 a4233484 Sofia Papagiannaki
786 a4233484 Sofia Papagiannaki
787 01ac12d5 Sofia Papagiannaki
class AstakosGroupSearchForm(forms.Form):
788 59728d4e Olga Brani
    q = forms.CharField(max_length=200, label='Search project')
789 789bcaf9 Sofia Papagiannaki
790 9a06d96f Olga Brani
791 54213d7a Sofia Papagiannaki
class TimelineForm(forms.Form):
792 88305cf0 root
    entity = forms.ModelChoiceField(
793 9a06d96f Olga Brani
        queryset=AstakosUser.objects.filter(is_active=True)
794 88305cf0 root
    )
795 54213d7a Sofia Papagiannaki
    resource = forms.ModelChoiceField(
796 6e52912b Sofia Papagiannaki
        queryset=Resource.objects.all()
797 54213d7a Sofia Papagiannaki
    )
798 54213d7a Sofia Papagiannaki
    start_date = forms.DateTimeField()
799 54213d7a Sofia Papagiannaki
    end_date = forms.DateTimeField()
800 82b05401 root
    details = forms.BooleanField(required=False, label="Detailed Listing")
801 82b05401 root
    operation = forms.ChoiceField(
802 9a06d96f Olga Brani
        label='Charge Method',
803 9a06d96f Olga Brani
        choices=(('', '-------------'),
804 9a06d96f Olga Brani
                 ('charge_usage', 'Charge Usage'),
805 9a06d96f Olga Brani
                 ('charge_traffic', 'Charge Traffic'), )
806 9a06d96f Olga Brani
    )
807 9a06d96f Olga Brani
808 6e52912b Sofia Papagiannaki
    def clean(self):
809 6e52912b Sofia Papagiannaki
        super(TimelineForm, self).clean()
810 6e52912b Sofia Papagiannaki
        d = self.cleaned_data
811 6e52912b Sofia Papagiannaki
        if 'resource' in d:
812 6e52912b Sofia Papagiannaki
            d['resource'] = str(d['resource'])
813 6e52912b Sofia Papagiannaki
        if 'start_date' in d:
814 9a06d96f Olga Brani
            d['start_date'] = d['start_date'].strftime(
815 9a06d96f Olga Brani
                "%Y-%m-%dT%H:%M:%S.%f")[:24]
816 6e52912b Sofia Papagiannaki
        if 'end_date' in d:
817 c3f6cdf1 root
            d['end_date'] = d['end_date'].strftime("%Y-%m-%dT%H:%M:%S.%f")[:24]
818 9a06d96f Olga Brani
        if 'entity' in d:
819 c9015cf6 Sofia Papagiannaki
            d['entity'] = d['entity'].email
820 c3f6cdf1 root
        return d
821 c3f6cdf1 root
822 9a06d96f Olga Brani
823 789bcaf9 Sofia Papagiannaki
class AstakosGroupSortForm(forms.Form):
824 098f333b Sofia Papagiannaki
    sorting = forms.ChoiceField(
825 098f333b Sofia Papagiannaki
        label='Sort by',
826 098f333b Sofia Papagiannaki
        choices=(
827 098f333b Sofia Papagiannaki
            ('groupname', 'Name'),
828 098f333b Sofia Papagiannaki
            ('issue_date', 'Issue Date'),
829 098f333b Sofia Papagiannaki
            ('expiration_date', 'Expiration Date'),
830 098f333b Sofia Papagiannaki
            ('approved_members_num', 'Participants'),
831 098f333b Sofia Papagiannaki
            ('moderation_enabled', 'Moderation'),
832 098f333b Sofia Papagiannaki
            ('membership_status', 'Enrollment Status')
833 098f333b Sofia Papagiannaki
        ),
834 098f333b Sofia Papagiannaki
        required=True
835 098f333b Sofia Papagiannaki
    )
836 9a06d96f Olga Brani
837 801be7a3 Sofia Papagiannaki
class MembersSortForm(forms.Form):
838 bfaeedb6 Sofia Papagiannaki
    sorting = forms.ChoiceField(
839 bfaeedb6 Sofia Papagiannaki
        label='Sort by',
840 bfaeedb6 Sofia Papagiannaki
        choices=(('person__email', 'User Id'),
841 bfaeedb6 Sofia Papagiannaki
                 ('person__first_name', 'Name'),
842 bfaeedb6 Sofia Papagiannaki
                 ('date_joined', 'Status')
843 bfaeedb6 Sofia Papagiannaki
        ),
844 bfaeedb6 Sofia Papagiannaki
        required=True
845 bfaeedb6 Sofia Papagiannaki
    )
846 9eafaa32 Sofia Papagiannaki
847 9eafaa32 Sofia Papagiannaki
class PickResourceForm(forms.Form):
848 9eafaa32 Sofia Papagiannaki
    resource = forms.ModelChoiceField(
849 9eafaa32 Sofia Papagiannaki
        queryset=Resource.objects.select_related().all()
850 9eafaa32 Sofia Papagiannaki
    )
851 9a06d96f Olga Brani
    resource.widget.attrs["onchange"] = "this.form.submit()"
852 9a06d96f Olga Brani
853 9a06d96f Olga Brani
854 48e9f076 Sofia Papagiannaki
class ExtendedSetPasswordForm(SetPasswordForm):
855 48e9f076 Sofia Papagiannaki
    """
856 48e9f076 Sofia Papagiannaki
    Extends SetPasswordForm by enabling user
857 48e9f076 Sofia Papagiannaki
    to optionally renew also the token.
858 48e9f076 Sofia Papagiannaki
    """
859 ee210d1d Sofia Papagiannaki
    if not NEWPASSWD_INVALIDATE_TOKEN:
860 bf0c6de5 Sofia Papagiannaki
        renew = forms.BooleanField(
861 bf0c6de5 Sofia Papagiannaki
            label='Renew token',
862 bf0c6de5 Sofia Papagiannaki
            required=False,
863 bf0c6de5 Sofia Papagiannaki
            initial=True,
864 bf0c6de5 Sofia Papagiannaki
            help_text='Unsetting this may result in security risk.'
865 bf0c6de5 Sofia Papagiannaki
        )
866 2e90e3ec Kostas Papadimitriou
867 48e9f076 Sofia Papagiannaki
    def __init__(self, user, *args, **kwargs):
868 48e9f076 Sofia Papagiannaki
        super(ExtendedSetPasswordForm, self).__init__(user, *args, **kwargs)
869 d2633501 Kostas Papadimitriou
870 d2633501 Kostas Papadimitriou
    @transaction.commit_on_success()
871 48e9f076 Sofia Papagiannaki
    def save(self, commit=True):
872 bf0c6de5 Sofia Papagiannaki
        try:
873 bf0c6de5 Sofia Papagiannaki
            self.user = AstakosUser.objects.get(id=self.user.id)
874 bf0c6de5 Sofia Papagiannaki
            if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
875 53161dd8 Sofia Papagiannaki
                self.user.renew_token()
876 d2633501 Kostas Papadimitriou
            #self.user.flush_sessions()
877 d2633501 Kostas Papadimitriou
            if not self.user.has_auth_provider('local'):
878 d2633501 Kostas Papadimitriou
                self.user.add_auth_provider('local', auth_backend='astakos')
879 d2633501 Kostas Papadimitriou
880 bf0c6de5 Sofia Papagiannaki
        except BaseException, e:
881 bf0c6de5 Sofia Papagiannaki
            logger.exception(e)
882 53161dd8 Sofia Papagiannaki
        return super(ExtendedSetPasswordForm, self).save(commit=commit)