|
|
71592af |
From 9486df151a2eb6d61a35e9466dbdf6c14a913086 Mon Sep 17 00:00:00 2001
|
|
|
71592af |
From: Randy Barlow <randy@electronsweatshop.com>
|
|
|
71592af |
Date: Mon, 4 Sep 2017 12:19:36 -0400
|
|
|
71592af |
Subject: [PATCH] Retry auth in the bindings upon captcha key errors.
|
|
|
71592af |
|
|
|
71592af |
fixes #1787
|
|
|
71592af |
|
|
|
71592af |
Signed-off-by: Randy Barlow <randy@electronsweatshop.com>
|
|
|
71592af |
---
|
|
|
71592af |
bodhi/client/bindings.py | 12 +++++++++++-
|
|
|
71592af |
bodhi/tests/client/test_bindings.py | 32 ++++++++++++++++++++++++++++++++
|
|
|
71592af |
2 files changed, 43 insertions(+), 1 deletion(-)
|
|
|
71592af |
|
|
|
71592af |
diff --git a/bodhi/client/bindings.py b/bodhi/client/bindings.py
|
|
|
71592af |
index 57c4260..0bcd717 100644
|
|
|
71592af |
--- a/bodhi/client/bindings.py
|
|
|
71592af |
+++ b/bodhi/client/bindings.py
|
|
|
71592af |
@@ -73,13 +73,23 @@ def errorhandled(method):
|
|
|
71592af |
def wrapper(*args, **kwargs):
|
|
|
71592af |
try:
|
|
|
71592af |
result = method(*args, **kwargs)
|
|
|
71592af |
+ # Bodhi allows comments to be written by unauthenticated users if they solve a Captcha.
|
|
|
71592af |
+ # Due to this, an authentication error is not raised by the server if the client fails
|
|
|
71592af |
+ # to authenticate for any reason, and instead an error about needing a captcha key is
|
|
|
71592af |
+ # presented instead. If we see that error, we can just raise an AuthError to trigger the
|
|
|
71592af |
+ # retry logic in the exception handler below.
|
|
|
71592af |
+ if 'errors' in result:
|
|
|
71592af |
+ for error in result['errors']:
|
|
|
71592af |
+ if 'name' in error and error['name'] == 'captcha_key':
|
|
|
71592af |
+ raise AuthError('Captcha key needed.')
|
|
|
71592af |
except AuthError:
|
|
|
71592af |
- # An AuthError can be raised for three different reasons:
|
|
|
71592af |
+ # An AuthError can be raised for four different reasons:
|
|
|
71592af |
#
|
|
|
71592af |
# 0) The password is wrong.
|
|
|
71592af |
# 1) The session cookies are expired. fedora.python does not handle this automatically.
|
|
|
71592af |
# 2) The session cookies are not expired, but are no longer valid (for example, this can
|
|
|
71592af |
# happen if the server's auth secret has changed.)
|
|
|
71592af |
+ # 3) The client received a captcha_key error, as described in the try block above.
|
|
|
71592af |
#
|
|
|
71592af |
# We don't know the difference between the cases here, but case #1 is fairly common and
|
|
|
71592af |
# we can work around it and case #2 by removing the session cookies and csrf token and
|
|
|
71592af |
diff --git a/bodhi/tests/client/test_bindings.py b/bodhi/tests/client/test_bindings.py
|
|
|
71592af |
index 15c239a..974ecde 100644
|
|
|
71592af |
--- a/bodhi/tests/client/test_bindings.py
|
|
|
71592af |
+++ b/bodhi/tests/client/test_bindings.py
|
|
|
71592af |
@@ -1001,6 +1001,38 @@ class TestErrorhandled(unittest.TestCase):
|
|
|
71592af |
self.assertTrue(a_fake_self.csrf_token is None)
|
|
|
71592af |
self.assertEqual(a_fake_self.call_count, 2)
|
|
|
71592af |
|
|
|
71592af |
+ def test_retry_on_captcha_key_failure(self):
|
|
|
71592af |
+ """
|
|
|
71592af |
+ Test the decorator when the wrapped method returns a captch_key error.
|
|
|
71592af |
+
|
|
|
71592af |
+ This test ensures that the decorator will retry the wrapped method if it returns a
|
|
|
71592af |
+ captcha_key error, after clearing cookies and the csrf token.
|
|
|
71592af |
+
|
|
|
71592af |
+ This test was written to assert the fix for
|
|
|
71592af |
+ https://github.com/fedora-infra/bodhi/issues/1787
|
|
|
71592af |
+ """
|
|
|
71592af |
+ a_fake_self = mock.MagicMock()
|
|
|
71592af |
+ a_fake_self.csrf_token = 'some_token'
|
|
|
71592af |
+ a_fake_self.call_count = 0
|
|
|
71592af |
+
|
|
|
71592af |
+ @bindings.errorhandled
|
|
|
71592af |
+ def captcha_plz(a_fake_self):
|
|
|
71592af |
+ a_fake_self.call_count = a_fake_self.call_count + 1
|
|
|
71592af |
+
|
|
|
71592af |
+ # Fail on the first call with a captcha_key error to simulate unauth'd user on a
|
|
|
71592af |
+ # comment.
|
|
|
71592af |
+ if a_fake_self.call_count == 1:
|
|
|
71592af |
+ return {'errors': [{'name': 'captcha_key'}]}
|
|
|
71592af |
+
|
|
|
71592af |
+ return 'here you go'
|
|
|
71592af |
+
|
|
|
71592af |
+ # No Exception should be raised.
|
|
|
71592af |
+ captcha_plz(a_fake_self)
|
|
|
71592af |
+
|
|
|
71592af |
+ a_fake_self._session.cookies.clear.assert_called_once_with()
|
|
|
71592af |
+ self.assertTrue(a_fake_self.csrf_token is None)
|
|
|
71592af |
+ self.assertEqual(a_fake_self.call_count, 2)
|
|
|
71592af |
+
|
|
|
71592af |
def test_success(self):
|
|
|
71592af |
"""
|
|
|
71592af |
Test the decorator for the success case.
|
|
|
71592af |
--
|
|
|
71592af |
2.9.5
|
|
|
71592af |
|