Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7 kB)

1 c101b32b Kostas Papadimitriou
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 c101b32b Kostas Papadimitriou
#
3 c101b32b Kostas Papadimitriou
# Redistribution and use in source and binary forms, with or
4 c101b32b Kostas Papadimitriou
# without modification, are permitted provided that the following
5 c101b32b Kostas Papadimitriou
# conditions are met:
6 c101b32b Kostas Papadimitriou
#
7 c101b32b Kostas Papadimitriou
#   1. Redistributions of source code must retain the above
8 c101b32b Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
9 c101b32b Kostas Papadimitriou
#      disclaimer.
10 c101b32b Kostas Papadimitriou
#
11 c101b32b Kostas Papadimitriou
#   2. Redistributions in binary form must reproduce the above
12 c101b32b Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
13 c101b32b Kostas Papadimitriou
#      disclaimer in the documentation and/or other materials
14 c101b32b Kostas Papadimitriou
#      provided with the distribution.
15 c101b32b Kostas Papadimitriou
#
16 c101b32b Kostas Papadimitriou
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 c101b32b Kostas Papadimitriou
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 c101b32b Kostas Papadimitriou
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 c101b32b Kostas Papadimitriou
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 c101b32b Kostas Papadimitriou
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 c101b32b Kostas Papadimitriou
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 c101b32b Kostas Papadimitriou
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 c101b32b Kostas Papadimitriou
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 c101b32b Kostas Papadimitriou
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 c101b32b Kostas Papadimitriou
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 c101b32b Kostas Papadimitriou
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 c101b32b Kostas Papadimitriou
# POSSIBILITY OF SUCH DAMAGE.
28 c101b32b Kostas Papadimitriou
#
29 c101b32b Kostas Papadimitriou
# The views and conclusions contained in the software and
30 c101b32b Kostas Papadimitriou
# documentation are those of the authors and should not be
31 c101b32b Kostas Papadimitriou
# interpreted as representing official policies, either expressed
32 c101b32b Kostas Papadimitriou
# or implied, of GRNET S.A.
33 c101b32b Kostas Papadimitriou
34 c630fee6 Kostas Papadimitriou
import json
35 c630fee6 Kostas Papadimitriou
36 c101b32b Kostas Papadimitriou
from django.http import HttpResponseBadRequest
37 c101b32b Kostas Papadimitriou
from django.utils.translation import ugettext as _
38 c101b32b Kostas Papadimitriou
from django.contrib import messages
39 c101b32b Kostas Papadimitriou
from django.template import RequestContext
40 c101b32b Kostas Papadimitriou
from django.views.decorators.http import require_http_methods
41 c101b32b Kostas Papadimitriou
from django.http import HttpResponseRedirect
42 c101b32b Kostas Papadimitriou
from django.core.urlresolvers import reverse
43 c101b32b Kostas Papadimitriou
from django.core.exceptions import ImproperlyConfigured
44 c101b32b Kostas Papadimitriou
from django.shortcuts import get_object_or_404
45 c101b32b Kostas Papadimitriou
46 c101b32b Kostas Papadimitriou
from urlparse import urlunsplit, urlsplit
47 c101b32b Kostas Papadimitriou
48 c101b32b Kostas Papadimitriou
from astakos.im.util import prepare_response, get_context
49 c101b32b Kostas Papadimitriou
from astakos.im.views import requires_anonymous, render_response, \
50 c101b32b Kostas Papadimitriou
        requires_auth_provider
51 c101b32b Kostas Papadimitriou
from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION, BASEURL
52 c101b32b Kostas Papadimitriou
from astakos.im.models import AstakosUser, PendingThirdPartyUser
53 c101b32b Kostas Papadimitriou
from astakos.im.forms import LoginForm
54 c101b32b Kostas Papadimitriou
from astakos.im.activation_backends import get_backend, SimpleBackend
55 c101b32b Kostas Papadimitriou
from astakos.im import settings
56 c630fee6 Kostas Papadimitriou
from astakos.im import auth_providers
57 c101b32b Kostas Papadimitriou
58 c101b32b Kostas Papadimitriou
import astakos.im.messages as astakos_messages
59 c101b32b Kostas Papadimitriou
60 c101b32b Kostas Papadimitriou
import logging
61 c101b32b Kostas Papadimitriou
62 c101b32b Kostas Papadimitriou
logger = logging.getLogger(__name__)
63 c101b32b Kostas Papadimitriou
64 c101b32b Kostas Papadimitriou
import oauth2 as oauth
65 c101b32b Kostas Papadimitriou
import cgi
66 c101b32b Kostas Papadimitriou
67 c101b32b Kostas Papadimitriou
consumer = oauth.Consumer(settings.TWITTER_TOKEN, settings.TWITTER_SECRET)
68 c101b32b Kostas Papadimitriou
client = oauth.Client(consumer)
69 c101b32b Kostas Papadimitriou
70 c101b32b Kostas Papadimitriou
request_token_url = 'http://twitter.com/oauth/request_token'
71 c101b32b Kostas Papadimitriou
access_token_url = 'http://twitter.com/oauth/access_token'
72 c101b32b Kostas Papadimitriou
authenticate_url = 'http://twitter.com/oauth/authenticate'
73 c101b32b Kostas Papadimitriou
74 c101b32b Kostas Papadimitriou
75 c101b32b Kostas Papadimitriou
@requires_auth_provider('twitter', login=True)
76 c101b32b Kostas Papadimitriou
@require_http_methods(["GET", "POST"])
77 c101b32b Kostas Papadimitriou
def login(request):
78 c101b32b Kostas Papadimitriou
    resp, content = client.request(request_token_url, "GET")
