Tidy up LinkedInApi so that it does authentication in conjunction with
authorAndrew Flegg <andrew@bleb.org>
Tue, 8 Jun 2010 23:04:26 +0000 (00:04 +0100)
committerAndrew Flegg <andrew@bleb.org>
Tue, 8 Jun 2010 23:04:26 +0000 (00:04 +0100)
the UI, and stores off the username (like Facebook does).

package/src/org/maemo/hermes/engine/linkedin/api.py
package/src/org/maemo/hermes/engine/linkedin/provider.py

index 0d9eb24..6eaf200 100644 (file)
@@ -13,10 +13,12 @@ class LinkedInApi():
     GCONF_API_KEY = '/apps/maemo/hermes/linkedin_key'
     GCONF_API_SECRET = '/apps/maemo/hermes/linkedin_secret'
     GCONF_ACCESS_TOKEN = '/apps/maemo/hermes/linkedin_access_token'
+    GCONF_USER = '/apps/maemo/hermes/linkedin_user'
     
     LI_SERVER = "api.linkedin.com"
     LI_API_URL = "https://api.linkedin.com"
     LI_CONN_API_URL = LI_API_URL + "/v1/people/~/connections"
+    LI_PROFILE_API_URL = LI_API_URL + "/v1/people/~"
 
     REQUEST_TOKEN_URL = LI_API_URL + "/uas/oauth/requestToken"
     AUTHORIZE_URL = LI_API_URL + "/uas/oauth/authorize"
@@ -42,8 +44,6 @@ class LinkedInApi():
 
         self.consumer = oauth.OAuthConsumer(api_key, secret_key)
         self.sig_method = oauth.OAuthSignatureMethod_HMAC_SHA1()
-        
-        self._verify_browser_command()
 
 
     # -----------------------------------------------------------------------
@@ -51,7 +51,7 @@ class LinkedInApi():
         need_auth()
         token = self._get_request_token()
         url = self._get_authorize_url(token)
-        verifier = block_for_auth(True)
+        verifier = block_for_auth(url)
         self._verify_verifier(token, verifier)
     
     
@@ -194,6 +194,10 @@ class LinkedInApi():
     def _verify_verifier(self, request_token, verifier):
         try:
             self.access_token = self._get_access_token(request_token, verifier)
+            xml = self._make_api_request(self.LI_PROFILE_API_URL)
+            dom = parseString(xml)
+            friends = self._parse_dom(dom)
+            self._gc.set_string(LinkedInApi.GCONF_USER, friends[0].get_name())
         except Exception, e:
             import traceback
             traceback.print_exc()
@@ -201,15 +205,10 @@ class LinkedInApi():
 
 
     # -----------------------------------------------------------------------
-    def _verify_browser_command(self):
-        # -- Check the environment is going to work...
-        # FIXME: duplication
-        if (self._gc.get_string('/desktop/gnome/url-handlers/http/command') == 'epiphany %s'):
-            raise Exception('Browser in gconf invalid (see NB#136012). Installation error.')
-
-
-    # -----------------------------------------------------------------------
     def _store_access_token_in_gconf(self, token_str):
+        if "oauth_problem" in token_str:
+            raise Exception("Authorization failure - access token reported OAuth problem")
+        
         self._gc.set_string(LinkedInApi.GCONF_ACCESS_TOKEN, token_str)
 
         
@@ -220,9 +219,6 @@ class LinkedInApi():
         token_str = self._gc.get_string(LinkedInApi.GCONF_ACCESS_TOKEN)
         if not token_str:
             return None
-        if "oauth_problem" in token_str:
-            self._store_access_token_in_gconf("")
-            raise Exception("Authorization failure - access token reported OAuth problem")
         return oauth.OAuthToken.from_string(token_str)
 
 
@@ -230,4 +226,5 @@ class LinkedInApi():
     def remove_access_token_from_gconf(self):
         """Remove the oauth.OAuthToken, if any."""
         
-        self._gc.unset(LinkedInAPI.GCONF_ACCESS_TOKEN)
+        self._gc.unset(LinkedInApi.GCONF_ACCESS_TOKEN)
+        self._gc.unset(LinkedInApi.GCONF_USER)
index f4f871a..a25db8b 100644 (file)
@@ -1,6 +1,7 @@
 import gnome.gconf
 import gobject, gtk, hildon
 import time, thread
+import webbrowser
 import org.maemo.hermes.engine.provider
 import org.maemo.hermes.engine.linkedin.service
 from org.maemo.hermes.engine.linkedin.api import LinkedInApi
