From: Matías Aguirre Date: Thu, 2 Jun 2011 16:30:42 +0000 (-0300) Subject: Add linkedin fields selector support X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=0ab9377a8ab0e54252426f2043a61c5d8c4427c2;p=django-social-auth.git Add linkedin fields selector support --- diff --git a/README.rst b/README.rst index eeb2a96..8c1dbee 100644 --- a/README.rst +++ b/README.rst @@ -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 diff --git a/doc/backends/index.rst b/doc/backends/index.rst index ac8d71e..d3fb25a 100644 --- a/doc/backends/index.rst +++ b/doc/backends/index.rst @@ -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 index 0000000..c3e6eb5 --- /dev/null +++ b/doc/backends/linkedin.rst @@ -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 diff --git a/social_auth/backends/contrib/linkedin.py b/social_auth/backends/contrib/linkedin.py index af5287a..1327b76 100644 --- a/social_auth/backends/contrib/linkedin.py +++ b/social_auth/backends/contrib/linkedin.py @@ -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('&', '&') - 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