79 c101b32b Kostas Papadimitriou
    if resp['status'] != '200':
80 c101b32b Kostas Papadimitriou
        messages.error(request, 'Invalid Twitter response')
81 c101b32b Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
82 c101b32b Kostas Papadimitriou
83 c101b32b Kostas Papadimitriou
    request.session['request_token'] = dict(cgi.parse_qsl(content))
84 c101b32b Kostas Papadimitriou
    url = "%s?oauth_token=%s" % (authenticate_url,
85 c101b32b Kostas Papadimitriou
        request.session['request_token']['oauth_token'])
86 c101b32b Kostas Papadimitriou
87 c101b32b Kostas Papadimitriou
    return HttpResponseRedirect(url)
88 c101b32b Kostas Papadimitriou
89 c101b32b Kostas Papadimitriou
90 c101b32b Kostas Papadimitriou
@requires_auth_provider('twitter', login=True)
91 c101b32b Kostas Papadimitriou
@require_http_methods(["GET", "POST"])
92 c101b32b Kostas Papadimitriou
def authenticated(
93 c101b32b Kostas Papadimitriou
    request,
94 c101b32b Kostas Papadimitriou
    template='im/third_party_check_local.html',
95 c101b32b Kostas Papadimitriou
    extra_context={}
96 c101b32b Kostas Papadimitriou
):
97 c101b32b Kostas Papadimitriou
98 c101b32b Kostas Papadimitriou
    if not 'request_token' in request.session:
99 c101b32b Kostas Papadimitriou
        messages.error(request, 'Twitter handshake failed')
100 c101b32b Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
101 c101b32b Kostas Papadimitriou
102 c101b32b Kostas Papadimitriou
    token = oauth.Token(request.session['request_token']['oauth_token'],
103 c101b32b Kostas Papadimitriou
        request.session['request_token']['oauth_token_secret'])
104 c101b32b Kostas Papadimitriou
    client = oauth.Client(consumer, token)
105 c101b32b Kostas Papadimitriou
106 c101b32b Kostas Papadimitriou
    # Step 2. Request the authorized access token from Twitter.
107 c101b32b Kostas Papadimitriou
    resp, content = client.request(access_token_url, "GET")
108 c101b32b Kostas Papadimitriou
    if resp['status'] != '200':
109 c101b32b Kostas Papadimitriou
        try:
110 c101b32b Kostas Papadimitriou
          del request.session['request_token']
111 c101b32b Kostas Papadimitriou
        except:
112 c101b32b Kostas Papadimitriou
          pass
113 c101b32b Kostas Papadimitriou
        messages.error(request, 'Invalid Twitter response')
114 c101b32b Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
115 c101b32b Kostas Papadimitriou
116 c101b32b Kostas Papadimitriou
    access_token = dict(cgi.parse_qsl(content))
117 c101b32b Kostas Papadimitriou
    userid = access_token['user_id']
118 3a72a5d4 Kostas Papadimitriou
    username = access_token.get('screen_name', userid)
119 c630fee6 Kostas Papadimitriou
    provider_info = {'screen_name': username}
120 c630fee6 Kostas Papadimitriou
    affiliation = 'Twitter.com'
121 c101b32b Kostas Papadimitriou
122 c101b32b Kostas Papadimitriou
    # an existing user accessed the view
123 c101b32b Kostas Papadimitriou
    if request.user.is_authenticated():
124 c101b32b Kostas Papadimitriou
        if request.user.has_auth_provider('twitter', identifier=userid):
125 c101b32b Kostas Papadimitriou
            return HttpResponseRedirect(reverse('edit_profile'))
