Home | History | Annotate | Download | only in hello-python
      1 #!/usr/bin/python
      2 # Copyright (c) 2010 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 from google.appengine.ext import webapp
      7 from google.appengine.ext.webapp import util
      8 from google.appengine.api import users
      9 from google.appengine.api import urlfetch
     10 from google.appengine.ext.webapp import template
     11 from google.appengine.api.urlfetch import DownloadError
     12 import oauth2
     13 import urllib
     14 import logging
     15 import os
     16 import time
     17 from django.utils import simplejson
     18 
     19 # Configuration
     20 
     21 CONFIG = {
     22   'oauth_consumer_key': 'anonymous',
     23   'oauth_consumer_secret': 'anonymous',
     24   'license_server': 'https://www.googleapis.com',
     25   'license_path': '%(server)s/chromewebstore/v1/licenses/%(appid)s/%(userid)s',
     26   'oauth_token': 'INSERT OAUTH TOKEN HERE',
     27   'oauth_token_secret': 'INSERT OAUTH TOKEN SECRET HERE',
     28   'app_id': 'INSERT APPLICATION ID HERE',
     29 }
     30 
     31 # Check to see if the server has been deployed.  In the dev server, this
     32 # env variable will start with 'Development', in production, it will start with
     33 # 'Google App Engine'
     34 IS_PRODUCTION = os.environ['SERVER_SOFTWARE'].startswith('Google App Engine')
     35 
     36 # Valid access levels that may be returned by the license server.
     37 VALID_ACCESS_LEVELS = ['FREE_TRIAL', 'FULL']
     38 
     39 def fetch_license_data(userid):
     40   """Fetches the license for a given user by making an OAuth signed request
     41   to the license server.
     42 
     43   Args:
     44     userid OpenID of the user you are checking access for.
     45 
     46   Returns:
     47     The server's response as text.
     48   """
     49   url = CONFIG['license_path'] % {
     50     'server': CONFIG['license_server'],
     51     'appid': CONFIG['app_id'],
     52     'userid': urllib.quote_plus(userid),
     53   }
     54 
     55   oauth_token = oauth2.Token(**{
     56     'key': CONFIG['oauth_token'],
     57     'secret': CONFIG['oauth_token_secret']
     58   })
     59 
     60   oauth_consumer = oauth2.Consumer(**{
     61     'key': CONFIG['oauth_consumer_key'],
     62     'secret': CONFIG['oauth_consumer_secret']
     63   })
     64 
     65   logging.debug('Requesting %s' % url)
     66   client = oauth2.Client(oauth_consumer, oauth_token)
     67   resp, content = client.request(url, 'GET')
     68   logging.debug('Got response code %s, content %s' % (resp, content))
     69   return content
     70 
     71 def parse_license_data(userid):
     72   """Returns the license for a given user as a structured object.
     73 
     74   Args:
     75     userid: The OpenID of the user to check.
     76 
     77   Returns:
     78     An object with the following parameters:
     79       error:  True if something went wrong, False otherwise.
     80       message: A descriptive message if error is True.
     81       access: One of 'NO', 'FREE_TRIAL', or 'FULL' depending on the access.
     82   """
     83   license = {'error': False, 'message': '', 'access': 'NO'}
     84   try:
     85     response_text = fetch_license_data(userid)
     86     try:
     87       logging.debug('Attempting to JSON parse: %s' % response_text)
     88       json = simplejson.loads(response_text)
     89       logging.debug('Got license server response: %s' % json)
     90     except ValueError:
     91       logging.exception('Could not parse response as JSON: %s' % response_text)
     92       license['error'] = True
     93       license['message'] = 'Could not parse the license server response'
     94   except DownloadError:
     95     logging.exception('Could not fetch license data')
     96     license['error'] = True
     97     license['message'] = 'Could not fetch license data'
     98 
     99   if json.has_key('error'):
    100     license['error'] = True
    101     license['message'] = json['error']['message']
    102   elif json['result'] == 'YES' and json['accessLevel'] in VALID_ACCESS_LEVELS:
    103     license['access'] = json['accessLevel']
    104 
    105   return license
    106 
    107 class MainHandler(webapp.RequestHandler):
    108   """Request handler class."""
    109   def get(self):
    110     """Handler for GET requests."""
    111     user = users.get_current_user()
    112     if user:
    113       if IS_PRODUCTION:
    114         # We should use federated_identity in production, since the license
    115         # server requires an OpenID
    116         userid = user.federated_identity()
    117       else:
    118         # On the dev server, we won't have access to federated_identity, so
    119         # just use a default OpenID which will never return YES.
    120         # If you want to test different response values on the development
    121         # server, just change this default value (e.g. append '-yes' or
    122         # '-trial').
    123         userid = ('https://www.google.com/accounts/o8/id?'
    124                   'id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
    125       license_data = parse_license_data(userid)
    126       template_data = {
    127         'license': license_data,
    128         'user_name': user.nickname(),
    129         'user_id': userid,
    130         'user_logout': users.create_logout_url(self.request.uri),
    131       }
    132     else:
    133       # Force the OpenID login endpoint to be for Google accounts only, since
    134       # the license server doesn't support any other type of OpenID provider.
    135       login_url = users.create_login_url(dest_url='/',
    136                       federated_identity='google.com/accounts/o8/id')
    137       template_data = {
    138         'user_login': login_url,
    139       }
    140 
    141     # Render a simple template
    142     path = os.path.join(os.path.dirname(__file__), 'templates', 'index.html')
    143     self.response.out.write(template.render(path, template_data))
    144 
    145 if __name__ == '__main__':
    146   application = webapp.WSGIApplication([
    147     ('/', MainHandler),
    148   ], debug=False)
    149   util.run_wsgi_app(application)
    150