##// END OF EJS Templates
re-captcha: adjust for v2 that is the only left one supported since 1st of May.
marcink -
r2731:f80f9da7 default
parent child Browse files
Show More
@@ -225,13 +225,6 b' self: super: {'
225 };
225 };
226 });
226 });
227
227
228 recaptcha-client = super.recaptcha-client.override (attrs: {
229 meta = {
230 # TODO: It is MIT/X11
231 license = pkgs.lib.licenses.mit;
232 };
233 });
234
235 python-editor = super.python-editor.override (attrs: {
228 python-editor = super.python-editor.override (attrs: {
236 meta = {
229 meta = {
237 license = pkgs.lib.licenses.asl20;
230 license = pkgs.lib.licenses.asl20;
@@ -1497,19 +1497,6 b''
1497 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "LGPL+BSD"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
1497 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "LGPL+BSD"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
1498 };
1498 };
1499 };
1499 };
1500 recaptcha-client = super.buildPythonPackage {
1501 name = "recaptcha-client-1.0.6";
1502 buildInputs = with self; [];
1503 doCheck = false;
1504 propagatedBuildInputs = with self; [];
1505 src = fetchurl {
1506 url = "https://files.pythonhosted.org/packages/0a/ea/5f2fbbfd894bdac1c68ef8d92019066cfcf9fbff5fe3d728d2b5c25c8db4/recaptcha-client-1.0.6.tar.gz";
1507 sha256 = "28c6853c1d13d365b7dc71a6b05e5ffb56471f70a850de318af50d3d7c0dea2f";
1508 };
1509 meta = {
1510 license = [ { fullName = "MIT/X11"; } ];
1511 };
1512 };
1513 redis = super.buildPythonPackage {
1500 redis = super.buildPythonPackage {
1514 name = "redis-2.10.6";
1501 name = "redis-2.10.6";
1515 buildInputs = with self; [];
1502 buildInputs = with self; [];
@@ -1553,7 +1540,7 b''
1553 name = "rhodecode-enterprise-ce-4.13.0";
1540 name = "rhodecode-enterprise-ce-4.13.0";
1554 buildInputs = with self; [pytest py pytest-cov pytest-sugar pytest-runner pytest-catchlog pytest-profiling gprof2dot pytest-timeout mock webtest cov-core coverage configobj];
1541 buildInputs = with self; [pytest py pytest-cov pytest-sugar pytest-runner pytest-catchlog pytest-profiling gprof2dot pytest-timeout mock webtest cov-core coverage configobj];
1555 doCheck = true;
1542 doCheck = true;
1556 propagatedBuildInputs = with self; [setuptools-scm amqp authomatic babel beaker celery chameleon channelstream click colander configobj cssselect decorator deform docutils dogpile.cache dogpile.core ecdsa formencode future futures gnureadline infrae.cache iso8601 itsdangerous jinja2 billiard kombu lxml mako markdown markupsafe msgpack-python mysql-python objgraph packaging paste pastedeploy pastescript pathlib2 peppercorn psutil psycopg2 py-bcrypt pycrypto pycurl pyflakes pygments-markdown-lexer pygments pyparsing pyramid-beaker pyramid-debugtoolbar pyramid-jinja2 pyramid-mako pyramid pysqlite python-dateutil python-ldap python-memcached python-pam pytz tzlocal pyzmq py-gfm recaptcha-client redis repoze.lru requests routes setproctitle simplejson six sqlalchemy sshpubkeys subprocess32 supervisor tempita translationstring trollius urllib3 urlobject venusian weberror webhelpers2 webhelpers webob whoosh wsgiref zope.cachedescriptors zope.deprecation zope.event zope.interface nbconvert bleach nbformat jupyter-client alembic invoke bumpversion gevent greenlet gunicorn waitress ipdb ipython cprofilev bottle rhodecode-tools appenlight-client pytest py pytest-cov pytest-sugar pytest-runner pytest-catchlog pytest-profiling gprof2dot pytest-timeout mock webtest cov-core coverage];
1543 propagatedBuildInputs = with self; [setuptools-scm amqp authomatic babel beaker celery chameleon channelstream click colander configobj cssselect decorator deform docutils dogpile.cache dogpile.core ecdsa formencode future futures gnureadline infrae.cache iso8601 itsdangerous jinja2 billiard kombu lxml mako markdown markupsafe msgpack-python mysql-python objgraph packaging paste pastedeploy pastescript pathlib2 peppercorn psutil psycopg2 py-bcrypt pycrypto pycurl pyflakes pygments-markdown-lexer pygments pyparsing pyramid-beaker pyramid-debugtoolbar pyramid-jinja2 pyramid-mako pyramid pysqlite python-dateutil python-ldap python-memcached python-pam pytz tzlocal pyzmq py-gfm redis repoze.lru requests routes setproctitle simplejson six sqlalchemy sshpubkeys subprocess32 supervisor tempita translationstring trollius urllib3 urlobject venusian weberror webhelpers2 webhelpers webob whoosh wsgiref zope.cachedescriptors zope.deprecation zope.event zope.interface nbconvert bleach nbformat jupyter-client alembic invoke bumpversion gevent greenlet gunicorn waitress ipdb ipython cprofilev bottle rhodecode-tools appenlight-client pytest py pytest-cov pytest-sugar pytest-runner pytest-catchlog pytest-profiling gprof2dot pytest-timeout mock webtest cov-core coverage];
1557 src = ./.;
1544 src = ./.;
1558 meta = {
1545 meta = {
1559 license = [ { fullName = "Affero GNU General Public License v3 or later (AGPLv3+)"; } { fullName = "AGPLv3, and Commercial License"; } ];
1546 license = [ { fullName = "Affero GNU General Public License v3 or later (AGPLv3+)"; } { fullName = "AGPLv3, and Commercial License"; } ];
@@ -65,7 +65,6 b' pytz==2018.4'
65 tzlocal==1.5.1
65 tzlocal==1.5.1
66 pyzmq==14.6.0
66 pyzmq==14.6.0
67 py-gfm==0.1.3
67 py-gfm==0.1.3
68 recaptcha-client==1.0.6
69 redis==2.10.6
68 redis==2.10.6
70 repoze.lru==0.7
69 repoze.lru==0.7
71 requests==2.9.1
70 requests==2.9.1
@@ -97,16 +97,16 b' class TestRegisterCaptcha(object):'
97 assertr.no_element_exists('#recaptcha_field')
97 assertr.no_element_exists('#recaptcha_field')
98
98
99 @pytest.mark.parametrize('valid', [False, True])
99 @pytest.mark.parametrize('valid', [False, True])
100 @mock.patch('rhodecode.apps.login.views.submit')
100 @mock.patch.object(LoginView, 'validate_captcha')
101 @mock.patch.object(LoginView, '_get_captcha_data')
101 @mock.patch.object(LoginView, '_get_captcha_data')
102 def test_register_with_active_captcha(
102 def test_register_with_active_captcha(
103 self, m_get_captcha_data, m_submit, valid, app, csrf_token):
103 self, m_get_captcha_data, m_validate_captcha, valid, app, csrf_token):
104 captcha = CaptchaData(
104 captcha = CaptchaData(
105 active=True, private_key='PRIVATE_KEY', public_key='PUBLIC_KEY')
105 active=True, private_key='PRIVATE_KEY', public_key='PUBLIC_KEY')
106 m_get_captcha_data.return_value = captcha
106 m_get_captcha_data.return_value = captcha
107 m_response = mock.Mock()
107 m_response = mock.Mock()
108 m_response.is_valid = valid
108 m_response.is_valid = valid
109 m_submit.return_value = m_response
109 m_validate_captcha.return_value = valid, 'ok'
110
110
111 params = {
111 params = {
112 'csrf_token': csrf_token,
112 'csrf_token': csrf_token,
@@ -25,10 +25,10 b' import formencode'
25 import formencode.htmlfill
25 import formencode.htmlfill
26 import logging
26 import logging
27 import urlparse
27 import urlparse
28 import requests
28
29
29 from pyramid.httpexceptions import HTTPFound
30 from pyramid.httpexceptions import HTTPFound
30 from pyramid.view import view_config
31 from pyramid.view import view_config
31 from recaptcha.client.captcha import submit
32
32
33 from rhodecode.apps._base import BaseAppView
33 from rhodecode.apps._base import BaseAppView
34 from rhodecode.authentication.base import authenticate, HTTP_TYPE
34 from rhodecode.authentication.base import authenticate, HTTP_TYPE
@@ -124,6 +124,29 b' class LoginView(BaseAppView):'
124 return CaptchaData(
124 return CaptchaData(
125 active=active, private_key=private_key, public_key=public_key)
125 active=active, private_key=private_key, public_key=public_key)
126
126
127 def validate_captcha(self, private_key):
128
129 captcha_rs = self.request.POST.get('g-recaptcha-response')
130 url = "https://www.google.com/recaptcha/api/siteverify"
131 params = {
132 'secret': private_key,
133 'response': captcha_rs,
134 'remoteip': get_ip_addr(self.request.environ)
135 }
136 verify_rs = requests.get(url, params=params, verify=True)
137 verify_rs = verify_rs.json()
138 captcha_status = verify_rs.get('success', False)
139 captcha_errors = verify_rs.get('error-codes', [])
140 if not isinstance(captcha_errors, list):
141 captcha_errors = [captcha_errors]
142 captcha_errors = ', '.join(captcha_errors)
143 captcha_message = ''
144 if captcha_status is False:
145 captcha_message = "Bad captcha. Errors: {}".format(
146 captcha_errors)
147
148 return captcha_status, captcha_message
149
127 @view_config(
150 @view_config(
128 route_name='login', request_method='GET',
151 route_name='login', request_method='GET',
129 renderer='rhodecode:templates/login.mako')
152 renderer='rhodecode:templates/login.mako')
@@ -262,17 +285,15 b' class LoginView(BaseAppView):'
262 form_result['active'] = auto_active
285 form_result['active'] = auto_active
263
286
264 if captcha.active:
287 if captcha.active:
265 response = submit(
288 captcha_status, captcha_message = self.validate_captcha(
266 self.request.POST.get('recaptcha_challenge_field'),
289 captcha.private_key)
267 self.request.POST.get('recaptcha_response_field'),
290
268 private_key=captcha.private_key,
291 if not captcha_status:
269 remoteip=get_ip_addr(self.request.environ))
270 if not response.is_valid:
271 _value = form_result
292 _value = form_result
272 _msg = _('Bad captcha')
293 _msg = _('Bad captcha')
273 error_dict = {'recaptcha_field': _msg}
294 error_dict = {'recaptcha_field': captcha_message}
274 raise formencode.Invalid(_msg, _value, None,
295 raise formencode.Invalid(
275 error_dict=error_dict)
296 _msg, _value, None, error_dict=error_dict)
276
297
277 new_user = UserModel().create_registration(form_result)
298 new_user = UserModel().create_registration(form_result)
278
299
@@ -339,15 +360,13 b' class LoginView(BaseAppView):'
339 user_email = form_result['email']
360 user_email = form_result['email']
340
361
341 if captcha.active:
362 if captcha.active:
342 response = submit(
363 captcha_status, captcha_message = self.validate_captcha(
343 self.request.POST.get('recaptcha_challenge_field'),
364 captcha.private_key)
344 self.request.POST.get('recaptcha_response_field'),
365
345 private_key=captcha.private_key,
366 if not captcha_status:
346 remoteip=get_ip_addr(self.request.environ))
347 if not response.is_valid:
348 _value = form_result
367 _value = form_result
349 _msg = _('Bad captcha')
368 _msg = _('Bad captcha')
350 error_dict = {'recaptcha_field': _msg}
369 error_dict = {'recaptcha_field': captcha_message}
351 raise formencode.Invalid(
370 raise formencode.Invalid(
352 _msg, _value, None, error_dict=error_dict)
371 _msg, _value, None, error_dict=error_dict)
353
372
@@ -305,9 +305,6 b''
305 "python2.7-pyzmq-14.6.0": {
305 "python2.7-pyzmq-14.6.0": {
306 "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause"
306 "BSD 4-clause \"Original\" or \"Old\" License": "http://spdx.org/licenses/BSD-4-Clause"
307 },
307 },
308 "python2.7-recaptcha-client-1.0.6": {
309 "MIT License": "http://spdx.org/licenses/MIT"
310 },
311 "python2.7-repoze.lru-0.6": {
308 "python2.7-repoze.lru-0.6": {
312 "Repoze License": "http://www.repoze.org/LICENSE.txt"
309 "Repoze License": "http://www.repoze.org/LICENSE.txt"
313 },
310 },
@@ -65,26 +65,26 b''
65 </div>
65 </div>
66 <div class="panel-body">
66 <div class="panel-body">
67 <div class="label">
67 <div class="label">
68 <label for="rhodecode_captcha_public_key">${_('Google ReCaptcha public key')}</label>
68 <label for="rhodecode_captcha_public_key">${_('Google reCaptcha v2 site key.')}</label>
69 </div>
69 </div>
70 <div class="field input">
70 <div class="field input">
71 ${h.text('rhodecode_captcha_public_key',size=60)}
71 ${h.text('rhodecode_captcha_public_key',size=60)}
72 </div>
72 </div>
73 <div class="field">
73 <div class="field">
74 <span class="help-block">
74 <span class="help-block">
75 ${_('Public key for reCaptcha system.')}
75 ${_('Site key for reCaptcha v2 system.')}
76 </span>
76 </span>
77 </div>
77 </div>
78
78
79 <div class="label">
79 <div class="label">
80 <label for="rhodecode_captcha_private_key">${_('Google ReCaptcha private key')}</label>
80 <label for="rhodecode_captcha_private_key">${_('Google reCaptcha v2 secret key.')}</label>
81 </div>
81 </div>
82 <div class="field input">
82 <div class="field input">
83 ${h.text('rhodecode_captcha_private_key',size=60)}
83 ${h.text('rhodecode_captcha_private_key',size=60)}
84 </div>
84 </div>
85 <div class="field">
85 <div class="field">
86 <span class="help-block">
86 <span class="help-block">
87 ${_('Private key for reCaptcha system. Setting this value will enable captcha on registration')}
87 ${_('Secret key for reCaptcha v2 system. Setting this value will enable captcha on registration and password reset forms.')}
88 </span>
88 </span>
89 </div>
89 </div>
90 </div>
90 </div>
@@ -61,6 +61,7 b''
61 <label for="email">${_('Captcha')}:</label>
61 <label for="email">${_('Captcha')}:</label>
62 ${h.hidden('recaptcha_field')}
62 ${h.hidden('recaptcha_field')}
63 <div id="recaptcha"></div>
63 <div id="recaptcha"></div>
64
64 %if 'recaptcha_field' in errors:
65 %if 'recaptcha_field' in errors:
65 <span class="error-message">${errors.get('recaptcha_field')}</span>
66 <span class="error-message">${errors.get('recaptcha_field')}</span>
66 <br />
67 <br />
@@ -78,14 +79,20 b''
78 </div>
79 </div>
79 </div>
80 </div>
80
81
81 %if captcha_active:
82 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
83 %endif
84 <script type="text/javascript">
82 <script type="text/javascript">
85 $(document).ready(function(){
83 $(document).ready(function(){
86 $('#email').focus();
84 $('#email').focus();
87 %if captcha_active:
88 Recaptcha.create("${captcha_public_key}", "recaptcha", {theme: "white"});
89 %endif
90 });
85 });
91 </script>
86 </script>
87
88 % if captcha_active:
89 <script type="text/javascript">
90 var onloadCallback = function() {
91 grecaptcha.render('recaptcha', {
92 'sitekey' : "${captcha_public_key}"
93 });
94 };
95 </script>
96 <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>
97 % endif
98
@@ -110,14 +110,21 b''
110 </div>
110 </div>
111 </div>
111 </div>
112
112
113 %if captcha_active:
113
114 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
115 %endif
116 <script type="text/javascript">
114 <script type="text/javascript">
117 $(document).ready(function(){
115 $(document).ready(function(){
118 $('#username').focus();
116 $('#username').focus();
119 %if captcha_active:
117 });
120 Recaptcha.create("${captcha_public_key}", "recaptcha", {theme: "white"});
121 %endif
122 });
123 </script>
118 </script>
119
120 % if captcha_active:
121 <script type="text/javascript">
122 var onloadCallback = function() {
123 grecaptcha.render('recaptcha', {
124 'sitekey' : "${captcha_public_key}"
125 });
126 };
127 </script>
128 <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>
129 % endif
130
General Comments 0
You need to be logged in to leave comments. Login now