From e5165abf043c2a411a0c7cdd78151c26f2c9441e Mon Sep 17 00:00:00 2001
From: Jens Langhammer <jens.langhammer@beryju.org>
Date: Sat, 4 Jul 2020 15:20:45 +0200
Subject: [PATCH] stages/user_login: Allow changing of session duration

---
 passbook/stages/user_login/api.py             |  1 +
 passbook/stages/user_login/forms.py           |  2 +-
 .../0002_userloginstage_session_duration.py   | 21 +++++++++++++++++++
 passbook/stages/user_login/models.py          |  9 ++++++++
 passbook/stages/user_login/stage.py           |  2 ++
 passbook/stages/user_login/tests.py           |  2 +-
 swagger.yaml                                  |  7 +++++++
 7 files changed, 42 insertions(+), 2 deletions(-)
 create mode 100644 passbook/stages/user_login/migrations/0002_userloginstage_session_duration.py

diff --git a/passbook/stages/user_login/api.py b/passbook/stages/user_login/api.py
index 19188172e..61f2115e8 100644
--- a/passbook/stages/user_login/api.py
+++ b/passbook/stages/user_login/api.py
@@ -14,6 +14,7 @@ class UserLoginStageSerializer(ModelSerializer):
         fields = [
             "pk",
             "name",
+            "session_duration",
         ]
 
 
diff --git a/passbook/stages/user_login/forms.py b/passbook/stages/user_login/forms.py
index e5f26fb71..ce7fb8996 100644
--- a/passbook/stages/user_login/forms.py
+++ b/passbook/stages/user_login/forms.py
@@ -10,7 +10,7 @@ class UserLoginStageForm(forms.ModelForm):
     class Meta:
 
         model = UserLoginStage
-        fields = ["name"]
+        fields = ["name", "session_duration"]
         widgets = {
             "name": forms.TextInput(),
         }
diff --git a/passbook/stages/user_login/migrations/0002_userloginstage_session_duration.py b/passbook/stages/user_login/migrations/0002_userloginstage_session_duration.py
new file mode 100644
index 000000000..66f5d9421
--- /dev/null
+++ b/passbook/stages/user_login/migrations/0002_userloginstage_session_duration.py
@@ -0,0 +1,21 @@
+# Generated by Django 3.0.7 on 2020-07-04 13:05
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("passbook_stages_user_login", "0001_initial"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="userloginstage",
+            name="session_duration",
+            field=models.PositiveIntegerField(
+                default=0,
+                help_text="Determines how long a session lasts, in seconds. Default of 0 means that the sessions lasts until the browser is closed.",
+            ),
+        ),
+    ]
diff --git a/passbook/stages/user_login/models.py b/passbook/stages/user_login/models.py
index 13c5164d5..08497983f 100644
--- a/passbook/stages/user_login/models.py
+++ b/passbook/stages/user_login/models.py
@@ -1,4 +1,5 @@
 """login stage models"""
+from django.db import models
 from django.utils.translation import gettext_lazy as _
 
 from passbook.flows.models import Stage
@@ -7,6 +8,14 @@ from passbook.flows.models import Stage
 class UserLoginStage(Stage):
     """Attaches the currently pending user to the current session."""
 
+    session_duration = models.PositiveIntegerField(
+        default=0,
+        help_text=_(
+            "Determines how long a session lasts, in seconds. Default of 0 means"
+            " that the sessions lasts until the browser is closed."
+        ),
+    )
+
     type = "passbook.stages.user_login.stage.UserLoginStageView"
     form = "passbook.stages.user_login.forms.UserLoginStageForm"
 
diff --git a/passbook/stages/user_login/stage.py b/passbook/stages/user_login/stage.py
index abfe18b84..4ec5323a3 100644
--- a/passbook/stages/user_login/stage.py
+++ b/passbook/stages/user_login/stage.py
@@ -32,9 +32,11 @@ class UserLoginStageView(StageView):
             self.executor.plan.context[PLAN_CONTEXT_PENDING_USER],
             backend=backend,
         )
+        self.request.session.set_expiry(self.executor.current_stage.session_duration)
         LOGGER.debug(
             "Logged in",
             user=self.executor.plan.context[PLAN_CONTEXT_PENDING_USER],
             flow_slug=self.executor.flow.slug,
+            session_duration=self.executor.current_stage.session_duration,
         )
         return self.executor.stage_ok()
diff --git a/passbook/stages/user_login/tests.py b/passbook/stages/user_login/tests.py
index 65b0336b3..26212a355 100644
--- a/passbook/stages/user_login/tests.py
+++ b/passbook/stages/user_login/tests.py
@@ -99,5 +99,5 @@ class TestUserLoginStage(TestCase):
 
     def test_form(self):
         """Test Form"""
-        data = {"name": "test"}
+        data = {"name": "test", "session_duration": 0}
         self.assertEqual(UserLoginStageForm(data).is_valid(), True)
diff --git a/swagger.yaml b/swagger.yaml
index 83f7b7047..36e920f3f 100755
--- a/swagger.yaml
+++ b/swagger.yaml
@@ -6925,6 +6925,13 @@ definitions:
         title: Name
         type: string
         minLength: 1
+      session_duration:
+        title: Session duration
+        description: Determines how long a session lasts, in seconds. Default of 0
+          means that the sessions lasts until the browser is closed.
+        type: integer
+        maximum: 2147483647
+        minimum: 0
   UserLogoutStage:
     required:
       - name