Massimo here is the full patch with modifications for oauth*_account.py login_methods
tnx! 2010/8/22 Michele Comitini <[email protected]>: > in tools.py line 1436: > next = URL(r=request) + '?_next=' + next > should be like this? > next = self.url('user', args='login') + '?_next=' + next > > > 2010/8/22 Michele Comitini <[email protected]>: >> Ok found a way to fix the problem with redirection (_next parameter). >> Massimo pls look if the following is correct! >> >> >> diff -r 9261ce4eda7f gluon/tools.py >> --- a/gluon/tools.py Thu Aug 19 04:13:54 2010 +0200 >> +++ b/gluon/tools.py Sun Aug 22 00:08:25 2010 +0200 >> @@ -982,7 +983,7 @@ >> request = self.environment.request >> args = request.args >> if not args: >> - redirect(self.url(args='login')) >> + redirect(self.url(args='login', vars=request.vars)) >> elif args[0] in self.settings.actions_disabled: >> raise HTTP(404) >> if args[0] == 'login': >> >> >> 2010/8/20 Michele Comitini <[email protected]>: >>> Hello Narendran, >>> >>> Do not use that it is old.. >>> >>> now facebook is supported inside web2py distribution with oauth20_account.py >>> you can find an example app here: >>> http://code.google.com/r/michelecomitini-facebookaccess/source/browse/#hg/applications/helloFacebook >>> >>> for a simple example usage of graph api look here: >>> http://code.google.com/r/michelecomitini-facebookaccess/source/browse/applications/helloFacebook/models/grafb.py >>> http://code.google.com/r/michelecomitini-facebookaccess/source/browse/applications/helloFacebook/controllers/graph.py >>> http://code.google.com/r/michelecomitini-facebookaccess/source/browse/#hg/applications/helloFacebook/views/graph >>> >>> >>> for the redirection after login I am investigating... >>> >>> mic >>> >>> 2010/8/20 Narendran <[email protected]>: >>>> Hello all, >>>> I picked the Facebook oauth submitted by mcm from >>>> https://code.google.com/r/michelecomitini-facebookaccess/source/browse/gluon/contrib/login_methods/facebook_account.py >>>> (referred in this thread: >>>> http://groups.google.com/group/web2py/browse_thread/thread/be441047bf237f9/6ea33cf0d4bfba63?lnk=gst&q=facebook+oauth#6ea33cf0d4bfba63) >>>> >>>> I am facing one isse: >>>> 1. I've placed require_login decoration on a method say a(). After the >>>> authentication is complete, the page always gets redirected to default/ >>>> index, whereas the ideal behaviour would be to go to a(). It works as >>>> intended if I use default auth instead of Facebook auth. >>>> >>>> Also, is there any plugin/package that would provide full-fledged >>>> support for using Facebook Graph API with web2py? >>>> >>>> -- >>>> Thanks >>>> Narendran >>> >> >
# HG changeset patch # User [email protected] # Date 1282431532 -7200 # Node ID 38ac5690519fb20f98d7ab51f02775b0cdae4482 # Parent 9261ce4eda7f5fb93f3cd5e717be99bfdeb086f9 Modification to keep the action flow after authentication. diff -r 9261ce4eda7f -r 38ac5690519f app.yaml --- a/app.yaml Thu Aug 19 04:13:54 2010 +0200 +++ b/app.yaml Sun Aug 22 00:58:52 2010 +0200 @@ -1,5 +1,5 @@ application: grafbook -version: 1.1 +version: 2 api_version: 1 runtime: python diff -r 9261ce4eda7f -r 38ac5690519f applications/helloFacebook/controllers/graph.py --- a/applications/helloFacebook/controllers/graph.py Thu Aug 19 04:13:54 2010 +0200 +++ b/applications/helloFacebook/controllers/graph.py Sun Aug 22 00:58:52 2010 +0200 @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import simplejson as json -from facebook import GraphAPI +from facebook import GraphAPI, GraphAPIError @auth.requires_login() def index(): @@ -12,7 +11,12 @@ fb_id = 'me' graph = getGraph() - fb_obj = graph.get_object(fb_id, metadata=1) + try: + fb_obj = graph.get_object(fb_id, metadata=1) + except GraphAPIError, e: + print("%s: %s " % (__name__, e)) + redirect(auth.url(f='user', args='logout')) + response.menu = [[k, False, URL(r=request, f='connection', args=[fb_id,k])] for k,v in fb_obj['metadata']['connections'].items()] return dict(message=T('You are at %(fb_id)s', dict(fb_id=fb_id))) @@ -23,7 +27,13 @@ return None fb_id = request.args[0] fb_connection_name = request.args[1] - connections = getGraph().get_connections(fb_id, fb_connection_name) + try: + connections = getGraph().get_connections(fb_id, fb_connection_name) + except GraphAPIError, e: + print("%s: %s " % (__name__, e)) + redirect(auth.url(f='user', args='logout')) + + print connections response.menu=[[v['name'], False, URL(r=request, f='index', args=['id', v['id']])] for v in connections['data']] return dict(message=T('Looking list of %(conn_name)s of %(id)s', dict(conn_name=fb_connection_name, id=fb_id))) diff -r 9261ce4eda7f -r 38ac5690519f applications/helloFacebook/languages/it-it.py --- a/applications/helloFacebook/languages/it-it.py Thu Aug 19 04:13:54 2010 +0200 +++ b/applications/helloFacebook/languages/it-it.py Sun Aug 22 00:58:52 2010 +0200 @@ -8,6 +8,7 @@ 'Available databases and tables': 'Available databases and tables', 'Cannot be empty': 'Cannot be empty', 'Check to delete': 'Check to delete', +'Client IP': 'Client IP', 'Controller': 'Controller', 'Copyright': 'Copyright', 'Current request': 'Current request', @@ -16,31 +17,48 @@ 'DB Model': 'DB Model', 'Database': 'Database', 'Delete:': 'Delete:', +'Description': 'Description', 'Edit': 'Edit', 'Edit This App': 'Edit This App', 'Edit current record': 'Edit current record', +'Group %(group_id)s created': 'Group %(group_id)s created', +'Group ID': 'Group ID', 'Hello World': 'Salve Mondo', +'Hello, Facebook is telling that you are %(first_name)s %(last_name)s': 'Hello, Facebook is telling that you are %(first_name)s %(last_name)s', 'Import/Export': 'Import/Export', 'Index': 'Index', 'Internal State': 'Internal State', 'Invalid Query': 'Query invalida', 'Layout': 'Layout', +'Logged in': 'Logged in', +'Logged out': 'Logged out', 'Main Menu': 'Main Menu', 'Menu Model': 'Menu Model', +'Name': 'Name', 'New Record': 'New Record', 'No databases in this application': 'No databases in this application', +'Origin': 'Origin', 'Powered by': 'Powered by', 'Query:': 'Query:', +'Record ID': 'Record ID', +'Role': 'Role', 'Rows in table': 'Rows in table', 'Rows selected': 'Rows selected', 'Stylesheet': 'Stylesheet', 'Sure you want to delete this object?': 'Sicuro che vuoi cancellare questo oggetto?', +'Table name': 'Table name', 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.', +'Timestamp': 'Timestamp', 'Update:': 'Update:', 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.', +'User %(id)s Logged-in': 'User %(id)s Logged-in', +'User %(id)s Logged-out': 'User %(id)s Logged-out', +'User ID': 'User ID', 'View': 'View', 'Welcome %s': 'Welcome %s', 'Welcome to web2py': 'Ciao da wek2py', +'You are %(name)s': 'You are %(name)s', +'You are at %(fb_id)s': 'You are at %(fb_id)s', 'appadmin is disabled because insecure channel': 'appadmin is disabled because insecure channel', 'cache': 'cache', 'change password': 'change password', diff -r 9261ce4eda7f -r 38ac5690519f applications/helloFacebook/models/db.py --- a/applications/helloFacebook/models/db.py Thu Aug 19 04:13:54 2010 +0200 +++ b/applications/helloFacebook/models/db.py Sun Aug 22 00:58:52 2010 +0200 @@ -4,6 +4,7 @@ ## This scaffolding model makes your app work on Google App Engine too ######################################################################### + if request.env.web2py_runtime_gae: # if running on Google App Engine db = DAL('gae') # connect to Google BigTable session.connect(request, response, db = db) # and store sessions and tickets there @@ -71,7 +72,7 @@ if not path in sys.path: sys.path.append(path) from fbappauth import CLIENT_ID,CLIENT_SECRET -from facebook import GraphAPI +from facebook import GraphAPI, GraphAPIError from gluon.contrib.login_methods.oauth20_account import OAuthAccount class FaceBookAccount(OAuthAccount): """OAuth impl for FaceBook""" @@ -96,15 +97,19 @@ user = None try: user = self.graph.get_object("me") - except GraphAPIError: + except GraphAPIError, e: self.session.token = None self.graph = None + if user: return dict(first_name = user['first_name'], last_name = user['last_name'], username = user['id']) + +crud.settings.auth = None # =auth to enforce authorization on crud +auth.settings.actions_disabled=['register','change_password','request_reset_password','profile'] auth.settings.login_form=FaceBookAccount(globals()) ######################################################################### diff -r 9261ce4eda7f -r 38ac5690519f gluon/contrib/login_methods/oauth10a_account.py --- a/gluon/contrib/login_methods/oauth10a_account.py Thu Aug 19 04:13:54 2010 +0200 +++ b/gluon/contrib/login_methods/oauth10a_account.py Sun Aug 22 00:58:52 2010 +0200 @@ -57,12 +57,13 @@ def __redirect_uri(self): """Build the uri used by the authenticating server to redirect the client back to the page originating the auth request. + Appends the _next action to the generated url so the flows continues. """ r = self.request http_host=self.request.env.http_x_forwarded_for if not http_host: http_host=self.request.env.http_host - return 'http://%s%s' %(http_host, self.request.env.path_info) + return 'http://%s%s' %(http_host, self.request.env.path_info + '?' + urlencode(dict(_next=self.request.vars._next))) def accessToken(self): @@ -123,7 +124,8 @@ def login_url(self, next="/"): - self.__oauth_login() + print ("next: %s, %s" % (next, self.request.vars._next)) + self.__oauth_login(next) return next def logout_url(self, next="/"): @@ -139,7 +141,7 @@ ''' raise NotImplementedError, "Must override get_user()" - def __oauth_login(self): + def __oauth_login(self, next): '''This method redirects the user to the authenticating form on authentication server if the authentication code and the authentication token are not available to the @@ -150,13 +152,15 @@ accessToken() ''' + if not self.accessToken(): # setup the client client = oauth.Client(self.consumer, None) # Get a request token. # oauth_callback *is REQUIRED* for OAuth1.0a # putting it in the body seems to work. - data = urlencode(dict(oauth_callback=self.__redirect_uri())) + callback_url = self.__redirect_uri() + data = urlencode(dict(oauth_callback=callback_url)) resp, content = client.request(self.token_url, "POST", body=data) if resp['status'] != '200': @@ -167,7 +171,7 @@ # Redirect the user to the authentication URL and pass the callback url. data = urlencode(dict(oauth_token=request_token['oauth_token'], - oauth_callback=self.__redirect_uri())) + oauth_callback=callback_url)) auth_request_url = self.auth_url + '?' +data diff -r 9261ce4eda7f -r 38ac5690519f gluon/contrib/login_methods/oauth20_account.py --- a/gluon/contrib/login_methods/oauth20_account.py Thu Aug 19 04:13:54 2010 +0200 +++ b/gluon/contrib/login_methods/oauth20_account.py Sun Aug 22 00:58:52 2010 +0200 @@ -52,12 +52,14 @@ def __redirect_uri(self): """Build the uri used by the authenticating server to redirect the client back to the page originating the auth request. + Appends the _next action to the generated url so the flows continues. """ r = self.request http_host=self.request.env.http_x_forwarded_for if not http_host: http_host=self.request.env.http_host - return 'http://%s%s' %(http_host, self.request.env.path_info) + return 'http://%s%s' %(http_host, self.request.env.path_info + '?' + urlencode(dict(_next=self.request.vars._next))) + def __build_url_opener(self, uri): """Build the url opener for managing HTTP Basic Athentication""" @@ -83,9 +85,9 @@ # reuse token until expiration if expires == 0 or expires > time.time(): return self.session.token['access_token'] - if self.code: + if self.session.code: data = urlencode(dict(redirect_uri=self.__redirect_uri(), - response_type='token', code=self.code)) + response_type='token', code=self.session.code)) open_url = None try: opener = self.__build_url_opener(self.token_url) @@ -98,7 +100,7 @@ redirect_uri=self.__redirect_uri(), client_id=self.client_id, client_secret=self.client_secret, - code=self.code)) + code=self.session.code)) open_url = urlopen(self.token_url + '?' + data) if open_url: tokendata = cgi.parse_qs(open_url.read()) @@ -110,6 +112,7 @@ else: exps = 'expires' self.session.token['expires'] == int(self.session.token[exps]) + time.time() + del self.session.code return self.session.token['access_token'] @@ -121,7 +124,6 @@ self.globals = g self.client_id = client_id self.client_secret = client_secret - self.code = None self.request = g['request'] self.session = g['session'] self.auth_url = auth_url @@ -132,7 +134,8 @@ return next def logout_url(self, next="/"): - return '' + del self.session.token + return next def get_user(self): '''Returns the user using the Graph API. @@ -181,7 +184,7 @@ "You are not authenticated: you are being redirected to the <a href='" + auth_request_url + "'> authentication server</a>", Location=auth_request_url) else: - self.code = self.request.vars.code + self.session.code = self.request.vars.code self.accessToken() - return self.code + return self.session.code return None diff -r 9261ce4eda7f -r 38ac5690519f gluon/tools.py --- a/gluon/tools.py Thu Aug 19 04:13:54 2010 +0200 +++ b/gluon/tools.py Sun Aug 22 00:58:52 2010 +0200 @@ -982,7 +982,7 @@ request = self.environment.request args = request.args if not args: - redirect(self.url(args='login')) + redirect(self.url(args='login', vars=request.vars)) elif args[0] in self.settings.actions_disabled: raise HTTP(404) if args[0] == 'login':

