Revision d2633501 snf-astakos-app/astakos/im/target/shibboleth.py

b/snf-astakos-app/astakos/im/target/shibboleth.py
40 40
from django.core.exceptions import ValidationError
41 41
from django.http import HttpResponseRedirect
42 42
from django.core.urlresolvers import reverse
43
from urlparse import urlunsplit, urlsplit
44 43
from django.utils.http import urlencode
44
from django.shortcuts import get_object_or_404
45

  
46
from urlparse import urlunsplit, urlsplit
45 47

  
46 48
from astakos.im.util import prepare_response, get_context, get_invitation
47
from astakos.im.views import requires_anonymous, render_response
49
from astakos.im.views import requires_anonymous, render_response, \
50
        requires_auth_provider
48 51
from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION, BASEURL
49 52

  
50 53
from astakos.im.models import AstakosUser, PendingThirdPartyUser
51 54
from astakos.im.forms import LoginForm
52 55
from astakos.im.activation_backends import get_backend, SimpleBackend
56
from astakos.im import settings
53 57

  
54 58
import logging
55 59

  
......
66 70
    SHIB_SESSION_ID = "HTTP_SHIB_SESSION_ID"
67 71
    SHIB_MAIL = "HTTP_SHIB_MAIL"
68 72

  
73
@requires_auth_provider('local', login=True)
69 74
@require_http_methods(["GET", "POST"])
70
@requires_anonymous
71 75
def login(
72 76
    request,
73
    login_template='im/login.html',
74
    signup_template='im/third_party_check_local.html',
77
    template='im/third_party_check_local.html',
75 78
    extra_context=None
76 79
):
77 80
    extra_context = extra_context or {}
78 81

  
79 82
    tokens = request.META
80
    
83

  
81 84
    try:
82 85
        eppn = tokens.get(Tokens.SHIB_EPPN)
83 86
        if not eppn:
84
            raise KeyError(_('Missing unique token in request'))
87
            raise KeyError(_('Missing provider token'))
85 88
        if Tokens.SHIB_DISPLAYNAME in tokens:
86 89
            realname = tokens[Tokens.SHIB_DISPLAYNAME]
87 90
        elif Tokens.SHIB_CN in tokens:
......
89 92
        elif Tokens.SHIB_NAME in tokens and Tokens.SHIB_SURNAME in tokens:
90 93
            realname = tokens[Tokens.SHIB_NAME] + ' ' + tokens[Tokens.SHIB_SURNAME]
91 94
        else:
92
            raise KeyError(_('Missing user name in request'))
95
            raise KeyError(_('Missing provider user information'))
93 96
    except KeyError, e:
94
        extra_context['login_form'] = LoginForm(request=request)
97
        # invalid shibboleth headers, redirect to login, display message
95 98
        messages.error(request, e)
96
        return render_response(
97
            login_template,
98
            context_instance=get_context(request, extra_context)
99
        )
100
    
99
        return HttpResponseRedirect(reverse('login'))
100

  
101 101
    affiliation = tokens.get(Tokens.SHIB_EP_AFFILIATION, '')
102 102
    email = tokens.get(Tokens.SHIB_MAIL, '')
103
    
103

  
104
    # an existing user accessed the view
105
    if request.user.is_authenticated():
106
        if request.user.has_auth_provider('shibboleth', identifier=eppn):
107
            return HttpResponseRedirect(reverse('edit_profile'))
108

  
109
        # automatically add eppn provider to user
110
        user = request.user
111
        user.add_provider('shibboleth', identifier=eppn)
112
        return HttpResponseRedirect('edit_profile')
113

  
104 114
    try:
