Let OAuth2Decorator take a list of scopes.

Reviewed in http://codereview.appspot.com/5277045/
This commit is contained in:
Joe Gregorio
2011-10-14 15:11:29 -04:00
parent f42dfdcdac
commit f2f8a5a4ac
5 changed files with 18 additions and 45 deletions

View File

@@ -318,7 +318,8 @@ class OAuth2Decorator(object):
Args: Args:
client_id: string, client identifier. client_id: string, client identifier.
client_secret: string client secret. client_secret: string client secret.
scope: string, scope of the credentials being requested. scope: string or list of strings, scope(s) of the credentials being
requested.
auth_uri: string, URI for authorization endpoint. For convenience auth_uri: string, URI for authorization endpoint. For convenience
defaults to Google's endpoints but any OAuth 2.0 provider can be used. defaults to Google's endpoints but any OAuth 2.0 provider can be used.
token_uri: string, URI for token endpoint. For convenience token_uri: string, URI for token endpoint. For convenience

View File

@@ -623,7 +623,8 @@ class OAuth2WebServerFlow(Flow):
Args: Args:
client_id: string, client identifier. client_id: string, client identifier.
client_secret: string client secret. client_secret: string client secret.
scope: string, scope of the credentials being requested. scope: string or list of strings, scope(s) of the credentials being
requested.
user_agent: string, HTTP User-Agent to provide for this application. user_agent: string, HTTP User-Agent to provide for this application.
auth_uri: string, URI for authorization endpoint. For convenience auth_uri: string, URI for authorization endpoint. For convenience
defaults to Google's endpoints but any OAuth 2.0 provider can be used. defaults to Google's endpoints but any OAuth 2.0 provider can be used.
@@ -634,6 +635,8 @@ class OAuth2WebServerFlow(Flow):
""" """
self.client_id = client_id self.client_id = client_id
self.client_secret = client_secret self.client_secret = client_secret
if type(scope) is list:
scope = ' '.join(scope)
self.scope = scope self.scope = scope
self.user_agent = user_agent self.user_agent = user_agent
self.auth_uri = auth_uri self.auth_uri = auth_uri
@@ -734,7 +737,7 @@ def flow_from_clientsecrets(filename, scope, message=None):
Args: Args:
filename: string, File name of client secrets. filename: string, File name of client secrets.
scope: string, Space separated list of scopes. scope: string or list of strings, scope(s) to request.
message: string, A friendly string to display to the user if the message: string, A friendly string to display to the user if the
clientsecrets file is missing or invalid. If message is provided then clientsecrets file is missing or invalid. If message is provided then
sys.exit will be called in the case of an error. If message in not sys.exit will be called in the case of an error. If message in not
@@ -766,36 +769,3 @@ def flow_from_clientsecrets(filename, scope, message=None):
else: else:
raise UnknownClientSecretsFlowError( raise UnknownClientSecretsFlowError(
'This OAuth 2.0 flow is unsupported: "%s"' * client_type) 'This OAuth 2.0 flow is unsupported: "%s"' * client_type)
class OAuth2WebServerFlowFromClientSecrets(Flow):
"""Does the Web Server Flow for OAuth 2.0.
"""
def __init__(self, client_secrets, scope, user_agent,
auth_uri='https://accounts.google.com/o/oauth2/auth',
token_uri='https://accounts.google.com/o/oauth2/token',
**kwargs):
"""Constructor for OAuth2WebServerFlow
Args:
client_id: string, client identifier.
client_secret: string client secret.
scope: string, scope of the credentials being requested.
user_agent: string, HTTP User-Agent to provide for this application.
auth_uri: string, URI for authorization endpoint. For convenience
defaults to Google's endpoints but any OAuth 2.0 provider can be used.
token_uri: string, URI for token endpoint. For convenience
defaults to Google's endpoints but any OAuth 2.0 provider can be used.
**kwargs: dict, The keyword arguments are all optional and required
parameters for the OAuth calls.
"""
self.client_id = client_id
self.client_secret = client_secret
self.scope = scope
self.user_agent = user_agent
self.auth_uri = auth_uri
self.token_uri = token_uri
self.params = kwargs
self.redirect_uri = None

View File

