Revision db7fecd9

b/snf-astakos-app/README
63 63
ASTAKOS_CLOUD_SERVICES              ({'icon': 'home-icon.png', 'id': 'cloud', 'name': 'grnet cloud', 'url': '/'},   Cloud services appear in the horizontal bar
64 64
                                    {'id': 'okeanos', 'name': '~okeanos', 'url': '/okeanos.html'},                  
65 65
                                    {'id': 'pithos', 'name': 'pithos+', 'url': '/ui/'})                             
66
RECAPTCHA_PUBLIC_KEY                                                                                                Recaptcha public key obtained after registration here: http://recaptcha.net
67
RECAPTCHA_PRIVATE_KEY                                                                                               Recaptcha private key obtained after registration here: http://recaptcha.net
66 68
==============================      =============================================================================   ===========================================================================================
67 69

  
68 70
Administrator functions
b/snf-astakos-app/astakos/im/backends.py
104 104
        main = provider.capitalize() if provider == 'local' else 'ThirdParty'
105 105
        suffix  = 'UserCreationForm'
106 106
        formclass = '%s%s%s' % (prefix, main, suffix)
107
        return globals()[formclass](initial_data)
107
        return globals()[formclass](initial_data, ip=self.request.META['REMOTE_ADDR'])
108 108
    
109 109
    def get_signup_initial_data(self, provider):
110 110
        """
......
198 198
        if request.method == 'POST':
199 199
            if provider == request.POST.get('provider', ''):
200 200
                initial_data = request.POST
201
        return globals()[formclass](initial_data)
201
        return globals()[formclass](initial_data, ip=self.request.META['REMOTE_ADDR'])
202 202
    
203 203
    @transaction.commit_manually
204 204
    def signup(self, form, email_template_name='im/activation_email.txt'):
b/snf-astakos-app/astakos/im/forms.py
42 42
from django.core.urlresolvers import reverse
43 43

  
44 44
from astakos.im.models import AstakosUser
45
from astakos.im.settings import INVITATIONS_PER_LEVEL, DEFAULT_FROM_EMAIL, BASEURL, SITENAME
45
from astakos.im.settings import INVITATIONS_PER_LEVEL, DEFAULT_FROM_EMAIL, BASEURL, SITENAME, RECAPTCHA_PRIVATE_KEY
46
from astakos.im.widgets import DummyWidget, RecaptchaWidget
46 47

  
47 48
import logging
49
import recaptcha.client.captcha as captcha
48 50

  
49 51
logger = logging.getLogger(__name__)
50 52

  
......
56 58
    * The username field isn't visible and it is assigned a generated id.
57 59
    * User created is not active. 
58 60
    """
61
    recaptcha_challenge_field = forms.CharField(widget=DummyWidget)
62
    recaptcha_response_field = forms.CharField(widget=RecaptchaWidget, label='')
59 63
    
60 64
    class Meta:
61 65
        model = AstakosUser
......
65 69
        """
66 70
        Changes the order of fields, and removes the username field.
67 71
        """
72
        if 'ip' in kwargs:
73
            self.ip = kwargs['ip']
74
            kwargs.pop('ip')
68 75
        super(LocalUserCreationForm, self).__init__(*args, **kwargs)
69 76
        self.fields.keyOrder = ['email', 'first_name', 'last_name',
70
                                'password1', 'password2']
77
                                'password1', 'password2',
78
                                'recaptcha_challenge_field',
79
                                'recaptcha_response_field']
71 80
    
72 81
    def clean_email(self):
73 82
        email = self.cleaned_data['email']
......
79 88
        except AstakosUser.DoesNotExist:
80 89
            return email
81 90
    
91
    def clean_recaptcha_response_field(self):
92
        if 'recaptcha_challenge_field' in self.cleaned_data:
93
            self.validate_captcha()
94
        return self.cleaned_data['recaptcha_response_field']
95

  
96
    def clean_recaptcha_challenge_field(self):
97
        if 'recaptcha_response_field' in self.cleaned_data:
98
            self.validate_captcha()
99
        return self.cleaned_data['recaptcha_challenge_field']
100

  
101
    def validate_captcha(self):
