OLD | NEW |
(Empty) | |
| 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) |
OLD | NEW |