Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (12.2 kB)

1 aba1e498 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 64cd4730 Antony Chazapis
# 
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 64cd4730 Antony Chazapis
# 
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 64cd4730 Antony Chazapis
# 
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 64cd4730 Antony Chazapis
# 
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 64cd4730 Antony Chazapis
# 
29 64cd4730 Antony Chazapis
# The views and conclusions contained in the software and
30 64cd4730 Antony Chazapis
# documentation are those of the authors and should not be
31 64cd4730 Antony Chazapis
# interpreted as representing official policies, either expressed
32 64cd4730 Antony Chazapis
# or implied, of GRNET S.A.
33 8f378756 Sofia Papagiannaki
from urlparse import urljoin
34 270dd48d Sofia Papagiannaki
from datetime import datetime
35 64cd4730 Antony Chazapis
36 64cd4730 Antony Chazapis
from django import forms
37 64cd4730 Antony Chazapis
from django.utils.translation import ugettext as _
38 e2125441 Sofia Papagiannaki
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, PasswordResetForm
39 e2125441 Sofia Papagiannaki
from django.core.mail import send_mail
40 e2125441 Sofia Papagiannaki
from django.contrib.auth.tokens import default_token_generator
41 e2125441 Sofia Papagiannaki
from django.template import Context, loader
42 e2125441 Sofia Papagiannaki
from django.utils.http import int_to_base36
43 374611bc Sofia Papagiannaki
from django.core.urlresolvers import reverse
44 270dd48d Sofia Papagiannaki
from django.utils.functional import lazy
45 5ed6816e Sofia Papagiannaki
46 0905ccd2 Sofia Papagiannaki
from astakos.im.models import AstakosUser
47 53bf2659 Sofia Papagiannaki
from astakos.im.settings import INVITATIONS_PER_LEVEL, DEFAULT_FROM_EMAIL, BASEURL, SITENAME, RECAPTCHA_PRIVATE_KEY, DEFAULT_CONTACT_EMAIL, RECAPTCHA_ENABLED
48 270dd48d Sofia Papagiannaki
from astakos.im.widgets import DummyWidget, RecaptchaWidget, ApprovalTermsWidget
49 270dd48d Sofia Papagiannaki
50 270dd48d Sofia Papagiannaki
# since Django 1.4 use django.core.urlresolvers.reverse_lazy instead
51 d8f63346 Sofia Papagiannaki
from astakos.im.util import reverse_lazy, get_latest_terms
52 64cd4730 Antony Chazapis
53 3bf924ec Sofia Papagiannaki
import logging
54 db7fecd9 Sofia Papagiannaki
import recaptcha.client.captcha as captcha
55 64cd4730 Antony Chazapis
56 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
57 e015e9e6 Sofia Papagiannaki
58 15efc749 Sofia Papagiannaki
class LocalUserCreationForm(UserCreationForm):
59 890b0eaf Sofia Papagiannaki
    """
60 890b0eaf Sofia Papagiannaki
    Extends the built in UserCreationForm in several ways:
61 64cd4730 Antony Chazapis
    
62 8316698a Sofia Papagiannaki
    * Adds email, first_name, last_name, recaptcha_challenge_field, recaptcha_response_field field.
63 5ed6816e Sofia Papagiannaki
    * The username field isn't visible and it is assigned a generated id.
64 af4eb974 Sofia Papagiannaki
    * User created is not active. 
65 890b0eaf Sofia Papagiannaki
    """
66 db7fecd9 Sofia Papagiannaki
    recaptcha_challenge_field = forms.CharField(widget=DummyWidget)
67 db7fecd9 Sofia Papagiannaki
    recaptcha_response_field = forms.CharField(widget=RecaptchaWidget, label='')
68 890b0eaf Sofia Papagiannaki
    
69 794852f2 Sofia Papagiannaki
    class Meta:
70 794852f2 Sofia Papagiannaki
        model = AstakosUser
71 270dd48d Sofia Papagiannaki
        fields = ("email", "first_name", "last_name", "has_signed_terms")
