diff options
Diffstat (limited to 'deprecated/cwp/bartlett/server.py')
-rwxr-xr-x | deprecated/cwp/bartlett/server.py | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/deprecated/cwp/bartlett/server.py b/deprecated/cwp/bartlett/server.py new file mode 100755 index 00000000..8fb7d61e --- /dev/null +++ b/deprecated/cwp/bartlett/server.py @@ -0,0 +1,153 @@ +#!/usr/bin/python2 +# Copyright 2012 Google Inc. All Rights Reserved. +# Author: mrdmnd@ (Matt Redmond) +# Based off of code in //depot/google3/experimental/mobile_gwp +"""Code to transport profile data between a user's machine and the CWP servers. + Pages: + "/": the main page for the app, left blank so that users cannot access + the file upload but left in the code for debugging purposes + "/upload": Updates the datastore with a new file. the upload depends on + the format which is templated on the main page ("/") + input includes: + profile_data: the zipped file containing profile data + board: the architecture we ran on + chromeos_version: the chromeos_version + "/serve": Lists all of the files in the datastore. Each line is a new entry + in the datastore. The format is key~date, where key is the entry's + key in the datastore and date is the file upload time and date. + (Authentication Required) + "/serve/([^/]+)?": For downloading a file of profile data, ([^/]+)? means + any character sequence so to download the file go to + '/serve/$key' where $key is the datastore key of the file + you want to download. + (Authentication Required) + "/del/([^/]+)?": For deleting an entry in the datastore. To use go to + '/del/$key' where $key is the datastore key of the entry + you want to be deleted form the datastore. + (Authentication Required) + TODO: Add more extensive logging""" + +import cgi +import logging +import md5 +import urllib + +from google.appengine.api import users +from google.appengine.ext import db +from google.appengine.ext import webapp +from google.appengine.ext.webapp.util import run_wsgi_app + +logging.getLogger().setLevel(logging.DEBUG) + + +class FileEntry(db.Model): + profile_data = db.BlobProperty() # The profile data + date = db.DateTimeProperty(auto_now_add=True) # Date it was uploaded + data_md5 = db.ByteStringProperty() # md5 of the profile data + board = db.StringProperty() # board arch + chromeos_version = db.StringProperty() # ChromeOS version + + +class MainPage(webapp.RequestHandler): + """Main page only used as the form template, not actually displayed.""" + + def get(self, response=''): # pylint: disable-msg=C6409 + if response: + self.response.out.write('<html><body>') + self.response.out.write("""<br> + <form action="/upload" enctype="multipart/form-data" method="post"> + <div><label>Profile Data:</label></div> + <div><input type="file" name="profile_data"/></div> + <div><label>Board</label></div> + <div><input type="text" name="board"/></div> + <div><label>ChromeOS Version</label></div> + <div><input type="text" name="chromeos_version"></div> + <div><input type="submit" value="send" name="submit"></div> + </form> + </body> + </html>""") + + +class Upload(webapp.RequestHandler): + """Handler for uploading data to the datastore, accessible by anyone.""" + + def post(self): # pylint: disable-msg=C6409 + """Takes input based on the main page's form.""" + getfile = FileEntry() + f1 = self.request.get('profile_data') + getfile.profile_data = db.Blob(f1) + getfile.data_md5 = md5.new(f1).hexdigest() + getfile.board = self.request.get('board') + getfile.chromeos_version = self.request.get('chromeos_version') + getfile.put() + self.response.out.write(getfile.key()) + #self.redirect('/') + + +class ServeHandler(webapp.RequestHandler): + """Given the entry's key in the database, output the profile data file. Only + accessible from @google.com accounts.""" + + def get(self, resource): # pylint: disable-msg=C6409 + if Authenticate(self): + file_key = str(urllib.unquote(resource)) + request = db.get(file_key) + self.response.out.write(request.profile_data) + + +class ListAll(webapp.RequestHandler): + """Displays all files uploaded. Only accessible by @google.com accounts.""" + + def get(self): # pylint: disable-msg=C6409 + """Displays all information in FileEntry, ~ delimited.""" + if Authenticate(self): + query_str = 'SELECT * FROM FileEntry ORDER BY date ASC' + query = db.GqlQuery(query_str) + delimiter = '~' + + for item in query: + display_list = [item.key(), item.date, item.data_md5, item.board, + item.chromeos_version] + str_list = [cgi.escape(str(i)) for i in display_list] + self.response.out.write(delimiter.join(str_list) + '</br>') + + +class DelEntries(webapp.RequestHandler): + """Deletes entries. Only accessible from @google.com accounts.""" + + def get(self, resource): # pylint: disable-msg=C6409 + """A specific entry is deleted, when the key is given.""" + if Authenticate(self): + fkey = str(urllib.unquote(resource)) + request = db.get(fkey) + if request: + db.delete(fkey) + + +def Authenticate(webpage): + """Some urls are only accessible if logged in with a @google.com account.""" + user = users.get_current_user() + if user is None: + webpage.redirect(users.create_login_url(webpage.request.uri)) + elif user.email().endswith('@google.com'): + return True + else: + webpage.response.out.write('Not Authenticated') + return False + + +def main(): + application = webapp.WSGIApplication( + [ + ('/', MainPage), + ('/upload', Upload), + ('/serve/([^/]+)?', ServeHandler), + ('/serve', ListAll), + ('/del/([^/]+)?', DelEntries), + ], + debug=False) + run_wsgi_app(application) + + +if __name__ == '__main__': + main() |