diff --git a/swh/web/assets/src/bundles/browse/origin-save.js b/swh/web/assets/src/bundles/browse/origin-save.js --- a/swh/web/assets/src/bundles/browse/origin-save.js +++ b/swh/web/assets/src/bundles/browse/origin-save.js @@ -13,7 +13,10 @@ function originSaveRequest(originType, originUrl, acceptedCallback, pendingCallback, errorCallback) { let addSaveOriginRequestUrl = Urls.browse_origin_save_request(originType, originUrl); - let grecaptchaData = {'g-recaptcha-response': grecaptcha.getResponse()}; + let grecaptchaData = {}; + if (swh.webapp.isReCaptchaActivated()) { + grecaptchaData['g-recaptcha-response'] = grecaptcha.getResponse(); + } let headers = { 'Accept': 'application/json', 'Content-Type': 'application/json' @@ -28,13 +31,17 @@ } else { pendingCallback(); } - grecaptcha.reset(); + if (swh.webapp.isReCaptchaActivated()) { + grecaptcha.reset(); + } }) .catch(response => { if (response.status === 403) { errorCallback(); } - grecaptcha.reset(); + if (swh.webapp.isReCaptchaActivated()) { + grecaptcha.reset(); + } }); } diff --git a/swh/web/assets/src/bundles/webapp/webapp-utils.js b/swh/web/assets/src/bundles/webapp/webapp-utils.js --- a/swh/web/assets/src/bundles/webapp/webapp-utils.js +++ b/swh/web/assets/src/bundles/webapp/webapp-utils.js @@ -137,3 +137,13 @@ }); $('td > a').on('click', function(e) { e.stopPropagation(); }); } + +let reCaptchaActivated; + +export function setReCaptchaActivated(activated) { + reCaptchaActivated = activated; +} + +export function isReCaptchaActivated() { + return reCaptchaActivated; +} diff --git a/swh/web/browse/views/origin_save.py b/swh/web/browse/views/origin_save.py --- a/swh/web/browse/views/origin_save.py +++ b/swh/web/browse/views/origin_save.py @@ -25,7 +25,7 @@ def _browse_origin_save_request(request, origin_type, origin_url): body_unicode = request.body.decode('utf-8') body = json.loads(body_unicode) - if is_recaptcha_valid(request, body['g-recaptcha-response']): + if is_recaptcha_valid(request, body.get('g-recaptcha-response')): try: response = json.dumps(create_save_origin_request(origin_type, origin_url), diff --git a/swh/web/common/utils.py b/swh/web/common/utils.py --- a/swh/web/common/utils.py +++ b/swh/web/common/utils.py @@ -329,15 +329,19 @@ bool: Whether the reCAPTCHA response is valid or not """ config = get_config() - return requests.post( - config['grecaptcha']['validation_url'], - data={ - 'secret': config['grecaptcha']['private_key'], - 'response': recaptcha_response, - 'remoteip': get_client_ip(request) - }, - verify=True - ).json().get("success", False) + if config['grecaptcha']['activated'] is False: + recaptcha_valid = True + else: + recaptcha_valid = requests.post( + config['grecaptcha']['validation_url'], + data={ + 'secret': config['grecaptcha']['private_key'], + 'response': recaptcha_response, + 'remoteip': get_client_ip(request) + }, + verify=True + ).json().get("success", False) + return recaptcha_valid def context_processor(request): @@ -347,4 +351,5 @@ """ config = get_config() return {'swh_object_icons': swh_object_icons, + 'grecaptcha_activated': config['grecaptcha']['activated'], 'grecaptcha_site_key': config['grecaptcha']['site_key']} diff --git a/swh/web/config.py b/swh/web/config.py --- a/swh/web/config.py +++ b/swh/web/config.py @@ -69,6 +69,7 @@ } }), 'grecaptcha': ('dict', { + 'activated': True, 'validation_url': 'https://www.google.com/recaptcha/api/siteverify', 'site_key': '', 'private_key': '' diff --git a/swh/web/templates/browse/layout.html b/swh/web/templates/browse/layout.html --- a/swh/web/templates/browse/layout.html +++ b/swh/web/templates/browse/layout.html @@ -15,7 +15,6 @@ {% block header %} {% render_bundle 'browse' %} {% render_bundle 'vault' %} - {% endblock %} {% block content %} diff --git a/swh/web/templates/browse/origin-save.html b/swh/web/templates/browse/origin-save.html --- a/swh/web/templates/browse/origin-save.html +++ b/swh/web/templates/browse/origin-save.html @@ -7,6 +7,13 @@ See top-level LICENSE file for more information {% endcomment %} +{% block header %} +{{ block.super }} +{% if grecaptcha_activated %} + +{% endif %} +{% endblock %} + {% block navbar-content %}

Save code now

{% endblock %} @@ -71,18 +78,27 @@
The origin url is not valid or does not reference a code repository
-
- -
-
-
-
-
-
- - +
+ {% if not grecaptcha_activated %} +
+ + +
+ {% endif %}
+ {% if grecaptcha_activated %} +
+
+
+
+
+
+ + +
+
+ {% endif %}
diff --git a/swh/web/templates/includes/take-new-snapshot.html b/swh/web/templates/includes/take-new-snapshot.html --- a/swh/web/templates/includes/take-new-snapshot.html +++ b/swh/web/templates/includes/take-new-snapshot.html @@ -9,6 +9,10 @@ {% if snapshot_context and snapshot_context.origin_info and snapshot_context.origin_info.type|origin_type_savable %} + {% if grecaptcha_activated %} + + {% endif %} +
-
-
-
-
-
-
- - +
+ {% if grecaptcha_activated %} +
+
+
+
+
+ + +
+ {% else %} +
+
+ + +
+
+ {% endif %} +
-
+
diff --git a/swh/web/templates/layout.html b/swh/web/templates/layout.html --- a/swh/web/templates/layout.html +++ b/swh/web/templates/layout.html @@ -181,6 +181,7 @@ diff --git a/swh/web/tests/browse/views/test_origin_save.py b/swh/web/tests/browse/views/test_origin_save.py new file mode 100644 --- /dev/null +++ b/swh/web/tests/browse/views/test_origin_save.py @@ -0,0 +1,143 @@ +# Copyright (C) 2019 The Software Heritage developers +# See the AUTHORS file at the top-level directory of this distribution +# License: GNU Affero General Public License version 3, or any later version +# See top-level LICENSE file for more information + +import json + +from datetime import datetime +from hypothesis import given +from unittest.mock import patch + +from swh.web.common.origin_save import ( + SAVE_REQUEST_ACCEPTED, SAVE_TASK_NOT_YET_SCHEDULED +) +from swh.web.config import get_config +from swh.web.common.utils import reverse +from swh.web.tests.strategies import origin +from swh.web.tests.testcase import WebTestCase + + +class SwhBrowseOriginSaveTest(WebTestCase): + + @given(origin()) + def test_recaptcha_activation_in_gui(self, origin): + + swh_web_config = get_config() + + for captcha_activated in (True, False): + + swh_web_config.update({ + 'grecaptcha': { + 'activated': captcha_activated, + 'site_key': '' + } + }) + + url = reverse('browse-origin-save') + resp = self.client.get(url) + + captcha_script_url = 'https://www.google.com/recaptcha/api.js' + captcha_dom_elt = '