173 lines
5.8 KiB
Python
173 lines
5.8 KiB
Python
#!/usr/bin/python2.5
|
|
|
|
# Copyright (C) 2010 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
# use this file except in compliance with the License. You may obtain a copy of
|
|
# the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations under
|
|
# the License.
|
|
|
|
"""Handlers for Sample SyncAdapter services.
|
|
|
|
Contains several RequestHandler subclasses used to handle post operations.
|
|
This script is designed to be run directly as a WSGI application.
|
|
|
|
Authenticate: Handles user requests for authentication.
|
|
FetchFriends: Handles user requests for friend list.
|
|
FriendData: Stores information about user's friends.
|
|
"""
|
|
|
|
import cgi
|
|
from datetime import datetime
|
|
from django.utils import simplejson
|
|
from google.appengine.api import users
|
|
from google.appengine.ext import db
|
|
from google.appengine.ext import webapp
|
|
from model import datastore
|
|
import wsgiref.handlers
|
|
|
|
|
|
class Authenticate(webapp.RequestHandler):
|
|
"""Handles requests for login and authentication.
|
|
|
|
UpdateHandler only accepts post events. It expects each
|
|
request to include username and password fields. It returns authtoken
|
|
after successful authentication and "invalid credentials" error otherwise.
|
|
"""
|
|
|
|
def post(self):
|
|
self.username = self.request.get('username')
|
|
self.password = self.request.get('password')
|
|
password = datastore.UserCredentials.get(self.username)
|
|
if password == self.password:
|
|
self.response.set_status(200, 'OK')
|
|
# return the password as AuthToken
|
|
self.response.out.write(password)
|
|
else:
|
|
self.response.set_status(401, 'Invalid Credentials')
|
|
|
|
|
|
class FetchFriends(webapp.RequestHandler):
|
|
"""Handles requests for fetching user's friendlist.
|
|
|
|
UpdateHandler only accepts post events. It expects each
|
|
request to include username and authtoken. If the authtoken is valid
|
|
it returns user's friend info in JSON format.It uses helper
|
|
class FriendData to fetch user's friendlist.
|
|
"""
|
|
|
|
def post(self):
|
|
self.username = self.request.get('username')
|
|
self.password = self.request.get('password')
|
|
self.timestamp = None
|
|
timestamp = self.request.get('timestamp')
|
|
if timestamp:
|
|
self.timestamp = datetime.strptime(timestamp, '%Y/%m/%d %H:%M')
|
|
password = datastore.UserCredentials.get(self.username)
|
|
if password == self.password:
|
|
self.friend_list = []
|
|
friends = datastore.UserFriends.get_friends(self.username)
|
|
if friends:
|
|
for friend in friends:
|
|
friend_handle = getattr(friend, 'friend_handle')
|
|
|
|
if self.timestamp is None or getattr(friend, 'updated') > self.timestamp:
|
|
if (getattr(friend, 'deleted')) == True:
|
|
friend = {}
|
|
friend['u'] = friend_handle
|
|
friend['d'] = 'true'
|
|
friend['i'] = str(datastore.User.get_user_id(friend_handle))
|
|
self.friend_list.append(friend)
|
|
else:
|
|
FriendsData(self.friend_list, friend_handle)
|
|
else:
|
|
if datastore.User.get_user_last_updated(friend_handle) > self.timestamp:
|
|
FriendsData(self.friend_list, friend_handle)
|
|
self.response.set_status(200)
|
|
self.response.out.write(toJSON(self.friend_list))
|
|
else:
|
|
self.response.set_status(401, 'Invalid Credentials')
|
|
|
|
class FetchStatus(webapp.RequestHandler):
|
|
"""Handles requests fetching friend statuses.
|
|
|
|
UpdateHandler only accepts post events. It expects each
|
|
request to include username and authtoken. If the authtoken is valid
|
|
it returns status info in JSON format.
|
|
"""
|
|
|
|
def post(self):
|
|
self.username = self.request.get('username')
|
|
self.password = self.request.get('password')
|
|
password = datastore.UserCredentials.get(self.username)
|
|
if password == self.password:
|
|
self.status_list = []
|
|
friends = datastore.UserFriends.get_friends(self.username)
|
|
if friends:
|
|
for friend in friends:
|
|
friend_handle = getattr(friend, 'friend_handle')
|
|
status_text = datastore.User.get_user_status(friend_handle)
|
|
user_id = datastore.User.get_user_id(friend_handle)
|
|
status = {}
|
|
status['i'] = str(user_id)
|
|
status['s'] = status_text
|
|
self.status_list.append(status)
|
|
self.response.set_status(200)
|
|
self.response.out.write(toJSON(self.status_list))
|
|
else:
|
|
self.response.set_status(401, 'Invalid Credentials')
|
|
|
|
def toJSON(self):
|
|
"""Dumps the data represented by the object to JSON for wire transfer."""
|
|
return simplejson.dumps(self.friend_list)
|
|
|
|
|
|
def toJSON(object):
|
|
"""Dumps the data represented by the object to JSON for wire transfer."""
|
|
return simplejson.dumps(object)
|
|
|
|
class FriendsData(object):
|
|
"""Holds data for user's friends.
|
|
|
|
This class knows how to serialize itself to JSON.
|
|
"""
|
|
__FIELD_MAP = {
|
|
'handle': 'u',
|
|
'firstname': 'f',
|
|
'lastname': 'l',
|
|
'status': 's',
|
|
'phone_home': 'h',
|
|
'phone_office': 'o',
|
|
'phone_mobile': 'm',
|
|
'email': 'e',
|
|
}
|
|
|
|
def __init__(self, friend_list, username):
|
|
obj = datastore.User.get_user_info(username)
|
|
friend = {}
|
|
for obj_name, json_name in self.__FIELD_MAP.items():
|
|
if hasattr(obj, obj_name):
|
|
friend[json_name] = str(getattr(obj, obj_name))
|
|
friend['i'] = str(obj.key().id())
|
|
friend_list.append(friend)
|
|
|
|
|
|
def main():
|
|
application = webapp.WSGIApplication(
|
|
[('/auth', Authenticate),
|
|
('/login', Authenticate),
|
|
('/fetch_friend_updates', FetchFriends),
|
|
('/fetch_status', FetchStatus),
|
|
],
|
|
debug=True)
|
|
wsgiref.handlers.CGIHandler().run(application)
|
|
|
|
if __name__ == "__main__":
|
|
main() |