Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views / target / twitter.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 logging
35

    
36
from django.contrib import messages
37
from django.views.decorators.http import require_http_methods
38
from django.http import HttpResponseRedirect, urlencode
39
from django.core.urlresolvers import reverse
40

    
41
from urlparse import urlunsplit, urlsplit, parse_qsl
42

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

    
50

    
51
logger = logging.getLogger(__name__)
52

    
53
import oauth2 as oauth
54
import cgi
55
import urllib
56

    
57
request_token_url = 'https://api.twitter.com/oauth/request_token'
58
access_token_url = 'https://api.twitter.com/oauth/access_token'
59
authenticate_url = 'https://api.twitter.com/oauth/authenticate'
60

    
61
@requires_auth_provider('twitter')
62
@require_http_methods(["GET", "POST"])
63
@cookie_fix
64
def login(request):
65
    init_third_party_session(request)
66
    force_login = request.GET.get('force_login',
67
                                  settings.TWITTER_AUTH_FORCE_LOGIN)
68
    consumer = oauth.Consumer(settings.TWITTER_TOKEN,
69
                              settings.TWITTER_SECRET)
70
    client = oauth.Client(consumer)
71
    resp, content = client.request(request_token_url, "GET")
72
    if resp['status'] != '200':
73
        messages.error(request, 'Invalid Twitter response')
74
        return HttpResponseRedirect(reverse('edit_profile'))
75

    
76
    request.session['request_token'] = dict(cgi.parse_qsl(content))
77
    params = {
78
        'oauth_token': request.session['request_token']['oauth_token'],
79
    }
80
    if force_login:
81
        params['force_login'] = 1
82

    
83
    if request.GET.get('key', None):
84
        request.session['pending_key'] = request.GET.get('key')
85

    
86
    if request.GET.get('next', None):
87
        request.session['next_url'] = request.GET.get('next')
88

    
89
    url = "%s?%s" % (authenticate_url, urllib.urlencode(params))
90
    return HttpResponseRedirect(url)
91

    
92

    
93
@requires_auth_provider('twitter', login=True)
94
@require_http_methods(["GET", "POST"])
95
@cookie_fix
96
def authenticated(
97
    request,
98
    template='im/third_party_check_local.html',
99
    extra_context=None):
100

    
101
    if extra_context is None:
102
        extra_context = {}
103

    
104
    consumer = oauth.Consumer(settings.TWITTER_TOKEN,
105
                              settings.TWITTER_SECRET)
106
    client = oauth.Client(consumer)
107

    
108
    if request.GET.get('denied'):
109
        return HttpResponseRedirect(reverse('edit_profile'))
110

    
111
    if not 'request_token' in request.session:
112
        messages.error(request, 'Twitter handshake failed')
113
        return HttpResponseRedirect(reverse('edit_profile'))
114

    
115
    token = oauth.Token(request.session['request_token']['oauth_token'],
116
        request.session['request_token']['oauth_token_secret'])
117
    client = oauth.Client(consumer, token)
118

    
119
    # Step 2. Request the authorized access token from Twitter.
120
    parts = list(urlsplit(access_token_url))
121
    params = dict(parse_qsl(parts[3], keep_blank_values=True))
122
    oauth_verifier = request.GET.get('oauth_verifier')
123
    params['oauth_verifier'] = oauth_verifier
124
    parts[3] = urlencode(params)
125
    parameterized_url = urlunsplit(parts)
126

    
127
    resp, content = client.request(parameterized_url, "GET")
128

    
129
    if resp['status'] != '200':
130
        try:
131
            del request.session['request_token']
132
        except:
133
            pass
134
        messages.error(request, 'Invalid Twitter response')
135
        return HttpResponseRedirect(reverse('edit_profile'))
136

    
137
    access_token = dict(cgi.parse_qsl(content))
138
    userid = access_token['user_id']
139
    username = access_token.get('screen_name', userid)
140
    provider_info = {'screen_name': username}
141
    affiliation = 'Twitter.com'
142

    
143

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