126 c101b32b Kostas Papadimitriou
127 c101b32b Kostas Papadimitriou
        # automatically add eppn provider to user
128 c101b32b Kostas Papadimitriou
        user = request.user
129 c101b32b Kostas Papadimitriou
        if not request.user.can_add_auth_provider('twitter',
130 c101b32b Kostas Papadimitriou
                                                  identifier=userid):
131 c101b32b Kostas Papadimitriou
            messages.error(request, 'Account already exists.')
132 c101b32b Kostas Papadimitriou
            return HttpResponseRedirect(reverse('edit_profile'))
133 c101b32b Kostas Papadimitriou
134 3a72a5d4 Kostas Papadimitriou
        user.add_auth_provider('twitter', identifier=userid,
135 c630fee6 Kostas Papadimitriou
                               affiliation=affiliation,
136 c630fee6 Kostas Papadimitriou
                               provider_info=provider_info)
137 c630fee6 Kostas Papadimitriou
        messages.success(request, 'Account assigned.')
138 c101b32b Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
139 c101b32b Kostas Papadimitriou
140 c101b32b Kostas Papadimitriou
    try:
141 c101b32b Kostas Papadimitriou
        # astakos user exists ?
142 c101b32b Kostas Papadimitriou
        user = AstakosUser.objects.get_auth_provider_user(
143 c101b32b Kostas Papadimitriou
            'twitter',
144 c101b32b Kostas Papadimitriou
            identifier=userid
145 c101b32b Kostas Papadimitriou
        )
146 c101b32b Kostas Papadimitriou
        if user.is_active:
147 c101b32b Kostas Papadimitriou
            # authenticate user
148 c101b32b Kostas Papadimitriou
            return prepare_response(request,
149 c101b32b Kostas Papadimitriou
                                    user,
150 c101b32b Kostas Papadimitriou
                                    request.GET.get('next'),
151 c101b32b Kostas Papadimitriou
                                    'renew' in request.GET)
152 c101b32b Kostas Papadimitriou
        else:
153 c4b1a172 Kostas Papadimitriou
            message = user.get_inactive_message()
154 c101b32b Kostas Papadimitriou
            messages.error(request, message)
155 c101b32b Kostas Papadimitriou
            return HttpResponseRedirect(reverse('login'))
156 c101b32b Kostas Papadimitriou
157 c101b32b Kostas Papadimitriou
    except AstakosUser.DoesNotExist, e:
158 c630fee6 Kostas Papadimitriou
        provider = auth_providers.get_provider('twitter')
159 c630fee6 Kostas Papadimitriou
        if not provider.is_available_for_create():
160 c4b1a172 Kostas Papadimitriou
            messages.error(request,
161 c4b1a172 Kostas Papadimitriou
                           _(astakos_messages.AUTH_PROVIDER_NOT_ACTIVE) % provider.get_title_display)
162 c630fee6 Kostas Papadimitriou
            return HttpResponseRedirect(reverse('login'))
163 c630fee6 Kostas Papadimitriou
164 c101b32b Kostas Papadimitriou
        # eppn not stored in astakos models, create pending profile
165 c101b32b Kostas Papadimitriou
        user, created = PendingThirdPartyUser.objects.get_or_create(
166 c101b32b Kostas Papadimitriou
            third_party_identifier=userid,
167 c101b32b Kostas Papadimitriou
            provider='twitter',
168 c101b32b Kostas Papadimitriou
        )
169 c101b32b Kostas Papadimitriou
        # update pending user
170 c630fee6 Kostas Papadimitriou
        user.affiliation = affiliation
171 3b258643 Kostas Papadimitriou
        user.info = json.dumps(provider_info)
172 c101b32b Kostas Papadimitriou
        user.generate_token()
173 c101b32b Kostas Papadimitriou
        user.save()
174 c101b32b Kostas Papadimitriou
175 c101b32b Kostas Papadimitriou
        extra_context['provider'] = 'twitter'
176 ab7e3a9e Kostas Papadimitriou
        extra_context['provider_title'] = 'Twitter'
177 c101b32b Kostas Papadimitriou
        extra_context['token'] = user.token
178 c630fee6 Kostas Papadimitriou
        extra_context['signup_url'] = reverse('signup') + \
179 c630fee6 Kostas Papadimitriou
                                    "?third_party_token=%s" % user.token
180 c101b32b Kostas Papadimitriou
181 c101b32b Kostas Papadimitriou
        return render_response(
182 c101b32b Kostas Papadimitriou
            template,
183 c101b32b Kostas Papadimitriou
            context_instance=get_context(request, extra_context)
184 c101b32b Kostas Papadimitriou
        )