72 270dd48d Sofia Papagiannaki
        widgets = {"has_signed_terms":ApprovalTermsWidget(terms_uri=reverse_lazy('latest_terms'))}
73 64cd4730 Antony Chazapis
    
74 64cd4730 Antony Chazapis
    def __init__(self, *args, **kwargs):
75 64cd4730 Antony Chazapis
        """
76 890b0eaf Sofia Papagiannaki
        Changes the order of fields, and removes the username field.
77 64cd4730 Antony Chazapis
        """
78 db7fecd9 Sofia Papagiannaki
        if 'ip' in kwargs:
79 db7fecd9 Sofia Papagiannaki
            self.ip = kwargs['ip']
80 db7fecd9 Sofia Papagiannaki
            kwargs.pop('ip')
81 15efc749 Sofia Papagiannaki
        super(LocalUserCreationForm, self).__init__(*args, **kwargs)
82 890b0eaf Sofia Papagiannaki
        self.fields.keyOrder = ['email', 'first_name', 'last_name',
83 d8f63346 Sofia Papagiannaki
                                'password1', 'password2']
84 d8f63346 Sofia Papagiannaki
        if get_latest_terms():
85 d8f63346 Sofia Papagiannaki
            self.fields.keyOrder.append('has_signed_terms')
86 53bf2659 Sofia Papagiannaki
        if RECAPTCHA_ENABLED:
87 53bf2659 Sofia Papagiannaki
            self.fields.keyOrder.extend(['recaptcha_challenge_field',
88 53bf2659 Sofia Papagiannaki
                                         'recaptcha_response_field',])
89 64cd4730 Antony Chazapis
    
90 af4eb974 Sofia Papagiannaki
    def clean_email(self):
91 af4eb974 Sofia Papagiannaki
        email = self.cleaned_data['email']
92 881c856c Sofia Papagiannaki
        if not email:
93 881c856c Sofia Papagiannaki
            raise forms.ValidationError(_("This field is required"))
94 af4eb974 Sofia Papagiannaki
        try:
95 af4eb974 Sofia Papagiannaki
            AstakosUser.objects.get(email = email)
96 c37263ea Sofia Papagiannaki
            raise forms.ValidationError(_("This email is already used"))
97 af4eb974 Sofia Papagiannaki
        except AstakosUser.DoesNotExist:
98 af4eb974 Sofia Papagiannaki
            return email
99 af4eb974 Sofia Papagiannaki
    
100 270dd48d Sofia Papagiannaki
    def clean_has_signed_terms(self):
101 270dd48d Sofia Papagiannaki
        has_signed_terms = self.cleaned_data['has_signed_terms']
102 270dd48d Sofia Papagiannaki
        if not has_signed_terms:
103 270dd48d Sofia Papagiannaki
            raise forms.ValidationError(_('You have to agree with the terms'))
104 270dd48d Sofia Papagiannaki
        return has_signed_terms
105 270dd48d Sofia Papagiannaki
    
106 db7fecd9 Sofia Papagiannaki
    def clean_recaptcha_response_field(self):
107 db7fecd9 Sofia Papagiannaki
        if 'recaptcha_challenge_field' in self.cleaned_data:
108 db7fecd9 Sofia Papagiannaki
            self.validate_captcha()
109 db7fecd9 Sofia Papagiannaki
        return self.cleaned_data['recaptcha_response_field']
110 db7fecd9 Sofia Papagiannaki
111 db7fecd9 Sofia Papagiannaki
    def clean_recaptcha_challenge_field(self):
112 db7fecd9 Sofia Papagiannaki
        if 'recaptcha_response_field' in self.cleaned_data:
113 db7fecd9 Sofia Papagiannaki
            self.validate_captcha()
114 db7fecd9 Sofia Papagiannaki
        return self.cleaned_data['recaptcha_challenge_field']
115 db7fecd9 Sofia Papagiannaki
116 db7fecd9 Sofia Papagiannaki
    def validate_captcha(self):
