Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views / target / linkedin.py @ 3e0a032d

History | View | Annotate | Download (5.8 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.contrib import messages
37
from django.views.decorators.http import require_http_methods
38
from django.http import HttpResponseRedirect
39
from django.core.urlresolvers import reverse
40

    
41
from astakos.im.models import AstakosUser
42
from astakos.im import settings
43
from astakos.im.views.target import get_pending_key, \
44
    handle_third_party_signup, handle_third_party_login, init_third_party_session
45
from astakos.im.views.decorators import cookie_fix, \
46
    requires_auth_provider
47

    
48
import logging
49

    
50
logger = logging.getLogger(__name__)
51

    
52
import oauth2 as oauth
53
import cgi
54

    
55

    
56
request_token_url      = 'https://api.linkedin.com/uas/oauth/requestToken?scope=r_basicprofile+r_emailaddress'
57
access_token_url       = 'https://api.linkedin.com/uas/oauth/accessToken'
58
authenticate_url       = 'https://www.linkedin.com/uas/oauth/authorize'
59

    
60

    
61
@requires_auth_provider('linkedin')
62
@require_http_methods(["GET", "POST"])
63
@cookie_fix
64
def login(request):
65
    init_third_party_session(request)
66
    resp, content = client.request(request_token_url, "GET")
67
    if resp['status'] != '200':
68
        messages.error(request, 'Invalid linkedin response')
69
        return HttpResponseRedirect(reverse('edit_profile'))
70

    
71
    request_token = dict(cgi.parse_qsl(content))
72
    request.session['request_token'] = request_token
73

    
74
    url = request_token.get('xoauth_request_auth_url') + "?oauth_token=%s" % request_token.get('oauth_token')
75

    
76
    if request.GET.get('key', None):
77
        request.session['pending_key'] = request.GET.get('key')
78

    
79
    if request.GET.get('next', None):
80
        request.session['next_url'] = request.GET.get('next')
81

    
82
    return HttpResponseRedirect(url)
83

    
84

    
85
@requires_auth_provider('linkedin', login=True)
86
@require_http_methods(["GET", "POST"])
87
@cookie_fix
88
def authenticated(
89
    request,
90
    template='im/third_party_check_local.html',
91
    extra_context=None
92
):
93

    
94
    if extra_context is None:
95
        extra_context = {}
96

    
97
    consumer = oauth.Consumer(settings.LINKEDIN_TOKEN,
98
                              settings.LINKEDIN_SECRET)
99
    client = oauth.Client(consumer)
100

    
101
    if request.GET.get('denied'):
102
        return HttpResponseRedirect(reverse('edit_profile'))
103

    
104
    if not 'request_token' in request.session:
105
        messages.error(request, 'linkedin handshake failed')
106
        return HttpResponseRedirect(reverse('edit_profile'))
107

    
108
    token = oauth.Token(request.session['request_token']['oauth_token'],
109
        request.session['request_token']['oauth_token_secret'])
110
    token.set_verifier(request.GET.get('oauth_verifier'))
111
    client = oauth.Client(consumer, token)
112
    resp, content = client.request(access_token_url, "POST")
113
    if resp['status'] != '200':
114
        try:
115
            del request.session['request_token']
116
        except:
117
            pass
118
        messages.error(request, 'Invalid linkedin token response')
119
        return HttpResponseRedirect(reverse('edit_profile'))
120
    access_token = dict(cgi.parse_qsl(content))
121

    
122
    token = oauth.Token(access_token['oauth_token'],
123
        access_token['oauth_token_secret'])
124
    client = oauth.Client(consumer, token)
125
    resp, content = client.request("http://api.linkedin.com/v1/people/~:(id,first-name,last-name,industry,email-address)?format=json", "GET")
126
    if resp['status'] != '200':
127
        try:
128
            del request.session['request_token']
129
        except:
130
            pass
131
        messages.error(request, 'Invalid linkedin profile response')
132
        return HttpResponseRedirect(reverse('edit_profile'))
133

    
134
    profile_data = json.loads(content)
135
    userid = profile_data['id']
136
    username = profile_data.get('emailAddress', None)
137
    realname = profile_data.get('firstName', '') + ' ' + profile_data.get('lastName', '')
138
    provider_info = profile_data
139
    affiliation = 'LinkedIn.com'
140

    
141

    
142
    try:
143
        return handle_third_party_login(request, 'linkedin', userid,
144
                                        provider_info, affiliation)
145
    except AstakosUser.DoesNotExist, e:
146
        third_party_key = get_pending_key(request)
147
        user_info = {'affiliation': affiliation, 'realname': realname}
148
        return handle_third_party_signup(request, userid, 'linkedin',
149
                                         third_party_key,
150
                                         provider_info,
151
                                         user_info,
152
                                         template,
153
                                         extra_context)
154