Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.9 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 c101b32b Kostas Papadimitriou
from django.http import HttpResponseBadRequest
35 c101b32b Kostas Papadimitriou
from django.utils.translation import ugettext as _
36 c101b32b Kostas Papadimitriou
from django.contrib import messages
37 c101b32b Kostas Papadimitriou
from django.template import RequestContext
38 c101b32b Kostas Papadimitriou
from django.views.decorators.http import require_http_methods
39 c101b32b Kostas Papadimitriou
from django.http import HttpResponseRedirect
40 c101b32b Kostas Papadimitriou
from django.core.urlresolvers import reverse
41 c101b32b Kostas Papadimitriou
from django.core.exceptions import ImproperlyConfigured
42 c101b32b Kostas Papadimitriou
from django.shortcuts import get_object_or_404
43 c101b32b Kostas Papadimitriou
44 c101b32b Kostas Papadimitriou
from urlparse import urlunsplit, urlsplit
45 c101b32b Kostas Papadimitriou
46 c101b32b Kostas Papadimitriou
from astakos.im.util import prepare_response, get_context
47 c101b32b Kostas Papadimitriou
from astakos.im.views import requires_anonymous, render_response, \
48 c101b32b Kostas Papadimitriou
        requires_auth_provider
49 c101b32b Kostas Papadimitriou
from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION, BASEURL
50 c101b32b Kostas Papadimitriou
from astakos.im.models import AstakosUser, PendingThirdPartyUser
51 c101b32b Kostas Papadimitriou
from astakos.im.forms import LoginForm
52 c101b32b Kostas Papadimitriou
from astakos.im.activation_backends import get_backend, SimpleBackend
53 c101b32b Kostas Papadimitriou
from astakos.im import settings
54 c101b32b Kostas Papadimitriou
55 c101b32b Kostas Papadimitriou
import astakos.im.messages as astakos_messages
56 c101b32b Kostas Papadimitriou
57 c101b32b Kostas Papadimitriou
import logging
58 c101b32b Kostas Papadimitriou
59 c101b32b Kostas Papadimitriou
logger = logging.getLogger(__name__)
60 c101b32b Kostas Papadimitriou
61 c101b32b Kostas Papadimitriou
import oauth2 as oauth
62 c101b32b Kostas Papadimitriou
import cgi
63 c101b32b Kostas Papadimitriou
64 c101b32b Kostas Papadimitriou
consumer = oauth.Consumer(settings.TWITTER_TOKEN, settings.TWITTER_SECRET)
65 c101b32b Kostas Papadimitriou
client = oauth.Client(consumer)
66 c101b32b Kostas Papadimitriou
67 c101b32b Kostas Papadimitriou
request_token_url = 'http://twitter.com/oauth/request_token'
68 c101b32b Kostas Papadimitriou
access_token_url = 'http://twitter.com/oauth/access_token'
69 c101b32b Kostas Papadimitriou
authenticate_url = 'http://twitter.com/oauth/authenticate'
70 c101b32b Kostas Papadimitriou
71 c101b32b Kostas Papadimitriou
72 c101b32b Kostas Papadimitriou
@requires_auth_provider('twitter', login=True)
73 c101b32b Kostas Papadimitriou
@require_http_methods(["GET", "POST"])
74 c101b32b Kostas Papadimitriou
def login(request):
75 c101b32b Kostas Papadimitriou
    resp, content = client.request(request_token_url, "GET")
76 c101b32b Kostas Papadimitriou
    if resp['status'] != '200':
77 c101b32b Kostas Papadimitriou
        messages.error(request, 'Invalid Twitter response')
78 c101b32b Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
79 c101b32b Kostas Papadimitriou
80 c101b32b Kostas Papadimitriou
    request.session['request_token'] = dict(cgi.parse_qsl(content))
81 c101b32b Kostas Papadimitriou
    url = "%s?oauth_token=%s" % (authenticate_url,
82 c101b32b Kostas Papadimitriou
        request.session['request_token']['oauth_token'])
83 c101b32b Kostas Papadimitriou
84 c101b32b Kostas Papadimitriou
    return HttpResponseRedirect(url)
85 c101b32b Kostas Papadimitriou
86 c101b32b Kostas Papadimitriou
87 c101b32b Kostas Papadimitriou
@requires_auth_provider('twitter', login=True)
88 c101b32b Kostas Papadimitriou
@require_http_methods(["GET", "POST"])
89 c101b32b Kostas Papadimitriou
def authenticated(
90 c101b32b Kostas Papadimitriou
    request,
91 c101b32b Kostas Papadimitriou
    template='im/third_party_check_local.html',
92 c101b32b Kostas Papadimitriou
    extra_context={}
93 c101b32b Kostas Papadimitriou
):
94 c101b32b Kostas Papadimitriou
95 c101b32b Kostas Papadimitriou
    if not 'request_token' in request.session:
