Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (6.3 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
import logging
36
import oauth2 as oauth
37
import cgi
38

    
39
from django.contrib import messages
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.conf import settings as django_settings
44

    
45
from astakos.im.models import AstakosUser
46
from astakos.im import settings
47
from astakos.im.views.target import get_pending_key, \
48
    handle_third_party_signup, handle_third_party_login, \
49
    init_third_party_session
50
from astakos.im.views.decorators import cookie_fix, \
51
    requires_auth_provider
52

    
53
logger = logging.getLogger(__name__)
54

    
55

    
56
def django_setting(key, default):
57
    return getattr(django_settings, 'GOOGLE_%s' % key.upper, default)
58

    
59
token_scope = 'r_basicprofile+r_emailaddress'
60
request_token_url = django_setting(
61
    'request_token_url',
62
    'https://api.linkedin.com/uas/oauth/requestToken?scope=' + token_scope)
63
access_token_url = django_setting(
64
    'access_token_url',
65
    'https://api.linkedin.com/uas/oauth/accessToken')
66
authenticate_url = django_setting(
67
    'authenticate_url',
68
    'https://www.linkedin.com/uas/oauth/authorize')
69

    
70

    
71
@requires_auth_provider('linkedin')
72
@require_http_methods(["GET", "POST"])
73
@cookie_fix
74
def login(request):
75
    init_third_party_session(request)
76
    consumer = oauth.Consumer(settings.LINKEDIN_TOKEN,
77
                              settings.LINKEDIN_SECRET)
78
    client = oauth.Client(consumer)
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') + \
88
        "?oauth_token=%s" % request_token.get('oauth_token')
89

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

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

    
96
    return HttpResponseRedirect(url)
97

    
98

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

    
108
    if extra_context is None:
109
        extra_context = {}
110

    
111
    consumer = oauth.Consumer(settings.LINKEDIN_TOKEN,
112
                              settings.LINKEDIN_SECRET)
113
    client = oauth.Client(consumer)
114

    
115
    if request.GET.get('denied'):
116
        return HttpResponseRedirect(reverse('edit_profile'))
117

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

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

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

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

    
155

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