Home | History | Annotate | Download | only in samplesyncadapter_server
      1 #!/usr/bin/python2.5
      2 
      3 # Copyright (C) 2010 The Android Open Source Project
      4 # 
      5 # Licensed under the Apache License, Version 2.0 (the "License"); you may not
      6 # use this file except in compliance with the License. You may obtain a copy of
      7 # the License at
      8 # 
      9 # http://www.apache.org/licenses/LICENSE-2.0
     10 # 
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     14 # License for the specific language governing permissions and limitations under
     15 # the License.
     16 
     17 """Handlers for Sample SyncAdapter services.
     18 
     19 Contains several RequestHandler subclasses used to handle post operations.
     20 This script is designed to be run directly as a WSGI application.
     21 
     22   Authenticate: Handles user requests for authentication.
     23   FetchFriends: Handles user requests for friend list.
     24   FriendData: Stores information about user's friends.
     25 """
     26 
     27 import cgi
     28 from datetime import datetime
     29 from django.utils import simplejson
     30 from google.appengine.api import users
     31 from google.appengine.ext import db
     32 from google.appengine.ext import webapp
     33 from model import datastore
     34 import wsgiref.handlers
     35 
     36 
     37 class Authenticate(webapp.RequestHandler):
     38   """Handles requests for login and authentication.
     39 
     40   UpdateHandler only accepts post events. It expects each
     41   request to include username and password fields. It returns authtoken
     42   after successful authentication and "invalid credentials" error otherwise.
     43   """
     44 
     45   def post(self):
     46     self.username = self.request.get('username')
     47     self.password = self.request.get('password')
     48     password = datastore.UserCredentials.get(self.username)
     49     if password == self.password:
     50       self.response.set_status(200, 'OK')
     51       # return the password as AuthToken
     52       self.response.out.write(password)
     53     else:
     54       self.response.set_status(401, 'Invalid Credentials')
     55 
     56 
     57 class FetchFriends(webapp.RequestHandler):
     58   """Handles requests for fetching user's friendlist.
     59 
     60   UpdateHandler only accepts post events. It expects each
     61   request to include username and authtoken. If the authtoken is valid
     62   it returns user's friend info in JSON format.It uses helper
     63   class FriendData to fetch user's friendlist.
     64   """
     65 
     66   def post(self):
     67     self.username = self.request.get('username')
     68     self.password = self.request.get('password')
     69     self.timestamp = None
     70     timestamp = self.request.get('timestamp')
     71     if timestamp:
     72       self.timestamp = datetime.strptime(timestamp, '%Y/%m/%d %H:%M')
     73     password = datastore.UserCredentials.get(self.username)
     74     if password == self.password:
     75       self.friend_list = []
     76       friends = datastore.UserFriends.get_friends(self.username)
     77       if friends:
     78         for friend in friends:
     79           friend_handle = getattr(friend, 'friend_handle')
     80 
     81           if self.timestamp is None or getattr(friend, 'updated') > self.timestamp:
     82             if (getattr(friend, 'deleted')) == True:
     83               friend = {}
     84               friend['u'] = friend_handle
     85               friend['d'] = 'true'
     86               friend['i'] = str(datastore.User.get_user_id(friend_handle))
     87               self.friend_list.append(friend)
     88             else:
     89               FriendsData(self.friend_list, friend_handle)
     90           else:
     91             if datastore.User.get_user_last_updated(friend_handle) > self.timestamp:
     92               FriendsData(self.friend_list, friend_handle)
     93       self.response.set_status(200)
     94       self.response.out.write(toJSON(self.friend_list))
     95     else:
     96       self.response.set_status(401, 'Invalid Credentials')
     97 
     98 class FetchStatus(webapp.RequestHandler):
     99   """Handles requests fetching friend statuses.
    100 
    101   UpdateHandler only accepts post events. It expects each
    102   request to include username and authtoken. If the authtoken is valid
    103   it returns status info in JSON format.
    104   """
    105 
    106   def post(self):
    107     self.username = self.request.get('username')
    108     self.password = self.request.get('password')
    109     password = datastore.UserCredentials.get(self.username)
    110     if password == self.password:
    111       self.status_list = []
    112       friends = datastore.UserFriends.get_friends(self.username)
    113       if friends:
    114         for friend in friends:
    115           friend_handle = getattr(friend, 'friend_handle')
    116           status_text = datastore.User.get_user_status(friend_handle)
    117 	  user_id = datastore.User.get_user_id(friend_handle)
    118           status = {}
    119           status['i'] = str(user_id)
    120           status['s'] = status_text
    121           self.status_list.append(status)
    122       self.response.set_status(200)
    123       self.response.out.write(toJSON(self.status_list))
    124     else:
    125       self.response.set_status(401, 'Invalid Credentials')
    126 
    127   def toJSON(self):
    128     """Dumps the data represented by the object to JSON for wire transfer."""
    129     return simplejson.dumps(self.friend_list)
    130 
    131 
    132 def toJSON(object):
    133   """Dumps the data represented by the object to JSON for wire transfer."""
    134   return simplejson.dumps(object)
    135 
    136 class FriendsData(object):
    137   """Holds data for user's friends.
    138 
    139   This class knows how to serialize itself to JSON.
    140   """
    141   __FIELD_MAP = {
    142       'handle': 'u',
    143       'firstname': 'f',
    144       'lastname': 'l',
    145       'status': 's',
    146       'phone_home': 'h',
    147       'phone_office': 'o',
    148       'phone_mobile': 'm',
    149       'email': 'e',
    150   }
    151 
    152   def __init__(self, friend_list, username):
    153     obj = datastore.User.get_user_info(username)
    154     friend = {}
    155     for obj_name, json_name in self.__FIELD_MAP.items():
    156       if hasattr(obj, obj_name):
    157         friend[json_name] = str(getattr(obj, obj_name))
    158         friend['i'] = str(obj.key().id())
    159     friend_list.append(friend)
    160 
    161 
    162 def main():
    163   application = webapp.WSGIApplication(
    164       [('/auth', Authenticate),
    165        ('/login', Authenticate),
    166        ('/fetch_friend_updates', FetchFriends),
    167        ('/fetch_status', FetchStatus),
    168       ],
    169       debug=True)
    170   wsgiref.handlers.CGIHandler().run(application)
    171 
    172 if __name__ == "__main__":
    173   main()