96 c101b32b Kostas Papadimitriou
        messages.error(request, 'Twitter handshake failed')
97 c101b32b Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
98 c101b32b Kostas Papadimitriou
99 c101b32b Kostas Papadimitriou
    token = oauth.Token(request.session['request_token']['oauth_token'],
100 c101b32b Kostas Papadimitriou
        request.session['request_token']['oauth_token_secret'])
101 c101b32b Kostas Papadimitriou
    client = oauth.Client(consumer, token)
102 c101b32b Kostas Papadimitriou
103 c101b32b Kostas Papadimitriou
    # Step 2. Request the authorized access token from Twitter.
104 c101b32b Kostas Papadimitriou
    resp, content = client.request(access_token_url, "GET")
105 c101b32b Kostas Papadimitriou
    if resp['status'] != '200':
106 c101b32b Kostas Papadimitriou
        try:
107 c101b32b Kostas Papadimitriou
          del request.session['request_token']
108 c101b32b Kostas Papadimitriou
        except:
109 c101b32b Kostas Papadimitriou
          pass
110 c101b32b Kostas Papadimitriou
        messages.error(request, 'Invalid Twitter response')
111 c101b32b Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
112 c101b32b Kostas Papadimitriou
113 c101b32b Kostas Papadimitriou
    access_token = dict(cgi.parse_qsl(content))
114 c101b32b Kostas Papadimitriou
    userid = access_token['user_id']
115 c101b32b Kostas Papadimitriou
116 c101b32b Kostas Papadimitriou
    # an existing user accessed the view
117 c101b32b Kostas Papadimitriou
    if request.user.is_authenticated():
118 c101b32b Kostas Papadimitriou
        if request.user.has_auth_provider('twitter', identifier=userid):
119 c101b32b Kostas Papadimitriou
            return HttpResponseRedirect(reverse('edit_profile'))
120 c101b32b Kostas Papadimitriou
121 c101b32b Kostas Papadimitriou
        # automatically add eppn provider to user
122 c101b32b Kostas Papadimitriou
        user = request.user
123 c101b32b Kostas Papadimitriou
        if not request.user.can_add_auth_provider('twitter',
124 c101b32b Kostas Papadimitriou
                                                  identifier=userid):
125 c101b32b Kostas Papadimitriou
            messages.error(request, 'Account already exists.')
126 c101b32b Kostas Papadimitriou
            return HttpResponseRedirect(reverse('edit_profile'))
127 c101b32b Kostas Papadimitriou
128 c101b32b Kostas Papadimitriou
        user.add_auth_provider('twitter', identifier=userid)
129 c101b32b Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
130 c101b32b Kostas Papadimitriou
131 c101b32b Kostas Papadimitriou
    try:
132 c101b32b Kostas Papadimitriou
        # astakos user exists ?
133 c101b32b Kostas Papadimitriou
        user = AstakosUser.objects.get_auth_provider_user(
134 c101b32b Kostas Papadimitriou
            'twitter',
135 c101b32b Kostas Papadimitriou
            identifier=userid
136 c101b32b Kostas Papadimitriou
        )
137 c101b32b Kostas Papadimitriou
        if user.is_active:
138 c101b32b Kostas Papadimitriou
            # authenticate user
139 c101b32b Kostas Papadimitriou
            return prepare_response(request,
140 c101b32b Kostas Papadimitriou
                                    user,
141 c101b32b Kostas Papadimitriou
                                    request.GET.get('next'),
142 c101b32b Kostas Papadimitriou
                                    'renew' in request.GET)
143 c101b32b Kostas Papadimitriou
        elif not user.activation_sent:
144 c101b32b Kostas Papadimitriou
            message = _('Your request is pending activation')
145 c101b32b Kostas Papadimitriou
                        #TODO: use astakos_messages
146 c101b32b Kostas Papadimitriou
            if not settings.MODERATION_ENABLED:
147 c101b32b Kostas Papadimitriou
                url = user.get_resend_activation_url()
148 c101b32b Kostas Papadimitriou
                msg_extra = _('<a href="%s">Resend activation email?</a>') % url
149 c101b32b Kostas Papadimitriou
                message = message + u' ' + msg_extra
150 c101b32b Kostas Papadimitriou
151 c101b32b Kostas Papadimitriou
            messages.error(request, message)
152 c101b32b Kostas Papadimitriou
            return HttpResponseRedirect(reverse('login'))
153 c101b32b Kostas Papadimitriou
154 c101b32b Kostas Papadimitriou
        else:
155 c101b32b Kostas Papadimitriou
                        #TODO: use astakos_messages
156 c101b32b Kostas Papadimitriou
            message = _(u'Account disabled. Please contact support')