117 db7fecd9 Sofia Papagiannaki
        rcf = self.cleaned_data['recaptcha_challenge_field']
118 db7fecd9 Sofia Papagiannaki
        rrf = self.cleaned_data['recaptcha_response_field']
119 db7fecd9 Sofia Papagiannaki
        check = captcha.submit(rcf, rrf, RECAPTCHA_PRIVATE_KEY, self.ip)
120 db7fecd9 Sofia Papagiannaki
        if not check.is_valid:
121 db7fecd9 Sofia Papagiannaki
            raise forms.ValidationError(_('You have not entered the correct words'))
122 db7fecd9 Sofia Papagiannaki
    
123 890b0eaf Sofia Papagiannaki
    def save(self, commit=True):
124 64cd4730 Antony Chazapis
        """
125 890b0eaf Sofia Papagiannaki
        Saves the email, first_name and last_name properties, after the normal
126 890b0eaf Sofia Papagiannaki
        save behavior is complete.
127 890b0eaf Sofia Papagiannaki
        """
128 15efc749 Sofia Papagiannaki
        user = super(LocalUserCreationForm, self).save(commit=False)
129 3bf924ec Sofia Papagiannaki
        user.renew_token()
130 270dd48d Sofia Papagiannaki
        user.date_signed_terms = datetime.now()
131 9fb8e808 Sofia Papagiannaki
        if commit:
132 9fb8e808 Sofia Papagiannaki
            user.save()
133 e015e9e6 Sofia Papagiannaki
        logger.info('Created user %s', user)
134 890b0eaf Sofia Papagiannaki
        return user
135 64cd4730 Antony Chazapis
136 15efc749 Sofia Papagiannaki
class InvitedLocalUserCreationForm(LocalUserCreationForm):
137 890b0eaf Sofia Papagiannaki
    """
138 15efc749 Sofia Papagiannaki
    Extends the LocalUserCreationForm: adds an inviter readonly field.
139 890b0eaf Sofia Papagiannaki
    """
140 3bf924ec Sofia Papagiannaki
    
141 3bf924ec Sofia Papagiannaki
    inviter = forms.CharField(widget=forms.TextInput(), label=_('Inviter Real Name'))
142 64cd4730 Antony Chazapis
    
143 794852f2 Sofia Papagiannaki
    class Meta:
144 794852f2 Sofia Papagiannaki
        model = AstakosUser
145 270dd48d Sofia Papagiannaki
        fields = ("email", "first_name", "last_name", "has_signed_terms")
146 270dd48d Sofia Papagiannaki
        widgets = {"has_signed_terms":ApprovalTermsWidget(terms_uri=reverse_lazy('latest_terms'))}
147 64cd4730 Antony Chazapis
    
148 64cd4730 Antony Chazapis
    def __init__(self, *args, **kwargs):
149 64cd4730 Antony Chazapis
        """
150 3bf924ec Sofia Papagiannaki
        Changes the order of fields, and removes the username field.
151 64cd4730 Antony Chazapis
        """
152 15efc749 Sofia Papagiannaki
        super(InvitedLocalUserCreationForm, self).__init__(*args, **kwargs)
153 53bf2659 Sofia Papagiannaki
        
154 64cd4730 Antony Chazapis
        #set readonly form fields
155 64cd4730 Antony Chazapis
        self.fields['inviter'].widget.attrs['readonly'] = True
156 794852f2 Sofia Papagiannaki
        self.fields['email'].widget.attrs['readonly'] = True
157 794852f2 Sofia Papagiannaki
        self.fields['username'].widget.attrs['readonly'] = True
158 9fb8e808 Sofia Papagiannaki
    
159 9fb8e808 Sofia Papagiannaki
    def save(self, commit=True):
160 15efc749 Sofia Papagiannaki
        user = super(InvitedLocalUserCreationForm, self).save(commit=False)
161 881c856c Sofia Papagiannaki
        level = user.invitation.inviter.level + 1
162 881c856c Sofia Papagiannaki
        user.level = level
