Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️(backend) rename playlist tokens #2377

Merged
merged 6 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class {{cookiecutter.model}}ViewSet(
queryset = {{cookiecutter.model}}.objects.all()
serializer_class = serializers.{{cookiecutter.model}}Serializer
permission_classes = [
core_permissions.IsTokenResourceRouteObject
core_permissions.IsTokenPlaylistRouteObject
& (core_permissions.IsTokenInstructor | core_permissions.IsTokenAdmin)
]

Expand All @@ -44,7 +44,7 @@ def get_permissions(self):
& (core_permissions.IsTokenInstructor | core_permissions.IsTokenAdmin)
]
elif self.action in ["retrieve"]:
permission_classes = [core_permissions.IsTokenResourceRouteObject]
permission_classes = [core_permissions.IsTokenPlaylistRouteObject]
else:
permission_classes = self.permission_classes
return [permission() for permission in permission_classes]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def test_api_{{cookiecutter.model_lower}}_fetch_list_student(self):
{{cookiecutter.model_lower}} = {{cookiecutter.model}}Factory()

jwt_token = StudentLtiTokenFactory(
resource={{cookiecutter.model_lower}},
playlist={{cookiecutter.model_lower}}.playlist,
permissions__can_update=True,
)

Expand All @@ -55,7 +55,7 @@ def test_api_{{cookiecutter.model_lower}}_fetch_list_instructor(self):
"""An instructor should not be able to fetch a {{cookiecutter.model_lower}} list."""
{{cookiecutter.model_lower}} = {{cookiecutter.model}}Factory()

jwt_token = InstructorOrAdminLtiTokenFactory(resource={{cookiecutter.model_lower}})
jwt_token = InstructorOrAdminLtiTokenFactory(playlist={{cookiecutter.model_lower}}.playlist)

