Statistics
| Branch: | Tag: | Revision:

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

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

    
39
from django.contrib import messages
40
from django.views.decorators.http import require_http_methods
41
from django.http import HttpResponseRedirect, urlencode
42
from django.core.urlresolvers import reverse
43
from django.conf import settings as django_settings
44

    
45
from urlparse import urlunsplit, urlsplit, parse_qsl
46

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

    
54
logger = logging.getLogger(__name__)
55

    
56

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

    
60
request_token_url = django_setting(
61
    'request_token_url',
62
    'https://api.twitter.com/oauth/request_token')
63
access_token_url = django_setting(
64
    'access_token_url',
65
    'https://api.twitter.com/oauth/access_token')
66
authenticate_url = django_setting(
67
    'authenticate_url',
68
    'https://api.twitter.com/oauth/authenticate')
69

    
70

    
71
@requires_auth_provider('twitter')
72
@require_http_methods(["GET", "POST"])
73
@cookie_fix
74
def login(request):
75
    init_third_party_session(request)
76
    force_login = request.GET.get('force_login',
77
                                  settings.TWITTER_AUTH_FORCE_LOGIN)
78
    consumer = oauth.Consumer(settings.TWITTER_TOKEN,
79
                              settings.TWITTER_SECRET)
80
    client = oauth.Client(consumer)
81
    resp, content = client.request(request_token_url, "GET")
82
    if resp['status'] != '200':
83
        messages.error(request, 'Invalid Twitter response')
84
        return HttpResponseRedirect(reverse('edit_profile'))
85

    
86
    request.session['request_token'] = dict(cgi.parse_qsl(content))
87
    params = {
88
        'oauth_token': request.session['request_token']['oauth_token'],
89
    }
90
    if force_login:
91
        params['force_login'] = 1
92

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

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

    
99
    url = "%s?%s" % (authenticate_url, urllib.urlencode(params))
100
    return HttpResponseRedirect(url)
101

    
102

    
103
@requires_auth_provider('twitter', login=True)
104
@require_http_methods(["GET", "POST"])
105
@cookie_fix
106
def authenticated(
107
    request,
108
    template='im/third_party_check_local.html',
109
    extra_context=None):
110

    
111
    if extra_context is None:
112
        extra_context = {}
113

    
114
    consumer = oauth.Consumer(settings.TWITTER_TOKEN,
115
                              settings.TWITTER_SECRET)
116
    client = oauth.Client(consumer)
117

    
118
    if request.GET.get('denied'):
119
        return HttpResponseRedirect(reverse('edit_profile'))
120

    
121
    if not 'request_token' in request.session:
122
        messages.error(request, 'Twitter handshake failed')
123
        return HttpResponseRedirect(reverse('edit_profile'))
124

    
125
    token = oauth.Token(request.session['request_token']['oauth_token'],
126
        request.session['request_token']['oauth_token_secret'])
127
    client = oauth.Client(consumer, token)
128

    
129
    # Step 2. Request the authorized access token from Twitter.
130
    parts = list(urlsplit(access_token_url))
131
    params = dict(parse_qsl(parts[3], keep_blank_values=True))
132
    oauth_verifier = request.GET.get('oauth_verifier')
133
    params['oauth_verifier'] = oauth_verifier
134
    parts[3] = urlencode(params)
135
    parameterized_url = urlunsplit(parts)
136

    
137
    resp, content = client.request(parameterized_url, "GET")
138

    
139
    if resp['status'] != '200':
140
        try:
141
            del request.session['request_token']
142
        except:
143
            pass
144
        messages.error(request, 'Invalid Twitter response')
145
        return HttpResponseRedirect(reverse('edit_profile'))
146

    
147
    access_token = dict(cgi.parse_qsl(content))
148
    userid = access_token['user_id']
149
    username = access_token.get('screen_name', userid)
150
    provider_info = {'screen_name': username}
151
    affiliation = 'Twitter.com'
152

    
153

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