163 8316698a Sofia Papagiannaki
        user.invitations = INVITATIONS_PER_LEVEL.get(level, 0)
164 8316698a Sofia Papagiannaki
        user.email_verified = True
165 9fb8e808 Sofia Papagiannaki
        if commit:
166 9fb8e808 Sofia Papagiannaki
            user.save()
167 9fb8e808 Sofia Papagiannaki
        return user
168 5ed6816e Sofia Papagiannaki
169 5ed6816e Sofia Papagiannaki
class LoginForm(AuthenticationForm):
170 5ed6816e Sofia Papagiannaki
    username = forms.EmailField(label=_("Email"))
171 64cd4730 Antony Chazapis
172 890b0eaf Sofia Papagiannaki
class ProfileForm(forms.ModelForm):
173 890b0eaf Sofia Papagiannaki
    """
174 890b0eaf Sofia Papagiannaki
    Subclass of ``ModelForm`` for permiting user to edit his/her profile.
175 890b0eaf Sofia Papagiannaki
    Most of the fields are readonly since the user is not allowed to change them.
176 890b0eaf Sofia Papagiannaki
    
177 890b0eaf Sofia Papagiannaki
    The class defines a save method which sets ``is_verified`` to True so as the user
178 890b0eaf Sofia Papagiannaki
    during the next login will not to be redirected to profile page.
179 890b0eaf Sofia Papagiannaki
    """
180 c301698f Sofia Papagiannaki
    renew = forms.BooleanField(label='Renew token', required=False)
181 c301698f Sofia Papagiannaki
    
182 890b0eaf Sofia Papagiannaki
    class Meta:
183 890b0eaf Sofia Papagiannaki
        model = AstakosUser
184 a196eb7e Sofia Papagiannaki
        fields = ('email', 'first_name', 'last_name', 'auth_token', 'auth_token_expires')
185 64cd4730 Antony Chazapis
    
186 64cd4730 Antony Chazapis
    def __init__(self, *args, **kwargs):
187 890b0eaf Sofia Papagiannaki
        super(ProfileForm, self).__init__(*args, **kwargs)
188 890b0eaf Sofia Papagiannaki
        instance = getattr(self, 'instance', None)
189 a196eb7e Sofia Papagiannaki
        ro_fields = ('auth_token', 'auth_token_expires', 'email')
190 890b0eaf Sofia Papagiannaki
        if instance and instance.id:
191 890b0eaf Sofia Papagiannaki
            for field in ro_fields:
192 890b0eaf Sofia Papagiannaki
                self.fields[field].widget.attrs['readonly'] = True
193 890b0eaf Sofia Papagiannaki
    
194 890b0eaf Sofia Papagiannaki
    def save(self, commit=True):
195 890b0eaf Sofia Papagiannaki
        user = super(ProfileForm, self).save(commit=False)
196 890b0eaf Sofia Papagiannaki
        user.is_verified = True
197 c301698f Sofia Papagiannaki
        if self.cleaned_data.get('renew'):
198 c301698f Sofia Papagiannaki
            user.renew_token()
199 890b0eaf Sofia Papagiannaki
        if commit:
200 890b0eaf Sofia Papagiannaki
            user.save()
201 890b0eaf Sofia Papagiannaki
        return user
202 64cd4730 Antony Chazapis
203 15efc749 Sofia Papagiannaki
class ThirdPartyUserCreationForm(ProfileForm):
204 15efc749 Sofia Papagiannaki
    class Meta:
205 15efc749 Sofia Papagiannaki
        model = AstakosUser
206 15efc749 Sofia Papagiannaki
        fields = ('email', 'last_name', 'first_name', 'affiliation', 'provider', 'third_party_identifier')
207 15efc749 Sofia Papagiannaki
    
208 15efc749 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
209 db7fecd9 Sofia Papagiannaki
        if 'ip' in kwargs:
210 db7fecd9 Sofia Papagiannaki
            self.ip = kwargs['ip']
211 db7fecd9 Sofia Papagiannaki
            kwargs.pop('ip')
