Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / target / __init__.py @ 0e79735c

History | View | Annotate | Download (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 json
35

    
36
from django.contrib import messages
37
from django.utils.translation import ugettext as _
38
from django.http import HttpResponseRedirect
39
from django.core.urlresolvers import reverse
40

    
41
from astakos.im.models import PendingThirdPartyUser, AstakosUser
42
from astakos.im.util import get_query, login_url
43
from astakos.im import messages as astakos_messages
44
from astakos.im import auth_providers
45
from astakos.im.util import prepare_response, get_context
46
from astakos.im.views import requires_anonymous, render_response
47

    
48

    
49
def init_third_party_session(request):
50
    params = dict(request.GET.items())
51
    request.session['third_party_request_params'] = params
52

    
53

    
54
def get_third_party_session_params(request):
55
    if 'third_party_request_params' in request.session:
56
        params = request.session['third_party_request_params']
57
        del request.session['third_party_request_params']
58
        return params
59
    return {}
60

    
61

    
62
def add_pending_auth_provider(request, third_party_token):
63
    if third_party_token:
64
        # use requests to assign the account he just authenticated with with
65
        # a third party provider account
66
        try:
67
            request.user.add_pending_auth_provider(third_party_token)
68
            messages.success(request, _(astakos_messages.AUTH_PROVIDER_ADDED))
69
        except PendingThirdPartyUser.DoesNotExist:
70
            messages.error(request, _(astakos_messages.AUTH_PROVIDER_ADD_FAILED))
71

    
72

    
73
def get_pending_key(request):
74
    third_party_token = get_query(request).get('key', request.session.get('pending_key', False))
75
    if 'pending_key' in request.session:
76
        del request.session['pending_key']
77
    return third_party_token
78

    
79

    
80
def handle_third_party_signup(request, userid, provider_module, third_party_key,
81
                              provider_info={},
82
                              pending_user_params={},
83
                              template="im/third_party_check_local.html",
84
                              extra_context={}):
85

    
86
    # user wants to add another third party login method
87
    if third_party_key:
88
        messages.error(request, _(astakos_messages.AUTH_PROVIDER_INVALID_LOGIN))
89
        return HttpResponseRedirect(reverse('login') + "?key=%s" % third_party_key)
90

    
91
    provider = auth_providers.get_provider(provider_module)
92
    if not provider.is_available_for_create():
93
        messages.error(request,
94
                       _(astakos_messages.AUTH_PROVIDER_INVALID_LOGIN))
95
        return HttpResponseRedirect(reverse('login'))
96

    
97
    # identifier not stored in astakos models, create pending profile
98
    user, created = PendingThirdPartyUser.objects.get_or_create(
99
        third_party_identifier=userid,
100
        provider=provider_module,
101
    )
102
    # update pending user
103
    for param, value in pending_user_params.iteritems():
104
        setattr(user, param, value)
105

    
106
    user.info = json.dumps(provider_info)
107
    user.generate_token()
108
    user.save()
109

    
110
    extra_context['provider'] = provider_module
111
    extra_context['provider_title'] = provider.get_title_display
112
    extra_context['token'] = user.token
113
    extra_context['signup_url'] = reverse('signup') + \
114
                                "?third_party_token=%s" % user.token
115
    extra_context['add_url'] = reverse('index') + \
116
                                "?key=%s#other-login-methods" % user.token
117
    extra_context['can_create'] = provider.is_available_for_create()
118
    extra_context['can_add'] = provider.is_available_for_add()
119

    
120
    return HttpResponseRedirect(extra_context['signup_url'])
121
    #return render_response(
122
        #template,
123
        #context_instance=get_context(request, extra_context)
124
    #)
125

    
126

    
127

    
128
def handle_third_party_login(request, provider_module, identifier,
129
                             provider_info=None, affiliation=None,
130
                             third_party_key=None):
131

    
132
    if not provider_info:
133
        provider_info = {}
134

    
135
    if not affiliation:
136
        affiliation = provider_module.title()
137

    
138
    next_redirect = request.GET.get('next', request.session.get('next_url', None))
139
    if 'next_url' in request.session:
140
        del request.session['next_url']
141

    
142
    third_party_request_params = get_third_party_session_params(request)
143
    from_login = third_party_request_params.get('from_login', False)
144

    
145
    # an existing user accessed the view
146
    if request.user.is_authenticated():
147

    
148
        if request.user.has_auth_provider(provider_module, identifier=identifier):
149
            return HttpResponseRedirect(reverse('edit_profile'))
150

    
151
        # automatically add identifier provider to user
152
        user = request.user
153
        if not request.user.can_add_auth_provider(provider_module,
154
                                                  identifier=identifier):
155
            # TODO: handle existing uuid message separately
156
            messages.error(request, _(astakos_messages.AUTH_PROVIDER_ADD_FAILED) +
157
                          u' ' + _(astakos_messages.AUTH_PROVIDER_ADD_EXISTS))
158
            return HttpResponseRedirect(reverse('edit_profile'))
159

    
160
        user.add_auth_provider(provider_module, identifier=identifier,
161
                               affiliation=affiliation,
162
                               provider_info=provider_info)
163
        messages.success(request, astakos_messages.AUTH_PROVIDER_ADDED)
164
        return HttpResponseRedirect(reverse('edit_profile'))
165

    
166
    # astakos user exists ?
167
    try:
168
        user = AstakosUser.objects.get_auth_provider_user(
169
            provider_module,
170
            identifier=identifier,
171
            user__email_verified=True,
172
        )
173
    except AstakosUser.DoesNotExist:
174
        # TODO: add a message ? redirec to login ?
175
        if astakos_messages.AUTH_PROVIDER_SIGNUP_FROM_LOGIN:
176
            messages.warning(request,
177
                             astakos_messages.AUTH_PROVIDER_SIGNUP_FROM_LOGIN)
178
        raise
179

    
180
    if not third_party_key:
181
        third_party_key = get_pending_key(request)
182

    
183
    if user.is_active:
184
        # authenticate user
185
        response = prepare_response(request,
186
                                user,
187
                                next_redirect,
188
                                'renew' in request.GET)
189
        provider = auth_providers.get_provider(provider_module)
190
        messages.success(request, _(astakos_messages.LOGIN_SUCCESS) %
191
                         _(provider.get_login_message_display))
192
        add_pending_auth_provider(request, third_party_key)
193
        response.set_cookie('astakos_last_login_method', provider_module)
194
        return response
195
    else:
196
        message = user.get_inactive_message()
197
        messages.error(request, message)
198
        return HttpResponseRedirect(login_url(request))
199