@@ -27,6 +28,13 @@ class Provider(org.maemo.hermes.engine.provider.Provider):
     
     
     # -----------------------------------------------------------------------
+    def get_account_detail(self):
+        """Return the name of the linked LinkedIn account."""
+        
+        return self._gc.get_string(LinkedInApi.GCONF_USER)
+    
+    
+    # -----------------------------------------------------------------------
     def has_preferences(self):
         """Whether or not this provider has any preferences. If it does not,
            open_preferences must NOT be called; as the behaviour is undetermined."""
@@ -38,20 +46,16 @@ class Provider(org.maemo.hermes.engine.provider.Provider):
     def open_preferences(self, parent):
         """Open the preferences for this provider as a child of the 'parent' widget."""
 
+        self.main_window = parent
         api = LinkedInApi(gconf = self._gc) 
         dialog = gtk.Dialog(self.get_name(), parent)
         dialog.add_button(_('Disable'), gtk.RESPONSE_NO)
         dialog.add_button(_('Enable'), gtk.RESPONSE_YES)
     
-        authenticated = api.get_access_token_from_gconf() is not None 
-        title = authenticated and _("Clear authorisation") or _("Authorise")
         button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT,
-                               hildon.BUTTON_ARRANGEMENT_VERTICAL,
-                               title = title)
-        if authenticated:
-            button.connect('clicked', lambda e: api.remove_access_token_from_gconf)
-        else:
-            button.connect('clicked', lambda e: api.authenticate(lambda: None, self.block_for_auth))
+                               hildon.BUTTON_ARRANGEMENT_VERTICAL)
+        self._handle_button(None, api, button)
+        button.connect('clicked', self._handle_button, api, button)
             
         dialog.vbox.add(gtk.Label(""))
         dialog.vbox.add(button)
@@ -64,47 +68,44 @@ class Provider(org.maemo.hermes.engine.provider.Provider):
             return None
     
         return result == gtk.RESPONSE_YES
-        # FIXME: do auth:
-        # get request token
-        # get auth token
-        # open browser to have user allow data access
-        # user inputs the 5 char  
+
+
+    # -----------------------------------------------------------------------
+    def _handle_button(self, e, api, button):
+        """Ensure the button state is correct."""
+        
+        authenticated = api.get_access_token_from_gconf() is not None
+        if e is not None:
+            if authenticated:
+                api.remove_access_token_from_gconf()
+            else:
+                api.authenticate(lambda: None, self.block_for_auth)
         
+            authenticated = api.get_access_token_from_gconf() is not None
+        
+        button.set_title(authenticated and _("Clear authorisation") or _("Authorise"))
+
         
     # -----------------------------------------------------------------------
-    def block_for_auth(self, prompt = True, main = False, lock = None):
+    def block_for_auth(self, url):
         """Part of the GUI callback API."""
 
-        print "Get input:", prompt, main, lock
-        return "12345"
-#        if main:
-#            note = gtk.Dialog(_('Service authorisation'), self.main_window)
-#            note.add_button(_("Validate"), gtk.RESPONSE_OK)
-#            if prompt:
-#                input = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
-#                input.set_property('is-focus', False)
-#                note.set_title(_("Verification code from web browser"))
-#                note.vbox.add(input)
-#            else:
-#                note.vbox.add(gtk.Label(_("\nPress 'Validate' once account has\nbeen authorised in web browser.\n")))
-#    
-#            note.show_all()
-#            result = note.run()
-#            note.hide()
-#            lock.release()
-#            if prompt and result == gtk.RESPONSE_OK:
-#                print input.get_text()
-#                return input.get_text()
-#            else:
-#                return None
-#        
-#        else:
-#            time.sleep(2)
-#            lock = thread.allocate_lock()
-#            lock.acquire()
-#            gobject.idle_add(self.block_for_auth, prompt, True, lock)
-#            lock.acquire()
-#            lock.release()
+        webbrowser.open(url)
+        time.sleep(2)
+        note = gtk.Dialog(_('Service authorisation'), self.main_window)
+        note.add_button(_("Validate"), gtk.RESPONSE_OK)
+        input = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
+        input.set_property('is-focus', False)
+        note.set_title(_("Verification code from web browser"))
+        note.vbox.add(input)
+
+        note.show_all()
+        result = note.run()
+        note.hide()
+        if result == gtk.RESPONSE_OK:
+            return input.get_text()
+        else:
+            return None
 
     
     # -----------------------------------------------------------------------