Fix an issue with non-dict values in flow exchange.
The OAuth2 for Devices implementation picked up an incidental change that failed to treat dicts and dict-like objects the same way. This is particularly painful in environments like App Engine, where `self.request.params` is a common dict-like value to pass in. This restores the previous behavior, and adds a test.
This commit is contained in:
@@ -1767,10 +1767,10 @@ class OAuth2WebServerFlow(Flow):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
||||||
code: string, dict or None. For a non-device flow, this is
|
code: string, a dict-like object, or None. For a non-device
|
||||||
either the response code as a string, or a dictionary of
|
flow, this is either the response code as a string, or a
|
||||||
query parameters to the redirect_uri. For a device flow,
|
dictionary of query parameters to the redirect_uri. For a
|
||||||
this should be None.
|
device flow, this should be None.
|
||||||
http: httplib2.Http, optional http instance to use when fetching
|
http: httplib2.Http, optional http instance to use when fetching
|
||||||
credentials.
|
credentials.
|
||||||
device_flow_info: DeviceFlowInfo, return value from step1 in the
|
device_flow_info: DeviceFlowInfo, return value from step1 in the
|
||||||
@@ -1793,7 +1793,7 @@ class OAuth2WebServerFlow(Flow):
|
|||||||
|
|
||||||
if code is None:
|
if code is None:
|
||||||
code = device_flow_info.device_code
|
code = device_flow_info.device_code
|
||||||
elif isinstance(code, dict):
|
elif not isinstance(code, basestring):
|
||||||
if 'code' not in code:
|
if 'code' not in code:
|
||||||
raise FlowExchangeError(code.get(
|
raise FlowExchangeError(code.get(
|
||||||
'error', 'No code was supplied in the query parameters.'))
|
'error', 'No code was supplied in the query parameters.'))
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ class HttpMockSequence(object):
|
|||||||
"""
|
"""
|
||||||
self._iterable = iterable
|
self._iterable = iterable
|
||||||
self.follow_redirects = True
|
self.follow_redirects = True
|
||||||
|
self.requests = []
|
||||||
|
|
||||||
def request(self, uri,
|
def request(self, uri,
|
||||||
method='GET',
|
method='GET',
|
||||||
@@ -98,6 +99,7 @@ class HttpMockSequence(object):
|
|||||||
redirections=1,
|
redirections=1,
|
||||||
connection_type=None):
|
connection_type=None):
|
||||||
resp, content = self._iterable.pop(0)
|
resp, content = self._iterable.pop(0)
|
||||||
|
self.requests.append({'uri': uri, 'body': body, 'headers': headers})
|
||||||
if content == 'echo_request_headers':
|
if content == 'echo_request_headers':
|
||||||
content = headers
|
content = headers
|
||||||
elif content == 'echo_request_headers_as_json':
|
elif content == 'echo_request_headers_as_json':
|
||||||
|
|||||||
@@ -875,6 +875,34 @@ class OAuth2WebServerFlowTest(unittest.TestCase):
|
|||||||
self.assertEqual('8xLOxBtZp8', credentials.refresh_token)
|
self.assertEqual('8xLOxBtZp8', credentials.refresh_token)
|
||||||
self.assertEqual('dummy_revoke_uri', credentials.revoke_uri)
|
self.assertEqual('dummy_revoke_uri', credentials.revoke_uri)
|
||||||
|
|
||||||
|
def test_exchange_dictlike(self):
|
||||||
|
class FakeDict(object):
|
||||||
|
def __init__(self, d):
|
||||||
|
self.d = d
|
||||||
|
|
||||||
|
def __getitem__(self, name):
|
||||||
|
return self.d[name]
|
||||||
|
|
||||||
|
def __contains__(self, name):
|
||||||
|
return name in self.d
|
||||||
|
|
||||||
|
code = 'some random code'
|
||||||
|
not_a_dict = FakeDict({'code': code})
|
||||||
|
http = HttpMockSequence([
|
||||||
|
({'status': '200'},
|
||||||
|
"""{ "access_token":"SlAV32hkKG",
|
||||||
|
"expires_in":3600,
|
||||||
|
"refresh_token":"8xLOxBtZp8" }"""),
|
||||||
|
])
|
||||||
|
|
||||||
|
credentials = self.flow.step2_exchange(not_a_dict, http=http)
|
||||||
|
self.assertEqual('SlAV32hkKG', credentials.access_token)
|
||||||
|
self.assertNotEqual(None, credentials.token_expiry)
|
||||||
|
self.assertEqual('8xLOxBtZp8', credentials.refresh_token)
|
||||||
|
self.assertEqual('dummy_revoke_uri', credentials.revoke_uri)
|
||||||
|
request_code = urlparse.parse_qs(http.requests[0]['body'])['code'][0]
|
||||||
|
self.assertEqual(code, request_code)
|
||||||
|
|
||||||
def test_urlencoded_exchange_success(self):
|
def test_urlencoded_exchange_success(self):
|
||||||
http = HttpMockSequence([
|
http = HttpMockSequence([
|
||||||
({'status': '200'}, 'access_token=SlAV32hkKG&expires_in=3600'),
|
({'status': '200'}, 'access_token=SlAV32hkKG&expires_in=3600'),
|
||||||
|
|||||||
Reference in New Issue
Block a user