Skip to content

Commit

Permalink
created a User model and integrated it in the authentication process
Browse files Browse the repository at this point in the history
  • Loading branch information
jessehattabaugh committed Feb 8, 2012
1 parent f8d4f05 commit 6f9f275
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 65 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.pyc
73 changes: 56 additions & 17 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from google.appengine.ext.webapp import util
from google.appengine.api.urlfetch import fetch
from google.appengine.api import memcache
from google.appengine.ext import db
import simplejson as json
from urllib import urlencode
from bottle import request
Expand All @@ -21,19 +22,58 @@
else: #prod
from prod_settings import *

def before(fn):
class User(db.Model):
oauth_token = db.StringProperty()
firstName = db.StringProperty()
lastName = db.StringProperty()
photo = db.LinkProperty()
email = db.EmailProperty()
link = db.LinkProperty()
checkins = db.IntegerProperty()

def from_api(self, data):
self.firstName = data['firstName']
self.lastName = data['lastName']
self.photo = db.Link(data['photo'])
self.link = db.Link(data['canonicalUrl'])
self.email = db.Email(data['contact']['email'])
self.checkins = int(data['checkins']['count'])


def prepare_request(fn):
""" before filter that sets properties in request to be used by all request handlers """
def wrapped():
request.out=dict()
request.oauth_token=request.get_cookie('user', secret=CLIENT_SECRET)
request.out=dict()
request.oauth_token = request.get_cookie('user', secret=CLIENT_SECRET)
if request.oauth_token:
user_info_url='https://api.foursquare.com/v2/users/self?oauth_token='+request.oauth_token+'&v='+DATEVERIFIED
api_response=json.loads(fetch(user_info_url).content)
if 'response' in api_response and 'user' in api_response['response']:
request.out['user']=api_response['response']['user']
else:
bottle.response.set_cookie('user', None, CLIENT_SECRET)
logging.info('invalidated auth token')
#todo memcache user data for up to 30 days
user = User.all().filter('oauth_token =', request.oauth_token).get() # look for a User with the token
if not user: # can't find the oauth_token
#todo: also do this if the user's data needs to be refreshed
# ask the api for user data
users_url = 'https://api.foursquare.com/v2/users/self?oauth_token=%s&v=%s'%(request.oauth_token, DATEVERIFIED)
api_response = json.loads(fetch(users_url).content)
if 'response' in api_response and 'user' in api_response['response']: # api call succeeded
# look for a user with the user id
foursquare_id=int(api_response['response']['user']['id'])
user = User.get_by_id(foursquare_id)
if not user: # no user is found
# make a new user record
user = User(key=db.Key.from_path('User', foursquare_id))
else: # oauth_token must have changed
user.oauth_token = request.oauth_token
# update the User's data while we have the api response
user.from_api(api_response['response']['user'])
user.put()
logging.info('created user')
else: # api call failed, the oauth_token is bad
# delete cookie
bottle.response.set_cookie('user', None, CLIENT_SECRET)
logging.info('invalidated auth token')
# store the user
if user:
request.user = user
# else: oauth_token must be bad, get another
#todo: bottle.redirect('login')?
return fn()
return wrapped

Expand Down Expand Up @@ -101,15 +141,15 @@ def mode(iterable):
return max(counts, key = counts.get)

@bottle.get('/')
@bottle.view('home')
@before
@prepare_request
def home():
if not 'user' in request.out:
if not request.user:
request.out['client_id']=CLIENT_ID
request.out['redirect_uri']=REDIRECT_URI
return bottle.template('welcome')
else:
#load all the user's checkins
checkins = get_checkins(request.oauth_token, request.out['user']['checkins']['count'])
checkins = get_checkins(request.oauth_token, request.user.checkins)
data = get_tod_data(checkins, request.oauth_token)
kmcl = KMeansClustering(data)
clusters = kmcl.getclusters(10)
Expand All @@ -127,8 +167,7 @@ def home():
))

groups=sorted(groups, key=lambda k: k['tod_min'])
request.out['groups'] = groups
return request.out
return bottle.template('home', user=request.user, groups=groups)

