Repository: openfun/marsha

Issue:
set different duration for invite and moderator classroom invite link
## Feature Request

**Is your feature request related to a problem or unsupported use case? Please describe.**

The same setting `BBB_INVITE_JWT_DEFAULT_DAYS_DURATION` is used for both public and moderator invite link. We would like to set a different setting dedicated to moderator invitation link. 

**Describe the solution you'd like**

Create a new setting dedicated to set the duration of a moderator invite link




Discussion:

Resolving patch:
diff --git a/src/backend/marsha/bbb/utils/tokens.py b/src/backend/marsha/bbb/utils/tokens.py
--- a/src/backend/marsha/bbb/utils/tokens.py
+++ b/src/backend/marsha/bbb/utils/tokens.py
@@ -4,7 +4,7 @@
 from django.conf import settings
 from django.utils import timezone
 
-from marsha.core.models import NONE
+from marsha.core.models import INSTRUCTOR, NONE
 from marsha.core.simple_jwt.tokens import ResourceAccessToken
 
 
@@ -51,9 +51,12 @@ def create_classroom_stable_invite_jwt(classroom, role=NONE, permissions=None):
     if classroom.starting_at:
         validity_end = classroom.starting_at + timedelta(days=2)
     else:
+        duration = settings.BBB_INVITE_JWT_DEFAULT_DAYS_DURATION
+        if role == INSTRUCTOR:
+            duration = settings.BBB_INVITE_JWT_INSTRUCTOR_DAYS_DURATION
         validity_end = timezone.now().replace(
             hour=0, minute=0, second=0, microsecond=0
-        ) + timedelta(days=settings.BBB_INVITE_JWT_DEFAULT_DAYS_DURATION)
+        ) + timedelta(days=duration)
 
     resource_jwt.set_exp(
         from_time=classroom.created_on,
diff --git a/src/backend/marsha/settings.py b/src/backend/marsha/settings.py
--- a/src/backend/marsha/settings.py
+++ b/src/backend/marsha/settings.py
@@ -381,6 +381,7 @@ class Base(Configuration):
     BBB_API_TIMEOUT = values.PositiveIntegerValue(10)
     ALLOWED_CLASSROOM_DOCUMENT_MIME_TYPES = values.ListValue(["application/pdf"])
     BBB_INVITE_JWT_DEFAULT_DAYS_DURATION = values.PositiveIntegerValue(30)
+    BBB_INVITE_JWT_INSTRUCTOR_DAYS_DURATION = values.PositiveIntegerValue(30)
 
     # deposit application
     DEPOSIT_ENABLED = values.BooleanValue(False)


Test patch:
diff --git a/src/backend/marsha/bbb/tests/test_utils_tokens.py b/src/backend/marsha/bbb/tests/test_utils_tokens.py
--- a/src/backend/marsha/bbb/tests/test_utils_tokens.py
+++ b/src/backend/marsha/bbb/tests/test_utils_tokens.py
@@ -158,6 +158,66 @@ def test_jwt_content_without_starting_at_and_duration(self):
             },
         )
 
+    @override_settings(BBB_INVITE_JWT_INSTRUCTOR_DAYS_DURATION=60)
+    def test_jwt_content_without_starting_at_and_no_duration_instructor(self):
+        """
+        Assert the payload contains the expected data,
+        when classroom has no starting time and no duration.
+
+        JWT will be valid for at least 24 hours.
+        """
+        now_fixed = datetime(2020, 8, 8, 14, tzinfo=baseTimezone.utc)
+        with mock.patch.object(timezone, "now", return_value=now_fixed):
+            classroom = ClassroomFactory(
+                pk="ad0395fd-3023-45da-8801-93d1ce64acd5",
+                created_on=timezone.now(),
+            )
+            jwt = create_classroom_stable_invite_jwt(classroom, role=INSTRUCTOR)
+
+        self.assertDictEqual(
+            jwt.payload,
+            {
+                "exp": 1602028800,  # Wednesday 7 October 2020 00:00:00 UTC
+                "iat": 1596895200,  # Saturday 8 August 2020 14:00:00 UTC
+                "jti": "classroom-invite-ad0395fd-3023-45da-8801-93d1ce64acd5-2020-08-08",
+                "locale": "en_US",
+                "maintenance": False,
+                "permissions": {"can_access_dashboard": False, "can_update": False},
+                "resource_id": "ad0395fd-3023-45da-8801-93d1ce64acd5",
+                "roles": ["instructor"],
+                "session_id": "ad0395fd-3023-45da-8801-93d1ce64acd5-invite",
+                "token_type": "resource_access",
+            },
+        )
+
+    @override_settings(BBB_INVITE_JWT_INSTRUCTOR_DAYS_DURATION=60)
+    def test_jwt_content_without_starting_at_and_duration_instructor(self):
+        """Assert the payload contains the expected data."""
+        now_fixed = datetime(2020, 8, 8, tzinfo=baseTimezone.utc)
+        with mock.patch.object(timezone, "now", return_value=now_fixed):
+            classroom = ClassroomFactory(
+                pk="ad0395fd-3023-45da-8801-93d1ce64acd5",
+                created_on=timezone.now(),
+                estimated_duration=timedelta(hours=2),
+            )
+            jwt = create_classroom_stable_invite_jwt(classroom, role=INSTRUCTOR)
+
+        self.assertDictEqual(
+            jwt.payload,
+            {
+                "exp": 1602028800,  # Wednesday 7 October 2020 00:00:00 UTC
+                "iat": 1596844800,  # Saturday 8 August 2020 00:00:00 UTC
+                "jti": "classroom-invite-ad0395fd-3023-45da-8801-93d1ce64acd5-2020-08-08",
+                "locale": "en_US",
+                "maintenance": False,
+                "permissions": {"can_access_dashboard": False, "can_update": False},
+                "resource_id": "ad0395fd-3023-45da-8801-93d1ce64acd5",
+                "roles": ["instructor"],
+                "session_id": "ad0395fd-3023-45da-8801-93d1ce64acd5-invite",
+                "token_type": "resource_access",
+            },
+        )
+
     def test_jwt_content_when_called_twice(self):
         """Assert the payload contains the same data for several calls for same classroom."""
         classroom = ClassroomFactory()