157 c101b32b Kostas Papadimitriou
            messages.error(request, message)
158 c101b32b Kostas Papadimitriou
            return HttpResponseRedirect(reverse('login'))
159 c101b32b Kostas Papadimitriou
160 c101b32b Kostas Papadimitriou
    except AstakosUser.DoesNotExist, e:
161 c101b32b Kostas Papadimitriou
                #TODO: use astakos_messages
162 c101b32b Kostas Papadimitriou
        # eppn not stored in astakos models, create pending profile
163 c101b32b Kostas Papadimitriou
        user, created = PendingThirdPartyUser.objects.get_or_create(
164 c101b32b Kostas Papadimitriou
            third_party_identifier=userid,
165 c101b32b Kostas Papadimitriou
            provider='twitter',
166 c101b32b Kostas Papadimitriou
        )
167 c101b32b Kostas Papadimitriou
        # update pending user
168 c101b32b Kostas Papadimitriou
        user.affiliation = 'Twitter'
169 c101b32b Kostas Papadimitriou
        user.generate_token()
170 c101b32b Kostas Papadimitriou
        user.save()
171 c101b32b Kostas Papadimitriou
172 c101b32b Kostas Papadimitriou
        extra_context['provider'] = 'twitter'
173 c101b32b Kostas Papadimitriou
        extra_context['token'] = user.token
174 db9083f9 Kostas Papadimitriou
        extra_context['signup_url'] = reverse('twitter_signup', args=(user.token,))
175 c101b32b Kostas Papadimitriou
176 c101b32b Kostas Papadimitriou
        return render_response(
177 c101b32b Kostas Papadimitriou
            template,
178 c101b32b Kostas Papadimitriou
            context_instance=get_context(request, extra_context)
179 c101b32b Kostas Papadimitriou
        )
180 c101b32b Kostas Papadimitriou
181 c101b32b Kostas Papadimitriou
182 c101b32b Kostas Papadimitriou
@requires_auth_provider('twitter', login=True, create=True)
183 c101b32b Kostas Papadimitriou
@require_http_methods(["GET"])
184 c101b32b Kostas Papadimitriou
@requires_anonymous
185 c101b32b Kostas Papadimitriou
def signup(
186 c101b32b Kostas Papadimitriou
    request,
187 c101b32b Kostas Papadimitriou
    token,
188 c101b32b Kostas Papadimitriou
    backend=None,
189 c101b32b Kostas Papadimitriou
    on_creation_template='im/third_party_registration.html',
190 c101b32b Kostas Papadimitriou
    extra_context={}):
191 c101b32b Kostas Papadimitriou
192 c101b32b Kostas Papadimitriou
    extra_context = extra_context or {}
193 c101b32b Kostas Papadimitriou
    if not token:
194 c101b32b Kostas Papadimitriou
                #TODO: use astakos_messages
195 c101b32b Kostas Papadimitriou
        return HttpResponseBadRequest(_('Missing key parameter.'))
196 c101b32b Kostas Papadimitriou
197 c101b32b Kostas Papadimitriou
    pending = get_object_or_404(PendingThirdPartyUser, token=token)
198 c101b32b Kostas Papadimitriou
    d = pending.__dict__
199 c101b32b Kostas Papadimitriou
    d.pop('_state', None)
200 c101b32b Kostas Papadimitriou
    d.pop('id', None)
201 c101b32b Kostas Papadimitriou
    d.pop('token', None)
202 c101b32b Kostas Papadimitriou
    d.pop('created', None)
203 c101b32b Kostas Papadimitriou
    user = AstakosUser(**d)
204 c101b32b Kostas Papadimitriou
205 c101b32b Kostas Papadimitriou
    try:
206 c101b32b Kostas Papadimitriou
        backend = backend or get_backend(request)
207 c101b32b Kostas Papadimitriou
    except ImproperlyConfigured, e:
208 c101b32b Kostas Papadimitriou
        messages.error(request, e)
209 c101b32b Kostas Papadimitriou
    else:
210 c101b32b Kostas Papadimitriou
        extra_context['form'] = backend.get_signup_form(
211 c101b32b Kostas Papadimitriou
            provider='twitter',
212 c101b32b Kostas Papadimitriou
            instance=user
213 c101b32b Kostas Papadimitriou
        )
214 c101b32b Kostas Papadimitriou
215 c101b32b Kostas Papadimitriou
    extra_context['provider'] = 'twitter'
216 c101b32b Kostas Papadimitriou
    extra_context['third_party_token'] = token
217 c101b32b Kostas Papadimitriou
    return render_response(
218 c101b32b Kostas Papadimitriou
            on_creation_template,
219 c101b32b Kostas Papadimitriou
            context_instance=get_context(request, extra_context)
220 c101b32b Kostas Papadimitriou
    )