From bb43d4cae446e8b6b25699a3272c339f1cb70f7c Mon Sep 17 00:00:00 2001 From: Chris Rossi Date: Tue, 17 Dec 2013 09:36:43 -0500 Subject: [PATCH] House cleaning. --- .../linkedin/management/commands/__init__.py | 112 ++++++++++++++++++ .../linkedin/management/commands/api.py | 99 ---------------- .../linkedin/management/commands/findusers.py | 2 +- .../linkedin/management/commands/login.py | 2 +- 4 files changed, 114 insertions(+), 101 deletions(-) delete mode 100644 lms/djangoapps/linkedin/management/commands/api.py diff --git a/lms/djangoapps/linkedin/management/commands/__init__.py b/lms/djangoapps/linkedin/management/commands/__init__.py index e69de29bb2..5a836bf3fc 100644 --- a/lms/djangoapps/linkedin/management/commands/__init__.py +++ b/lms/djangoapps/linkedin/management/commands/__init__.py @@ -0,0 +1,112 @@ +""" +Class for accessing LinkedIn's API. +""" +import hashlib +import json +import urllib2 +import urlparse +import uuid + +from django.conf import settings +from django.core.management.base import CommandError + +from ...models import LinkedInToken + + +class LinkedinAPI(object): + """ + Encapsulates the LinkedIn API. + """ + def __init__(self): + config = getattr(settings, "LINKEDIN_API", None) + if not config: + raise CommandError("LINKEDIN_API is not configured") + self.config = config + + try: + self.tokens = LinkedInToken.objects.get() + except LinkedInToken.DoesNotExist: + self.tokens = None + + self.state = str(uuid.uuid4()) + + def http_error(self, error, message): + """ + Handle an unexpected HTTP response. + """ + print "!!ERROR!!" + print error + print error.read() + raise CommandError(message) + + def authorization_url(self): + """ + Synthesize a URL for beginning the authorization flow. + """ + config = self.config + return ("https://www.linkedin.com/uas/oauth2/authorization" + "?response_type=code" + "&client_id=%s&state=%s&redirect_uri=%s" % ( + config['CLIENT_ID'], self.state, config['REDIRECT_URI'])) + + def get_authorization_code(self, redirect): + """ + Extract the authorization code from the redirect URL at the end of + the authorization flow. + """ + query = urlparse.parse_qs(urlparse.urlparse(redirect).query) + assert query['state'][0] == self.state, (query['state'][0], self.state) + return query['code'][0] + + def get_access_token(self, code): + """ + Given an authorization code, get an access token. + """ + config = self.config + url = ("https://www.linkedin.com/uas/oauth2/accessToken" + "?grant_type=authorization_code" + "&code=%s&redirect_uri=%s&client_id=%s&client_secret=%s" % ( + code, config['REDIRECT_URI'], config['CLIENT_ID'], + config['CLIENT_SECRET'])) + + try: + response = urllib2.urlopen(url).read() + except urllib2.HTTPError, error: + self.http_error(error, "Unable to retrieve access token") + + access_token = json.loads(response)['access_token'] + try: + tokens = LinkedInToken.objects.get() + tokens.access_token = access_token + tokens.authorization_code = code + except LinkedInToken.DoesNotExist: + tokens = LinkedInToken(access_token=access_token) + tokens.save() + self.tokens = tokens + + return access_token + + def batch(self, emails): + """ + Get the LinkedIn status for a batch of emails. + """ + if self.tokens is None: + raise CommandError( + "You must log in to LinkedIn in order to use this script. " + "Please use the 'login' command to log in to LinkedIn.") + + def md5(email): + "Compute md5 hash for an email address." + md5hash = hashlib.md5() + md5hash.update(email) + return md5hash.hexdigest() + + hashes = ','.join(("email-hash=" + md5(email) for email in emails)) + url = "https://api.linkedin.com/v1/people::(%s):(id)" % hashes + url += "?oauth2_access_token=%s" % self.tokens.access_token + try: + response = urllib2.urlopen(url).read() + print "GOT IT!", response + except urllib2.HTTPError, error: + self.http_error(error, "Unable to access People API") + return (True for email in emails) diff --git a/lms/djangoapps/linkedin/management/commands/api.py b/lms/djangoapps/linkedin/management/commands/api.py deleted file mode 100644 index 5b0f46a209..0000000000 --- a/lms/djangoapps/linkedin/management/commands/api.py +++ /dev/null @@ -1,99 +0,0 @@ -import hashlib -import json -import urllib2 -import urlparse -import uuid - -from django.conf import settings -from django.core.management.base import CommandError - -from ...models import LinkedInToken - -class LinkedinAPI(object): - """ - Encapsulates the LinkedIn API. - """ - def __init__(self): - config = getattr(settings, "LINKEDIN_API", None) - if not config: - raise CommandError("LINKEDIN_API is not configured") - self.config = config - - try: - self.tokens = LinkedInToken.objects.get() - except LinkedInToken.DoesNotExist: - self.tokens = None - - self.state = str(uuid.uuid4()) - - def http_error(error, message): - print "!!ERROR!!" - print error - print error.read() - raise CommandError(message) - - def authorization_url(self): - config = self.config - return ("https://www.linkedin.com/uas/oauth2/authorization" - "?response_type=code" - "&client_id=%s&state=%s&redirect_uri=%s" % ( - config['CLIENT_ID'], self.state, config['REDIRECT_URI'])) - - def get_authorization_code(self, redirect): - query = urlparse.parse_qs(urlparse.urlparse(redirect).query) - assert query['state'][0] == self.state, (query['state'][0], self.state) - return query['code'][0] - - def get_access_token(self, code): - config = self.config - url = ("https://www.linkedin.com/uas/oauth2/accessToken" - "?grant_type=authorization_code" - "&code=%s&redirect_uri=%s&client_id=%s&client_secret=%s" % ( - code, config['REDIRECT_URI'], config['CLIENT_ID'], - config['CLIENT_SECRET'])) - - try: - response = urllib2.urlopen(url).read() - except urllib2.HTTPError, error: - self.http_error(error, "Unable to retrieve access token") - - access_token = json.loads(response)['access_token'] - try: - tokens = LinkedInToken.objects.get() - tokens.access_token = access_token - tokens.authorization_code = code - except LinkedInToken.DoesNotExist: - tokens = LinkedInToken(access_token=access_token) - tokens.save() - self.tokens = tokens - - return access_token - - def batch(self, emails): - """ - Get the LinkedIn status for a batch of emails. - """ - if self.tokens is None: - raise CommandError( - "You must log in to LinkedIn in order to use this script. " - "Please use the 'login' command to log in to LinkedIn.") - - def md5(email): - "Compute md5 hash for an email address." - hash = hashlib.md5() - hash.update(email) - return hash.hexdigest() - - hashes = ','.join(("email-hash=" + md5(email) for email in emails)) - url = "https://api.linkedin.com/v1/people::(%s):(id)" % hashes - url += "?oauth2_access_token=%s" % self.tokens.access_token - try: - response = urllib2.urlopen(url).read() - except urllib2.HTTPError, error: - print "!!ERROR!!" - print error - print error.read() - - raise CommandError("Unable to access People API") - - return (True for email in emails) diff --git a/lms/djangoapps/linkedin/management/commands/findusers.py b/lms/djangoapps/linkedin/management/commands/findusers.py index 5311bfc581..30a31d5c00 100644 --- a/lms/djangoapps/linkedin/management/commands/findusers.py +++ b/lms/djangoapps/linkedin/management/commands/findusers.py @@ -13,7 +13,7 @@ from django.utils import timezone from optparse import make_option from ...models import LinkedIn -from .api import LinkedinAPI +from . import LinkedinAPI FRIDAY = 4 diff --git a/lms/djangoapps/linkedin/management/commands/login.py b/lms/djangoapps/linkedin/management/commands/login.py index 04c16696e4..7f835892cb 100644 --- a/lms/djangoapps/linkedin/management/commands/login.py +++ b/lms/djangoapps/linkedin/management/commands/login.py @@ -3,7 +3,7 @@ Log into LinkedIn API. """ from django.core.management.base import BaseCommand -from .api import LinkedinAPI +from . import LinkedinAPI class Command(BaseCommand):