|  | #!/usr/bin/env python | 
|  | # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | from google.appengine.ext import webapp | 
|  | from google.appengine.ext.webapp import util | 
|  | from google.appengine.api import users | 
|  | from google.appengine.api import urlfetch | 
|  | from google.appengine.ext.webapp import template | 
|  | from google.appengine.api.urlfetch import DownloadError | 
|  | import oauth2 | 
|  | import urllib | 
|  | import logging | 
|  | import os | 
|  | import time | 
|  | import json | 
|  |  | 
|  | # Configuration | 
|  |  | 
|  | CONFIG = { | 
|  | 'oauth_consumer_key': 'anonymous', | 
|  | 'oauth_consumer_secret': 'anonymous', | 
|  | 'license_server': 'https://www.googleapis.com', | 
|  | 'license_path': '%(server)s/chromewebstore/v1/licenses/%(appid)s/%(userid)s', | 
|  | 'oauth_token': 'INSERT OAUTH TOKEN HERE', | 
|  | 'oauth_token_secret': 'INSERT OAUTH TOKEN SECRET HERE', | 
|  | 'app_id': 'INSERT APPLICATION ID HERE', | 
|  | } | 
|  |  | 
|  | # Check to see if the server has been deployed.  In the dev server, this | 
|  | # env variable will start with 'Development', in production, it will start with | 
|  | # 'Google App Engine' | 
|  | IS_PRODUCTION = os.environ['SERVER_SOFTWARE'].startswith('Google App Engine') | 
|  |  | 
|  | # Valid access levels that may be returned by the license server. | 
|  | VALID_ACCESS_LEVELS = ['FREE_TRIAL', 'FULL'] | 
|  |  | 
|  |  | 
|  | def fetch_license_data(userid): | 
|  | """Fetches the license for a given user by making an OAuth signed request | 
|  | to the license server. | 
|  |  | 
|  | Args: | 
|  | userid OpenID of the user you are checking access for. | 
|  |  | 
|  | Returns: | 
|  | The server's response as text. | 
|  | """ | 
|  | url = CONFIG['license_path'] % { | 
|  | 'server': CONFIG['license_server'], | 
|  | 'appid': CONFIG['app_id'], | 
|  | 'userid': urllib.quote_plus(userid), | 
|  | } | 
|  |  | 
|  | oauth_token = oauth2.Token(**{ | 
|  | 'key': CONFIG['oauth_token'], | 
|  | 'secret': CONFIG['oauth_token_secret'] | 
|  | }) | 
|  |  | 
|  | oauth_consumer = oauth2.Consumer(**{ | 
|  | 'key': CONFIG['oauth_consumer_key'], | 
|  | 'secret': CONFIG['oauth_consumer_secret'] | 
|  | }) | 
|  |  | 
|  | logging.debug('Requesting %s' % url) | 
|  | client = oauth2.Client(oauth_consumer, oauth_token) | 
|  | resp, content = client.request(url, 'GET') | 
|  | logging.debug('Got response code %s, content %s' % (resp, content)) | 
|  | return content | 
|  |  | 
|  |  | 
|  | def parse_license_data(userid): | 
|  | """Returns the license for a given user as a structured object. | 
|  |  | 
|  | Args: | 
|  | userid: The OpenID of the user to check. | 
|  |  | 
|  | Returns: | 
|  | An object with the following parameters: | 
|  | error:  True if something went wrong, False otherwise. | 
|  | message: A descriptive message if error is True. | 
|  | access: One of 'NO', 'FREE_TRIAL', or 'FULL' depending on the access. | 
|  | """ | 
|  | license = {'error': False, 'message': '', 'access': 'NO'} | 
|  | try: | 
|  | response_text = fetch_license_data(userid) | 
|  | try: | 
|  | logging.debug('Attempting to JSON parse: %s' % response_text) | 
|  | response = json.loads(response_text) | 
|  | logging.debug('Got license server response: %s' % response) | 
|  | except ValueError: | 
|  | logging.exception('Could not parse response as JSON: %s' % response_text) | 
|  | license['error'] = True | 
|  | license['message'] = 'Could not parse the license server response' | 
|  | except DownloadError: | 
|  | logging.exception('Could not fetch license data') | 
|  | license['error'] = True | 
|  | license['message'] = 'Could not fetch license data' | 
|  |  | 
|  | if response.has_key('error'): | 
|  | license['error'] = True | 
|  | license['message'] = response['error']['message'] | 
|  | elif (response['result'] == 'YES' | 
|  | and response['accessLevel'] in VALID_ACCESS_LEVELS): | 
|  | license['access'] = response['accessLevel'] | 
|  |  | 
|  | return license | 
|  |  | 
|  |  | 
|  | class MainHandler(webapp.RequestHandler): | 
|  | """Request handler class.""" | 
|  | def get(self): | 
|  | """Handler for GET requests.""" | 
|  | user = users.get_current_user() | 
|  | if user: | 
|  | if IS_PRODUCTION: | 
|  | # We should use federated_identity in production, since the license | 
|  | # server requires an OpenID | 
|  | userid = user.federated_identity() | 
|  | else: | 
|  | # On the dev server, we won't have access to federated_identity, so | 
|  | # just use a default OpenID which will never return YES. | 
|  | # If you want to test different response values on the development | 
|  | # server, just change this default value (e.g. append '-yes' or | 
|  | # '-trial'). | 
|  | userid = ('https://www.google.com/accounts/o8/id?' | 
|  | 'id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') | 
|  | license_data = parse_license_data(userid) | 
|  | template_data = { | 
|  | 'license': license_data, | 
|  | 'user_name': user.nickname(), | 
|  | 'user_id': userid, | 
|  | 'user_logout': users.create_logout_url(self.request.uri), | 
|  | } | 
|  | else: | 
|  | # Force the OpenID login endpoint to be for Google accounts only, since | 
|  | # the license server doesn't support any other type of OpenID provider. | 
|  | login_url = users.create_login_url(dest_url='/', | 
|  | federated_identity='google.com/accounts/o8/id') | 
|  | template_data = { | 
|  | 'user_login': login_url, | 
|  | } | 
|  |  | 
|  | # Render a simple template | 
|  | path = os.path.join(os.path.dirname(__file__), 'templates', 'index.html') | 
|  | self.response.out.write(template.render(path, template_data)) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | application = webapp.WSGIApplication([ | 
|  | ('/', MainHandler), | 
|  | ], debug=False) | 
|  | util.run_wsgi_app(application) |