• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
19Contains several RequestHandler subclasses used to handle post operations.
20This 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
27import cgi
28from datetime import datetime
29from django.utils import simplejson
30from google.appengine.api import users
31from google.appengine.ext import db
32from google.appengine.ext import webapp
33from model import datastore
34import wsgiref.handlers
35
36
37class 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
57class 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
98class 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
132def toJSON(object):
133  """Dumps the data represented by the object to JSON for wire transfer."""
134  return simplejson.dumps(object)
135
136class 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
162def 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
172if __name__ == "__main__":
173  main()