Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / target / linkedin.py @ 9d20fe23

History | View | Annotate | Download (6.4 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

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

    
74

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

    
84
    request_token = dict(cgi.parse_qsl(content))
85
    request.session['request_token'] = request_token
86

    
87
    url = request_token.get('xoauth_request_auth_url') + "?oauth_token=%s" % request_token.get('oauth_token')
88

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

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

    
95
    return HttpResponseRedirect(url)
96

    
97

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

    
106
    consumer = oauth.Consumer(settings.LINKEDIN_TOKEN,
107
                              settings.LINKEDIN_SECRET)
108
    client = oauth.Client(consumer)
109

    
110
    if request.GET.get('denied'):
111
        return HttpResponseRedirect(reverse('edit_profile'))
112

    
113
    if not 'request_token' in request.session:
114
        messages.error(request, 'linkedin handshake failed')
115
        return HttpResponseRedirect(reverse('edit_profile'))
116

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

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

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

    
150

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