From 2289b8350eb644d0f089a9a73abd5bd33eb4f9b7 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Wed, 13 Jan 2016 17:41:13 +0100 Subject: [PATCH] implement session_not_on_or_after using new session engines (fixes #9640) --- README | 12 ++++++++++++ mellon/sessions_backends/__init__.py | 0 mellon/sessions_backends/cached_db.py | 6 ++++++ mellon/sessions_backends/db.py | 23 +++++++++++++++++++++++ mellon/views.py | 3 ++- 5 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 mellon/sessions_backends/__init__.py create mode 100644 mellon/sessions_backends/cached_db.py create mode 100644 mellon/sessions_backends/db.py diff --git a/README b/README index 239c0e9..c799b7b 100644 --- a/README +++ b/README @@ -253,3 +253,15 @@ Tests Unit tests are written using pytest, and can be run with: DJANGO_SETTINGS_MODULE=testsettings py.test + +Remarks +======= + +To honor the SessionNotOnOrAfter attribute sent by an IdP you must use a specific SessionEngine, +only db and cached_db are supported currently, the equivalent session engines are: + + mellon.sessions_backends.db + +and + + mellon.sessions_backends.cached_db diff --git a/mellon/sessions_backends/__init__.py b/mellon/sessions_backends/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mellon/sessions_backends/cached_db.py b/mellon/sessions_backends/cached_db.py new file mode 100644 index 0000000..eb56e6f --- /dev/null +++ b/mellon/sessions_backends/cached_db.py @@ -0,0 +1,6 @@ +from django.contrib.sessions.backends.db import SessionStore + +from . import db + +class SessionStore(db.SessionStore, SessionStore): + pass diff --git a/mellon/sessions_backends/db.py b/mellon/sessions_backends/db.py new file mode 100644 index 0000000..066142a --- /dev/null +++ b/mellon/sessions_backends/db.py @@ -0,0 +1,23 @@ +from django.contrib.sessions.backends.db import SessionStore + +from mellon import utils + +class SessionStore(SessionStore): + + def get_session_not_on_or_after(self): + session_not_on_or_after = self.get('mellon_session', {}).get('session_not_on_or_after') + if session_not_on_or_after: + return utils.iso8601_to_datetime(session_not_on_or_after) + return None + + def get_expiry_age(self, **kwargs): + session_not_on_or_after = self.get_session_not_on_or_after() + if session_not_on_or_after and 'expiry' not in kwargs: + kwargs['expiry'] = session_not_on_or_after + return super(SessionStore, self).get_expiry_age(**kwargs) + + def get_expiry_date(self, **kwargs): + session_not_on_or_after = self.get_session_not_on_or_after() + if session_not_on_or_after and 'expiry' not in kwargs: + kwargs['expiry'] = session_not_on_or_after + return super(SessionStore, self).get_expiry_date(**kwargs) diff --git a/mellon/views.py b/mellon/views.py index 881d3ec..b9e83b3 100644 --- a/mellon/views.py +++ b/mellon/views.py @@ -132,7 +132,8 @@ class LoginView(LogMixin, View): self.log.info('user %r (NameID is %r) logged in using SAML', unicode(user), attributes['name_id_content']) request.session['mellon_session'] = utils.flatten_datetime(attributes) - if 'session_not_on_or_after' in attributes: + if ('session_not_on_or_after' in attributes and + not settings.SESSION_EXPIRE_AT_BROWSER_CLOSE): request.session.set_expiry(utils.get_seconds_expiry(attributes['session_not_on_or_after'])) else: return render(request, 'mellon/inactive_user.html', {