response = self.client.get(
"/api/{{cookiecutter.model_url_part}}/", HTTP_AUTHORIZATION=f"Bearer {jwt_token}"
Expand All @@ -66,7 +66,7 @@ def test_api_{{cookiecutter.model_lower}}_fetch_student(self):
"""A student should be allowed to fetch a {{cookiecutter.model_lower}}."""
{{cookiecutter.model_lower}} = {{cookiecutter.model}}Factory()

jwt_token = StudentLtiTokenFactory(resource={{cookiecutter.model_lower}})
jwt_token = StudentLtiTokenFactory(playlist={{cookiecutter.model_lower}}.playlist)

response = self.client.get(
f"/api/{{cookiecutter.model_url_part}}/{ {{cookiecutter.model_lower}}.id!s}/",
Expand Down Expand Up @@ -95,7 +95,7 @@ def test_api_{{cookiecutter.model_lower}}_fetch_from_other_{{cookiecutter.model_
other_{{cookiecutter.model_lower}} = {{cookiecutter.model}}Factory()


jwt_token = StudentLtiTokenFactory(resource=other_{{cookiecutter.model_lower}})
jwt_token = StudentLtiTokenFactory(playlist=other_{{cookiecutter.model_lower}}.playlist)

response = self.client.get(
f"/api/{{cookiecutter.model_url_part}}/{ {{cookiecutter.model_lower}}.id!s}/",
Expand All @@ -107,7 +107,7 @@ def test_api_{{cookiecutter.model_lower}}_fetch_instructor(self):
"""An instructor should be able to fetch a {{cookiecutter.model_lower}}."""
{{cookiecutter.model_lower}} = {{cookiecutter.model}}Factory()

jwt_token = InstructorOrAdminLtiTokenFactory(resource={{cookiecutter.model_lower}})
jwt_token = InstructorOrAdminLtiTokenFactory(playlist={{cookiecutter.model_lower}}.playlist)

response = self.client.get(
f"/api/{{cookiecutter.model_url_part}}/{ {{cookiecutter.model_lower}}.id!s}/",
Expand Down Expand Up @@ -140,7 +140,7 @@ def test_api_{{cookiecutter.model_lower}}_create_student(self):
{{cookiecutter.model_lower}} = {{cookiecutter.model}}Factory()

jwt_token = StudentLtiTokenFactory(
resource={{cookiecutter.model_lower}},
playlist={{cookiecutter.model_lower}}.playlist,
permissions__can_update=True,
)

Expand All @@ -163,7 +163,7 @@ def test_api_{{cookiecutter.model_lower}}_create_instructor(self):
"""An instructor without playlist token should not be able to create a {{cookiecutter.model_lower}}."""
{{cookiecutter.model_lower}} = {{cookiecutter.model}}Factory()

jwt_token = InstructorOrAdminLtiTokenFactory(resource={{cookiecutter.model_lower}})
jwt_token = InstructorOrAdminLtiTokenFactory(playlist={{cookiecutter.model_lower}}.playlist)

response = self.client.post(
"/api/{{cookiecutter.model_url_part}}/", HTTP_AUTHORIZATION=f"Bearer {jwt_token}"
Expand Down Expand Up @@ -230,7 +230,7 @@ def test_api_{{cookiecutter.model_lower}}_update_student(self):
"""A student user should not be able to update a {{cookiecutter.model_lower}}."""
{{cookiecutter.model_lower}} = {{cookiecutter.model}}Factory()

jwt_token = StudentLtiTokenFactory(resource={{cookiecutter.model_lower}})
jwt_token = StudentLtiTokenFactory(playlist={{cookiecutter.model_lower}}.playlist)
data = {"title": "new title"}

response = self.client.patch(
Expand All @@ -246,7 +246,7 @@ def test_api_{{cookiecutter.model_lower}}_update_instructor_read_only(self):
{{cookiecutter.model_lower}} = {{cookiecutter.model}}Factory()

jwt_token = InstructorOrAdminLtiTokenFactory(
resource={{cookiecutter.model_lower}},
playlist={{cookiecutter.model_lower}}.playlist,
permissions__can_update=False,
)
data = {"title": "new title"}
Expand All @@ -263,7 +263,7 @@ def test_api_{{cookiecutter.model_lower}}_update_instructor(self):
"""An instructor should be able to update a {{cookiecutter.model_lower}}."""
{{cookiecutter.model_lower}} = {{cookiecutter.model}}Factory()

jwt_token = InstructorOrAdminLtiTokenFactory(resource={{cookiecutter.model_lower}})
jwt_token = InstructorOrAdminLtiTokenFactory(playlist={{cookiecutter.model_lower}}.playlist)
data = {"title": "new title", "description": "Hello"}

response = self.client.patch(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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}}")
Expand Down Expand Up @@ -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"],
Expand Down
4 changes: 2 additions & 2 deletions src/backend/marsha/account/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/backend/marsha/account/tests/api/test_password_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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
Expand Down
20 changes: 10 additions & 10 deletions src/backend/marsha/account/tests/api/test_token_refresh.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

from marsha.core.factories import UserFactory
from marsha.core.simple_jwt.tokens import (
ResourceAccessToken,
ResourceRefreshToken,
PlaylistAccessToken,
PlaylistRefreshToken,
UserAccessToken,
UserRefreshToken,
)
Expand Down Expand Up @@ -86,13 +86,13 @@ def test_success_user_access(self):
# ... and new refresh token is not
new_refresh_token.verify()

def test_success_resource_access(self):
def test_success_playlist_access(self):
"""
A request with a correct resource refresh token should return a 200 with a new token pair.
A request with a correct playlist refresh token should return a 200 with a new token pair.
"""
session_id = str(uuid.uuid4())
resource_id = str(uuid.uuid4())
refresh_token = ResourceRefreshToken.for_resource_id(resource_id, session_id)
playlist_id = str(uuid.uuid4())
refresh_token = PlaylistRefreshToken.for_playlist_id(playlist_id, session_id)

response = self.client.post(
"/account/api/token/refresh/",
Expand All @@ -110,12 +110,12 @@ 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(new_token.payload["token_type"], "playlist_access")
self.assertEqual(
new_refresh_token.payload["access_token_type"], "resource_access"
new_refresh_token.payload["access_token_type"], "playlist_access"
)

# Assert old refresh token is blacklisted ...
Expand Down
18 changes: 9 additions & 9 deletions src/backend/marsha/bbb/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class ClassroomViewSet(

permission_classes = [
(
core_permissions.IsPlaylistToken
core_permissions.IsPlaylistTokenMatchingRouteObject
& (core_permissions.IsTokenInstructor | core_permissions.IsTokenAdmin)
)
| (
Expand All @@ -116,7 +116,7 @@ def get_permissions(self):
if self.action in ["create"]:
permission_classes = [
(
core_permissions.HasPlaylistToken
core_permissions.IsPlaylistToken
& (
core_permissions.IsTokenInstructor
| core_permissions.IsTokenAdmin
Expand All @@ -142,8 +142,8 @@ def get_permissions(self):
]
elif self.action in ["retrieve", "service_join"]:
permission_classes = [
core_permissions.IsPlaylistToken
| core_permissions.IsTokenResourceRouteObject # needed for invite links
core_permissions.IsPlaylistTokenMatchingRouteObject
| core_permissions.IsTokenPlaylistRouteObject # needed for invite links
| (
core_permissions.UserIsAuthenticated # asserts request.resource is None
& (
Expand Down Expand Up @@ -188,8 +188,8 @@ def get_serializer_context(self):
)
# For LTI
| (
core_permissions.ResourceIsAuthenticated
& core_permissions.IsPlaylistToken
core_permissions.PlaylistIsAuthenticated
& core_permissions.IsPlaylistTokenMatchingRouteObject
& (
core_permissions.IsTokenInstructor
| core_permissions.IsTokenAdmin
Expand Down Expand Up @@ -241,7 +241,7 @@ def create(self, request, *args, **kwargs):
methods=["get"],
detail=False,
url_path="lti-select",
permission_classes=[core_permissions.HasPlaylistToken],
permission_classes=[core_permissions.IsPlaylistToken],
)
def lti_select(self, request):
"""Get selectable content for LTI.
Expand All @@ -263,7 +263,7 @@ def lti_select(self, request):
new_url = self.request.build_absolute_uri(LTI_ROUTE)

classrooms = serializers.ClassroomSelectLTISerializer(
Classroom.objects.filter(playlist__id=request.resource.playlist_id),
Classroom.objects.filter(playlist__id=request.resource.id),
many=True,
context={"request": self.request},
).data
Expand Down Expand Up @@ -539,7 +539,7 @@ def get_permissions(self):
)
]
elif self.action in ["metadata"]:
permission_classes = [core_permissions.UserOrResourceIsAuthenticated]
permission_classes = [core_permissions.UserOrPlaylistIsAuthenticated]
else:
permission_classes = self.permission_classes
return [permission() for permission in permission_classes]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def test_api_classroom_recording_create_anonymous_unknown_recording(self):
def test_api_classroom_recording_create_vod_student(self):
"""Students should not be able to convert a recording to a VOD."""
recording = ClassroomRecordingFactory()
jwt_token = StudentLtiTokenFactory(resource=recording.classroom.playlist)
jwt_token = StudentLtiTokenFactory(playlist=recording.classroom.playlist)

with mock.patch("marsha.bbb.api.invoke_lambda_convert"):
response = self.client.post(
Expand All @@ -100,7 +100,7 @@ def test_api_classroom_recording_create_vod_instructor_or_admin(self):
started_at="2019-08-21T15:00:02Z",
)
jwt_token = InstructorOrAdminLtiTokenFactory(
resource=recording.classroom.playlist
playlist=recording.classroom.playlist
)

self.assertEqual(Video.objects.count(), 0)
Expand Down Expand Up @@ -155,7 +155,7 @@ def test_api_classroom_recording_create_vod_instructor_or_admin_unknown_recordin
started_at="2019-08-21T15:00:02Z",
)
jwt_token = InstructorOrAdminLtiTokenFactory(
resource=recording.classroom.playlist
playlist=recording.classroom.playlist
)

self.assertEqual(Video.objects.count(), 0)
Expand Down Expand Up @@ -372,7 +372,7 @@ def test_api_classroom_recording_create_vod_instructor_or_admin_inactive_convers
classroom__playlist__consumer_site__inactive_features=["vod_convert"],
)
jwt_token = InstructorOrAdminLtiTokenFactory(
resource=recording.classroom.playlist
playlist=recording.classroom.playlist
)

self.assertEqual(Video.objects.count(), 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def test_api_delete_classroom_recording_anonymous(self, delete_recording_mock):
def test_api_delete_classroom_recording_student(self, delete_recording_mock):
"""Students should not be able to delete a recording."""
recording = ClassroomRecordingFactory()
jwt_token = StudentLtiTokenFactory(resource=recording.classroom.playlist)
jwt_token = StudentLtiTokenFactory(playlist=recording.classroom.playlist)
self.assertEqual(ClassroomRecording.objects.count(), 1)

response = self.client.delete(
Expand All @@ -94,7 +94,7 @@ def test_api_delete_classroom_recording_instructor_or_admin(
started_at="2019-08-21T15:00:02Z",
)
jwt_token = InstructorOrAdminLtiTokenFactory(
resource=recording.classroom.playlist
playlist=recording.classroom.playlist
)
self.assertEqual(ClassroomRecording.objects.count(), 1)

Expand Down
Loading