← Back to team overview

sts-sponsors team mailing list archive

[Merge] ~ack/maas:session-timeout-update-existing-sessions into maas:master

 

Alberto Donato has proposed merging ~ack/maas:session-timeout-update-existing-sessions into maas:master.

Commit message:
update existing sessions expirations if new expiration is shorter



Requested reviews:
  MAAS Maintainers (maas-maintainers)

For more details, see:
https://code.launchpad.net/~ack/maas/+git/maas/+merge/438471
-- 
Your team MAAS Maintainers is requested to review the proposed merge of ~ack/maas:session-timeout-update-existing-sessions into maas:master.
diff --git a/src/maasserver/models/signals/config.py b/src/maasserver/models/signals/config.py
index 45ca8f4..c939b35 100644
--- a/src/maasserver/models/signals/config.py
+++ b/src/maasserver/models/signals/config.py
@@ -15,9 +15,14 @@ def dns_kms_setting_changed(sender, instance, created, **kwargs):
     dns_kms_setting_changed()
 
 
-# Changes to windows_kms_host.
-signals.watch_config(dns_kms_setting_changed, "windows_kms_host")
+def session_length_changed(sender, instance, *args, **kwargs):
+    from maasserver.sessiontimeout import update_sessions_expiration
+
+    update_sessions_expiration()
 
 
+signals.watch_config(dns_kms_setting_changed, "windows_kms_host")
+signals.watch_config(session_length_changed, "session_length")
+
 # Enable all signals by default.
 signals.enable()
diff --git a/src/maasserver/models/signals/tests/test_config.py b/src/maasserver/models/signals/tests/test_config.py
index 2e3e9c3..fa9c06f 100644
--- a/src/maasserver/models/signals/tests/test_config.py
+++ b/src/maasserver/models/signals/tests/test_config.py
@@ -1,11 +1,12 @@
-# Copyright 2016 Canonical Ltd.  This software is licensed under the
+# Copyright 2016-2023 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
-"""Test the behaviour of config signals."""
-
+from datetime import datetime, timedelta
 
+from maasserver.models import Config
 from maasserver.models import domain as domain_module
-from maasserver.models.config import Config
+from maasserver.sessiontimeout import SessionStore
+from maasserver.testing.factory import factory
 from maasserver.testing.testcase import MAASServerTestCase
 from maastesting.matchers import MockCalledOnceWith
 
@@ -17,3 +18,32 @@ class TestConfigSignals(MAASServerTestCase):
         )
         Config.objects.set_config("windows_kms_host", "8.8.8.8")
         self.assertThat(dns_kms_setting_changed, MockCalledOnceWith())
+
+    def test_changing_session_length_updates_sessions(self):
+        Config.objects.set_config("session_length", 600)
+        SessionStore().create()
+        SessionStore().create()
+        expire_date = datetime.utcnow() + timedelta(seconds=400)
+        Session = SessionStore.get_model_class()
+        self.assertEqual(
+            Session.objects.filter(expire_date__gt=expire_date).count(),
+            2,
+        )
+        Config.objects.set_config("session_length", 300)
+        self.assertEqual(
+            Session.objects.filter(expire_date__gt=expire_date).count(),
+            0,
+        )
+
+    def test_changing_session_length_clears_expired(self):
+        Session = SessionStore.get_model_class()
+        Session.objects.create(
+            session_key=factory.make_string(),
+            expire_date=datetime.utcnow() - timedelta(minutes=1),
+        )
+        Session.objects.create(
+            session_key=factory.make_string(),
+            expire_date=datetime.utcnow() - timedelta(minutes=5),
+        )
+        Config.objects.set_config("session_length", 60)
+        self.assertFalse(Session.objects.exists())
diff --git a/src/maasserver/sessiontimeout.py b/src/maasserver/sessiontimeout.py
index 6564b4d..c8f1e8f 100644
--- a/src/maasserver/sessiontimeout.py
+++ b/src/maasserver/sessiontimeout.py
@@ -1,15 +1,29 @@
 """ Custom sessionstore for a user-configurable session timeout. """
 
+from datetime import datetime, timedelta
+
 from django.contrib.sessions.backends.db import SessionStore as DBStore
+from django.db.models import F
+from django.db.models.functions import Least
 
 from maasserver.models import Config
 
 
-def _get_timeout() -> int:
-    timeout = Config.objects.get_config("session_length")
-    return timeout
-
-
 class SessionStore(DBStore):
     def get_session_cookie_age(self) -> int:
-        return _get_timeout()
+        return _get_session_length()
+
+
+def update_sessions_expiration():
+    """Update sessions expiration date to match the session length"""
+    expiry_date = datetime.utcnow() + timedelta(seconds=_get_session_length())
+
+    SessionStore.get_model_class().objects.update(
+        expire_date=Least(F("expire_date"), expiry_date)
+    )
+    SessionStore.clear_expired()
+
+
+def _get_session_length() -> int:
+    """Return the session duration."""
+    return Config.objects.get_config("session_length")

Follow ups