]> git.parisson.com Git - django-social-auth.git/commitdiff
Add linkedin fields selector support
authorMatías Aguirre <matiasaguirre@gmail.com>
Thu, 2 Jun 2011 16:30:42 +0000 (13:30 -0300)
committerMatías Aguirre <matiasaguirre@gmail.com>
Thu, 2 Jun 2011 16:30:42 +0000 (13:30 -0300)
README.rst
doc/backends/index.rst
doc/backends/linkedin.rst [new file with mode: 0644]
social_auth/backends/contrib/linkedin.py

index eeb2a967f2585c01e6108b2fcd29242f14410cf0..8c1dbee065e664657d6e00164cf8df51a33df8f1 100644 (file)
@@ -483,6 +483,20 @@ To enable OAuth2 support:
 Check which applications can be included in their `Google Data Protocol Directory`_
 
 
+--------
+LinkedIn
+--------
+LinkedIn setup is similar to any other OAuth service. To request extra fields
+using `LinkedIn fields selectors`_ just define the setting::
+
+    LINKEDIN_EXTRA_FIELD_SELECTORS = [...]
+
+with the needed fields selectors, also define LINKEDIN_EXTRA_DATA properly, that
+way the values will be stored in ``UserSocialAuth.extra_data`` field.
+
+By default ``id``, ``first-name`` and ``last-name`` are requested and stored.
+
+
 -------
 Testing
 -------
@@ -649,3 +663,4 @@ Base work is copyrighted by:
 .. _django-social-auth: https://convore.com/django-social-auth/
 .. _Convore: https://convore.com/
 .. _Selenium: http://seleniumhq.org/
+.. _LinkedIn fields selectors: http://developer.linkedin.com/docs/DOC-1014
index ac8d71ed7ddb99bf971075032e585f02148e3ba3..d3fb25ae68b6bd7615fd11897d687cf91e434ae0 100644 (file)
@@ -11,3 +11,4 @@ Contents:
    google
    twitter
    facebook
+   linkedin
diff --git a/doc/backends/linkedin.rst b/doc/backends/linkedin.rst
new file mode 100644 (file)
index 0000000..c3e6eb5
--- /dev/null
@@ -0,0 +1,15 @@
+LinkedIn
+========
+
+LinkedIn setup is similar to any other OAuth service. To request extra fields
+using `LinkedIn fields selectors`_ just define this setting::
+
+    LINKEDIN_EXTRA_FIELD_SELECTORS = [...]
+
+with the needed fields selectors, also define LINKEDIN_EXTRA_DATA properly, that
+way the values will be stored in ``UserSocialAuth.extra_data`` field.
+
+By default ``id``, ``first-name`` and ``last-name`` are requested and stored.
+
+
+.. _LinkedIn fields selectors: http://developer.linkedin.com/docs/DOC-1014
index af5287acd47501ef44054dd373fe122d27666675..1327b7613e03d39132c066edc4f5e56e1ba314e5 100644 (file)
@@ -3,11 +3,12 @@ Linkedin OAuth support
 
 No extra configurations are needed to make this work.
 """
-from cgi import parse_qs
 from xml.etree import ElementTree
 from xml.parsers.expat import ExpatError
 
-from social_auth.backends import ConsumerBasedOAuth, OAuthBackend
+from django.conf import settings
+
+from social_auth.backends import ConsumerBasedOAuth, OAuthBackend, USERNAME
 
 
 LINKEDIN_SERVER = 'linkedin.com'
@@ -18,19 +19,26 @@ LINKEDIN_ACCESS_TOKEN_URL = 'https://api.%s/uas/oauth/accessToken' % \
 LINKEDIN_AUTHORIZATION_URL = 'https://www.%s/uas/oauth/authenticate' % \
                                     LINKEDIN_SERVER
 LINKEDIN_CHECK_AUTH = 'https://api.%s/v1/people/~' % LINKEDIN_SERVER
+# Check doc at http://developer.linkedin.com/docs/DOC-1014 about how to use
+# fields selectors to retrieve extra user data
+LINKEDIN_FIELD_SELECTORS = ['id', 'first-name', 'last-name']
 
 
 class LinkedinBackend(OAuthBackend):
     """Linkedin OAuth authentication backend"""
     name = 'linkedin'
+    EXTRA_DATA = [('id', 'id'),
+                  ('first-name', 'first_name'),
+                  ('last-name', 'last_name')]
 
     def get_user_details(self, response):
         """Return user details from Linkedin account"""
-        return {
-            'first_name': response['first-name'],
-            'last_name': response['last-name'],
-            'email': '',  # not supplied
-        }
+        first_name, last_name = response['first-name'], response['last-name']
+        return {USERNAME: first_name + last_name,
+                'fullname': first_name + ' ' + last_name,
+                'first_name': first_name,
+                'last_name': last_name,
+                'email': ''}
 
 
 class LinkedinAuth(ConsumerBasedOAuth):
@@ -45,14 +53,15 @@ class LinkedinAuth(ConsumerBasedOAuth):
 
     def user_data(self, access_token):
         """Return user data provided"""
-        request = self.oauth_request(access_token, LINKEDIN_CHECK_AUTH)
+        fields_selectors = LINKEDIN_FIELD_SELECTORS + \
+                           getattr(settings, 'LINKEDIN_EXTRA_FIELD_SELECTORS',
+                                   [])
+        url = LINKEDIN_CHECK_AUTH + ':(%s)' % ','.join(fields_selectors)
+        request = self.oauth_request(access_token, url)
         raw_xml = self.fetch_response(request)
         try:
             xml = ElementTree.fromstring(raw_xml)
-            data = _xml_to_dict(xml)
-            url = data['site-standard-profile-request']['url']
-            url = url.replace('&amp;', '&')
-            data['id'] = parse_qs(url)['key'][0]
+            data = to_dict(xml)
             return data
         except (ExpatError, KeyError, IndexError):
             return None
@@ -62,16 +71,10 @@ class LinkedinAuth(ConsumerBasedOAuth):
         return True
 
 
-def _xml_to_dict(xml):
-    """Convert xml structure to dict"""
-    data = {}
-    for child in xml.getchildren():
-        if child.getchildren():
-            data[child.tag] = _xml_to_dict(child)
-        else:
-            data[child.tag] = child.text
-
-    return data
+def to_dict(xml):
+    """Convert XML structure to dict recursively"""
+    return dict((node.tag, to_dict(node) if node.getchildren() else node.text)
+                        for node in xml.getchildren())
 
 
 # Backend definition