/gdata/sample_util.py
Python | 269 lines | 218 code | 27 blank | 24 comment | 25 complexity | 5a2120ee54c469167281306c404c4aa0 MD5 | raw file
1#!/usr/bin/env python 2# 3# Copyright (C) 2009 Google Inc. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17 18"""Provides utility functions used with command line samples.""" 19 20# This module is used for version 2 of the Google Data APIs. 21 22import sys 23import getpass 24import urllib 25import gdata.gauth 26 27__author__ = 'j.s@google.com (Jeff Scudder)' 28 29 30CLIENT_LOGIN = 1 31AUTHSUB = 2 32OAUTH = 3 33 34HMAC = 1 35RSA = 2 36 37 38class SettingsUtil(object): 39 """Gather's user preferences from flags or command prompts. 40 41 An instance of this object stores the choices made by the user. At some 42 point it might be useful to save the user's preferences so that they do 43 not need to always set flags or answer preference prompts. 44 """ 45 46 def __init__(self, prefs=None): 47 self.prefs = prefs or {} 48 49 def get_param(self, name, prompt='', secret=False, ask=True, reuse=False): 50 # First, check in this objects stored preferences. 51 if name in self.prefs: 52 return self.prefs[name] 53 # Second, check for a command line parameter. 54 value = None 55 for i in xrange(len(sys.argv)): 56 if sys.argv[i].startswith('--%s=' % name): 57 value = sys.argv[i].split('=')[1] 58 elif sys.argv[i] == '--%s' % name: 59 value = sys.argv[i + 1] 60 # Third, if it was not on the command line, ask the user to input the 61 # value. 62 if value is None and ask: 63 prompt = '%s: ' % prompt 64 if secret: 65 value = getpass.getpass(prompt) 66 else: 67 value = raw_input(prompt) 68 # If we want to save the preference for reuse in future requests, add it 69 # to this object's prefs. 70 if value is not None and reuse: 71 self.prefs[name] = value 72 return value 73 74 def authorize_client(self, client, auth_type=None, service=None, 75 source=None, scopes=None, oauth_type=None, 76 consumer_key=None, consumer_secret=None): 77 """Uses command line arguments, or prompts user for token values.""" 78 if 'client_auth_token' in self.prefs: 79 return 80 if auth_type is None: 81 auth_type = int(self.get_param( 82 'auth_type', 'Please choose the authorization mechanism you want' 83 ' to use.\n' 84 '1. to use your email address and password (ClientLogin)\n' 85 '2. to use a web browser to visit an auth web page (AuthSub)\n' 86 '3. if you have registed to use OAuth\n', reuse=True)) 87 88 # Get the scopes for the services we want to access. 89 if auth_type == AUTHSUB or auth_type == OAUTH: 90 if scopes is None: 91 scopes = self.get_param( 92 'scopes', 'Enter the URL prefixes (scopes) for the resources you ' 93 'would like to access.\nFor multiple scope URLs, place a comma ' 94 'between each URL.\n' 95 'Example: http://www.google.com/calendar/feeds/,' 96 'http://www.google.com/m8/feeds/\n', reuse=True).split(',') 97 elif isinstance(scopes, (str, unicode)): 98 scopes = scopes.split(',') 99 100 if auth_type == CLIENT_LOGIN: 101 email = self.get_param('email', 'Please enter your username', 102 reuse=False) 103 password = self.get_param('password', 'Password', True, reuse=False) 104 if service is None: 105 service = self.get_param( 106 'service', 'What is the name of the service you wish to access?' 107 '\n(See list:' 108 ' http://code.google.com/apis/gdata/faq.html#clientlogin)', 109 reuse=True) 110 if source is None: 111 source = self.get_param('source', ask=False, reuse=True) 112 client.client_login(email, password, source=source, service=service) 113 elif auth_type == AUTHSUB: 114 auth_sub_token = self.get_param('auth_sub_token', ask=False, reuse=True) 115 session_token = self.get_param('session_token', ask=False, reuse=True) 116 private_key = None 117 auth_url = None 118 single_use_token = None 119 rsa_private_key = self.get_param( 120 'rsa_private_key', 121 'If you want to use secure mode AuthSub, please provide the\n' 122 ' location of your RSA private key which corresponds to the\n' 123 ' certificate you have uploaded for your domain. If you do not\n' 124 ' have an RSA key, simply press enter', reuse=True) 125 126 if rsa_private_key: 127 try: 128 private_key_file = open(rsa_private_key, 'rb') 129 private_key = private_key_file.read() 130 private_key_file.close() 131 except IOError: 132 print 'Unable to read private key from file' 133 134 if private_key is not None: 135 if client.auth_token is None: 136 if session_token: 137 client.auth_token = gdata.gauth.SecureAuthSubToken( 138 session_token, private_key, scopes) 139 self.prefs['client_auth_token'] = gdata.gauth.token_to_blob( 140 client.auth_token) 141 return 142 elif auth_sub_token: 143 client.auth_token = gdata.gauth.SecureAuthSubToken( 144 auth_sub_token, private_key, scopes) 145 client.upgrade_token() 146 self.prefs['client_auth_token'] = gdata.gauth.token_to_blob( 147 client.auth_token) 148 return 149 150 auth_url = gdata.gauth.generate_auth_sub_url( 151 'http://gauthmachine.appspot.com/authsub', scopes, True) 152 print 'with a private key, get ready for this URL', auth_url 153 154 else: 155 if client.auth_token is None: 156 if session_token: 157 client.auth_token = gdata.gauth.AuthSubToken(session_token, 158 scopes) 159 self.prefs['client_auth_token'] = gdata.gauth.token_to_blob( 160 client.auth_token) 161 return 162 elif auth_sub_token: 163 client.auth_token = gdata.gauth.AuthSubToken(auth_sub_token, 164 scopes) 165 client.upgrade_token() 166 self.prefs['client_auth_token'] = gdata.gauth.token_to_blob( 167 client.auth_token) 168 return 169 170 auth_url = gdata.gauth.generate_auth_sub_url( 171 'http://gauthmachine.appspot.com/authsub', scopes) 172 173 print 'Visit the following URL in your browser to authorize this app:' 174 print str(auth_url) 175 print 'After agreeing to authorize the app, copy the token value from' 176 print ' the URL. Example: "www.google.com/?token=ab12" token value is' 177 print ' ab12' 178 token_value = raw_input('Please enter the token value: ') 179 if private_key is not None: 180 single_use_token = gdata.gauth.SecureAuthSubToken( 181 token_value, private_key, scopes) 182 else: 183 single_use_token = gdata.gauth.AuthSubToken(token_value, scopes) 184 client.auth_token = single_use_token 185 client.upgrade_token() 186 187 elif auth_type == OAUTH: 188 if oauth_type is None: 189 oauth_type = int(self.get_param( 190 'oauth_type', 'Please choose the authorization mechanism you want' 191 ' to use.\n' 192 '1. use an HMAC signature using your consumer key and secret\n' 193 '2. use RSA with your private key to sign requests\n', 194 reuse=True)) 195 196 consumer_key = self.get_param( 197 'consumer_key', 'Please enter your OAuth conumer key ' 198 'which identifies your app', reuse=True) 199 200 if oauth_type == HMAC: 201 consumer_secret = self.get_param( 202 'consumer_secret', 'Please enter your OAuth conumer secret ' 203 'which you share with the OAuth provider', True, reuse=False) 204 # Swap out this code once the client supports requesting an oauth 205 # token. 206 # Get a request token. 207 request_token = client.get_oauth_token( 208 scopes, 'http://gauthmachine.appspot.com/oauth', consumer_key, 209 consumer_secret=consumer_secret) 210 elif oauth_type == RSA: 211 rsa_private_key = self.get_param( 212 'rsa_private_key', 213 'Please provide the location of your RSA private key which\n' 214 ' corresponds to the certificate you have uploaded for your' 215 ' domain.', 216 reuse=True) 217 try: 218 private_key_file = open(rsa_private_key, 'rb') 219 private_key = private_key_file.read() 220 private_key_file.close() 221 except IOError: 222 print 'Unable to read private key from file' 223 224 request_token = client.get_oauth_token( 225 scopes, 'http://gauthmachine.appspot.com/oauth', consumer_key, 226 rsa_private_key=private_key) 227 else: 228 print 'Invalid OAuth signature type' 229 return None 230 231 # Authorize the request token in the browser. 232 print 'Visit the following URL in your browser to authorize this app:' 233 print str(request_token.generate_authorization_url()) 234 print 'After agreeing to authorize the app, copy URL from the browser\'s' 235 print ' address bar.' 236 url = raw_input('Please enter the url: ') 237 gdata.gauth.authorize_request_token(request_token, url) 238 # Exchange for an access token. 239 client.auth_token = client.get_access_token(request_token) 240 else: 241 print 'Invalid authorization type.' 242 return None 243 if client.auth_token: 244 self.prefs['client_auth_token'] = gdata.gauth.token_to_blob( 245 client.auth_token) 246 247 248def get_param(name, prompt='', secret=False, ask=True): 249 settings = SettingsUtil() 250 return settings.get_param(name=name, prompt=prompt, secret=secret, ask=ask) 251 252 253def authorize_client(client, auth_type=None, service=None, source=None, 254 scopes=None, oauth_type=None, consumer_key=None, 255 consumer_secret=None): 256 """Uses command line arguments, or prompts user for token values.""" 257 settings = SettingsUtil() 258 return settings.authorize_client(client=client, auth_type=auth_type, 259 service=service, source=source, 260 scopes=scopes, oauth_type=oauth_type, 261 consumer_key=consumer_key, 262 consumer_secret=consumer_secret) 263 264 265def print_options(): 266 """Displays usage information, available command line params.""" 267 # TODO: fill in the usage description for authorizing the client. 268 print '' 269