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':

Reply via email to