212 15efc749 Sofia Papagiannaki
        super(ThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
213 15efc749 Sofia Papagiannaki
        self.fields.keyOrder = ['email']
214 15efc749 Sofia Papagiannaki
    
215 15efc749 Sofia Papagiannaki
    def clean_email(self):
216 15efc749 Sofia Papagiannaki
        email = self.cleaned_data['email']
217 15efc749 Sofia Papagiannaki
        if not email:
218 15efc749 Sofia Papagiannaki
            raise forms.ValidationError(_("This field is required"))
219 15efc749 Sofia Papagiannaki
        try:
220 15efc749 Sofia Papagiannaki
            user = AstakosUser.objects.get(email = email)
221 c37263ea Sofia Papagiannaki
            raise forms.ValidationError(_("This email is already used"))
222 15efc749 Sofia Papagiannaki
        except AstakosUser.DoesNotExist:
223 15efc749 Sofia Papagiannaki
            return email
224 15efc749 Sofia Papagiannaki
    
225 15efc749 Sofia Papagiannaki
    def save(self, commit=True):
226 15efc749 Sofia Papagiannaki
        user = super(ThirdPartyUserCreationForm, self).save(commit=False)
227 15efc749 Sofia Papagiannaki
        user.verified = False
228 15efc749 Sofia Papagiannaki
        user.renew_token()
229 15efc749 Sofia Papagiannaki
        if commit:
230 15efc749 Sofia Papagiannaki
            user.save()
231 e015e9e6 Sofia Papagiannaki
        logger.info('Created user %s', user)
232 15efc749 Sofia Papagiannaki
        return user
233 15efc749 Sofia Papagiannaki
234 15efc749 Sofia Papagiannaki
class InvitedThirdPartyUserCreationForm(ThirdPartyUserCreationForm):
235 15efc749 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
236 15efc749 Sofia Papagiannaki
        super(InvitedThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
237 15efc749 Sofia Papagiannaki
        #set readonly form fields
238 15efc749 Sofia Papagiannaki
        self.fields['email'].widget.attrs['readonly'] = True
239 64cd4730 Antony Chazapis
240 890b0eaf Sofia Papagiannaki
class FeedbackForm(forms.Form):
241 890b0eaf Sofia Papagiannaki
    """
242 890b0eaf Sofia Papagiannaki
    Form for writing feedback.
243 890b0eaf Sofia Papagiannaki
    """
244 890b0eaf Sofia Papagiannaki
    feedback_msg = forms.CharField(widget=forms.Textarea(),
245 890b0eaf Sofia Papagiannaki
                                label=u'Message', required=False)
246 92defad4 Sofia Papagiannaki
    feedback_data = forms.CharField(widget=forms.HiddenInput(),
247 92defad4 Sofia Papagiannaki
                                label='', required=False)
248 5ed6816e Sofia Papagiannaki
249 5ed6816e Sofia Papagiannaki
class SendInvitationForm(forms.Form):
250 5ed6816e Sofia Papagiannaki
    """
251 5ed6816e Sofia Papagiannaki
    Form for sending an invitations
252 5ed6816e Sofia Papagiannaki
    """
253 5ed6816e Sofia Papagiannaki
    
254 5ed6816e Sofia Papagiannaki
    email = forms.EmailField(required = True, label = 'Email address')
255 5ed6816e Sofia Papagiannaki
    first_name = forms.EmailField(label = 'First name')
256 5ed6816e Sofia Papagiannaki
    last_name = forms.EmailField(label = 'Last name')
257 e2125441 Sofia Papagiannaki
258 e2125441 Sofia Papagiannaki
class ExtendedPasswordResetForm(PasswordResetForm):
259 e2125441 Sofia Papagiannaki
    """
260 e2125441 Sofia Papagiannaki
    Extends PasswordResetForm by overriding save method:
261 e2125441 Sofia Papagiannaki
    passes a custom from_email in send_mail.
262 e2125441 Sofia Papagiannaki
    
263 e2125441 Sofia Papagiannaki
    Since Django 1.3 this is useless since ``django.contrib.auth.views.reset_password``
264 e2125441 Sofia Papagiannaki
    accepts a from_email argument.
265 e2125441 Sofia Papagiannaki
    """
266 e2125441 Sofia Papagiannaki
    def save(self, domain_override=None, email_template_name='registration/password_reset_email.html',
267 e2125441 Sofia Papagiannaki
             use_https=False, token_generator=default_token_generator, request=None):
268 e2125441 Sofia Papagiannaki
        """
269 e2125441 Sofia Papagiannaki
        Generates a one-use only link for resetting password and sends to the user.
270 e2125441 Sofia Papagiannaki
        """
271 e2125441 Sofia Papagiannaki
        for user in self.users_cache:
272 8f378756 Sofia Papagiannaki
            url = urljoin(BASEURL,
273 8f378756 Sofia Papagiannaki
                          '/im/local/reset/confirm/%s-%s' %(int_to_base36(user.id),
274 8f378756 Sofia Papagiannaki
                                                            token_generator.make_token(user)))
275 e2125441 Sofia Papagiannaki
            t = loader.get_template(email_template_name)
276 e2125441 Sofia Papagiannaki
            c = {
277 e2125441 Sofia Papagiannaki
                'email': user.email,
278 8f378756 Sofia Papagiannaki
                'url': url,
279 374611bc Sofia Papagiannaki
                'site_name': SITENAME,
280 e2125441 Sofia Papagiannaki
                'user': user,
281 09122dd8 Sofia Papagiannaki
                'baseurl': BASEURL,
282 09122dd8 Sofia Papagiannaki
                'support': DEFAULT_CONTACT_EMAIL
283 e2125441 Sofia Papagiannaki
            }
284 d552ecb7 Antony Chazapis
            from_email = DEFAULT_FROM_EMAIL
285 4abc7b29 Sofia Papagiannaki
            send_mail(_("Password reset on %s alpha2 testing") % SITENAME,
286 e2125441 Sofia Papagiannaki
                t.render(Context(c)), from_email, [user.email])
287 270dd48d Sofia Papagiannaki
288 270dd48d Sofia Papagiannaki
class SignApprovalTermsForm(forms.ModelForm):
289 270dd48d Sofia Papagiannaki
    class Meta:
290 270dd48d Sofia Papagiannaki
        model = AstakosUser
291 270dd48d Sofia Papagiannaki
        fields = ("has_signed_terms",)
292 270dd48d Sofia Papagiannaki
    
293 270dd48d Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
294 270dd48d Sofia Papagiannaki
        super(SignApprovalTermsForm, self).__init__(*args, **kwargs)
295 270dd48d Sofia Papagiannaki
    
296 270dd48d Sofia Papagiannaki
    def clean_has_signed_terms(self):
297 270dd48d Sofia Papagiannaki
        has_signed_terms = self.cleaned_data['has_signed_terms']
298 270dd48d Sofia Papagiannaki
        if not has_signed_terms:
299 270dd48d Sofia Papagiannaki
            raise forms.ValidationError(_('You have to agree with the terms'))
300 270dd48d Sofia Papagiannaki
        return has_signed_terms
301 270dd48d Sofia Papagiannaki
    
302 270dd48d Sofia Papagiannaki
    def save(self, commit=True):
303 270dd48d Sofia Papagiannaki
        """
304 270dd48d Sofia Papagiannaki
        Saves the , after the normal
305 270dd48d Sofia Papagiannaki
        save behavior is complete.
306 270dd48d Sofia Papagiannaki
        """
307 270dd48d Sofia Papagiannaki
        user = super(SignApprovalTermsForm, self).save(commit=False)
308 270dd48d Sofia Papagiannaki
        user.date_signed_terms = datetime.now()
309 270dd48d Sofia Papagiannaki
        if commit:
310 270dd48d Sofia Papagiannaki
            user.save()
311 270dd48d Sofia Papagiannaki
        return user