From d2ee4d84b03cff84da1a637d0b870d3a65a0ae17 Mon Sep 17 00:00:00 2001 From: Joe Gregorio Date: Thu, 15 Sep 2011 14:32:45 -0400 Subject: [PATCH] Fixed bug with refreshing tokens in file Storage --- Makefile | 1 - oauth2client/appengine.py | 4 ++-- oauth2client/django_orm.py | 4 ++-- oauth2client/file.py | 24 ++++++++++++++++-------- samples/django_sample/buzz/views.py | 4 ++-- tests/test_oauth2client_file.py | 28 ++++++++++++++++++++++++++++ 6 files changed, 50 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 6c08a9a..f53fa87 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,6 @@ docs: .PHONY: prerelease prerelease: - python2.4 runtests.py tests --exit_on_failure python2.6 runtests.py tests --exit_on_failure python2.7 runtests.py tests --exit_on_failure -sudo rm -rf dist/ diff --git a/oauth2client/appengine.py b/oauth2client/appengine.py index 2811069..68d5066 100644 --- a/oauth2client/appengine.py +++ b/oauth2client/appengine.py @@ -229,7 +229,7 @@ class StorageByKeyName(Storage): self._property_name = property_name self._cache = cache - def get(self): + def locked_get(self): """Retrieve Credential from datastore. Returns: @@ -248,7 +248,7 @@ class StorageByKeyName(Storage): return credential - def put(self, credentials): + def locked_put(self, credentials): """Write a Credentials to the datastore. Args: diff --git a/oauth2client/django_orm.py b/oauth2client/django_orm.py index 581fe8e..5e511db 100644 --- a/oauth2client/django_orm.py +++ b/oauth2client/django_orm.py @@ -86,7 +86,7 @@ class Storage(BaseStorage): self.key_value = key_value self.property_name = property_name - def get(self): + def locked_get(self): """Retrieve Credential from datastore. Returns: @@ -102,7 +102,7 @@ class Storage(BaseStorage): credential.set_store(self) return credential - def put(self, credentials): + def locked_put(self, credentials): """Write a Credentials to the datastore. Args: diff --git a/oauth2client/file.py b/oauth2client/file.py index 89140b8..60a6385 100644 --- a/oauth2client/file.py +++ b/oauth2client/file.py @@ -46,20 +46,32 @@ class Storage(BaseStorage): self._filename = filename self._lock = threading.Lock() - def get(self): + def acquire_lock(self): + """Acquires any lock necessary to access this Storage. + + This lock is not reentrant.""" + self._lock.acquire() + + def release_lock(self): + """Release the Storage lock. + + Trying to release a lock that isn't held will result in a + RuntimeError. + """ + self._lock.release() + + def locked_get(self): """Retrieve Credential from file. Returns: oauth2client.client.Credentials """ - self._lock.acquire() credentials = None try: f = open(self._filename, 'r') content = f.read() f.close() except IOError: - self._lock.release() return credentials # First try reading as JSON, and if that fails fall back to pickle. @@ -74,19 +86,15 @@ class Storage(BaseStorage): credentials.set_store(self) except: pass - finally: - self._lock.release() return credentials - def put(self, credentials): + def locked_put(self, credentials): """Write Credentials to file. Args: credentials: Credentials, the credentials to store. """ - self._lock.acquire() f = open(self._filename, 'w') f.write(credentials.to_json()) f.close() - self._lock.release() diff --git a/samples/django_sample/buzz/views.py b/samples/django_sample/buzz/views.py index d89af6d..c942aaf 100644 --- a/samples/django_sample/buzz/views.py +++ b/samples/django_sample/buzz/views.py @@ -24,8 +24,8 @@ def index(request): credential = storage.get() if credential is None or credential.invalid == True: flow = OAuth2WebServerFlow( - client_id='887851474342.apps.googleusercontent.com', - client_secret='6V9MHBUQqOQtxI7uXPIEnV8e', + client_id='837647042410.apps.googleusercontent.com', + client_secret='+SWwMCL9d8gWtzPRa1lXw5R8', scope='https://www.googleapis.com/auth/buzz', user_agent='buzz-django-sample/1.0', ) diff --git a/tests/test_oauth2client_file.py b/tests/test_oauth2client_file.py index 05deaa0..5ada4a3 100644 --- a/tests/test_oauth2client_file.py +++ b/tests/test_oauth2client_file.py @@ -22,6 +22,7 @@ Unit tests for oauth2client.file __author__ = 'jcgregorio@google.com (Joe Gregorio)' +import copy import os import pickle import unittest @@ -38,6 +39,7 @@ except ImportError: # pragma: no cover # Should work for Python2.6 and higher. import json as simplejson +from apiclient.http import HttpMockSequence from oauth2client.client import OAuth2Credentials from oauth2client.client import AccessTokenCredentials @@ -104,6 +106,32 @@ class OAuth2ClientFileTests(unittest.TestCase): self.assertEquals(data['_class'], 'OAuth2Credentials') self.assertEquals(data['_module'], 'oauth2client.client') + def test_token_refresh(self): + # Write a file with a pickled OAuth2Credentials. + access_token = 'foo' + client_id = 'some_client_id' + client_secret = 'cOuDdkfjxxnv+' + refresh_token = '1/0/a.df219fjls0' + token_expiry = datetime.datetime.utcnow() + token_uri = 'https://www.google.com/accounts/o8/oauth2/token' + user_agent = 'refresh_checker/1.0' + + credentials = OAuth2Credentials( + access_token, client_id, client_secret, + refresh_token, token_expiry, token_uri, + user_agent) + + s = Storage(FILENAME) + s.put(credentials) + credentials = s.get() + new_cred = copy.copy(credentials) + new_cred.access_token = 'bar' + s.put(new_cred) + + credentials._refresh(lambda x: x) + self.assertEquals(credentials.access_token, 'bar') + + def test_access_token_credentials(self): access_token = 'foo' user_agent = 'refresh_checker/1.0'