102
        rcf = self.cleaned_data['recaptcha_challenge_field']
103
        rrf = self.cleaned_data['recaptcha_response_field']
104
        check = captcha.submit(rcf, rrf, RECAPTCHA_PRIVATE_KEY, self.ip)
105
        if not check.is_valid:
106
            raise forms.ValidationError(_('You have not entered the correct words'))
107
    
82 108
    def save(self, commit=True):
83 109
        """
84 110
        Saves the email, first_name and last_name properties, after the normal
......
163 189
        fields = ('email', 'last_name', 'first_name', 'affiliation', 'provider', 'third_party_identifier')
164 190
    
165 191
    def __init__(self, *args, **kwargs):
192
        if 'ip' in kwargs:
193
            self.ip = kwargs['ip']
194
            kwargs.pop('ip')
166 195
        super(ThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
167 196
        self.fields.keyOrder = ['email']
168 197
    
b/snf-astakos-app/astakos/im/settings.py
51 51
        { 'url':'/', 'name':'grnet cloud', 'id':'cloud', 'icon':'home-icon.png' },
52 52
        { 'url':'/okeanos.html', 'name':'~okeanos', 'id':'okeanos' },
53 53
        { 'url':'/ui/', 'name':'pithos+', 'id':'pithos' }))
54

  
55
# Set recaptcha keys
56
RECAPTCHA_PUBLIC_KEY = getattr(settings, 'ASTAKOS_RECAPTCHA_PUBLIC_KEY', '')
57
RECAPTCHA_PRIVATE_KEY = getattr(settings, 'ASTAKOS_RECAPTCHA_PRIVATE_KEY', '')
b/snf-astakos-app/astakos/im/target/twitter.py
167 167
        elif user and not user.is_active:
168 168
            messages.add_message(request, messages.ERROR, 'Inactive account: %s' % user.email)
169 169
    return render_response(login_template,
170
                   form = LocalUserCreationForm(),
170
                   form = LocalUserCreationForm(ip=request.META['REMOTE_ADDR']),
171 171
                   context_instance=get_context(request, extra_context))
172 172

  
173 173
def reserved_screen_name(screen_name):
......
231 231
    for provider in IM_MODULES:
232 232
        extra_context['%s_form' % provider] = backend.get_signup_form(provider)
233 233
    return render_response(on_failure,
234
                           form = LocalUserCreationForm(),
234
                           form = LocalUserCreationForm(ip=request.META['REMOTE_ADDR']),
235 235
                           context_instance=get_context(request, extra_context))
b/snf-astakos-app/astakos/im/templates/im/form_render.html
10 10
        {{ field.errors }}
11 11
     <p class="{% if field.blank %}required{% endif %}">
12 12
        {{ field.label_tag }}
13
        {{ field }}
13
        {{ field|safe }}
14 14
        </p>
15 15
    </div>
16 16
{% endfor %}
b/snf-astakos-app/astakos/im/widgets.py
1
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2
# 
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
# 
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
# 
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
# 
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
# 
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

  
34
import recaptcha.client.captcha as captcha
35
from django import forms
36

  
37
from astakos.im.settings import RECAPTCHA_PUBLIC_KEY
38

  
39
class RecaptchaWidget(forms.Widget):
40
    """ A Widget which "renders" the output of captcha.displayhtml """
41
    def render(self, *args, **kwargs):
42
        return captcha.displayhtml(RECAPTCHA_PUBLIC_KEY)
43

  
44
class DummyWidget(forms.Widget):
45
    """
46
    A dummy Widget class for a placeholder input field which will
47
    be created by captcha.displayhtml
48

  
49
    """
50
    # make sure that labels are not displayed either
51
    is_hidden=True
52
    def render(self, *args, **kwargs):
53
        return ''
b/snf-astakos-app/setup.py
78 78
    'Django>=1.2, <1.3',
79 79
    'South>=0.7, <=0.7.3',
80 80
    'httplib2==0.6.0',
81
    'snf-common>=0.8.1'
81
    'snf-common>=0.8.1',
82
    'recaptcha-client>=1.0.5'
82 83
]
83 84

  
84 85
EXTRAS_REQUIRES = {

Also available in: Unified diff