Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views / target / twitter.py @ 02c1f22a

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 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
        logger.error("Invalid twitter response %s", resp)
85
        return HttpResponseRedirect(reverse('edit_profile'))
86

    
87
    oa_resp = dict(cgi.parse_qsl(content))
88
    if 'status' in oa_resp and oa_resp['status'] != '200':
89
        messages.error(request, 'Invalid Twitter response')
90
        logger.error("Invalid twitter response %s", resp)
91
        return HttpResponseRedirect(reverse('edit_profile'))
92

    
93
    request.session['request_token'] = dict(cgi.parse_qsl(content))
94
    params = {
95
        'oauth_token': request.session['request_token']['oauth_token'],
96
    }
97
    if force_login:
98
        params['force_login'] = 1
99

    
100
    if request.GET.get('key', None):
101
        request.session['pending_key'] = request.GET.get('key')
102

    
103
    if request.GET.get('next', None):
104
        request.session['next_url'] = request.GET.get('next')
105

    
106
    url = "%s?%s" % (authenticate_url, urllib.urlencode(params))
107
    return HttpResponseRedirect(url)
108

    
109

    
110
@requires_auth_provider('twitter', login=True)
111
@require_http_methods(["GET", "POST"])
112
@cookie_fix
113
def authenticated(
114
    request,
115
    template='im/third_party_check_local.html',
116
    extra_context=None):
117

    
118
    if extra_context is None:
119
        extra_context = {}
120

    
121
    consumer = oauth.Consumer(settings.TWITTER_TOKEN,
122
                              settings.TWITTER_SECRET)
123
    client = oauth.Client(consumer)
124

    
125
    if request.GET.get('denied'):
126
        return HttpResponseRedirect(reverse('edit_profile'))
127

    
128
    if not 'request_token' in request.session:
129
        messages.error(request, 'Twitter handshake failed')
130
        return HttpResponseRedirect(reverse('edit_profile'))
131

    
132
    token = oauth.Token(request.session['request_token']['oauth_token'],
133
        request.session['request_token']['oauth_token_secret'])
134
    client = oauth.Client(consumer, token)
135

    
136
    # Step 2. Request the authorized access token from Twitter.
137
    parts = list(urlsplit(access_token_url))
138
    params = dict(parse_qsl(parts[3], keep_blank_values=True))
139
    oauth_verifier = request.GET.get('oauth_verifier')
140
    params['oauth_verifier'] = oauth_verifier
141
    parts[3] = urlencode(params)
142
    parameterized_url = urlunsplit(parts)
143

    
144
    resp, content = client.request(parameterized_url, "GET")
145

    
146
    if resp['status'] != '200':
147
        try:
148
            del request.session['request_token']
149
        except:
150
            pass
151
        messages.error(request, 'Invalid Twitter response')
152
        logger.error("Invalid twitter response %s", resp)
153
        return HttpResponseRedirect(reverse('edit_profile'))
154

    
155
    access_token = dict(cgi.parse_qsl(content))
156
    userid = access_token['user_id']
157
    username = access_token.get('screen_name', userid)
158
    provider_info = {'screen_name': username}
159
    affiliation = 'Twitter.com'
160

    
161
    try:
162
        return handle_third_party_login(request, 'twitter', userid,
163
                                        provider_info, affiliation)
164
    except AstakosUser.DoesNotExist, e:
165
        third_party_key = get_pending_key(request)
166
        user_info = {'affiliation': affiliation}
167
        return handle_third_party_signup(request, userid, 'twitter',
168
                                         third_party_key,
169
                                         provider_info,
170
                                         user_info,
171
                                         template,
172
                                         extra_context)
173