270 lines
10 KiB
Python
270 lines
10 KiB
Python
|
#!/usr/bin/env python
|
||
|
#
|
||
|
# Copyright (C) 2009 Google Inc.
|
||
|
#
|
||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
# you may not use this file except in compliance with the License.
|
||
|
# You may obtain a copy of the License at
|
||
|
#
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
#
|
||
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
# See the License for the specific language governing permissions and
|
||
|
# limitations under the License.
|
||
|
|
||
|
|
||
|
"""Provides utility functions used with command line samples."""
|
||
|
|
||
|
# This module is used for version 2 of the Google Data APIs.
|
||
|
|
||
|
import sys
|
||
|
import getpass
|
||
|
import urllib
|
||
|
import gdata.gauth
|
||
|
|
||
|
__author__ = 'j.s@google.com (Jeff Scudder)'
|
||
|
|
||
|
|
||
|
CLIENT_LOGIN = 1
|
||
|
AUTHSUB = 2
|
||
|
OAUTH = 3
|
||
|
|
||
|
HMAC = 1
|
||
|
RSA = 2
|
||
|
|
||
|
|
||
|
class SettingsUtil(object):
|
||
|
"""Gather's user preferences from flags or command prompts.
|
||
|
|
||
|
An instance of this object stores the choices made by the user. At some
|
||
|
point it might be useful to save the user's preferences so that they do
|
||
|
not need to always set flags or answer preference prompts.
|
||
|
"""
|
||
|
|
||
|
def __init__(self, prefs=None):
|
||
|
self.prefs = prefs or {}
|
||
|
|
||
|
def get_param(self, name, prompt='', secret=False, ask=True, reuse=False):
|
||
|
# First, check in this objects stored preferences.
|
||
|
if name in self.prefs:
|
||
|
return self.prefs[name]
|
||
|
# Second, check for a command line parameter.
|
||
|
value = None
|
||
|
for i in xrange(len(sys.argv)):
|
||
|
if sys.argv[i].startswith('--%s=' % name):
|
||
|
value = sys.argv[i].split('=')[1]
|
||
|
elif sys.argv[i] == '--%s' % name:
|
||
|
value = sys.argv[i + 1]
|
||
|
# Third, if it was not on the command line, ask the user to input the
|
||
|
# value.
|
||
|
if value is None and ask:
|
||
|
prompt = '%s: ' % prompt
|
||
|
if secret:
|
||
|
value = getpass.getpass(prompt)
|
||
|
else:
|
||
|
value = raw_input(prompt)
|
||
|
# If we want to save the preference for reuse in future requests, add it
|
||
|
# to this object's prefs.
|
||
|
if value is not None and reuse:
|
||
|
self.prefs[name] = value
|
||
|
return value
|
||
|
|
||
|
def authorize_client(self, client, auth_type=None, service=None,
|
||
|
source=None, scopes=None, oauth_type=None,
|
||
|
consumer_key=None, consumer_secret=None):
|
||
|
"""Uses command line arguments, or prompts user for token values."""
|
||
|
if 'client_auth_token' in self.prefs:
|
||
|
return
|
||
|
if auth_type is None:
|
||
|
auth_type = int(self.get_param(
|
||
|
'auth_type', 'Please choose the authorization mechanism you want'
|
||
|
' to use.\n'
|
||
|
'1. to use your email address and password (ClientLogin)\n'
|
||
|
'2. to use a web browser to visit an auth web page (AuthSub)\n'
|
||
|
'3. if you have registed to use OAuth\n', reuse=True))
|
||
|
|
||
|
# Get the scopes for the services we want to access.
|
||
|
if auth_type == AUTHSUB or auth_type == OAUTH:
|
||
|
if scopes is None:
|
||
|
scopes = self.get_param(
|
||
|
'scopes', 'Enter the URL prefixes (scopes) for the resources you '
|
||
|
'would like to access.\nFor multiple scope URLs, place a comma '
|
||
|
'between each URL.\n'
|
||
|
'Example: http://www.google.com/calendar/feeds/,'
|
||
|
'http://www.google.com/m8/feeds/\n', reuse=True).split(',')
|
||
|
elif isinstance(scopes, (str, unicode)):
|
||
|
scopes = scopes.split(',')
|
||
|
|
||
|
if auth_type == CLIENT_LOGIN:
|
||
|
email = self.get_param('email', 'Please enter your username',
|
||
|
reuse=False)
|
||
|
password = self.get_param('password', 'Password', True, reuse=False)
|
||
|
if service is None:
|
||
|
service = self.get_param(
|
||
|
'service', 'What is the name of the service you wish to access?'
|
||
|
'\n(See list:'
|
||
|
' http://code.google.com/apis/gdata/faq.html#clientlogin)',
|
||
|
reuse=True)
|
||
|
if source is None:
|
||
|
source = self.get_param('source', ask=False, reuse=True)
|
||
|
client.client_login(email, password, source=source, service=service)
|
||
|
elif auth_type == AUTHSUB:
|
||
|
auth_sub_token = self.get_param('auth_sub_token', ask=False, reuse=True)
|
||
|
session_token = self.get_param('session_token', ask=False, reuse=True)
|
||
|
private_key = None
|
||
|
auth_url = None
|
||
|
single_use_token = None
|
||
|
rsa_private_key = self.get_param(
|
||
|
'rsa_private_key',
|
||
|
'If you want to use secure mode AuthSub, please provide the\n'
|
||
|
' location of your RSA private key which corresponds to the\n'
|
||
|
' certificate you have uploaded for your domain. If you do not\n'
|
||
|
' have an RSA key, simply press enter', reuse=True)
|
||
|
|
||
|
if rsa_private_key:
|
||
|
try:
|
||
|
private_key_file = open(rsa_private_key, 'rb')
|
||
|
private_key = private_key_file.read()
|
||
|
private_key_file.close()
|
||
|
except IOError:
|
||
|
print 'Unable to read private key from file'
|
||
|
|
||
|
if private_key is not None:
|
||
|
if client.auth_token is None:
|
||
|
if session_token:
|
||
|
client.auth_token = gdata.gauth.SecureAuthSubToken(
|
||
|
session_token, private_key, scopes)
|
||
|
self.prefs['client_auth_token'] = gdata.gauth.token_to_blob(
|
||
|
client.auth_token)
|
||
|
return
|
||
|
elif auth_sub_token:
|
||
|
client.auth_token = gdata.gauth.SecureAuthSubToken(
|
||
|
auth_sub_token, private_key, scopes)
|
||
|
client.upgrade_token()
|
||
|
self.prefs['client_auth_token'] = gdata.gauth.token_to_blob(
|
||
|
client.auth_token)
|
||
|
return
|
||
|
|
||
|
auth_url = gdata.gauth.generate_auth_sub_url(
|
||
|
'http://gauthmachine.appspot.com/authsub', scopes, True)
|
||
|
print 'with a private key, get ready for this URL', auth_url
|
||
|
|
||
|
else:
|
||
|
if client.auth_token is None:
|
||
|
if session_token:
|
||
|
client.auth_token = gdata.gauth.AuthSubToken(session_token,
|
||
|
scopes)
|
||
|
self.prefs['client_auth_token'] = gdata.gauth.token_to_blob(
|
||
|
client.auth_token)
|
||
|
return
|
||
|
elif auth_sub_token:
|
||
|
client.auth_token = gdata.gauth.AuthSubToken(auth_sub_token,
|
||
|
scopes)
|
||
|
client.upgrade_token()
|
||
|
self.prefs['client_auth_token'] = gdata.gauth.token_to_blob(
|
||
|
client.auth_token)
|
||
|
return
|
||
|
|
||
|
auth_url = gdata.gauth.generate_auth_sub_url(
|
||
|
'http://gauthmachine.appspot.com/authsub', scopes)
|
||
|
|
||
|
print 'Visit the following URL in your browser to authorize this app:'
|
||
|
print str(auth_url)
|
||
|
print 'After agreeing to authorize the app, copy the token value from'
|
||
|
print ' the URL. Example: "www.google.com/?token=ab12" token value is'
|
||
|
print ' ab12'
|
||
|
token_value = raw_input('Please enter the token value: ')
|
||
|
if private_key is not None:
|
||
|
single_use_token = gdata.gauth.SecureAuthSubToken(
|
||
|
token_value, private_key, scopes)
|
||
|
else:
|
||
|
single_use_token = gdata.gauth.AuthSubToken(token_value, scopes)
|
||
|
client.auth_token = single_use_token
|
||
|
client.upgrade_token()
|
||
|
|
||
|
elif auth_type == OAUTH:
|
||
|
if oauth_type is None:
|
||
|
oauth_type = int(self.get_param(
|
||
|
'oauth_type', 'Please choose the authorization mechanism you want'
|
||
|
' to use.\n'
|
||
|
'1. use an HMAC signature using your consumer key and secret\n'
|
||
|
'2. use RSA with your private key to sign requests\n',
|
||
|
reuse=True))
|
||
|
|
||
|
consumer_key = self.get_param(
|
||
|
'consumer_key', 'Please enter your OAuth conumer key '
|
||
|
'which identifies your app', reuse=True)
|
||
|
|
||
|
if oauth_type == HMAC:
|
||
|
consumer_secret = self.get_param(
|
||
|
'consumer_secret', 'Please enter your OAuth conumer secret '
|
||
|
'which you share with the OAuth provider', True, reuse=False)
|
||
|
# Swap out this code once the client supports requesting an oauth
|
||
|
# token.
|
||
|
# Get a request token.
|
||
|
request_token = client.get_oauth_token(
|
||
|
scopes, 'http://gauthmachine.appspot.com/oauth', consumer_key,
|
||
|
consumer_secret=consumer_secret)
|
||
|
elif oauth_type == RSA:
|
||
|
rsa_private_key = self.get_param(
|
||
|
'rsa_private_key',
|
||
|
'Please provide the location of your RSA private key which\n'
|
||
|
' corresponds to the certificate you have uploaded for your'
|
||
|
' domain.',
|
||
|
reuse=True)
|
||
|
try:
|
||
|
private_key_file = open(rsa_private_key, 'rb')
|
||
|
private_key = private_key_file.read()
|
||
|
private_key_file.close()
|
||
|
except IOError:
|
||
|
print 'Unable to read private key from file'
|
||
|
|
||
|
request_token = client.get_oauth_token(
|
||
|
scopes, 'http://gauthmachine.appspot.com/oauth', consumer_key,
|
||
|
rsa_private_key=private_key)
|
||
|
else:
|
||
|
print 'Invalid OAuth signature type'
|
||
|
return None
|
||
|
|
||
|
# Authorize the request token in the browser.
|
||
|
print 'Visit the following URL in your browser to authorize this app:'
|
||
|
print str(request_token.generate_authorization_url())
|
||
|
print 'After agreeing to authorize the app, copy URL from the browser\'s'
|
||
|
print ' address bar.'
|
||
|
url = raw_input('Please enter the url: ')
|
||
|
gdata.gauth.authorize_request_token(request_token, url)
|
||
|
# Exchange for an access token.
|
||
|
client.auth_token = client.get_access_token(request_token)
|
||
|
else:
|
||
|
print 'Invalid authorization type.'
|
||
|
return None
|
||
|
if client.auth_token:
|
||
|
self.prefs['client_auth_token'] = gdata.gauth.token_to_blob(
|
||
|
client.auth_token)
|
||
|
|
||
|
|
||
|
def get_param(name, prompt='', secret=False, ask=True):
|
||
|
settings = SettingsUtil()
|
||
|
return settings.get_param(name=name, prompt=prompt, secret=secret, ask=ask)
|
||
|
|
||
|
|
||
|
def authorize_client(client, auth_type=None, service=None, source=None,
|
||
|
scopes=None, oauth_type=None, consumer_key=None,
|
||
|
consumer_secret=None):
|
||
|
"""Uses command line arguments, or prompts user for token values."""
|
||
|
settings = SettingsUtil()
|
||
|
return settings.authorize_client(client=client, auth_type=auth_type,
|
||
|
service=service, source=source,
|
||
|
scopes=scopes, oauth_type=oauth_type,
|
||
|
consumer_key=consumer_key,
|
||
|
consumer_secret=consumer_secret)
|
||
|
|
||
|
|
||
|
def print_options():
|
||
|
"""Displays usage information, available command line params."""
|
||
|
# TODO: fill in the usage description for authorizing the client.
|
||
|
print ''
|
||
|
|