| Index: auth.py
|
| diff --git a/auth.py b/auth.py
|
| index 70e706e45f43cd1ec8191075f1e4eae2ec9f2006..6e0d2f32f4957e79befbac092fcd66df18916ac2 100644
|
| --- a/auth.py
|
| +++ b/auth.py
|
| @@ -48,6 +48,11 @@ OAUTH_CLIENT_SECRET = 'uBfbay2KCy9t4QveJ-dOqHtp'
|
| # use userinfo.email scope for authentication.
|
| OAUTH_SCOPES = 'https://www.googleapis.com/auth/userinfo.email'
|
|
|
| +# Additional OAuth scopes.
|
| +ADDITIONAL_SCOPES = {
|
| + 'code.google.com': 'https://www.googleapis.com/auth/projecthosting',
|
| +}
|
| +
|
| # Path to a file with cached OAuth2 credentials used by default relative to the
|
| # home dir (see _get_token_cache_path). It should be a safe location accessible
|
| # only to a current user: knowing content of this file is roughly equivalent to
|
| @@ -219,11 +224,15 @@ def get_authenticator_for_host(hostname, config):
|
| # Append some scheme, otherwise urlparse puts hostname into parsed.path.
|
| if '://' not in hostname:
|
| hostname = 'https://' + hostname
|
| + scopes = OAUTH_SCOPES
|
| parsed = urlparse.urlparse(hostname)
|
| + if parsed.netloc in ADDITIONAL_SCOPES:
|
| + scopes = "%s %s" % (scopes, ADDITIONAL_SCOPES[parsed.netloc])
|
| +
|
| if parsed.path or parsed.params or parsed.query or parsed.fragment:
|
| raise AuthenticationError(
|
| 'Expecting a hostname or root host URL, got %s instead' % hostname)
|
| - return Authenticator(parsed.netloc, config)
|
| + return Authenticator(parsed.netloc, config, scopes)
|
|
|
|
|
| class Authenticator(object):
|
| @@ -235,7 +244,7 @@ class Authenticator(object):
|
| config: AuthConfig object that holds authentication configuration.
|
| """
|
|
|
| - def __init__(self, token_cache_key, config):
|
| + def __init__(self, token_cache_key, config, scopes):
|
| assert isinstance(config, AuthConfig)
|
| assert config.use_oauth2
|
| self._access_token = None
|
| @@ -243,6 +252,7 @@ class Authenticator(object):
|
| self._lock = threading.Lock()
|
| self._token_cache_key = token_cache_key
|
| self._external_token = None
|
| + self._scopes = scopes
|
| if config.refresh_token_json:
|
| self._external_token = _read_refresh_token_json(config.refresh_token_json)
|
| logging.debug('Using auth config %r', config)
|
| @@ -487,7 +497,7 @@ class Authenticator(object):
|
| logging.debug('Requesting user to login')
|
| raise LoginRequiredError(self._token_cache_key)
|
| logging.debug('Launching OAuth browser flow')
|
| - credentials = _run_oauth_dance(self._config)
|
| + credentials = _run_oauth_dance(self._config, self._scopes)
|
| _log_credentials_info('new token', credentials)
|
|
|
| logging.info(
|
| @@ -560,7 +570,7 @@ def _log_credentials_info(title, credentials):
|
| })
|
|
|
|
|
| -def _run_oauth_dance(config):
|
| +def _run_oauth_dance(config, scopes):
|
| """Perform full 3-legged OAuth2 flow with the browser.
|
|
|
| Returns:
|
| @@ -572,7 +582,7 @@ def _run_oauth_dance(config):
|
| flow = client.OAuth2WebServerFlow(
|
| OAUTH_CLIENT_ID,
|
| OAUTH_CLIENT_SECRET,
|
| - OAUTH_SCOPES,
|
| + scopes,
|
| approval_prompt='force')
|
|
|
| use_local_webserver = config.use_local_webserver
|
|
|