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