105
        user = AstakosUser.objects.get(
106
            provider='shibboleth',
107
            third_party_identifier=eppn
115
        # astakos user exists ?
116
        user = AstakosUser.objects.get_auth_provider_user(
117
            'shibboleth',
118
            identifier=eppn
108 119
        )
109 120
        if user.is_active:
121
            # authenticate user
110 122
            return prepare_response(request,
111 123
                                    user,
112 124
                                    request.GET.get('next'),
113 125
                                    'renew' in request.GET)
114 126
        elif not user.activation_sent:
115 127
            message = _('Your request is pending activation')
128
            if not settings.MODERATION_ENABLED:
129
                url = user.get_resend_activation_url()
130
                msg_extra = _('<a href="%s">Resend activation email?</a>') % url
131
                message = message + u' ' + msg_extra
132

  
116 133
            messages.error(request, message)
134
            return HttpResponseRedirect(reverse('login'))
135

  
117 136
        else:
118
            urls = {}
119
            urls['send_activation'] = reverse(
120
                'send_activation',
121
                kwargs={'user_id':user.id}
122
            )
123
            urls['signup'] = reverse(
124
                'shibboleth_signup',
125
                args= [user.username]
126
            )   
127
            message = _(
128
                'You have not followed the activation link. \
129
                <a href="%(send_activation)s">Resend activation email?</a> or \
130
                <a href="%(signup)s">Provide new email?</a>' % urls
131
            )
137
            message = _(u'Account disabled. Please contact support')
132 138
            messages.error(request, message)
133
        return render_response(login_template,
134
                               login_form = LoginForm(request=request),
135
                               context_instance=RequestContext(request))
139
            return HttpResponseRedirect(reverse('login'))
140

  
136 141
    except AstakosUser.DoesNotExist, e:
137
        # First time
138
        try:
139
            user, created = PendingThirdPartyUser.objects.get_or_create(
140
                third_party_identifier=eppn,
141
                provider='shibboleth',
142
                defaults=dict(
143
                    realname=realname,
144
                    affiliation=affiliation,
145
                    email=email
146
                )
147
            )
148
            user.save()
149
        except BaseException, e:
150
            logger.exception(e)
151
            template = login_template
152
            extra_context['login_form'] = LoginForm(request=request)
153
            messages.error(request, _('Something went wrong.'))
154
        else:
155
            if not ENABLE_LOCAL_ACCOUNT_MIGRATION:
156
                url = reverse(
157
                    'shibboleth_signup',
158
                    args= [user.username]
159
                )
160
                return HttpResponseRedirect(url)
161
            else:
162
                template = signup_template
163
                extra_context['username'] = user.username
164
        
165
        extra_context['provider']='shibboleth'
142
        # eppn not stored in astakos models, create pending profile
143
        user, created = PendingThirdPartyUser.objects.get_or_create(
144
            third_party_identifier=eppn,
145
            provider='shibboleth',
146
        )
147
        # update pending user
148
        user.realname = realname
149
        user.affiliation = affiliation
150
        user.email = email
151
        user.generate_token()
152
        user.save()
153

  
154
        extra_context['provider'] = 'shibboleth'
155
        extra_context['token'] = user.token
156

  
166 157
        return render_response(
167 158
            template,
168 159
            context_instance=get_context(request, extra_context)
169 160
        )
170 161

  
162

  
163
@requires_auth_provider('local', login=True, create=True)
171 164
@require_http_methods(["GET"])
172 165
@requires_anonymous
173 166
def signup(
174 167
    request,
175
    username,
168
    token,
176 169
    backend=None,
177 170
    on_creation_template='im/third_party_registration.html',
178
    extra_context=None
179
):
171
    extra_context=None):
172

  
180 173
    extra_context = extra_context or {}
181
    if not username:
174
    if not token:
182 175
        return HttpResponseBadRequest(_('Missing key parameter.'))
183
    try:
184
        pending = PendingThirdPartyUser.objects.get(username=username)
185
    except PendingThirdPartyUser.DoesNotExist:
186
        try:
187
            user = AstakosUser.objects.get(username=username)
188
        except AstakosUser.DoesNotExist:
189
            return HttpResponseBadRequest(_('Invalid key.'))
190
    else:
191
        d = pending.__dict__
192
        d.pop('_state', None)
193
        d.pop('id', None)
194
        user = AstakosUser(**d)
176

  
177
    pending = get_object_or_404(PendingThirdPartyUser, token=token)
178
    d = pending.__dict__
179
    d.pop('_state', None)
180
    d.pop('id', None)
181
    d.pop('token', None)
182
    d.pop('created', None)
183
    user = AstakosUser(**d)
184

  
195 185
    try:
196 186
        backend = backend or get_backend(request)
197 187
    except ImproperlyConfigured, e:
......
201 191
            provider='shibboleth',
202 192
            instance=user
203 193
        )
204
    extra_context['provider']='shibboleth'
194

  
195
    extra_context['provider'] = 'shibboleth'
196
    extra_context['third_party_token'] = token
205 197
    return render_response(
206 198
            on_creation_template,
207 199
            context_instance=get_context(request, extra_context)
208
    )
200
    )
201

  

Also available in: Unified diff