16 |
16 |
from __future__ import unicode_literals
|
17 |
17 |
|
18 |
18 |
from importlib import import_module
|
|
19 |
from io import StringIO
|
19 |
20 |
import logging
|
20 |
21 |
import requests
|
21 |
22 |
import lasso
|
... | ... | |
26 |
27 |
|
27 |
28 |
import django.http
|
28 |
29 |
from django.views.generic import View
|
29 |
|
from django.http import HttpResponseRedirect, HttpResponse
|
|
30 |
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden
|
30 |
31 |
from django.contrib import auth
|
31 |
32 |
from django.contrib.auth import get_user_model
|
32 |
33 |
from django.conf import settings
|
... | ... | |
142 |
143 |
|
143 |
144 |
|
144 |
145 |
class LoginView(ProfileMixin, LogMixin, View):
|
|
146 |
allow_redirect_to_debug = True
|
|
147 |
|
|
148 |
def dispatch(self, request, *args, **kwargs):
|
|
149 |
if request.session.get('mellon_debug_login') and self.allow_redirect_to_debug:
|
|
150 |
url = reverse('mellon_debug_login')
|
|
151 |
url = "%s?%s" % (url, request.META.get('QUERY_STRING', ''))
|
|
152 |
if request.method == 'POST':
|
|
153 |
url += '&' + request.POST.urlencode()
|
|
154 |
return HttpResponseRedirect(url)
|
|
155 |
return super().dispatch(request, *args, **kwargs)
|
|
156 |
|
145 |
157 |
@property
|
146 |
158 |
def template_base(self):
|
147 |
159 |
return self.kwargs.get('template_base', 'base.html')
|
... | ... | |
277 |
289 |
next_url = self.get_next_url(default=resolve_url(settings.LOGIN_REDIRECT_URL))
|
278 |
290 |
if user is not None:
|
279 |
291 |
if user.is_active:
|
280 |
|
utils.login(request, user)
|
281 |
|
session_index = attributes['session_index']
|
282 |
|
if session_index:
|
283 |
|
if not request.session.session_key:
|
284 |
|
request.session.create()
|
285 |
|
models.SessionIndex.objects.get_or_create(
|
286 |
|
saml_identifier=user.saml_identifier,
|
287 |
|
session_key=request.session.session_key,
|
288 |
|
session_index=session_index,
|
289 |
|
)
|
290 |
|
self.log.info(
|
291 |
|
'user %s (NameID is %r) logged in using SAML', user, attributes['name_id_content']
|
292 |
|
)
|
293 |
|
request.session['mellon_session'] = utils.flatten_datetime(attributes)
|
294 |
|
if 'session_not_on_or_after' in attributes and not settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
|
295 |
|
request.session.set_expiry(
|
296 |
|
utils.get_seconds_expiry(attributes['session_not_on_or_after'])
|
297 |
|
)
|
|
292 |
self.login(user, attributes)
|
298 |
293 |
else:
|
299 |
294 |
self.log.warning(
|
300 |
295 |
'user %s (NameID is %r) is inactive, login refused', user, attributes['name_id_content']
|
... | ... | |
309 |
304 |
|
310 |
305 |
return HttpResponseRedirect(next_url)
|
311 |
306 |
|
|
307 |
def login(self, user, attributes):
|
|
308 |
utils.login(self.request, user)
|
|
309 |
session_index = attributes['session_index']
|
|
310 |
if session_index:
|
|
311 |
if not self.request.session.session_key:
|
|
312 |
self.request.session.create()
|
|
313 |
models.SessionIndex.objects.get_or_create(
|
|
314 |
saml_identifier=user.saml_identifier,
|
|
315 |
session_key=self.request.session.session_key,
|
|
316 |
session_index=session_index,
|
|
317 |
)
|
|
318 |
self.log.info(
|
|
319 |
'user %s (NameID is %r) logged in using SAML', user, attributes['name_id_content']
|
|
320 |
)
|
|
321 |
self.request.session['mellon_session'] = utils.flatten_datetime(attributes)
|
|
322 |
if 'session_not_on_or_after' in attributes and not settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
|
|
323 |
self.request.session.set_expiry(
|
|
324 |
utils.get_seconds_expiry(attributes['session_not_on_or_after'])
|
|
325 |
)
|
|
326 |
|
312 |
327 |
def retry_login(self):
|
313 |
328 |
"""Retry login if it failed for a temporary error.
|
314 |
329 |
|
... | ... | |
719 |
734 |
def metadata(request, **kwargs):
|
720 |
735 |
metadata = utils.create_metadata(request)
|
721 |
736 |
return HttpResponse(metadata, content_type='text/xml')
|
|
737 |
|
|
738 |
|
|
739 |
class DebugLoginView(LoginView):
|
|
740 |
allow_redirect_to_debug = False
|
|
741 |
|
|
742 |
def dispatch(self, request, *args, **kwargs):
|
|
743 |
if not request.user.is_superuser or not settings.DEBUG:
|
|
744 |
return HttpResponseForbidden()
|
|
745 |
request.session['mellon_debug_login'] = True
|
|
746 |
self.stream = StringIO()
|
|
747 |
handler = logging.StreamHandler(self.stream)
|
|
748 |
handler.setLevel(logging.DEBUG)
|
|
749 |
self.log.root.addHandler(handler)
|
|
750 |
return super().dispatch(request, *args, **kwargs)
|
|
751 |
|
|
752 |
def authenticate(self, request, login, attributes):
|
|
753 |
response = super().authenticate(request, login, attributes)
|
|
754 |
request.session['mellon_debug_login'] = False
|
|
755 |
context = {
|
|
756 |
'logs': self.stream.getvalue(),
|
|
757 |
'attributes': attributes,
|
|
758 |
'login': login,
|
|
759 |
'response_dump': login.response and login.response.debug(4),
|
|
760 |
'assertion_dump': login.assertion and login.assertion.debug(4),
|
|
761 |
}
|
|
762 |
return self.render(request, 'mellon/debug_login.html', context)
|
|
763 |
|
|
764 |
def login(self, user, *args, **kwargs):
|
|
765 |
self.log.info('mellon: would login user %s (username %s)', user.get_full_name(), user)
|
|
766 |
|
|
767 |
|
|
768 |
debug_login = csrf_exempt(DebugLoginView.as_view())
|
722 |
|
-
|