Changeset - 44f7f73da4a6
[Not reviewed]
default
0 4 0
Patrick Vane - 8 years ago 2018-04-03 16:20:05
patrick_vane@lowentry.com
recaptcha: Update to Google recaptcha API v2 (Issue #313)

Recaptcha stopped working. It was using google recaptcha v1, and
https://developers.google.com/recaptcha/docs/faq says: "Any calls to the v1 API
will not work after March 31, 2018."

Note:

1) Not using 'async defer' - it's not used anywhere else, plus I have no idea
of what exactly it does.

2) The recaptcha div has an ID so the label for="recaptcha_field" can reference
it (although I'm not certain a div can technically have a label, but it's
better than removing the label, or the for="").
4 files changed with 34 insertions and 56 deletions:
0 comments (0 inline, 0 general)
kallithea/controllers/login.py
Show inline comments
 
@@ -130,17 +130,16 @@ class LoginController(BaseController):
 
            try:
 
                form_result = register_form.to_python(dict(request.POST))
 
                form_result['active'] = c.auto_active
 

	
 
                if c.captcha_active:
 
                    from kallithea.lib.recaptcha import submit
 
                    response = submit(request.POST.get('recaptcha_challenge_field'),
 
                                      request.POST.get('recaptcha_response_field'),
 
                    response = submit(request.POST.get('g-recaptcha-response'),
 
                                      private_key=captcha_private_key,
 
                                      remoteip=request.ip_addr)
 
                    if c.captcha_active and not response.is_valid:
 
                    if not response.is_valid:
 
                        _value = form_result
 
                        _msg = _('Bad captcha')
 
                        error_dict = {'recaptcha_field': _msg}
 
                        raise formencode.Invalid(_msg, _value, None,
 
                                                 error_dict=error_dict)
 

	
 
@@ -176,17 +175,16 @@ class LoginController(BaseController):
 
        if request.POST:
 
            password_reset_form = PasswordResetRequestForm()()
 
            try:
 
                form_result = password_reset_form.to_python(dict(request.POST))
 
                if c.captcha_active:
 
                    from kallithea.lib.recaptcha import submit
 
                    response = submit(request.POST.get('recaptcha_challenge_field'),
 
                                      request.POST.get('recaptcha_response_field'),
 
                    response = submit(request.POST.get('g-recaptcha-response'),
 
                                      private_key=captcha_private_key,
 
                                      remoteip=request.ip_addr)
 
                    if c.captcha_active and not response.is_valid:
 
                    if not response.is_valid:
 
                        _value = form_result
 
                        _msg = _('Bad captcha')
 
                        error_dict = {'recaptcha_field': _msg}
 
                        raise formencode.Invalid(_msg, _value, None,
 
                                                 error_dict=error_dict)
 
                redirect_link = UserModel().send_reset_password_email(form_result)
kallithea/lib/recaptcha.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
import urllib
 
import urllib2
 

	
 
API_SSL_SERVER = "https://www.google.com/recaptcha/api"
 
API_SERVER = "http://www.google.com/recaptcha/api"
 
VERIFY_SERVER = "www.google.com"
 
import json
 

	
 

	
 
class RecaptchaResponse(object):
 
    def __init__(self, is_valid, error_code=None):
 
        self.is_valid = is_valid
 
        self.error_code = error_code
 

	
 
    def __repr__(self):
 
        return '<RecaptchaResponse:%s>' % (self.is_valid)
 

	
 

	
 
def submit(recaptcha_challenge_field, recaptcha_response_field, private_key,
 
           remoteip):
 
def submit(g_recaptcha_response, private_key, remoteip):
 
    """
 
    Submits a reCAPTCHA request for verification. Returns RecaptchaResponse
 
    for the request
 
    Submits a reCAPTCHA request for verification. Returns RecaptchaResponse for the request
 

	
 
    recaptcha_challenge_field -- The value of recaptcha_challenge_field from the form
 
    recaptcha_response_field -- The value of recaptcha_response_field from the form
 
    g_recaptcha_response -- The value of g_recaptcha_response from the form
 
    private_key -- your reCAPTCHA private key
 
    remoteip -- the user's IP address
 
    """
 

	
 
    if not (recaptcha_response_field and recaptcha_challenge_field and
 
                len(recaptcha_response_field) and len(
 
            recaptcha_challenge_field)):
 
        return RecaptchaResponse(is_valid=False,
 
                                 error_code='incorrect-captcha-sol')
 
    if not (g_recaptcha_response and len(g_recaptcha_response)):
 
        return RecaptchaResponse(is_valid=False, error_code='incorrect-captcha-sol')
 

	
 
    def encode_if_necessary(s):
 
        if isinstance(s, unicode):
 
            return s.encode('utf-8')
 
        return s
 

	
 
    params = urllib.urlencode({
 
        'privatekey': encode_if_necessary(private_key),
 
        'secret': encode_if_necessary(private_key),
 
        'remoteip': encode_if_necessary(remoteip),
 
        'challenge': encode_if_necessary(recaptcha_challenge_field),
 
        'response': encode_if_necessary(recaptcha_response_field),
 
        'response': encode_if_necessary(g_recaptcha_response),
 
    })
 

	
 
    req = urllib2.Request(
 
        url="http://%s/recaptcha/api/verify" % VERIFY_SERVER,
 
        url="https://www.google.com/recaptcha/api/siteverify",
 
        data=params,
 
        headers={
 
            "Content-type": "application/x-www-form-urlencoded",
 
            "User-agent": "reCAPTCHA Python"
 
        }
 
    )
 

	
 
    httpresp = urllib2.urlopen(req)
 

	
 
    return_values = httpresp.read().splitlines()
 
    return_values = json.loads(httpresp.read())
 
    httpresp.close()
 

	
 
    return_code = return_values[0]
 

	
 
    if return_code == "true":
 
    if not (isinstance(return_values, dict)):
 
        return RecaptchaResponse(is_valid=False, error_code='incorrect-captcha-sol')
 
    elif (("success" in return_values) and ((return_values["success"] == True) or (return_values["success"] == "true"))):
 
        return RecaptchaResponse(is_valid=True)
 
    elif (("error-codes" in return_values) and isinstance(return_values["error-codes"], list) and (len(return_values["error-codes"]) > 0)):
 
        return RecaptchaResponse(is_valid=False, error_code=return_values["error-codes"][0])
 
    else:
 
        return RecaptchaResponse(is_valid=False, error_code=return_values[1])
 
        return RecaptchaResponse(is_valid=False, error_code='incorrect-captcha-sol')
kallithea/templates/password_reset.html
Show inline comments
 
@@ -2,12 +2,18 @@
 
<%inherit file="base/root.html"/>
 

	
 
<%block name="title">
 
    ${_('Password Reset')}
 
</%block>
 

	
 
<%block name="js_extra">
 
    %if c.captcha_active:
 
        <script type="text/javascript" src="https://www.google.com/recaptcha/api.js"></script>
 
    %endif
 
</%block>
 

	
 
<%include file="/base/flash_msg.html"/>
 
<div class="container">
 
<div class="row">
 
<div class="centered-column">
 
<div id="register" class="panel panel-primary">
 
    <div class="panel-heading">
 
@@ -28,14 +34,13 @@
 
                </div>
 

	
 
                %if c.captcha_active:
 
                <div class="form-group">
 
                    <label class="control-label" for="recaptcha_field">${_('Captcha')}:</label>
 
                    <div>
 
                        ${h.hidden('recaptcha_field')}
 
                        <div id="recaptcha"></div>
 
                        <div id="recaptcha_field" class="g-recaptcha" data-sitekey="${c.captcha_public_key}"></div>
 
                    </div>
 
                </div>
 
                %endif
 

	
 
                <div class="form-group">
 
                    <div class="buttons">
 
@@ -45,25 +50,15 @@
 

	
 
                <div class="alert alert-info">
 
                    ${_('A password reset link will be sent to the specified email address if it is registered in the system.')}
 
                </div>
 
        </div>
 
        ${h.end_form()}
 
        %if c.captcha_active:
 
        <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
 
        %endif
 
        <script type="text/javascript">
 
         $(document).ready(function(){
 
            $('#email').focus();
 
            %if c.captcha_active:
 
            Recaptcha.create(${h.js(c.captcha_public_key)}, "recaptcha",
 
                {
 
                  theme: "white"
 
                }
 
            );
 
            %endif
 
         });
 
        </script>
 
    </div>
 
</div>
 
</div>
 
</div>
kallithea/templates/register.html
Show inline comments
 
@@ -2,12 +2,18 @@
 
<%inherit file="base/root.html"/>
 

	
 
<%block name="title">
 
    ${_('Sign Up')}
 
</%block>
 

	
 
<%block name="js_extra">
 
    %if c.captcha_active:
 
        <script type="text/javascript" src="https://www.google.com/recaptcha/api.js"></script>
 
    %endif
 
</%block>
 

	
 
<%include file="/base/flash_msg.html"/>
 

	
 
<div class="container">
 
<div class="row">
 
<div class="centered-column">
 
<div id="register" class="panel panel-primary">
 
@@ -64,14 +70,13 @@
 
                </div>
 

	
 
                %if c.captcha_active:
 
                <div class="form-group">
 
                    <label class="control-label" for="recaptcha_field">${_('Captcha')}:</label>
 
                    <div>
 
                        ${h.hidden('recaptcha_field')}
 
                        <div id="recaptcha"></div>
 
                        <div id="recaptcha_field" class="g-recaptcha" data-sitekey="${c.captcha_public_key}"></div>
 
                    </div>
 
                </div>
 
                %endif
 

	
 
                <div class="form-group">
 
                    <div class="buttons">
 
@@ -82,26 +87,15 @@
 
                            <div class="alert alert-info">${_('Please wait for an administrator to activate your account.')}</div>
 
                        %endif
 
                    </div>
 
                </div>
 
        </div>
 
        ${h.end_form()}
 
        %if c.captcha_active:
 
        <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
 
        %endif
 
        <script type="text/javascript">
 
        $(document).ready(function(){
 
            $('#username').focus();
 

	
 
            %if c.captcha_active:
 
            Recaptcha.create(${h.js(c.captcha_public_key)}, "recaptcha",
 
                {
 
                  theme: "white"
 
                }
 
            );
 
            %endif
 
        });
 
        </script>
 
    </div>
 
 </div>
 
 </div>
 
 </div>
0 comments (0 inline, 0 general)