From 081015174f80907e1c97a389b96466e4df5d8047 Mon Sep 17 00:00:00 2001 From: Nicolas Clerc Date: Thu, 17 Aug 2023 10:32:19 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(backend)=20rename=20simple?= =?UTF-8?q?=5Fjwt=20classes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As we now have only playlist tokens, the simple_jwt classes must be renamed for reflecting it. --- .../tests/test_views_lti.py | 6 +- src/backend/marsha/account/serializers.py | 4 +- .../account/tests/api/test_password_change.py | 4 +- .../account/tests/api/test_token_refresh.py | 10 +-- .../tests/api/classroom/test_invite_token.py | 6 +- .../marsha/bbb/tests/test_views_lti.py | 10 +-- src/backend/marsha/bbb/utils/tokens.py | 6 +- src/backend/marsha/core/api/base.py | 4 +- .../marsha/core/simple_jwt/authentication.py | 12 ++-- .../marsha/core/simple_jwt/factories.py | 64 ++++++++----------- .../marsha/core/simple_jwt/permissions.py | 4 +- src/backend/marsha/core/simple_jwt/tokens.py | 44 ++++++------- .../tests/api/live_sessions/test_create.py | 50 +++++++-------- .../api/live_sessions/test_display_name.py | 24 +++---- .../core/tests/api/live_sessions/test_list.py | 14 ++-- .../api/live_sessions/test_push_attendance.py | 22 +++---- .../tests/api/live_sessions/test_retrieve.py | 26 ++++---- .../tests/api/live_sessions/test_update.py | 14 ++-- .../core/tests/simple_jwt/test_factories.py | 10 +-- .../core/tests/simple_jwt/test_tokens.py | 22 +++---- src/backend/marsha/core/tests/test_xapi.py | 18 +++--- .../marsha/core/tests/views/test_lti_base.py | 6 +- .../core/tests/views/test_lti_document.py | 14 ++-- .../core/tests/views/test_lti_select.py | 6 +- .../marsha/core/tests/views/test_lti_video.py | 50 +++++++-------- .../core/tests/views/test_public_document.py | 10 +-- .../core/tests/views/test_public_video.py | 22 +++---- src/backend/marsha/core/views.py | 12 ++-- .../marsha/deposit/tests/test_views_lti.py | 8 +-- .../tests/test_views_lti_development.py | 8 +-- .../marsha/markdown/tests/test_views_lti.py | 6 +- src/backend/marsha/settings.py | 6 +- .../marsha/websocket/consumers/video.py | 6 +- .../websocket/tests/test_consumers_video.py | 8 +-- .../websocket/tests/test_middleware_jwt.py | 6 +- 35 files changed, 265 insertions(+), 277 deletions(-) diff --git a/src/backend/marsha/.cookiecutter/{{cookiecutter.app_name}}/tests/test_views_lti.py b/src/backend/marsha/.cookiecutter/{{cookiecutter.app_name}}/tests/test_views_lti.py index 3be3330fc0..a442359d2c 100644 --- a/src/backend/marsha/.cookiecutter/{{cookiecutter.app_name}}/tests/test_views_lti.py +++ b/src/backend/marsha/.cookiecutter/{{cookiecutter.app_name}}/tests/test_views_lti.py @@ -18,7 +18,7 @@ ) from marsha.core.lti import LTI from marsha.core.models import ADMINISTRATOR -from marsha.core.simple_jwt.tokens import ResourceAccessToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken from marsha.core.tests.test_views_lti_base import BaseLTIViewForPortabilityTestCase from ..factories import {{cookiecutter.model}}Factory @@ -65,7 +65,7 @@ def test_views_lti_{{cookiecutter.model_lower}}_student(self, mock_get_consumer_ ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(context.get("state"), "success") self.assertIsNotNone(context.get("resource")) self.assertEqual(context.get("modelName"), "{{cookiecutter.model_plural_lower}}") @@ -153,7 +153,7 @@ def test_views_lti_{{cookiecutter.model_lower}}_instructor_same_playlist( ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(jwt_token.payload["resource_id"], str({{cookiecutter.model_lower}}.id)) self.assertEqual( jwt_token.payload["user"], diff --git a/src/backend/marsha/account/serializers.py b/src/backend/marsha/account/serializers.py index bd7d46cd1c..d1f16787fe 100644 --- a/src/backend/marsha/account/serializers.py +++ b/src/backend/marsha/account/serializers.py @@ -18,7 +18,7 @@ TokenRefreshSerializer as BaseTokenRefreshSerializer, ) -from marsha.core.simple_jwt.authentication import TokenResource +from marsha.core.simple_jwt.authentication import TokenPlaylist from marsha.core.simple_jwt.tokens import MarshaRefreshToken, UserRefreshToken @@ -79,7 +79,7 @@ def __init__(self, *args, **kwargs): """Instantiate the serializer and make the `TokenUser` to `User` conversion.""" super().__init__(*args, **kwargs) if isinstance(self.user, TokenUser) and not isinstance( - self.user, TokenResource + self.user, TokenPlaylist ): # May raise 500 here but this is not expected so let it raise self.user = get_user_model().objects.get(pk=self.user.pk) diff --git a/src/backend/marsha/account/tests/api/test_password_change.py b/src/backend/marsha/account/tests/api/test_password_change.py index 1a193ed129..80217fbcaa 100644 --- a/src/backend/marsha/account/tests/api/test_password_change.py +++ b/src/backend/marsha/account/tests/api/test_password_change.py @@ -4,7 +4,7 @@ from django.test import TestCase from marsha.core.factories import UserFactory -from marsha.core.simple_jwt.factories import LTIResourceAccessTokenFactory +from marsha.core.simple_jwt.factories import LTIPlaylistAccessTokenFactory from marsha.core.simple_jwt.tokens import UserAccessToken @@ -54,7 +54,7 @@ def test_password_change_wrong_authentication(self): "new_password2": "new_password", } ), - HTTP_AUTHORIZATION=f"Bearer {str(LTIResourceAccessTokenFactory())}", + HTTP_AUTHORIZATION=f"Bearer {str(LTIPlaylistAccessTokenFactory())}", ) self.assertEqual(response.status_code, 401) # Unauthorized diff --git a/src/backend/marsha/account/tests/api/test_token_refresh.py b/src/backend/marsha/account/tests/api/test_token_refresh.py index e0d761d58e..b384cdef4a 100644 --- a/src/backend/marsha/account/tests/api/test_token_refresh.py +++ b/src/backend/marsha/account/tests/api/test_token_refresh.py @@ -8,8 +8,8 @@ from marsha.core.factories import UserFactory from marsha.core.simple_jwt.tokens import ( - ResourceAccessToken, - ResourceRefreshToken, + PlaylistAccessToken, + PlaylistRefreshToken, UserAccessToken, UserRefreshToken, ) @@ -92,7 +92,7 @@ def test_success_resource_access(self): """ session_id = str(uuid.uuid4()) resource_id = str(uuid.uuid4()) - refresh_token = ResourceRefreshToken.for_resource_id(resource_id, session_id) + refresh_token = PlaylistRefreshToken.for_resource_id(resource_id, session_id) response = self.client.post( "/account/api/token/refresh/", @@ -110,8 +110,8 @@ def test_success_resource_access(self): self.assertIn("refresh", response_data) # Verify tokens - new_token = ResourceAccessToken(response_data["access"]) - new_refresh_token = ResourceRefreshToken(response_data["refresh"]) + new_token = PlaylistAccessToken(response_data["access"]) + new_refresh_token = PlaylistRefreshToken(response_data["refresh"]) self.assertEqual(new_token.payload["token_type"], "resource_access") self.assertEqual( diff --git a/src/backend/marsha/bbb/tests/api/classroom/test_invite_token.py b/src/backend/marsha/bbb/tests/api/classroom/test_invite_token.py index afd87db018..e7f04c92df 100644 --- a/src/backend/marsha/bbb/tests/api/classroom/test_invite_token.py +++ b/src/backend/marsha/bbb/tests/api/classroom/test_invite_token.py @@ -5,7 +5,7 @@ from marsha.bbb.factories import ClassroomFactory from marsha.core.models import INSTRUCTOR, NONE -from marsha.core.simple_jwt.tokens import ResourceAccessToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken from marsha.core.tests.testing_utils import reload_urlconf @@ -52,7 +52,7 @@ def test_invite_public_token(self): self.assertEqual(response.status_code, 200) public_token = response.json().get("access_token") - decoded_public_token = ResourceAccessToken(public_token) + decoded_public_token = PlaylistAccessToken(public_token) self.assertEqual(decoded_public_token.payload["resource_id"], str(classroom.id)) self.assertEqual(decoded_public_token.payload["roles"], [NONE]) self.assertEqual( @@ -71,7 +71,7 @@ def test_invite_instructor_token(self): self.assertEqual(response.status_code, 200) instructor_token = response.json().get("access_token") - decoded_instructor_token = ResourceAccessToken(instructor_token) + decoded_instructor_token = PlaylistAccessToken(instructor_token) self.assertEqual( decoded_instructor_token.payload["resource_id"], str(classroom.id) ) diff --git a/src/backend/marsha/bbb/tests/test_views_lti.py b/src/backend/marsha/bbb/tests/test_views_lti.py index e4b3aeef62..996c20be8a 100644 --- a/src/backend/marsha/bbb/tests/test_views_lti.py +++ b/src/backend/marsha/bbb/tests/test_views_lti.py @@ -21,7 +21,7 @@ ) from marsha.core.lti import LTI from marsha.core.models import ADMINISTRATOR -from marsha.core.simple_jwt.tokens import ResourceAccessToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken from marsha.core.tests.testing_utils import reload_urlconf from marsha.core.tests.views.test_lti_base import BaseLTIViewForPortabilityTestCase @@ -98,7 +98,7 @@ def test_views_lti_classroom_student(self, mock_get_consumer_site, mock_verify): ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(context.get("state"), "success") self.assertIsNotNone(context.get("resource")) self.assertEqual(context.get("modelName"), "classrooms") @@ -249,7 +249,7 @@ def test_views_lti_classroom_instructor_same_playlist( ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(jwt_token.payload["resource_id"], str(classroom.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -437,7 +437,7 @@ def test_views_lti_classroom_student(self, mock_get_consumer_site, mock_verify): ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(context.get("state"), "success") self.assertIsNotNone(context.get("resource")) self.assertEqual(context.get("modelName"), "classrooms") @@ -588,7 +588,7 @@ def test_views_lti_classroom_instructor_same_playlist( ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(jwt_token.payload["resource_id"], str(classroom.playlist.id)) self.assertEqual( jwt_token.payload["user"], diff --git a/src/backend/marsha/bbb/utils/tokens.py b/src/backend/marsha/bbb/utils/tokens.py index 96ad2f686d..75b754ae97 100644 --- a/src/backend/marsha/bbb/utils/tokens.py +++ b/src/backend/marsha/bbb/utils/tokens.py @@ -5,7 +5,7 @@ from django.utils import timezone from marsha.core.models import INSTRUCTOR, NONE -from marsha.core.simple_jwt.tokens import ResourceAccessToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken def create_classroom_stable_invite_jwt(classroom, role=NONE, permissions=None): @@ -24,11 +24,11 @@ def create_classroom_stable_invite_jwt(classroom, role=NONE, permissions=None): Returns ------- - ResourceAccessToken + PlaylistAccessToken The JWT. """ - resource_jwt = ResourceAccessToken.for_resource_id( + resource_jwt = PlaylistAccessToken.for_resource_id( resource_id=str(classroom.id), session_id=f"{classroom.id}-invite", roles=[role], diff --git a/src/backend/marsha/core/api/base.py b/src/backend/marsha/core/api/base.py index d949dbff9f..9de6eb6129 100644 --- a/src/backend/marsha/core/api/base.py +++ b/src/backend/marsha/core/api/base.py @@ -12,7 +12,7 @@ from ..defaults import SENTRY, VOD_CONVERT from ..models import SiteConfig, Video from ..signals import signal_object_uploaded -from ..simple_jwt.tokens import ResourceAccessToken +from ..simple_jwt.tokens import PlaylistAccessToken from ..utils.api_utils import get_uploadable_models_s3_mapping, validate_signature @@ -278,7 +278,7 @@ def check_permissions(self, request): we keep it as a TokenResource... """ request.resource = None - if isinstance(request.auth, ResourceAccessToken): # otherwise, nothing to do + if isinstance(request.auth, PlaylistAccessToken): # otherwise, nothing to do request.resource = request.user super().check_permissions(request) diff --git a/src/backend/marsha/core/simple_jwt/authentication.py b/src/backend/marsha/core/simple_jwt/authentication.py index a62ec67c5c..d7d8fbbe88 100644 --- a/src/backend/marsha/core/simple_jwt/authentication.py +++ b/src/backend/marsha/core/simple_jwt/authentication.py @@ -7,8 +7,8 @@ from rest_framework_simplejwt.models import TokenUser -class TokenResource(TokenUser): - """Same as TokenUser but for resource access JWT, with helpers for payload.""" +class TokenPlaylist(TokenUser): + """Same as TokenUser but for playlist access JWT, with helpers for payload.""" @cached_property def id(self): @@ -26,7 +26,7 @@ def user(self): return self.token.get("user", {}) -class JWTStatelessUserOrResourceAuthentication(JWTStatelessUserAuthentication): +class JWTStatelessUserOrPlaylistAuthentication(JWTStatelessUserAuthentication): """ An authentication plugin that authenticates requests through a JSON web token provided in a request header without performing a database lookup @@ -41,15 +41,15 @@ def get_user(self, validated_token): We keep an actual user-like object to go through Django logic but this method can return: - TokenUser for user authentication - - TokenResource for resource authentication + - TokenPlaylist for playlist authentication """ try: user = super().get_user(validated_token) except InvalidToken as exc: if "resource_id" not in validated_token: raise InvalidToken( - _("Token contained no recognizable resource identification") + _("Token contained no recognizable playlist identification") ) from exc - return TokenResource(validated_token) + return TokenPlaylist(validated_token) return user diff --git a/src/backend/marsha/core/simple_jwt/factories.py b/src/backend/marsha/core/simple_jwt/factories.py index b6c8add7b5..994c090a42 100644 --- a/src/backend/marsha/core/simple_jwt/factories.py +++ b/src/backend/marsha/core/simple_jwt/factories.py @@ -17,11 +17,11 @@ STUDENT, Playlist, ) -from marsha.core.simple_jwt.permissions import ResourceAccessPermissions +from marsha.core.simple_jwt.permissions import PlaylistAccessPermissions from marsha.core.simple_jwt.tokens import ( ChallengeToken, LTIUserToken, - ResourceAccessToken, + PlaylistAccessToken, UserAccessToken, ) @@ -112,14 +112,14 @@ class Meta: # pylint:disable=missing-class-docstring model = ChallengeToken.for_user -class ResourcePermissionsFactory(factory.DictFactory): - """Factory for resource access permissions.""" +class PlaylistPermissionsFactory(factory.DictFactory): + """Factory for playlist access permissions.""" can_access_dashboard = False can_update = False class Meta: # pylint:disable=missing-class-docstring - model = ResourceAccessPermissions + model = PlaylistAccessPermissions @classmethod def _build(cls, model_class, *args, **kwargs): @@ -128,9 +128,9 @@ def _build(cls, model_class, *args, **kwargs): return permissions.as_dict() -class BaseResourceTokenFactory(BaseTokenFactory): +class BasePlaylistTokenFactory(BaseTokenFactory): """ - Base class for all resource token factories. + Base class for all playlist token factories. This forces to provide a playlist to forge the JWT, or nothing to use a random UUID. """ @@ -157,18 +157,18 @@ class Params: # pylint:disable=missing-class-docstring resource = None -class ResourceAccessTokenFactory(BaseResourceTokenFactory): - """Simple resource token. Looks like a public resource token.""" +class PlaylistAccessTokenFactory(BasePlaylistTokenFactory): + """Simple playlist token. Looks like a public playlist token.""" session_id = factory.Faker("uuid4") class Meta: # pylint:disable=missing-class-docstring - model = ResourceAccessToken.for_resource_id + model = PlaylistAccessToken.for_resource_id -class LTIResourceAccessTokenFactory(BaseResourceTokenFactory): +class LTIPlaylistAccessTokenFactory(BasePlaylistTokenFactory): """ - LTI resource forged token. + LTI playlist forged token. This token's payload is forged to remove a heavy call to `generate_passport_and_signed_lti_parameters` each time @@ -177,7 +177,7 @@ class LTIResourceAccessTokenFactory(BaseResourceTokenFactory): # for_resource_id payload session_id = factory.Faker("uuid4") - permissions = factory.SubFactory(ResourcePermissionsFactory) + permissions = factory.SubFactory(PlaylistPermissionsFactory) roles = factory.fuzzy.FuzzyChoice( [ADMINISTRATOR, INSTRUCTOR, STUDENT, NONE], getter=lambda x: [x], @@ -200,58 +200,46 @@ class LTIResourceAccessTokenFactory(BaseResourceTokenFactory): ) class Meta: # pylint:disable=missing-class-docstring - model = ResourceAccessToken + model = PlaylistAccessToken -class StudentLtiTokenFactory(LTIResourceAccessTokenFactory): - """LTI resource forged token for student.""" +class StudentLtiTokenFactory(LTIPlaylistAccessTokenFactory): + """LTI playlist forged token for student.""" roles = factory.fuzzy.FuzzyChoice(LTI_ROLES.get(STUDENT), getter=lambda x: [x]) -class InstructorOrAdminLtiTokenFactory(LTIResourceAccessTokenFactory): +class InstructorOrAdminLtiTokenFactory(LTIPlaylistAccessTokenFactory): """ - LTI resource forged token for instructor or administrators. + LTI playlist forged token for instructor or administrators. See `marsha.core.views.BaseLTIView`. Note: the `can_update` permission is set to True - to mean "the LTI request context ID is the resource playlist LTI ID". + to mean "the LTI request context ID is the playlist playlist LTI ID". When this is not the case, the test must explicitly add `permissions__can_update=False`. """ roles = factory.fuzzy.FuzzyChoice([ADMINISTRATOR, INSTRUCTOR], getter=lambda x: [x]) permissions = factory.SubFactory( - ResourcePermissionsFactory, + PlaylistPermissionsFactory, can_access_dashboard=True, can_update=True, ) -# class PlaylistLtiTokenFactory(InstructorOrAdminLtiTokenFactory): -# """ -# LTI resource forged token for instructor or administrators with a playlist access. -# See `marsha.core.views.LTISelectView`. -# """ -# -# permissions = factory.SubFactory(ResourcePermissionsFactory, can_update=True) -# -# class Params: # pylint:disable=missing-class-docstring -# playlist = factory.SubFactory(PlaylistFactory) - - -class LiveSessionResourceAccessTokenFactory(BaseTokenFactory): - """Generates a resource access token from a live session.""" +class LiveSessionPlaylistAccessTokenFactory(BaseTokenFactory): + """Generates a playlist access token from a live session.""" live_session = factory.SubFactory(LiveSessionFactory) session_id = factory.Faker("uuid4") class Meta: # pylint:disable=missing-class-docstring - model = ResourceAccessToken.for_live_session + model = PlaylistAccessToken.for_live_session -class LiveSessionLtiTokenFactory(LTIResourceAccessTokenFactory): +class LiveSessionLtiTokenFactory(LTIPlaylistAccessTokenFactory): """ - Prefer the use of LiveSessionResourceAccessTokenFactory, + Prefer the use of LiveSessionPlaylistAccessTokenFactory, but this one allows to deeply customize the final JWT. """ @@ -272,7 +260,7 @@ class LiveSessionLtiTokenFactory(LTIResourceAccessTokenFactory): ) class Meta: # pylint:disable=missing-class-docstring - model = ResourceAccessToken + model = PlaylistAccessToken class Params: # pylint:disable=missing-class-docstring live_session = factory.SubFactory( diff --git a/src/backend/marsha/core/simple_jwt/permissions.py b/src/backend/marsha/core/simple_jwt/permissions.py index c68c583c78..10bf206d8f 100644 --- a/src/backend/marsha/core/simple_jwt/permissions.py +++ b/src/backend/marsha/core/simple_jwt/permissions.py @@ -3,8 +3,8 @@ @dataclass -class ResourceAccessPermissions: - """Permissions which can be provided in ResourceAccessToken""" +class PlaylistAccessPermissions: + """Permissions which can be provided in PlaylistAccessToken""" can_access_dashboard: bool = False can_update: bool = False diff --git a/src/backend/marsha/core/simple_jwt/tokens.py b/src/backend/marsha/core/simple_jwt/tokens.py index 70032efd3a..d549df1ba0 100644 --- a/src/backend/marsha/core/simple_jwt/tokens.py +++ b/src/backend/marsha/core/simple_jwt/tokens.py @@ -12,7 +12,7 @@ from marsha.core.simple_jwt.utils import define_locales from marsha.core.utils.react_locales_utils import react_locale -from .permissions import ResourceAccessPermissions +from .permissions import PlaylistAccessPermissions class MarshaRefreshToken(RefreshToken): @@ -106,10 +106,10 @@ def verify(self): raise TokenError(_("Malformed LTI form token")) -class ResourceAccessMixin: +class PlaylistAccessMixin: """ - Methods dedicated to access JWT. They are both used by the ResourceAccessToken - and the ResourceRefreshToken classes. + Methods dedicated to access JWT. They are both used by the PlaylistAccessToken + and the PlaylistRefreshToken classes. """ def verify(self): @@ -117,9 +117,9 @@ def verify(self): super().verify() try: - ResourceAccessPermissions(**self.payload["permissions"]) + PlaylistAccessPermissions(**self.payload["permissions"]) except TypeError as exc: - raise TokenError(_("Malformed resource access token")) from exc + raise TokenError(_("Malformed playlist access token")) from exc @classmethod def for_lti( @@ -130,7 +130,7 @@ def for_lti( port_to_playlist_id, ): """ - Returns an authorization token for the resource in the LTI request that will be provided + Returns an authorization token for the playlist in the LTI request that will be provided after authenticating the credentials. Parameters @@ -149,7 +149,7 @@ def for_lti( Returns ------- - ResourceAccessToken + PlaylistAccessToken JWT containing: - session_id - resource_id @@ -201,7 +201,7 @@ def for_lti_portability_request( port_to_playlist_id, ): """ - Returns an authorization token without resource + Returns an authorization token without playlist to allow only portability requests creation. Parameters @@ -217,7 +217,7 @@ def for_lti_portability_request( Returns ------- - ResourceAccessToken + PlaylistAccessToken JWT containing: - session_id - resource_id @@ -290,7 +290,7 @@ def for_resource_id( # pylint: disable=too-many-arguments Returns ------- - ResourceAccessToken + PlaylistAccessToken JWT containing: - session_id - resource_id @@ -299,9 +299,9 @@ def for_resource_id( # pylint: disable=too-many-arguments - permissions - maintenance """ - permissions = ResourceAccessPermissions(**(permissions or {})) + permissions = PlaylistAccessPermissions(**(permissions or {})) - # Create a short-lived JWT token for the resource selection + # Create a short-lived JWT token for the playlist selection token = cls() token.payload.update( { @@ -318,8 +318,8 @@ def for_resource_id( # pylint: disable=too-many-arguments @classmethod def for_live_session(cls, live_session, session_id): """ - Returns an authorization token for the resource liked to the live session - that will be provided after authenticating the resource's credentials. + Returns an authorization token for the playlist liked to the live session + that will be provided after authenticating the playlist's credentials. Parameters ---------- @@ -331,7 +331,7 @@ def for_live_session(cls, live_session, session_id): Returns ------- - ResourceAccessToken + PlaylistAccessToken JWT containing: - resource_id - consumer_site (if from LTI connection) @@ -375,9 +375,9 @@ def for_live_session(cls, live_session, session_id): return token -class ResourceAccessToken(ResourceAccessMixin, AccessToken): +class PlaylistAccessToken(PlaylistAccessMixin, AccessToken): """ - Resource dedicated access JWT. + Playlist dedicated access JWT. This token has the same lifetime as the default AccessToken (see `ACCESS_TOKEN_LIFETIME` setting). @@ -400,11 +400,11 @@ def set_jti(self, jti=None): self.payload[api_settings.JTI_CLAIM] = jti -class ResourceRefreshToken(ResourceAccessMixin, MarshaRefreshToken): - """Refresh token for resource access which relies on `ResourceAccessToken`""" +class PlaylistRefreshToken(PlaylistAccessMixin, MarshaRefreshToken): + """Refresh token for playlist access which relies on `PlaylistAccessToken`""" - access_token_class = ResourceAccessToken - access_token_type = ResourceAccessToken.token_type + access_token_class = PlaylistAccessToken + access_token_type = PlaylistAccessToken.token_type class LTIUserToken(AccessToken): diff --git a/src/backend/marsha/core/tests/api/live_sessions/test_create.py b/src/backend/marsha/core/tests/api/live_sessions/test_create.py index 9df7a04c4c..6da1975126 100644 --- a/src/backend/marsha/core/tests/api/live_sessions/test_create.py +++ b/src/backend/marsha/core/tests/api/live_sessions/test_create.py @@ -25,8 +25,8 @@ from marsha.core.serializers.live_session import timezone as LiveSessionTimezone from marsha.core.simple_jwt.factories import ( LiveSessionLtiTokenFactory, - LTIResourceAccessTokenFactory, - ResourceAccessTokenFactory, + LTIPlaylistAccessTokenFactory, + PlaylistAccessTokenFactory, UserAccessTokenFactory, ) @@ -166,7 +166,7 @@ def test_api_livesession_create_send_mail_fails(self, mock_logger, _mock_send_ma ) self.assertTrue(video.is_scheduled) # token with no context_id and no user information - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) anonymous_id = uuid.uuid4() response = self.client.post( @@ -214,7 +214,7 @@ def test_api_livesession_create_public_token(self): ) self.assertTrue(video.is_scheduled) # token with no context_id and no user information - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) anonymous_id = uuid.uuid4() response = self.client.post( self._post_url(video), @@ -260,7 +260,7 @@ def test_api_livesession_create_public_token_is_registered_false(self): ) self.assertTrue(video.is_scheduled) # token with no context_id and no user information - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) anonymous_id = uuid.uuid4() now = datetime(2022, 4, 7, tzinfo=baseTimezone.utc) with mock.patch.object(LiveSessionTimezone, "now", return_value=now): @@ -310,7 +310,7 @@ def test_api_livesession_create_public_token_anonymous_mandatory( ) self.assertTrue(video.is_scheduled) # token with no context_id and no user information - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.post( self._post_url(video), { @@ -339,7 +339,7 @@ def test_api_livesession_create_public_partially_lti1(self): starting_at=timezone.now() + timedelta(days=100), ) self.assertTrue(video.is_scheduled) - jwt_token = LTIResourceAccessTokenFactory(resource=video.playlist, user={}) + jwt_token = LTIPlaylistAccessTokenFactory(resource=video.playlist, user={}) response = self.client.post( self._post_url(video), @@ -372,7 +372,7 @@ def test_api_livesession_create_public_partially_lti2(self): starting_at=timezone.now() + timedelta(days=100), ) self.assertTrue(video.is_scheduled) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, context_id=None, ) @@ -408,7 +408,7 @@ def test_api_livesession_create_public_partially_lti3(self): starting_at=timezone.now() + timedelta(days=100), ) self.assertTrue(video.is_scheduled) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=None, ) @@ -441,7 +441,7 @@ def test_api_livesession_create_token_lti_email_with(self): ) self.assertTrue(video.is_scheduled) # token has same consumer_site than the video - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, context_id="Maths", # explicit to be found in response consumer_site=str(video.playlist.consumer_site.id), @@ -492,7 +492,7 @@ def test_api_livesession_create_token_lti_is_registered_false(self): ) self.assertTrue(video.is_scheduled) # token has same consumer_site than the video - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, context_id="Maths", # explicit to be found in response consumer_site=str(video.playlist.consumer_site.id), @@ -544,7 +544,7 @@ def test_api_livesession_create_token_lti_email_none(self): self.assertTrue(video.is_scheduled) other_playlist = PlaylistFactory() # token has different context_id than the video - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, context_id=str(other_playlist.lti_id), consumer_site=str(video.playlist.consumer_site.id), @@ -600,7 +600,7 @@ def test_api_livesession_create_public_token_record_email_other_livesession_lti( ) self.assertEqual(LiveSession.objects.count(), 1) self.assertTrue(video.is_scheduled) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) anonymous_id = uuid.uuid4() response = self.client.post( self._post_url(video), @@ -659,7 +659,7 @@ def test_api_livesession_create_lti_token_record_email_other_consumer_site( ) self.assertEqual(LiveSession.objects.count(), 1) self.assertTrue(video.is_scheduled) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=str(other_consumer_site.id), context_id=live_session.lti_id, @@ -720,7 +720,7 @@ def test_api_livesession_create_lti_token_record_email_other_context_id( self.assertTrue(video.is_scheduled) other_context_id = f"{live_session.lti_id}_diff" - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=str(video.playlist.consumer_site.id), context_id=other_context_id, @@ -778,7 +778,7 @@ def test_api_livesession_create_lti_token_record_email_lti_user_id(self): ) self.assertEqual(LiveSession.objects.count(), 1) self.assertTrue(video.is_scheduled) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=str(live_session.consumer_site.id), context_id=live_session.lti_id, @@ -832,7 +832,7 @@ def test_api_livesession_create_token_lti_email_restricted_token(self): ) self.assertTrue(video.is_scheduled) # token with different context_id - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=str(video.playlist.consumer_site.id), ) @@ -864,7 +864,7 @@ def test_api_livesession_create_public_token_cant_register_when_not_scheduled( """Can't register if video is not scheduled.""" video = VideoFactory() self.assertFalse(video.is_scheduled) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.post( self._post_url(video), @@ -891,7 +891,7 @@ def test_api_livesession_create_lti_token_cant_register_when_not_scheduled( """LTI token can't register if video is not scheduled.""" video = VideoFactory() self.assertFalse(video.is_scheduled) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, context_id=str(video.playlist.lti_id), consumer_site=str(video.playlist.consumer_site.id), @@ -1064,7 +1064,7 @@ def test_api_livesession_create_cant_register_same_email_same_consumer_none( AnonymousLiveSessionFactory(email="salome@test-fun-mooc.fr", video=video) self.assertTrue(video.is_scheduled) # token with no context_id leading to an undefined consumer_site - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.post( self._post_url(video), { @@ -1141,7 +1141,7 @@ def test_api_livesession_create_public_token_same_email_different_video( # livesession with no consumer_site AnonymousLiveSessionFactory(email="chantal@test-fun-mooc.fr", video=video) # token with no context_id leading to no consumer_site - jwt_token = ResourceAccessTokenFactory(resource=video2.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video2.playlist) anonymous_id = uuid.uuid4() # With the same email but other video, livesession is possible @@ -1205,7 +1205,7 @@ def test_api_livesession_create_token_lti_same_email_different_video( lti_id="Maths", lti_user_id="56255f3807599c377bf0e5bf072359fd", ) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video2.playlist, context_id=live_session.lti_id, consumer_site=str(video.playlist.consumer_site.id), @@ -1259,7 +1259,7 @@ def test_api_livesession_create_username_doesnt_change( starting_at=timezone.now() + timedelta(days=100), ) self.assertTrue(video.is_scheduled) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, context_id="Maths", consumer_site=str(video.playlist.consumer_site.id), @@ -1389,7 +1389,7 @@ def test_api_livesession_create_role_none_email_empty(self): ) self.assertTrue(video.is_scheduled) # token with context_id - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, context_id=str(video.playlist.lti_id), consumer_site=str(video.playlist.consumer_site.id), @@ -1438,7 +1438,7 @@ def test_api_livesession_send_mail_i18n(self): self.assertTrue(video.is_scheduled) other_playlist = PlaylistFactory() # token has different context_id than the video - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=str(video.playlist.consumer_site.id), context_id=str(other_playlist.lti_id), diff --git a/src/backend/marsha/core/tests/api/live_sessions/test_display_name.py b/src/backend/marsha/core/tests/api/live_sessions/test_display_name.py index d5a385fc4a..eff8137267 100644 --- a/src/backend/marsha/core/tests/api/live_sessions/test_display_name.py +++ b/src/backend/marsha/core/tests/api/live_sessions/test_display_name.py @@ -15,8 +15,8 @@ from marsha.core.models import ADMINISTRATOR, INSTRUCTOR, STUDENT, LiveSession from marsha.core.simple_jwt.factories import ( LiveSessionLtiTokenFactory, - LTIResourceAccessTokenFactory, - ResourceAccessTokenFactory, + LTIPlaylistAccessTokenFactory, + PlaylistAccessTokenFactory, UserAccessTokenFactory, ) @@ -152,7 +152,7 @@ def test_api_livesession_put_username_public_no_anonymous( ): """Field anonymous_id is mandatory when the JWT token is a public one.""" video = VideoFactory() - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.put( self._put_url(video), {"display_name": "Antoine"}, @@ -167,7 +167,7 @@ def test_api_livesession_put_username_public_no_anonymous_no_displayname( ): """Field display_name is mandatory.""" video = VideoFactory() - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.put( self._put_url(video), {"anonymous_id": uuid.uuid4()}, @@ -188,7 +188,7 @@ def test_api_livesession_put_username_public_session_existing( ) self.assertEqual(LiveSession.objects.count(), 1) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.put( self._put_url(video), {"anonymous_id": anonymous_id, "display_name": "Antoine"}, @@ -232,7 +232,7 @@ def test_api_livesession_put_username_public_session_exists_other_video( live_session = AnonymousLiveSessionFactory(display_name="Samuel", video=video2) self.assertEqual(LiveSession.objects.count(), 1) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.put( self._put_url(video), {"anonymous_id": live_session.anonymous_id, "display_name": "Antoine"}, @@ -274,7 +274,7 @@ def test_api_livesession_put_username_public_session_no( anonymous_id = uuid.uuid4() self.assertEqual(LiveSession.objects.count(), 0) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.put( self._put_url(video), {"anonymous_id": anonymous_id, "display_name": "Antoine"}, @@ -315,7 +315,7 @@ def test_api_livesession_put_username_public_already_exists( video = VideoFactory() AnonymousLiveSessionFactory(display_name="Samuel", video=video) self.assertEqual(LiveSession.objects.count(), 1) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.put( self._put_url(video), {"anonymous_id": uuid.uuid4(), "display_name": "Samuel"}, @@ -331,7 +331,7 @@ def test_api_livesession_put_username_public_already_exists( def test_api_livesession_put_username_lti_no_displayname(self): """Field display_name is mandatory.""" video = VideoFactory() - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=str(video.playlist.consumer_site.id), ) @@ -417,7 +417,7 @@ def test_api_livesession_put_username_lti_session_exists_other_video(self): ) self.assertEqual(LiveSession.objects.count(), 1) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=str(live_session.consumer_site.id), context_id=live_session.lti_id, @@ -462,7 +462,7 @@ def test_api_livesession_put_username_lti_session_no(self): video = VideoFactory() self.assertEqual(LiveSession.objects.count(), 0) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=str(video.playlist.consumer_site.id), context_id="Maths", @@ -510,7 +510,7 @@ def test_api_livesession_put_username_lti_already_exists( video = VideoFactory() AnonymousLiveSessionFactory(display_name="Samuel", video=video) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=str(video.playlist.consumer_site.id), ) diff --git a/src/backend/marsha/core/tests/api/live_sessions/test_list.py b/src/backend/marsha/core/tests/api/live_sessions/test_list.py index a9b4e678ef..fb94c08edf 100644 --- a/src/backend/marsha/core/tests/api/live_sessions/test_list.py +++ b/src/backend/marsha/core/tests/api/live_sessions/test_list.py @@ -22,8 +22,8 @@ from marsha.core.simple_jwt.factories import ( InstructorOrAdminLtiTokenFactory, LiveSessionLtiTokenFactory, - LiveSessionResourceAccessTokenFactory, - ResourceAccessTokenFactory, + LiveSessionPlaylistAccessTokenFactory, + PlaylistAccessTokenFactory, UserAccessTokenFactory, ) @@ -231,7 +231,7 @@ def test_list_livesession_public_token(self): AnonymousLiveSessionFactory(email=user.email, video=video2) # public token - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.get( self._get_url(video), HTTP_AUTHORIZATION=f"Bearer {jwt_token}", @@ -245,7 +245,7 @@ def test_api_livesession_list_throttling(self): # first 3 requests shouldn't be throttled for _i in range(3): video = VideoFactory() - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.get( f"{self._get_url(video)}?anonymous_id={uuid.uuid4()}", @@ -293,7 +293,7 @@ def test_api_livesession_list_throttling_no_anonymous(self): # first 3 requests shouldn't be throttled for _i in range(3): video = VideoFactory() - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.get( self._get_url(video), @@ -346,7 +346,7 @@ def test_list_livesession_public_token_anonymous(self): ) # public token - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.get( f"{self._get_url(video)}?anonymous_id={livesession.anonymous_id}", HTTP_AUTHORIZATION=f"Bearer {jwt_token}", @@ -640,7 +640,7 @@ def test_list_livesession_token_lti_wrong_is_registered_field(self): ) # token has context_id and no email - jwt_token = LiveSessionResourceAccessTokenFactory(live_session=live_session) + jwt_token = LiveSessionPlaylistAccessTokenFactory(live_session=live_session) response = self.client.get( f"{self._get_url(video)}?is_registered=True", HTTP_AUTHORIZATION=f"Bearer {jwt_token}", diff --git a/src/backend/marsha/core/tests/api/live_sessions/test_push_attendance.py b/src/backend/marsha/core/tests/api/live_sessions/test_push_attendance.py index 2de44fb8de..a1536a10f3 100644 --- a/src/backend/marsha/core/tests/api/live_sessions/test_push_attendance.py +++ b/src/backend/marsha/core/tests/api/live_sessions/test_push_attendance.py @@ -18,8 +18,8 @@ from marsha.core.models import ADMINISTRATOR, INSTRUCTOR, STUDENT, LiveSession from marsha.core.simple_jwt.factories import ( LiveSessionLtiTokenFactory, - LTIResourceAccessTokenFactory, - ResourceAccessTokenFactory, + LTIPlaylistAccessTokenFactory, + PlaylistAccessTokenFactory, UserAccessTokenFactory, ) from marsha.core.utils.time_utils import to_timestamp @@ -183,7 +183,7 @@ def test_api_livesession_post_attendance_no_payload(self): def test_api_livesession_post_attendance_no_attendance(self): """Request without attendance should raise an error.""" video = VideoFactory() - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, context_id=str(video.playlist.lti_id), consumer_site=str(video.playlist.consumer_site.id), @@ -204,7 +204,7 @@ def test_api_livesession_post_attendance_token_lti_consumer_site_not_existing( ): """Pushing an attendance on a not existing video should fail.""" video = VideoFactory() - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, context_id=str(video.playlist.lti_id), user__email=None, @@ -226,7 +226,7 @@ def test_api_livesession_post_attendance_token_lti_email_none_previous_none( ): """Endpoint push_attendance works with no email and no previous record.""" video = VideoFactory() - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, context_id=str(video.playlist.lti_id), consumer_site=str(video.playlist.consumer_site.id), @@ -286,7 +286,7 @@ def test_api_livesession_post_attendance_token_lti_existing_record(self): video=video, ) self.assertEqual(LiveSession.objects.count(), 1) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, context_id=str(livesession.lti_id), consumer_site=str(video.playlist.consumer_site.id), @@ -344,7 +344,7 @@ def test_api_livesession_post_new_attendance_token_public_unexisting_video( """Pushing an attendance on a not existing video should fail""" anonymous_id = uuid.uuid4() self.assertEqual(LiveSession.objects.count(), 0) - jwt_token = ResourceAccessTokenFactory() + jwt_token = PlaylistAccessTokenFactory() response = self.client.post( f"/api/videos/unexisting/livesessions/push_attendance/?anonymous_id={anonymous_id}", {"live_attendance": {}}, @@ -359,7 +359,7 @@ def test_api_livesession_post_new_attendance_token_public(self): video = VideoFactory() anonymous_id = uuid.uuid4() self.assertEqual(LiveSession.objects.count(), 0) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.post( f"/api/videos/{video.id}/livesessions/push_attendance/?anonymous_id={anonymous_id}", {"language": "fr", "live_attendance": {}}, @@ -395,7 +395,7 @@ def test_api_livesession_post_attendance_existing_token_public(self): self.assertEqual(LiveSession.objects.count(), 1) timestamp = to_timestamp(timezone.now()) - jwt_token = ResourceAccessTokenFactory(resource=livesession.video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=livesession.video.playlist) response = self.client.post( f"/api/videos/{livesession.video_id}/livesessions/push_attendance/" f"?anonymous_id={livesession.anonymous_id}", @@ -447,7 +447,7 @@ def test_api_livesession_post_attendance_token_public_missing_anonymous_id(self) self.assertEqual(LiveSession.objects.count(), 0) timestamp = to_timestamp(timezone.now()) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.post( self._post_url(video), { @@ -799,7 +799,7 @@ def test_api_livesession_post_attendance_token_with_could_match_other_records( nb_created = 6 self.assertEqual(LiveSession.objects.count(), nb_created) # token with same email - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=str(video.playlist.consumer_site.id), context_id="Maths", diff --git a/src/backend/marsha/core/tests/api/live_sessions/test_retrieve.py b/src/backend/marsha/core/tests/api/live_sessions/test_retrieve.py index f6625bfddc..88d4a6df75 100644 --- a/src/backend/marsha/core/tests/api/live_sessions/test_retrieve.py +++ b/src/backend/marsha/core/tests/api/live_sessions/test_retrieve.py @@ -19,9 +19,9 @@ from marsha.core.simple_jwt.factories import ( InstructorOrAdminLtiTokenFactory, LiveSessionLtiTokenFactory, - LiveSessionResourceAccessTokenFactory, - LTIResourceAccessTokenFactory, - ResourceAccessTokenFactory, + LiveSessionPlaylistAccessTokenFactory, + LTIPlaylistAccessTokenFactory, + PlaylistAccessTokenFactory, UserAccessTokenFactory, ) @@ -181,7 +181,7 @@ def test_api_livesession_read_token_public(self): video = VideoFactory() livesession = AnonymousLiveSessionFactory(video=video) # token has no consumer_site, no context_id and no user's info - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.get( self._get_url(livesession.video, livesession), @@ -200,7 +200,7 @@ def test_api_livesession_read_token_public_with_anonymous(self): """ livesession = AnonymousLiveSessionFactory() # token has no consumer_site, no context_id and no user's info - jwt_token = ResourceAccessTokenFactory(resource=livesession.video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=livesession.video.playlist) response = self.client.get( f"{self._get_url(livesession.video, livesession)}" @@ -241,7 +241,7 @@ def test_api_livesession_read_token_lti_email_set(self): lti_user_id="56255f3807599c377bf0e5bf072359fd", ) # token from LTI has context_id, consumer_site and user.id - jwt_token = LiveSessionResourceAccessTokenFactory(live_session=livesession) + jwt_token = LiveSessionPlaylistAccessTokenFactory(live_session=livesession) response = self.client.get( self._get_url(livesession.video, livesession), HTTP_AUTHORIZATION=f"Bearer {jwt_token}", @@ -281,7 +281,7 @@ def test_api_livesession_read_token_lti_email_none( ) # token with right context_id and lti_user_id - jwt_token = LiveSessionResourceAccessTokenFactory(live_session=livesession) + jwt_token = LiveSessionPlaylistAccessTokenFactory(live_session=livesession) response = self.client.get( self._get_url(livesession.video, livesession), @@ -365,7 +365,7 @@ def test_api_livesession_read_token_lti_record_consumer_none(self): livesession = AnonymousLiveSessionFactory() # token has context_id so different consumer_site - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=livesession.video.playlist, # as usual roles=[random.choice([STUDENT, NONE])], user__email=livesession.email, # as usual @@ -749,7 +749,7 @@ def test_api_livesession_read_token_public_wrong_video_token(self): livesession = AnonymousLiveSessionFactory() # token with no context_id leading to the same undefined consumer_site - jwt_token = ResourceAccessTokenFactory() + jwt_token = PlaylistAccessTokenFactory() response = self.client.get( self._get_url(livesession.video, livesession), @@ -762,7 +762,7 @@ def test_api_livesession_read_token_lti_wrong_video_token(self): # livesession with consumer_site livesession = LiveSessionFactory(is_from_lti_connection=True) # token with unexisting consumer_site - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( context_id=str(livesession.video.playlist.lti_id), consumer_site=str(livesession.video.playlist.consumer_site.id), user__email=None, @@ -779,7 +779,7 @@ def test_api_livesession_read_token_public_other_video_context_none_role(self): livesession = AnonymousLiveSessionFactory() # token with no context_id leading to the same undefined consumer_site - jwt_token = ResourceAccessTokenFactory(resource=VideoFactory().playlist) + jwt_token = PlaylistAccessTokenFactory(resource=VideoFactory().playlist) response = self.client.get( self._get_url(livesession.video, livesession), @@ -792,7 +792,7 @@ def test_api_livesession_read_token_lti_other_video_context_none_role(self): # livesession with no consumer_site livesession = LiveSessionFactory(is_from_lti_connection=True) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=VideoFactory().playlist, # other video context_id=str(livesession.video.playlist.lti_id), consumer_site=str(livesession.video.playlist.consumer_site.id), @@ -812,7 +812,7 @@ def test_api_livesession_read_detail_unknown_video(self): video = VideoFactory(live_state=IDLE, live_type=RAW, starting_at=starting_at) livesession = AnonymousLiveSessionFactory(video=video) # token with no user information - jwt_token = ResourceAccessTokenFactory() + jwt_token = PlaylistAccessTokenFactory() response = self.client.get( self._get_url(livesession.video, livesession), content_type="application/json", diff --git a/src/backend/marsha/core/tests/api/live_sessions/test_update.py b/src/backend/marsha/core/tests/api/live_sessions/test_update.py index 02de338b31..b7e0a7ed20 100644 --- a/src/backend/marsha/core/tests/api/live_sessions/test_update.py +++ b/src/backend/marsha/core/tests/api/live_sessions/test_update.py @@ -22,8 +22,8 @@ from marsha.core.simple_jwt.factories import ( InstructorOrAdminLtiTokenFactory, LiveSessionLtiTokenFactory, - LTIResourceAccessTokenFactory, - ResourceAccessTokenFactory, + LTIPlaylistAccessTokenFactory, + PlaylistAccessTokenFactory, UserAccessTokenFactory, ) @@ -210,7 +210,7 @@ def test_api_livesession_update_put_with_token_not_allowed(self): starting_at=timezone.now() + timedelta(days=100), ) live_session = AnonymousLiveSessionFactory(video=video) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) response = self.client.put( self._update_url(video, live_session), @@ -233,7 +233,7 @@ def test_api_livesession_put_not_allowed(self): video=video, ) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( resource=video.playlist, consumer_site=str(video.playlist.consumer_site.id), context_id=live_session.lti_id, @@ -732,7 +732,7 @@ def test_api_livesession_patch_email_from_anonymous_livesession(self): ) self.assertIsNone(live_session.registered_at) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) now = datetime(2022, 4, 7, tzinfo=baseTimezone.utc) with mock.patch.object(LiveSessionTimezone, "now", return_value=now): @@ -782,7 +782,7 @@ def test_api_livesession_update_email_with_another_anonymous_id(self): video=video, ) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) other_anonymous_id = uuid.uuid4() response = self.client.patch( @@ -813,7 +813,7 @@ def test_api_livesession_patch_language(self): self.assertIsNone(live_session.registered_at) self.assertEqual(live_session.language, "en") - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) # if a wrong language is set response = self.client.patch( diff --git a/src/backend/marsha/core/tests/simple_jwt/test_factories.py b/src/backend/marsha/core/tests/simple_jwt/test_factories.py index 13c0b3a373..269fb1b2ef 100644 --- a/src/backend/marsha/core/tests/simple_jwt/test_factories.py +++ b/src/backend/marsha/core/tests/simple_jwt/test_factories.py @@ -8,9 +8,9 @@ from marsha.core.models import INSTRUCTOR from marsha.core.simple_jwt.factories import ( LiveSessionLtiTokenFactory, - LTIResourceAccessTokenFactory, + LTIPlaylistAccessTokenFactory, ) -from marsha.core.simple_jwt.tokens import ResourceAccessToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken from marsha.core.tests.testing_utils import generate_passport_and_signed_lti_parameters @@ -44,9 +44,9 @@ def test_payload_keys(self): self.assertTrue(lti.verify()) session_id = uuid.uuid4() - jwt = ResourceAccessToken.for_lti(lti, {}, session_id, playlist_id) + jwt = PlaylistAccessToken.for_lti(lti, {}, session_id, playlist_id) - jwt_from_factory = LTIResourceAccessTokenFactory( + jwt_from_factory = LTIPlaylistAccessTokenFactory( port_to_playlist_id=playlist_id ) @@ -62,7 +62,7 @@ class LiveSessionLtiTokenFactoryTestCase(TestCase): def test_payload_keys(self): """Tests the factory generates a payload with the same keys as the original method.""" session_id = uuid.uuid4() - jwt = ResourceAccessToken.for_live_session( + jwt = PlaylistAccessToken.for_live_session( LiveSessionFactory(is_from_lti_connection=True), session_id, ) diff --git a/src/backend/marsha/core/tests/simple_jwt/test_tokens.py b/src/backend/marsha/core/tests/simple_jwt/test_tokens.py index 640946b7b8..305d932f47 100644 --- a/src/backend/marsha/core/tests/simple_jwt/test_tokens.py +++ b/src/backend/marsha/core/tests/simple_jwt/test_tokens.py @@ -10,8 +10,8 @@ from marsha.core.models import INSTRUCTOR, NONE, STUDENT from marsha.core.simple_jwt.tokens import ( LTISelectFormAccessToken, - ResourceAccessToken, - ResourceRefreshToken, + PlaylistAccessToken, + PlaylistRefreshToken, UserAccessToken, ) from marsha.core.tests.testing_utils import generate_passport_and_signed_lti_parameters @@ -91,7 +91,7 @@ def test_for_resource_id(self): session_id = str(uuid.uuid4()) resource_id = str(uuid.uuid4()) - refresh_token = ResourceRefreshToken.for_resource_id(resource_id, session_id) + refresh_token = PlaylistRefreshToken.for_resource_id(resource_id, session_id) token = refresh_token.access_token refresh_token.verify() # Must not raise @@ -108,7 +108,7 @@ def test_for_resource_id(self): ) self.assertFalse(token.payload["maintenance"]) # settings.MAINTENANCE_MODE - token = ResourceAccessToken.for_resource_id( + token = PlaylistAccessToken.for_resource_id( resource_id, session_id, roles=[STUDENT], @@ -116,7 +116,7 @@ def test_for_resource_id(self): token.verify() # Must not raise self.assertEqual(token.payload["roles"], [STUDENT]) - token = ResourceAccessToken.for_resource_id( + token = PlaylistAccessToken.for_resource_id( resource_id, session_id, locale="fr_FR", @@ -124,7 +124,7 @@ def test_for_resource_id(self): token.verify() # Must not raise self.assertEqual(token.payload["locale"], "fr_FR") - token = ResourceAccessToken.for_resource_id( + token = PlaylistAccessToken.for_resource_id( resource_id, session_id, permissions={"can_access_dashboard": True}, @@ -143,7 +143,7 @@ def test_for_lti(self): lti, passport = self.make_lti_instance(resource_id=resource_id) playlist_id = str(uuid.uuid4()) - refresh_token = ResourceRefreshToken.for_lti( + refresh_token = PlaylistRefreshToken.for_lti( lti, permissions, session_id, @@ -182,7 +182,7 @@ def test_for_lti_with_playlist(self): lti, passport = self.make_lti_instance(resource_id=resource_id) playlist_id = str(uuid.uuid4()) - refresh_token = ResourceRefreshToken.for_lti( + refresh_token = PlaylistRefreshToken.for_lti( lti, permissions, session_id, @@ -224,7 +224,7 @@ def test_for_live_session_anonymous(self): email="chantal@test-fun-mooc.fr", ) - refresh_token = ResourceRefreshToken.for_live_session(live_session, session_id) + refresh_token = PlaylistRefreshToken.for_live_session(live_session, session_id) token = refresh_token.access_token refresh_token.verify() # Must not raise @@ -264,7 +264,7 @@ def test_for_live_session_lti(self): self.assertTrue(live_session.is_from_lti_connection) - refresh_token = ResourceRefreshToken.for_live_session(live_session, session_id) + refresh_token = PlaylistRefreshToken.for_live_session(live_session, session_id) token = refresh_token.access_token refresh_token.verify() # Must not raise @@ -297,7 +297,7 @@ def test_verify_fails(self): resource_id = str(uuid.uuid4()) # Build a proper token - token = ResourceAccessToken.for_resource_id(resource_id, session_id) + token = PlaylistAccessToken.for_resource_id(resource_id, session_id) # Mess with the permissions token.payload["permissions"] = {"can_break_everything": True} diff --git a/src/backend/marsha/core/tests/test_xapi.py b/src/backend/marsha/core/tests/test_xapi.py index b1a1021a7b..ea89c8af95 100644 --- a/src/backend/marsha/core/tests/test_xapi.py +++ b/src/backend/marsha/core/tests/test_xapi.py @@ -3,7 +3,7 @@ from django.test import TestCase, override_settings -from marsha.core.simple_jwt.factories import LTIResourceAccessTokenFactory +from marsha.core.simple_jwt.factories import LTIPlaylistAccessTokenFactory from ..defaults import ENDED, RAW, READY, RUNNING from ..factories import DocumentFactory, VideoFactory @@ -27,7 +27,7 @@ def test_xapi_statement_missing_user(self): title="test video xapi", ) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( session_id="326c0689-48c1-493e-8d2d-9fb0c289de7f", context_id="course-v1:ufr+mathematics+0001", ) @@ -115,7 +115,7 @@ def test_xapi_statement_enrich_statement(self): title="test video xapi", ) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( session_id="326c0689-48c1-493e-8d2d-9fb0c289de7f", context_id="course-v1:ufr+mathematics+0001", user__id="b2584aa405540758db2a6278521b6478", @@ -204,7 +204,7 @@ def test_xapi_statement_live_video(self): live_type=RAW, ) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( session_id="326c0689-48c1-493e-8d2d-9fb0c289de7f", context_id="course-v1:ufr+mathematics+0001", user__id="b2584aa405540758db2a6278521b6478", @@ -294,7 +294,7 @@ def test_xapi_statement_live_video_ended(self): upload_state=READY, ) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( session_id="326c0689-48c1-493e-8d2d-9fb0c289de7f", context_id="course-v1:ufr+mathematics+0001", user__id="b2584aa405540758db2a6278521b6478", @@ -381,7 +381,7 @@ def test_xapi_statement_missing_context_id(self): title="test video xapi", ) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( session_id="326c0689-48c1-493e-8d2d-9fb0c289de7f", ) del jwt_token.payload["user"] @@ -464,7 +464,7 @@ def test_xapi_statement_enrich_statement(self): title="test document xapi", ) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( session_id="326c0689-48c1-493e-8d2d-9fb0c289de7f", context_id="course-v1:ufr+mathematics+0001", user__id="b2584aa405540758db2a6278521b6478", @@ -541,7 +541,7 @@ def test_xapi_statement_missing_context_id(self): title="test document xapi", ) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( session_id="326c0689-48c1-493e-8d2d-9fb0c289de7f", user__id="b2584aa405540758db2a6278521b6478", ) @@ -607,7 +607,7 @@ def test_xapi_statement_missing_user_id(self): title="test document xapi", ) - jwt_token = LTIResourceAccessTokenFactory( + jwt_token = LTIPlaylistAccessTokenFactory( session_id="326c0689-48c1-493e-8d2d-9fb0c289de7f", context_id="course-v1:ufr+mathematics+0001", ) diff --git a/src/backend/marsha/core/tests/views/test_lti_base.py b/src/backend/marsha/core/tests/views/test_lti_base.py index e463c9587a..4182505052 100644 --- a/src/backend/marsha/core/tests/views/test_lti_base.py +++ b/src/backend/marsha/core/tests/views/test_lti_base.py @@ -18,7 +18,7 @@ ) from marsha.core.lti import LTI from marsha.core.models import ADMINISTRATOR, INSTRUCTOR, STUDENT, Playlist -from marsha.core.simple_jwt.tokens import LTIUserToken, ResourceAccessToken +from marsha.core.simple_jwt.tokens import LTIUserToken, PlaylistAccessToken @override_settings(SENTRY_DSN="https://sentry.dsn") @@ -140,7 +140,7 @@ def assertLTIViewReturnsPortabilityContextForAdminOrInstructor( newly_create_playlist = Playlist.objects.get(lti_id="other:lti:context") - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(jwt_token.payload["resource_id"], "") # important self.assertEqual( jwt_token.payload["port_to_playlist_id"], str(newly_create_playlist.id) @@ -186,7 +186,7 @@ def assertLTIViewReturnsPortabilityContextForAdminOrInstructor( newly_create_playlist = Playlist.objects.get(lti_id="other:lti:context") - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(jwt_token.payload["resource_id"], "") # important self.assertEqual( jwt_token.payload["port_to_playlist_id"], str(newly_create_playlist.id) diff --git a/src/backend/marsha/core/tests/views/test_lti_document.py b/src/backend/marsha/core/tests/views/test_lti_document.py index 36025d3ff7..5ffccfe8e0 100644 --- a/src/backend/marsha/core/tests/views/test_lti_document.py +++ b/src/backend/marsha/core/tests/views/test_lti_document.py @@ -24,7 +24,7 @@ ) from marsha.core.lti import LTI from marsha.core.models import ADMINISTRATOR -from marsha.core.simple_jwt.tokens import ResourceAccessToken, ResourceRefreshToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken, PlaylistRefreshToken from .test_lti_base import BaseLTIViewForPortabilityTestCase @@ -70,8 +70,8 @@ def test_views_lti_document_instructor_same_playlist( ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(document.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -135,8 +135,8 @@ def test_views_lti_document_instructor_other_playlist( ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(document.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -196,8 +196,8 @@ def test_views_lti_document_student_with_video( ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(document.playlist.id)) self.assertEqual( jwt_token.payload["user"], diff --git a/src/backend/marsha/core/tests/views/test_lti_select.py b/src/backend/marsha/core/tests/views/test_lti_select.py index 6069d7cf17..db6a175ea6 100644 --- a/src/backend/marsha/core/tests/views/test_lti_select.py +++ b/src/backend/marsha/core/tests/views/test_lti_select.py @@ -13,7 +13,7 @@ from marsha.core.defaults import ENDED, IDLE, JITSI from marsha.core.factories import DocumentFactory, PlaylistFactory, VideoFactory from marsha.core.models import Playlist -from marsha.core.simple_jwt.tokens import LTISelectFormAccessToken, ResourceAccessToken +from marsha.core.simple_jwt.tokens import LTISelectFormAccessToken, PlaylistAccessToken from marsha.core.tests.testing_utils import generate_passport_and_signed_lti_parameters @@ -142,7 +142,7 @@ def test_views_lti_select(self): lti_parameters.update({"lti_message_type": "ContentItemSelection"}) self.assertEqual(initial_jwt_token.get("lti_select_form_data"), lti_parameters) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual( jwt_token.get("permissions"), {"can_access_dashboard": False, "can_update": True}, @@ -235,7 +235,7 @@ def test_views_lti_select_video(self): lti_parameters.update({"lti_message_type": "ContentItemSelection"}) self.assertEqual(initial_jwt_token.get("lti_select_form_data"), lti_parameters) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual( jwt_token.get("permissions"), {"can_access_dashboard": False, "can_update": True}, diff --git a/src/backend/marsha/core/tests/views/test_lti_video.py b/src/backend/marsha/core/tests/views/test_lti_video.py index 59b4df871c..7db6a5b45c 100644 --- a/src/backend/marsha/core/tests/views/test_lti_video.py +++ b/src/backend/marsha/core/tests/views/test_lti_video.py @@ -38,7 +38,7 @@ ) from marsha.core.lti import LTI from marsha.core.models import ADMINISTRATOR -from marsha.core.simple_jwt.tokens import ResourceAccessToken, ResourceRefreshToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken, PlaylistRefreshToken from .test_lti_base import BaseLTIViewForPortabilityTestCase @@ -90,8 +90,8 @@ def test_views_lti_video_post_instructor(self, mock_get_consumer_site, mock_veri ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(context.get("frontend_home_url"), "https://marsha.education") self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual(jwt_token.payload["context_id"], data["context_id"]) @@ -247,8 +247,8 @@ def test_views_lti_video_instructor_live_mode_on( ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -428,8 +428,8 @@ def test_views_lti_video_instructor_live_mode_and_chat_on( ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -649,8 +649,8 @@ def test_views_lti_video_student_live_mode_on( ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -806,8 +806,8 @@ def test_views_lti_video_post_administrator( ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -922,8 +922,8 @@ def test_views_lti_video_read_other_playlist( ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual( jwt_token.payload["permissions"], {"can_access_dashboard": True, "can_update": False}, @@ -1054,8 +1054,8 @@ def test_views_lti_video_restricted_resolutions_list( ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -1194,8 +1194,8 @@ def test_views_lti_video_harvested_live_state_student( ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -1308,8 +1308,8 @@ def test_views_lti_video_harvested_live_state_instructor( ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -1450,8 +1450,8 @@ def test_views_lti_video_post_student_with_video( ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -1594,8 +1594,8 @@ def test_views_lti_video_without_user_id_parameter( ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual(jwt_token.payload["context_id"], data["context_id"]) self.assertEqual( @@ -1728,8 +1728,8 @@ def test_views_lti_video_with_timed_text(self, mock_get_consumer_site, mock_veri ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual(jwt_token.payload["context_id"], data["context_id"]) self.assertEqual( diff --git a/src/backend/marsha/core/tests/views/test_public_document.py b/src/backend/marsha/core/tests/views/test_public_document.py index fcb971d29d..9d97bf67cf 100644 --- a/src/backend/marsha/core/tests/views/test_public_document.py +++ b/src/backend/marsha/core/tests/views/test_public_document.py @@ -10,7 +10,7 @@ from marsha.core.defaults import STATE_CHOICES from marsha.core.factories import DocumentFactory, OrganizationFactory, PlaylistFactory -from marsha.core.simple_jwt.tokens import ResourceAccessToken, ResourceRefreshToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken, PlaylistRefreshToken # We don't enforce arguments documentation in tests @@ -58,8 +58,8 @@ def test_document_publicly_accessible(self): ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual( jwt_token.payload["permissions"], @@ -138,8 +138,8 @@ def test_public_document_without_consumer_site(self): ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual( jwt_token.payload["permissions"], diff --git a/src/backend/marsha/core/tests/views/test_public_video.py b/src/backend/marsha/core/tests/views/test_public_video.py index e467c4af31..ff91f68009 100644 --- a/src/backend/marsha/core/tests/views/test_public_video.py +++ b/src/backend/marsha/core/tests/views/test_public_video.py @@ -23,7 +23,7 @@ PlaylistFactory, VideoFactory, ) -from marsha.core.simple_jwt.tokens import ResourceAccessToken, ResourceRefreshToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken, PlaylistRefreshToken # We don't enforce arguments documentation in tests @@ -73,8 +73,8 @@ def test_video_publicly_accessible(self): ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual( jwt_token.payload["permissions"], @@ -283,8 +283,8 @@ def test_video_live_publicly_available(self): ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual( jwt_token.payload["permissions"], @@ -388,8 +388,8 @@ def test_video_accessible_from_mail(self): ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual( jwt_token.payload["permissions"], @@ -438,8 +438,8 @@ def test_video_ressource_public_accessible_from_mail(self): ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual( jwt_token.payload["permissions"], @@ -565,8 +565,8 @@ def test_video_public_without_consumer_site(self): ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) - ResourceRefreshToken(context.get("refresh_token")) # Must not raise + jwt_token = PlaylistAccessToken(context.get("jwt")) + PlaylistRefreshToken(context.get("refresh_token")) # Must not raise self.assertEqual( jwt_token.payload["permissions"], diff --git a/src/backend/marsha/core/views.py b/src/backend/marsha/core/views.py index 75c8922624..ebc94c5027 100644 --- a/src/backend/marsha/core/views.py +++ b/src/backend/marsha/core/views.py @@ -38,7 +38,7 @@ from marsha.core.simple_jwt.tokens import ( LTISelectFormAccessToken, LTIUserToken, - ResourceRefreshToken, + PlaylistRefreshToken, ) from marsha.core.utils.lti_select_utils import get_lti_select_resources @@ -504,7 +504,7 @@ def _get_app_data(self): "redirect_to": redirect_to, "portability_request_exists": portability_request_exists, } - refresh_token = ResourceRefreshToken.for_lti_portability_request( + refresh_token = PlaylistRefreshToken.for_lti_portability_request( lti=self.lti, session_id=session_id, port_to_playlist_id=str(destination_playlist.pk), @@ -535,7 +535,7 @@ def _get_app_data(self): cache.set(self.cache_key, app_data, settings.APP_DATA_CACHE_DURATION) if app_data["resource"] is not None: - refresh_token = ResourceRefreshToken.for_lti( + refresh_token = PlaylistRefreshToken.for_lti( lti=self.lti, permissions=permissions, session_id=session_id, @@ -620,7 +620,7 @@ def _get_app_data(self): ) if app_data["resource"] is not None: - refresh_token = ResourceRefreshToken.for_resource_id( + refresh_token = PlaylistRefreshToken.for_resource_id( resource_id=app_data["resource"]["id"], session_id=session_id, ) @@ -745,7 +745,7 @@ def get_direct_access_from_livesession(self, video_pk, livesession_pk, key): ) cache.set(cache_key, app_data, settings.APP_DATA_CACHE_DURATION) - refresh_token = ResourceRefreshToken.for_live_session(livesession, session_id) + refresh_token = PlaylistRefreshToken.for_live_session(livesession, session_id) jwt_token = refresh_token.access_token app_data["jwt"] = str(jwt_token) app_data["refresh_token"] = str(refresh_token) @@ -938,7 +938,7 @@ def _get_app_data(self): if self.request.POST.get("title") != settings.LTI_CONFIG_TITLE: activity_title = self.request.POST.get("title") - refresh_token = ResourceRefreshToken.for_lti( + refresh_token = PlaylistRefreshToken.for_lti( lti=self.lti, permissions={"can_access_dashboard": False, "can_update": True}, session_id=str(uuid.uuid4()), diff --git a/src/backend/marsha/deposit/tests/test_views_lti.py b/src/backend/marsha/deposit/tests/test_views_lti.py index 2995fa2159..e5e7ec1773 100644 --- a/src/backend/marsha/deposit/tests/test_views_lti.py +++ b/src/backend/marsha/deposit/tests/test_views_lti.py @@ -17,7 +17,7 @@ UserFactory, ) from marsha.core.lti import LTI -from marsha.core.simple_jwt.tokens import ResourceAccessToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken from marsha.core.tests.testing_utils import reload_urlconf from marsha.core.tests.views.test_lti_base import BaseLTIViewForPortabilityTestCase from marsha.core.utils.lti_select_utils import get_lti_select_resources @@ -77,7 +77,7 @@ def test_views_lti_file_depository_student( ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(context.get("state"), "success") self.assertIsNotNone(context.get("resource")) self.assertEqual(context.get("modelName"), "filedepositories") @@ -130,7 +130,7 @@ def test_views_lti_file_depository_student_legacy( ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(context.get("state"), "success") self.assertIsNotNone(context.get("resource")) self.assertEqual(context.get("modelName"), "filedepositories") @@ -218,7 +218,7 @@ def test_views_lti_file_depository_instructor_same_playlist( ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual( jwt_token.payload["resource_id"], str(file_depository.playlist.id) ) diff --git a/src/backend/marsha/development/tests/test_views_lti_development.py b/src/backend/marsha/development/tests/test_views_lti_development.py index fb7a486875..94afcee524 100644 --- a/src/backend/marsha/development/tests/test_views_lti_development.py +++ b/src/backend/marsha/development/tests/test_views_lti_development.py @@ -11,7 +11,7 @@ from marsha.core.defaults import STATE_CHOICES from marsha.core.factories import VideoFactory from marsha.core.models import ConsumerSite, Video -from marsha.core.simple_jwt.tokens import ResourceAccessToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken # We don't enforce arguments documentation in tests @@ -66,7 +66,7 @@ def test_views_lti_development_post_bypass_lti_student(self): ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -120,7 +120,7 @@ def test_views_lti_development_post_bypass_lti_instructor(self): ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual( jwt_token.payload["user"], @@ -212,7 +212,7 @@ def test_views_lti_development_post_bypass_lti_instructor_no_video(self): ) context = json.loads(unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) video = Video.objects.get() self.assertEqual(jwt_token.payload["resource_id"], str(video.playlist.id)) self.assertEqual( diff --git a/src/backend/marsha/markdown/tests/test_views_lti.py b/src/backend/marsha/markdown/tests/test_views_lti.py index 9fd6fa709b..3e3ae41402 100644 --- a/src/backend/marsha/markdown/tests/test_views_lti.py +++ b/src/backend/marsha/markdown/tests/test_views_lti.py @@ -18,7 +18,7 @@ ) from marsha.core.lti import LTI from marsha.core.models import ADMINISTRATOR -from marsha.core.simple_jwt.tokens import ResourceAccessToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken from marsha.core.tests.views.test_lti_base import BaseLTIViewForPortabilityTestCase from marsha.markdown.factories import MarkdownDocumentFactory @@ -66,7 +66,7 @@ def test_views_lti_markdown_document_student( ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual(context.get("state"), "success") self.assertIsNotNone(context.get("resource")) self.assertEqual(context.get("modelName"), "markdown-documents") @@ -156,7 +156,7 @@ def test_views_lti_markdown_document_instructor_same_playlist( ) context = json.loads(html.unescape(match.group(1))) - jwt_token = ResourceAccessToken(context.get("jwt")) + jwt_token = PlaylistAccessToken(context.get("jwt")) self.assertEqual( jwt_token.payload["resource_id"], str(markdown_document.playlist.id) ) diff --git a/src/backend/marsha/settings.py b/src/backend/marsha/settings.py index 6dd5112fcf..843f76312c 100644 --- a/src/backend/marsha/settings.py +++ b/src/backend/marsha/settings.py @@ -208,7 +208,7 @@ class Base(Configuration): REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ( - "marsha.core.simple_jwt.authentication.JWTStatelessUserOrResourceAuthentication", + "marsha.core.simple_jwt.authentication.JWTStatelessUserOrPlaylistAuthentication", ), "EXCEPTION_HANDLER": "marsha.core.views.exception_handler", "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination", @@ -760,11 +760,11 @@ def SIMPLE_JWT(self): "AUTH_TOKEN_CLASSES": ( "rest_framework_simplejwt.tokens.AccessToken", "marsha.core.simple_jwt.tokens.ChallengeToken", - # For now ResourceAccessToken & UserAccessToken are also AccessToken + # For now PlaylistAccessToken & UserAccessToken are also AccessToken # but this will allow migration when types will differ. # Note: AccessToken must remain enabled during the migration and removed # only after (version N changes token types, N+1 removes AccessToken). - "marsha.core.simple_jwt.tokens.ResourceAccessToken", + "marsha.core.simple_jwt.tokens.PlaylistAccessToken", "marsha.core.simple_jwt.tokens.UserAccessToken", ), # Settings for authentication API diff --git a/src/backend/marsha/websocket/consumers/video.py b/src/backend/marsha/websocket/consumers/video.py index 97379f9c79..38181061bb 100644 --- a/src/backend/marsha/websocket/consumers/video.py +++ b/src/backend/marsha/websocket/consumers/video.py @@ -16,7 +16,7 @@ ) from marsha.core.permissions import IsTokenAdmin, IsTokenInstructor from marsha.core.services import live_session as LiveSessionServices -from marsha.core.simple_jwt.tokens import ResourceAccessToken, UserAccessToken +from marsha.core.simple_jwt.tokens import PlaylistAccessToken, UserAccessToken from marsha.websocket import defaults @@ -43,7 +43,7 @@ async def _check_permissions(self): # Check permissions, MUST be the same as in the `retrieve` method # of the Video API view set. - if isinstance(token, ResourceAccessToken): + if isinstance(token, PlaylistAccessToken): # With LTI: anyone with a valid token for the video can access if not await self._has_access_to_video(token): raise ConnectionRefusedError() @@ -155,7 +155,7 @@ async def _is_admin(self): if not token: return False - if isinstance(token, ResourceAccessToken): + if isinstance(token, PlaylistAccessToken): return IsTokenInstructor().check_role(token) or IsTokenAdmin().check_role( token ) diff --git a/src/backend/marsha/websocket/tests/test_consumers_video.py b/src/backend/marsha/websocket/tests/test_consumers_video.py index d51193139d..4f7866717d 100644 --- a/src/backend/marsha/websocket/tests/test_consumers_video.py +++ b/src/backend/marsha/websocket/tests/test_consumers_video.py @@ -29,8 +29,8 @@ ) from marsha.core.simple_jwt.factories import ( InstructorOrAdminLtiTokenFactory, - LiveSessionResourceAccessTokenFactory, - ResourceAccessTokenFactory, + LiveSessionPlaylistAccessTokenFactory, + PlaylistAccessTokenFactory, StudentLtiTokenFactory, UserAccessTokenFactory, ) @@ -270,7 +270,7 @@ async def test_connect_matching_video_student(self): self.assertIsNone(live_session.channel_name) - jwt_token = LiveSessionResourceAccessTokenFactory(live_session=live_session) + jwt_token = LiveSessionPlaylistAccessTokenFactory(live_session=live_session) communicator = WebsocketCommunicator( base_application, @@ -300,7 +300,7 @@ async def test_connect_matching_video_anonymous(self): self.assertIsNone(live_session.channel_name) - jwt_token = ResourceAccessTokenFactory(resource=video.playlist) + jwt_token = PlaylistAccessTokenFactory(resource=video.playlist) communicator = WebsocketCommunicator( base_application, diff --git a/src/backend/marsha/websocket/tests/test_middleware_jwt.py b/src/backend/marsha/websocket/tests/test_middleware_jwt.py index c635c9efc9..e8293738b1 100644 --- a/src/backend/marsha/websocket/tests/test_middleware_jwt.py +++ b/src/backend/marsha/websocket/tests/test_middleware_jwt.py @@ -7,7 +7,7 @@ from channels.generic.websocket import AsyncWebsocketConsumer from channels.testing import WebsocketCommunicator -from marsha.core.simple_jwt.factories import ResourceAccessTokenFactory +from marsha.core.simple_jwt.factories import PlaylistAccessTokenFactory from marsha.websocket.middlewares import JWTMiddleware @@ -28,7 +28,7 @@ async def test_missing_token(self): async def test_invalid_token(self): """With an invalid token the connection is refused.""" - token = ResourceAccessTokenFactory() + token = PlaylistAccessTokenFactory() token.set_exp( from_time=timezone.now() - timedelta(minutes=30), lifetime=timedelta(minutes=1), @@ -48,7 +48,7 @@ async def test_invalid_token(self): async def test_valid_token(self): """With a valid token the connection is accepted.""" - token = ResourceAccessTokenFactory() + token = PlaylistAccessTokenFactory() token.set_exp(lifetime=timedelta(minutes=20)) application = JWTMiddleware(AsyncWebsocketConsumer())