Projet

Général

Profil

0001-wip.patch

Valentin Deniaud, 19 juillet 2021 17:04

Télécharger (6,97 ko)

Voir les différences:

Subject: [PATCH] wip

 mellon/templates/mellon/debug_login.html | 10 +++
 mellon/urls.py                           |  1 +
 mellon/views.py                          | 85 ++++++++++++++++++------
 3 files changed, 77 insertions(+), 19 deletions(-)
 create mode 100644 mellon/templates/mellon/debug_login.html
mellon/templates/mellon/debug_login.html
1
{% load i18n %}
2

  
3
{% block content %}
4
<p><a class="button" href="?">{% trans "Try again" %}</a></p>
5
<p><strong>{% trans "Attributes:" %}</strong> <pre>{{ attributes|pprint }}</pre></p>
6
<p><strong>{% trans "SAML assertion:" %}</strong> <pre>{{ assertion_dump }}</pre></p>
7
<p><strong>{% trans "SAML response:" %}</strong> <pre>{{ response_dump }}</pre></p>
8
<p><strong>{% trans "SAML artifact:" %}</strong> <pre>{{ login.msgBody }}</pre></p>
9
<p><strong>{% trans "Logs:" %}</strong> <pre>{{ logs }}</pre></p>
10
{% endblock %}
mellon/urls.py
8 8

  
9 9
urlpatterns = [
10 10
    url('login/$', views.login, name='mellon_login'),
11
    url('login/debug/$', views.debug_login, name='mellon_debug_login'),
11 12
    url('logout/$', views.logout, name='mellon_logout'),
12 13
    url('metadata/$', views.metadata, name='mellon_metadata'),
13 14
]
mellon/views.py
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
-