Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / target / linkedin.py @ 0e79735c

History | View | Annotate | Download (6.5 kB)

1
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
import json
35

    
36
from django.http import HttpResponseBadRequest
37
from django.utils.translation import ugettext as _
38
from django.contrib import messages
39
from django.template import RequestContext
40
from django.views.decorators.http import require_http_methods
41
from django.http import HttpResponseRedirect
42
from django.core.urlresolvers import reverse
43
from django.core.exceptions import ImproperlyConfigured
44
from django.shortcuts import get_object_or_404
45

    
46
from urlparse import urlunsplit, urlsplit
47

    
48
from astakos.im.util import prepare_response, get_context, login_url
49
from astakos.im.views import requires_anonymous, render_response, \
50
        requires_auth_provider
51
from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION, BASEURL
52
from astakos.im.models import AstakosUser, PendingThirdPartyUser
53
from astakos.im.forms import LoginForm
54
from astakos.im.activation_backends import get_backend, SimpleBackend
55
from astakos.im import settings
56
from astakos.im import auth_providers
57
from astakos.im.target import add_pending_auth_provider, get_pending_key, \
58
    handle_third_party_signup, handle_third_party_login, init_third_party_session
59

    
60
import astakos.im.messages as astakos_messages
61

    
62
import logging
63

    
64
logger = logging.getLogger(__name__)
65

    
66
import oauth2 as oauth
67
import cgi
68

    
69
consumer = oauth.Consumer(settings.LINKEDIN_TOKEN, settings.LINKEDIN_SECRET)
70
client = oauth.Client(consumer)
71

    
72
request_token_url      = 'https://api.linkedin.com/uas/oauth/requestToken?scope=r_basicprofile+r_emailaddress'
73
access_token_url       = 'https://api.linkedin.com/uas/oauth/accessToken'
74
authenticate_url       = 'https://www.linkedin.com/uas/oauth/authorize'
75

    
76

    
77
@requires_auth_provider('linkedin', login=True)
78
@require_http_methods(["GET", "POST"])
79
def login(request):
80
    init_third_party_session(request)
81
    resp, content = client.request(request_token_url, "GET")
82
    if resp['status'] != '200':
83
        messages.error(request, 'Invalid linkedin response')
84
        return HttpResponseRedirect(reverse('edit_profile'))
85

    
86
    request_token = dict(cgi.parse_qsl(content))
87
    request.session['request_token'] = request_token
88

    
89
    url = request_token.get('xoauth_request_auth_url') + "?oauth_token=%s" % request_token.get('oauth_token')
90

    
91
    if request.GET.get('key', None):
92
        request.session['pending_key'] = request.GET.get('key')
93

    
94
    if request.GET.get('next', None):
95
        request.session['next_url'] = request.GET.get('next')
96

    
97
    return HttpResponseRedirect(url)
98

    
99

    
100
@requires_auth_provider('linkedin', login=True)
101
@require_http_methods(["GET", "POST"])
102
def authenticated(
103
    request,
104
    template='im/third_party_check_local.html',
105
    extra_context={}
106
):
107

    
108
    next_url = None
109
    if 'next_url' in request.session:
110
        next_url = request.session['next_url']
111
        del request.session['next_url']
112

    
113
    if request.GET.get('denied'):
114
        return HttpResponseRedirect(reverse('edit_profile'))
115

    
116
    if not 'request_token' in request.session:
117
        messages.error(request, 'linkedin handshake failed')
118
        return HttpResponseRedirect(reverse('edit_profile'))
119

    
120
    token = oauth.Token(request.session['request_token']['oauth_token'],
121
        request.session['request_token']['oauth_token_secret'])
122
    token.set_verifier(request.GET.get('oauth_verifier'))
123
    client = oauth.Client(consumer, token)
124
    resp, content = client.request(access_token_url, "POST")
125
    if resp['status'] != '200':
126
        try:
127
            del request.session['request_token']
128
        except:
129
            pass
130
        messages.error(request, 'Invalid linkedin token response')
131
        return HttpResponseRedirect(reverse('edit_profile'))
132
    access_token = dict(cgi.parse_qsl(content))
133

    
134
    token = oauth.Token(access_token['oauth_token'],
135
        access_token['oauth_token_secret'])
136
    client = oauth.Client(consumer, token)
137
    resp, content = client.request("http://api.linkedin.com/v1/people/~:(id,first-name,last-name,industry,email-address)?format=json", "GET")
138
    if resp['status'] != '200':
139
        try:
140
            del request.session['request_token']
141
        except:
142
            pass
143
        messages.error(request, 'Invalid linkedin profile response')
144
        return HttpResponseRedirect(reverse('edit_profile'))
145

    
146
    profile_data = json.loads(content)
147
    userid = profile_data['id']
148
    username = profile_data.get('emailAddress', None)
149
    realname = profile_data.get('firstName', '') + ' ' + profile_data.get('lastName', '')
150
    provider_info = profile_data
151
    affiliation = 'LinkedIn.com'
152

    
153

    
154
    try:
155
        return handle_third_party_login(request, 'linkedin', userid,
156
                                        provider_info, affiliation)
157
    except AstakosUser.DoesNotExist, e:
158
        third_party_key = get_pending_key(request)
159
        user_info = {'affiliation': affiliation, 'realname': realname}
160
        return handle_third_party_signup(request, userid, 'linkedin',
161
                                         third_party_key,
162
                                         provider_info,
163
                                         user_info,
164
                                         template,
165
                                         extra_context)
166