@bottle.get('/callback')
@bottle.view('auth')
Expand Down
5 changes: 0 additions & 5 deletions views/auth.tpl

This file was deleted.

51 changes: 8 additions & 43 deletions views/home.tpl
Original file line number Diff line number Diff line change
@@ -1,44 +1,13 @@
%import time
%def unauthed():

<article class="hero-unit" role="main">
<h1>Lets hang out sometime!</h1>
<p>You and your friends always say that, but everybody's so busy
it's hard to find a time to meet up. Using your Foursquare
checkins we can tell where you and your friends hang out
and what time you're there. So lets get started. Shall we!?</p>
<p><a href="https://foursquare.com/oauth2/authenticate?client_id={{client_id}}&response_type=code&redirect_uri={{redirect_uri}}"><img src="https://playfoursquare.s3.amazonaws.com/press/logo/connect-blue@2x.png"></a></p>

<h2>Don't worry</h2>
<p>We only use your personal information for our records and to send you notifications from your friends. We won't send you spam, or sell your information to third parties.</p>
</article>

<div class="row">
<div class="span4">
<h2>Everybody flakes.</h2>
<p>It's not their fault though. Sometimes you just need a little nudge to get the party started.</p>
<p><a class="btn" href="#">View details &raquo;</a></p>
</div>
<div class="span4">
<h2>Who has the time?</h2>
<p>People's work and school schedules make it hard to find a time when you're both available. If you're checking in maybe you have time to hang out.</p>
<p><a class="btn" href="#">View details &raquo;</a></p>
</div>
<div class="span4">
<h2>That's so far!</h2>
<p>Using the geolocation of your checkins we can find places nearby where you already go.</p>
<p><a class="btn" href="#">View details &raquo;</a></p>
</div>
</div>
%end

%def authed():
%def stage():
<article>

<h1><img src="{{user['photo']}}">{{user['firstName']}} {{user['lastName']}}</h1>
<h2>{{user['homeCity']}}</h2>
<p><a href="{{user['canonicalUrl']}}">Foursquare Profile</a></p>
<p>{{user['contact']['email']}}</p>
<header>
<h1><img src="{{user.photo}}">{{user.firstName}} {{user.lastName}}</h1>
<p><a href="{{user.link}}">Foursquare Profile</a></p>
<p>{{user.email}}</p>
</header>

<!--<ul class="nav nav-pills">
<li class="active"><a href="#">Any Day</a></li>
Expand Down Expand Up @@ -67,7 +36,7 @@
<li><a href="#">Tomorrow</a></li>
</ul>-->

<p>These are the </p>
<h2>Times when you checkin</h2>
<div class="flexbox btn-group">
%for g in range(len(groups)):
<div class="btn" style="-webkit-box-flex: {{groups[g]['width']}};
Expand All @@ -87,8 +56,4 @@
$('.btn').button()
%end

%if defined('user'):
%rebase main stage=authed, debug=get('debug', None), script=script
%else:
%rebase main stage=unauthed, debug=get('debug', None)
%end
%rebase main stage=stage, debug=get('debug', None), script=script
15 changes: 15 additions & 0 deletions views/welcome.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
%def unauthed():
<article class="hero-unit" role="main">
<h1>Lets hang out sometime!</h1>
<p>You and your friends always say that, but everybody's so busy
it's hard to find a time to meet up. Using your Foursquare
checkins we can tell where you and your friends hang out
and what time you're there. So lets get started. Shall we!?</p>
<p><a href="https://foursquare.com/oauth2/authenticate?client_id={{client_id}}&response_type=code&redirect_uri={{redirect_uri}}"><img src="https://playfoursquare.s3.amazonaws.com/press/logo/connect-blue@2x.png"></a></p>

<h2>Don't worry</h2>
<p>We only use your personal information for our records and to send you notifications from your friends. We won't send you spam, or sell your information to third parties.</p>
</article>
%end

%rebase main stage=stage

0 comments on commit 6f9f275

Please sign in to comment.