@@ -76,7 +76,7 @@ def get_credential_storage(filename, client_id, user_agent, scope,
filename: The JSON file storing a set of credentials filename: The JSON file storing a set of credentials
client_id: The client_id for the credential client_id: The client_id for the credential
user_agent: The user agent for the credential user_agent: The user agent for the credential
scope: A string for the scope being requested scope: string or list of strings, Scope(s) being requested
warn_on_readonly: if True, log a warning if the store is readonly warn_on_readonly: if True, log a warning if the store is readonly
Returns: Returns:
@@ -90,6 +90,8 @@ def get_credential_storage(filename, client_id, user_agent, scope,
filename, _MultiStore(filename, warn_on_readonly)) filename, _MultiStore(filename, warn_on_readonly))
finally: finally:
_multistores_lock.release() _multistores_lock.release()
if type(scope) is list:
scope = ' '.join(scope)
return multistore._get_storage(client_id, user_agent, scope) return multistore._get_storage(client_id, user_agent, scope)
@@ -328,7 +330,7 @@ class _MultiStore(object):
Args: Args:
client_id: The client_id for the credential client_id: The client_id for the credential
user_agent: The user agent for the credential user_agent: The user agent for the credential
scope: A string for the scope being requested scope: A string for the scope(s) being requested
Returns: Returns:
The credential specified or None if not present The credential specified or None if not present
@@ -344,7 +346,7 @@ class _MultiStore(object):
Args: Args:
cred: The OAuth2Credential to update/set cred: The OAuth2Credential to update/set
scope: The scope that this credential covers scope: The scope(s) that this credential covers
""" """
key = (cred.client_id, cred.user_agent, scope) key = (cred.client_id, cred.user_agent, scope)
self._data[key] = cred self._data[key] = cred
@@ -358,7 +360,7 @@ class _MultiStore(object):
Args: Args:
client_id: The client_id for the credential client_id: The client_id for the credential
user_agent: The user agent for the credential user_agent: The user agent for the credential
scope: A string for the scope being requested scope: A string for the scope(s) being requested
Returns: Returns:
A Storage object that can be used to get/set this cred A Storage object that can be used to get/set this cred

View File

@@ -131,7 +131,7 @@ class DecoratorTests(unittest.TestCase):
decorator = OAuth2Decorator(client_id='foo_client_id', decorator = OAuth2Decorator(client_id='foo_client_id',
client_secret='foo_client_secret', client_secret='foo_client_secret',
scope='foo_scope') scope=['foo_scope', 'bar_scope'])
self.decorator = decorator self.decorator = decorator
class TestRequiredHandler(webapp.RequestHandler): class TestRequiredHandler(webapp.RequestHandler):
@@ -168,7 +168,7 @@ class DecoratorTests(unittest.TestCase):
q = parse_qs(response.headers['Location'].split('?', 1)[1]) q = parse_qs(response.headers['Location'].split('?', 1)[1])
self.assertEqual('http://localhost/oauth2callback', q['redirect_uri'][0]) self.assertEqual('http://localhost/oauth2callback', q['redirect_uri'][0])
self.assertEqual('foo_client_id', q['client_id'][0]) self.assertEqual('foo_client_id', q['client_id'][0])
self.assertEqual('foo_scope', q['scope'][0]) self.assertEqual('foo_scope bar_scope', q['scope'][0])
self.assertEqual('http://localhost/foo_path', q['state'][0]) self.assertEqual('http://localhost/foo_path', q['state'][0])
self.assertEqual('code', q['response_type'][0]) self.assertEqual('code', q['response_type'][0])
self.assertEqual(False, self.decorator.has_credentials()) self.assertEqual(False, self.decorator.has_credentials())
@@ -210,7 +210,7 @@ class DecoratorTests(unittest.TestCase):
q = parse_qs(url.split('?', 1)[1]) q = parse_qs(url.split('?', 1)[1])
self.assertEqual('http://localhost/oauth2callback', q['redirect_uri'][0]) self.assertEqual('http://localhost/oauth2callback', q['redirect_uri'][0])
self.assertEqual('foo_client_id', q['client_id'][0]) self.assertEqual('foo_client_id', q['client_id'][0])
self.assertEqual('foo_scope', q['scope'][0]) self.assertEqual('foo_scope bar_scope', q['scope'][0])
self.assertEqual('http://localhost/bar_path', q['state'][0]) self.assertEqual('http://localhost/bar_path', q['state'][0])
self.assertEqual('code', q['response_type'][0]) self.assertEqual('code', q['response_type'][0])

View File

@@ -152,7 +152,7 @@ class OAuth2ClientFileTests(unittest.TestCase):
FILENAME, FILENAME,
'some_client_id', 'some_client_id',
'user-agent/1.0', 'user-agent/1.0',
'some-scope') ['some-scope', 'some-other-scope'])
credentials = store.get() credentials = store.get()
self.assertEquals(None, credentials) self.assertEquals(None, credentials)
@@ -175,7 +175,7 @@ class OAuth2ClientFileTests(unittest.TestCase):
FILENAME, FILENAME,
credentials.client_id, credentials.client_id,
credentials.user_agent, credentials.user_agent,
'some-scope') ['some-scope', 'some-other-scope'])
store.put(credentials) store.put(credentials)
credentials = store.get() credentials = store.get()