Merge lp:~maxiberta/canonical-identity-provider/drop-account-registration-captcha-web into lp:canonical-identity-provider/release
- drop-account-registration-captcha-web
- Merge into trunk
Proposed by
Maximiliano Bertacchini
Status: | Merged |
---|---|
Merged at revision: | 1668 |
Proposed branch: | lp:~maxiberta/canonical-identity-provider/drop-account-registration-captcha-web |
Merge into: | lp:canonical-identity-provider/release |
Prerequisite: | lp:~maxiberta/canonical-identity-provider/drop-account-registration-captcha-api-v1 |
Diff against target: |
448 lines (+2/-258) 7 files modified
src/webui/templates/registration/_create_account_form.html (+0/-11) src/webui/templates/widgets/recaptcha.html (+0/-43) src/webui/tests/test_views_registration.py (+0/-51) src/webui/tests/test_views_ui.py (+1/-85) src/webui/views/registration.py (+0/-26) src/webui/views/ui.py (+1/-35) src/webui/views/utils.py (+0/-7) |
To merge this branch: | bzr merge lp:~maxiberta/canonical-identity-provider/drop-account-registration-captcha-web |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matias Bordese (community) | Approve | ||
Review via email: mp+356877@code.launchpad.net |
Commit message
Drop captcha from account registration via web.
Description of the change
Account registration captcha has been disabled for a long time (years?). And the implementation depends on reCaptcha v1 which is dead since March 2018. So, let's just drop all captcha bits from there.
To post a comment you must log in.
Revision history for this message
Otto Co-Pilot (otto-copilot) wrote : | # |
Running landing tests failed
https:/
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/webui/templates/registration/_create_account_form.html' |
2 | --- src/webui/templates/registration/_create_account_form.html 2018-07-04 17:51:43 +0000 |
3 | +++ src/webui/templates/registration/_create_account_form.html 2018-10-22 16:30:41 +0000 |
4 | @@ -50,17 +50,6 @@ |
5 | |
6 | {% include "widgets/passwords.html" with fields=create_form %} |
7 | |
8 | - {% if captcha_required %} |
9 | - <div class="captcha" id="captcha"> |
10 | - {% if captcha_error_message %} |
11 | - <span class="error"> |
12 | - {{ captcha_error_message }} |
13 | - </span> |
14 | - {% endif %} |
15 | - {% include "widgets/recaptcha.html" %} |
16 | - </div> |
17 | - {% endif %} |
18 | - |
19 | <div class="input-row{% if create_form.accept_tos.errors %} haserrors{% endif %} accept-tos-input"> |
20 | |
21 | {% if create_form.accept_tos.errors %} |
22 | |
23 | === removed file 'src/webui/templates/widgets/recaptcha.html' |
24 | --- src/webui/templates/widgets/recaptcha.html 2014-12-11 17:44:29 +0000 |
25 | +++ src/webui/templates/widgets/recaptcha.html 1970-01-01 00:00:00 +0000 |
26 | @@ -1,43 +0,0 @@ |
27 | -{% comment %} |
28 | -Copyright 2010 Canonical Ltd. This software is licensed under the |
29 | -GNU Affero General Public License version 3 (see the file LICENSE). |
30 | -{% endcomment %} |
31 | - |
32 | -{% load i18n %} |
33 | -{% load static_url %} |
34 | -<script type="text/javascript"> |
35 | - var RecaptchaOptions = { |
36 | - theme: 'white', |
37 | - custom_translations: { |
38 | - visual_challenge : "{% trans "Get a visual challenge" %}", |
39 | - audio_challenge : "{% trans "Get an audio challenge" %}", |
40 | - refresh_btn : "{% trans "Get a new challenge" %}", |
41 | - instructions_visual : "{% trans "Type the two words:" %}", |
42 | - instructions_audio : "{% trans "Type what you hear:" %}", |
43 | - help_btn : "{% trans "Help" %}", |
44 | - play_again : "{% trans "Play sound again" %}", |
45 | - cant_hear_this : "{% trans "Download sound as MP3" %}", |
46 | - incorrect_try_again : "{% trans "Incorrect. Try again." %}" |
47 | - }, |
48 | - }; |
49 | -</script> |
50 | -<div {% if captcha_error %}class='captchaError'{% endif %}> |
51 | -{% ifequal captcha_error "&error=no-challenge" %} |
52 | -<p> |
53 | -{% blocktrans with "support_form"|static_url as support_form_url %} |
54 | -It appears that our captcha service was unable to load on this page. |
55 | -This may be caused by a plugin on your browser. |
56 | -Please correct this and try again. If the problem persists, please <a href="{{ support_form_url }}">contact support</a> |
57 | -{% endblocktrans %} |
58 | -</p> |
59 | -{% endifequal %} |
60 | -<script type="text/javascript" src="{{ CAPTCHA_API_URL_SECURE }}/challenge?k={{ CAPTCHA_PUBLIC_KEY }}{{ captcha_error }}"> |
61 | -</script> |
62 | -<noscript> |
63 | - <iframe src="{{ CAPTCHA_API_URL_SECURE }}/noscript?k={{ CAPTCHA_PUBLIC_KEY }}" height="300" width="500" frameborder="0" class="recaptcha-noscript"> |
64 | - </iframe> |
65 | - <textarea class="recaptcha-challenge-field" name="recaptcha_challenge_field" rows="3" cols="40"> |
66 | - </textarea> |
67 | - <input type="hidden" name="recaptcha_response_field" value="manual_challenge"> |
68 | -</noscript> |
69 | -</div> |
70 | |
71 | === modified file 'src/webui/tests/test_views_registration.py' |
72 | --- src/webui/tests/test_views_registration.py 2018-05-28 20:15:33 +0000 |
73 | +++ src/webui/tests/test_views_registration.py 2018-10-22 16:30:41 +0000 |
74 | @@ -161,16 +161,6 @@ |
75 | ctx = response.context_data |
76 | self.assertEqual(ctx['form']['email'].value(), 'test@test.com') |
77 | |
78 | - @switches(CAPTCHA=False) |
79 | - def test_get_optional_captcha_switch_off(self): |
80 | - response = self.get() |
81 | - self.assertEqual(response.context_data['captcha_required'], False) |
82 | - |
83 | - @switches(CAPTCHA=True, CAPTCHA_NEW_ACCOUNT=True) |
84 | - def test_get_optional_captcha_switch_on(self): |
85 | - response = self.get() |
86 | - self.assertEqual(response.context_data['captcha_required'], True) |
87 | - |
88 | def test_post_required_fields(self): |
89 | response = self.post() |
90 | self.assert_form_displayed( |
91 | @@ -213,9 +203,6 @@ |
92 | email=self.TESTDATA['email'], |
93 | password=self.TESTDATA['password'], |
94 | displayname=self.TESTDATA['displayname'], |
95 | - captcha_id=None, |
96 | - captcha_solution=None, |
97 | - create_captcha=False, |
98 | creation_source=WEB_CREATION_SOURCE, |
99 | ) |
100 | |
101 | @@ -242,9 +229,6 @@ |
102 | password=self.TESTDATA['password'], |
103 | displayname=self.TESTDATA['displayname'], |
104 | username=self.TESTDATA['username'], |
105 | - captcha_id=None, |
106 | - captcha_solution=None, |
107 | - create_captcha=False, |
108 | creation_source=WEB_CREATION_SOURCE, |
109 | ) |
110 | self.TESTDATA.pop('username') |
111 | @@ -337,9 +321,6 @@ |
112 | expected_args = dict(email=self.TESTDATA['email'], |
113 | password=self.TESTDATA['password'], |
114 | displayname=self.TESTDATA['displayname'], |
115 | - create_captcha=False, |
116 | - captcha_solution=None, |
117 | - captcha_id=None, |
118 | creation_source='web-flow', |
119 | oid_token=token) |
120 | self.mock_api_register.assert_called_once_with(**expected_args) |
121 | @@ -351,38 +332,6 @@ |
122 | self.assert_form_displayed(response, email=VERIFY_EMAIL_MESSAGE) |
123 | self.assert_stat_calls(['error.email']) |
124 | |
125 | - def test_post_captcha_required(self): |
126 | - exc = api_errors.CaptchaRequired(Mock()) |
127 | - self.mock_api_register.side_effect = exc |
128 | - response = self.post(**self.TESTDATA) |
129 | - self.assert_form_displayed(response) |
130 | - self.assertEqual(response.context_data['captcha_required'], True) |
131 | - |
132 | - def test_post_captcha_failure(self): |
133 | - mock_response = Mock() |
134 | - body = {'extra': {'captcha_message': 'XXX'}} |
135 | - exc = api_errors.CaptchaFailure(mock_response, body) |
136 | - self.mock_api_register.side_effect = exc |
137 | - |
138 | - response = self.post(**self.TESTDATA) |
139 | - self.assert_form_displayed(response) |
140 | - self.assertEqual(response.context_data['captcha_required'], True) |
141 | - self.assertEqual( |
142 | - response.context_data['captcha_error'], |
143 | - '&error=XXX') |
144 | - self.assert_stat_calls(['error.captcha']) |
145 | - |
146 | - def test_post_captcha_error(self): |
147 | - mock_response = Mock() |
148 | - body = {} |
149 | - exc = api_errors.CaptchaError(mock_response, body) |
150 | - self.mock_api_register.side_effect = exc |
151 | - |
152 | - response = self.post(**self.TESTDATA) |
153 | - self.assert_form_displayed(response) |
154 | - self.assertEqual(response.context_data['captcha_required'], True) |
155 | - self.assert_stat_calls(['error.captcha']) |
156 | - |
157 | |
158 | class RegisterTimelineTestCase( |
159 | SSOBaseTestCase, RegisterTestMixin, TimelineActionMixin): |
160 | |
161 | === modified file 'src/webui/tests/test_views_ui.py' |
162 | --- src/webui/tests/test_views_ui.py 2018-09-07 21:54:44 +0000 |
163 | +++ src/webui/tests/test_views_ui.py 2018-10-22 16:30:41 +0000 |
164 | @@ -10,7 +10,6 @@ |
165 | import urllib2 |
166 | from datetime import date |
167 | from functools import partial |
168 | -from StringIO import StringIO |
169 | from urlparse import urlsplit |
170 | |
171 | from django.conf import settings |
172 | @@ -29,7 +28,6 @@ |
173 | from django.test.utils import override_settings |
174 | from django.urls import reverse |
175 | from django.utils.html import escape |
176 | -from gargoyle import gargoyle |
177 | from gargoyle.testutils import switches |
178 | from mock import Mock, patch |
179 | from pyquery import PyQuery |
180 | @@ -50,11 +48,7 @@ |
181 | OpenIDRPConfig, |
182 | twofactor, |
183 | ) |
184 | -from identityprovider.models.captcha import ( |
185 | - Captcha, |
186 | - CaptchaResponse, |
187 | - CaptchaV2, |
188 | -) |
189 | +from identityprovider.models.captcha import CaptchaV2 |
190 | from identityprovider.models.const import ( |
191 | AccountStatus, |
192 | AuthLogType, |
193 | @@ -65,7 +59,6 @@ |
194 | from identityprovider.tests import DEFAULT_USER_PASSWORD |
195 | from identityprovider.tests.test_auth import AuthLogTestCaseMixin |
196 | from identityprovider.tests.utils import ( |
197 | - MockHandler, |
198 | SSOBaseTestCase, |
199 | TimelineActionMixin, |
200 | ) |
201 | @@ -115,9 +108,6 @@ |
202 | 'passwordconfirm': 'Testing123', |
203 | 'accept_tos': True |
204 | } |
205 | - if gargoyle.is_active('CAPTCHA'): |
206 | - data['recaptcha_challenge_field'] = 'ignored' |
207 | - data['recaptcha_response_field'] = 'ignored' |
208 | |
209 | return self.client.post(url, data, follow=follow) |
210 | |
211 | @@ -132,24 +122,6 @@ |
212 | assert self.client.login( |
213 | username=self.data['email'], password=self.data['password']) |
214 | |
215 | - def request_when_captcha_fails(self, url, data): |
216 | - class MockCaptcha(object): |
217 | - def __init__(self, *args): |
218 | - pass |
219 | - |
220 | - def verify(self, solution, ip_addr, email): |
221 | - self.message = 'no-challenge' |
222 | - return False |
223 | - |
224 | - @classmethod |
225 | - def new(cls, env): |
226 | - return cls() |
227 | - |
228 | - with patch.object(ui, 'Captcha', MockCaptcha): |
229 | - r = self.client.post(url, data) |
230 | - |
231 | - return r |
232 | - |
233 | |
234 | @override_settings(LANGUAGE_CODE='es') |
235 | class SpanishUIViewsTestCase(BaseTestCase): |
236 | @@ -1348,62 +1320,6 @@ |
237 | self.assertFalse(email.is_verified) |
238 | |
239 | |
240 | -@override_settings(CAPTCHA_PRIVATE_KEY='some-private-key') |
241 | -class CaptchaVerificationTestCase(BaseTestCase): |
242 | - |
243 | - success_status = 302 |
244 | - |
245 | - def setUp(self): |
246 | - super(CaptchaVerificationTestCase, self).setUp() |
247 | - mock_handler = MockHandler() |
248 | - mock_handler.set_next_response(200, 'false\nno-challenge') |
249 | - self.patch(Captcha, 'opener', new=urllib2.build_opener(mock_handler)) |
250 | - |
251 | - p = switches(CAPTCHA=True) |
252 | - p.patch() |
253 | - self.addCleanup(p.unpatch) |
254 | - |
255 | - def test_new_account_when_form_validation_fails(self): |
256 | - r = self.post_new_account() |
257 | - self.assertTemplateUsed(r, 'registration/new_account.html') |
258 | - msg = 'It appears that our captcha service was unable to load' |
259 | - self.assertContains(r, msg) |
260 | - |
261 | - def test_new_account_captcha_whitelist(self): |
262 | - email = 'canonicaltest@gmail.com' |
263 | - pattern = '^canonicaltest(?:\+.+)?@gmail\.com$' |
264 | - with self.settings(EMAIL_WHITELIST_REGEXP_LIST=[pattern]): |
265 | - response = self.post_new_account(email=email) |
266 | - self.assertEqual(response.status_code, self.success_status) |
267 | - |
268 | - def test_new_account_captcha_whitelist_with_uuid(self): |
269 | - email = 'canonicaltest+something@gmail.com' |
270 | - pattern = '^canonicaltest(?:\+.+)?@gmail\.com$' |
271 | - with self.settings(EMAIL_WHITELIST_REGEXP_LIST=[pattern]): |
272 | - response = self.post_new_account(email=email) |
273 | - self.assertEqual(response.status_code, self.success_status) |
274 | - |
275 | - def test_new_account_captcha_whitelist_fail(self): |
276 | - email = 'notcanonicaltest@gmail.com' |
277 | - pattern = '^canonicaltest(?:\+.+)?@gmail\.com$' |
278 | - with self.settings(EMAIL_WHITELIST_REGEXP_LIST=[pattern]): |
279 | - response = self.post_new_account(email=email) |
280 | - msg = 'It appears that our captcha service was unable to load' |
281 | - self.assertContains(response, msg) |
282 | - |
283 | - @patch.object(Captcha, '_open') |
284 | - def test_uses_timeline_from_request(self, mock_open): |
285 | - mock_open.return_value = CaptchaResponse(200, StringIO('true\na')) |
286 | - request = Mock() |
287 | - timeline = Timeline() |
288 | - request.META = {'timeline.timeline': timeline} |
289 | - request.POST = {'recaptcha_challenge_field': 'captcha-id'} |
290 | - request.environ = {'REMOTE_ADDR': '127.0.0.1'} |
291 | - ui._verify_captcha_response(None, request, None) |
292 | - self.assertEqual(1, len(timeline.actions)) |
293 | - self.assertEqual('captcha-verify', timeline.actions[0].category) |
294 | - |
295 | - |
296 | class CookiesTestCase(SSOBaseTestCase): |
297 | |
298 | def setUp(self): |
299 | |
300 | === modified file 'src/webui/views/registration.py' |
301 | --- src/webui/views/registration.py 2018-05-28 20:15:33 +0000 |
302 | +++ src/webui/views/registration.py 2018-10-22 16:30:41 +0000 |
303 | @@ -53,7 +53,6 @@ |
304 | requires_cookies, |
305 | ) |
306 | from webui.views.utils import ( |
307 | - add_captcha_settings, |
308 | display_email_sent, |
309 | set_session_email, |
310 | ) |
311 | @@ -87,10 +86,6 @@ |
312 | @requires_cookies |
313 | @require_http_methods(['GET', 'POST']) |
314 | def new_account(request, token=None): |
315 | - captcha_required = (gargoyle.is_active('CAPTCHA', request) and |
316 | - gargoyle.is_active('CAPTCHA_NEW_ACCOUNT', request)) |
317 | - captcha_error = '' |
318 | - captcha_error_message = None |
319 | rpconfig = get_rpconfig_from_request(request, token) |
320 | |
321 | def collect_stats(key): |
322 | @@ -108,14 +103,7 @@ |
323 | data = dict((k, v) for k, v in form.cleaned_data.items() |
324 | if k in ('email', 'password', 'displayname', |
325 | 'username')) |
326 | - data['captcha_id'] = request.POST.get( |
327 | - 'recaptcha_challenge_field' |
328 | - ) |
329 | - data['captcha_solution'] = request.POST.get( |
330 | - 'recaptcha_response_field' |
331 | - ) |
332 | # we'll handle our own capture generation |
333 | - data['create_captcha'] = False |
334 | data['creation_source'] = WEB_CREATION_SOURCE |
335 | if token: |
336 | data['oid_token'] = token |
337 | @@ -136,15 +124,6 @@ |
338 | collect_stats('error.email') |
339 | form._errors['email'] = [VERIFY_EMAIL_MESSAGE] |
340 | |
341 | - except api_errors.CaptchaRequired as e: |
342 | - captcha_required = True |
343 | - collect_stats('captcha_required') |
344 | - |
345 | - except (api_errors.CaptchaFailure, api_errors.CaptchaError) as e: |
346 | - captcha_required = True |
347 | - captcha_error = '&error=' + e.extra.get('captcha_message', '') |
348 | - captcha_error_message = _('Incorrect captcha solution') |
349 | - collect_stats('error.captcha') |
350 | except Exception as e: |
351 | return HttpResponseServerError("exception: " + str(e)) |
352 | else: |
353 | @@ -175,12 +154,7 @@ |
354 | 'form': form, |
355 | 'rpconfig': rpconfig, |
356 | 'token': token, |
357 | - 'captcha_required': captcha_required, |
358 | - 'captcha_error': captcha_error, |
359 | - 'captcha_error_message': captcha_error_message, |
360 | } |
361 | - if captcha_required: |
362 | - context = add_captcha_settings(context) |
363 | |
364 | if form.errors: |
365 | err = form.errors.get('email', [''])[0] |
366 | |
367 | === modified file 'src/webui/views/ui.py' |
368 | --- src/webui/views/ui.py 2018-08-24 15:30:53 +0000 |
369 | +++ src/webui/views/ui.py 2018-10-22 16:30:41 +0000 |
370 | @@ -56,11 +56,7 @@ |
371 | |
372 | ) |
373 | from identityprovider.models import twofactor |
374 | -from identityprovider.models.captcha import ( |
375 | - Captcha, |
376 | - CaptchaV2, |
377 | - VerifyCaptchaError |
378 | -) |
379 | +from identityprovider.models.captcha import CaptchaV2 |
380 | from identityprovider.models.const import AccountStatus, AuthTokenType |
381 | from identityprovider.signals import login_failed, login_succeeded |
382 | from identityprovider.signed import BadSignedValue |
383 | @@ -94,7 +90,6 @@ |
384 | requires_cookies, |
385 | ) |
386 | from webui.views import registration |
387 | -from webui.views.utils import add_captcha_settings |
388 | |
389 | |
390 | ACCOUNT_CREATED = _("Your account was created successfully") |
391 | @@ -150,11 +145,6 @@ |
392 | self, request, token, rpconfig, form, create_account_form=None): |
393 | context = super(LoginView, self).get_context( |
394 | request, token=token, rpconfig=rpconfig, form=form) |
395 | - # add captcha and account creation form |
396 | - context['captcha_required'] = ( |
397 | - gargoyle.is_active('CAPTCHA', request) and |
398 | - gargoyle.is_active('CAPTCHA_NEW_ACCOUNT', request)) |
399 | - context = add_captcha_settings(context) |
400 | context['create_account_form'] = create_account_form |
401 | return context |
402 | |
403 | @@ -503,30 +493,6 @@ |
404 | return registration.new_account(request, token) |
405 | |
406 | |
407 | -def _verify_captcha_response(template, request, form): |
408 | - captcha = Captcha(request.POST.get('recaptcha_challenge_field')) |
409 | - captcha_solution = request.POST.get('recaptcha_response_field') |
410 | - email = request.POST.get('email', '') |
411 | - ip_addr = request.environ["REMOTE_ADDR"] |
412 | - try: |
413 | - timer_fn = get_request_timing_function(request) |
414 | - verified = captcha.verify(captcha_solution, ip_addr, email, |
415 | - timer=timer_fn) |
416 | - if verified: |
417 | - return None |
418 | - except VerifyCaptchaError: |
419 | - logger.exception("reCaptcha connection error") |
420 | - |
421 | - # not verified |
422 | - return render( |
423 | - request, |
424 | - template, |
425 | - add_captcha_settings({ |
426 | - 'form': form, |
427 | - 'captcha_error': ('&error=%s' % captcha.message), |
428 | - 'captcha_required': True})) |
429 | - |
430 | - |
431 | @require_twofactor_authenticated( |
432 | _("Please log in to use this confirmation code")) |
433 | def confirm_email(request, authtoken, email_address, token=None): |
434 | |
435 | === modified file 'src/webui/views/utils.py' |
436 | --- src/webui/views/utils.py 2015-05-08 19:25:27 +0000 |
437 | +++ src/webui/views/utils.py 2018-10-22 16:30:41 +0000 |
438 | @@ -43,10 +43,3 @@ |
439 | def set_session_email(session, email): |
440 | """Place information about the current token's email in the session""" |
441 | session['token_email'] = email |
442 | - |
443 | - |
444 | -def add_captcha_settings(context): |
445 | - d = {'CAPTCHA_PUBLIC_KEY': settings.CAPTCHA_PUBLIC_KEY, |
446 | - 'CAPTCHA_API_URL_SECURE': settings.CAPTCHA_API_URL_SECURE} |
447 | - d.update(context) |
448 | - return d |
LGTM