#!/usr/bin/python # Copyright (c) 2010 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 from django.utils import simplejson # 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) json = simplejson.loads(response_text) logging.debug('Got license server response: %s' % json) 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 json.has_key('error'): license['error'] = True license['message'] = json['error']['message'] elif json['result'] == 'YES' and json['accessLevel'] in VALID_ACCESS_LEVELS: license['access'] = json['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)