Statistics
| Branch: | Tag: | Revision:

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

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
        except PendingThirdPartyUser.DoesNotExist:
69
            messages.error(request, _(astakos_messages.AUTH_PROVIDER_ADD_FAILED))
70

    
71

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

    
78

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

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

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

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

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

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

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

    
125

    
126

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

    
131
    if not provider_info:
132
        provider_info = {}
133

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

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

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

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

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

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

    
159
        user.add_auth_provider(provider_module, identifier=identifier,
160
                               affiliation=affiliation,
161
                               provider_info=provider_info)
162
        provider = auth_providers.get_provider(provider_module)
163
        message = _(astakos_messages.AUTH_PROVIDER_ADDED) % provider.get_method_prompt_display
164
        messages.success(request, message)
165
        return HttpResponseRedirect(reverse('edit_profile'))
166

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

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

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