Skip to content

Commit 5d7edb4

Browse files
committed
🐛(back) manage playlist constraint with DRF 3.15
In DRF 3.15 they added, in the serializer validator, the model constraint validation. With the playlist model, we have to force the lti_id default value and manage better in the test the constraint between organization or consumer_site existence with the lti_id. See encode/django-rest-framework#7438
1 parent 2792657 commit 5d7edb4

File tree

6 files changed

+101
-4
lines changed

6 files changed

+101
-4
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Versioning](https://semver.org/spec/v2.0.0.html).
88

99
## [Unreleased]
1010

11+
### Fixed
12+
13+
- Manage playlist constraint with DRF 3.15
14+
1115
## [5.0.0] - 2024-06-24
1216

1317
### Added
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Generated by Django 4.2.13 on 2024-07-03 14:53
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("core", "0079_timedtexttrack_process_pipeline"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="playlist",
15+
name="lti_id",
16+
field=models.CharField(
17+
blank=True,
18+
default=None,
19+
help_text="ID for synchronization with an external LTI tool",
20+
max_length=255,
21+
null=True,
22+
verbose_name="lti id",
23+
),
24+
),
25+
]

src/backend/marsha/core/models/playlist.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class Playlist(BaseModel):
7070
help_text=_("ID for synchronization with an external LTI tool"),
7171
null=True,
7272
blank=True,
73+
default=None,
7374
)
7475
organization = models.ForeignKey(
7576
to="Organization",

src/backend/marsha/core/serializers/playlist.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ class Meta:
6666
# Field consuming the `can_edit` property filled by
6767
# the `PlaylistManager` `annotate_can_edit`
6868
can_edit = serializers.BooleanField(read_only=True)
69-
lti_id = serializers.CharField(required=False)
7069

7170
def get_portable_to(self, obj):
7271
"""Getter for portable_to attribute instead of PlaylistSerializer to prevent recursion."""

src/backend/marsha/core/tests/api/playlists/test_create.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,59 @@ def test_create_playlist_by_organization_administrator(self):
201201
self.assertEqual(created_permission.user, user)
202202
self.assertEqual(created_permission.playlist, created_playlist)
203203
self.assertEqual(created_permission.role, ADMINISTRATOR)
204+
205+
def test_create_playlist_by_organization_administrator_without_lti_id(self):
206+
"""Organization administrators can create playlists without lti_id."""
207+
user = factories.UserFactory()
208+
org = factories.OrganizationFactory()
209+
factories.OrganizationAccessFactory(
210+
role=models.ADMINISTRATOR, organization=org, user=user
211+
)
212+
213+
jwt_token = UserAccessTokenFactory(user=user)
214+
215+
self.assertEqual(models.Playlist.objects.count(), 0)
216+
217+
response = self.client.post(
218+
"/api/playlists/",
219+
{
220+
"consumer_site": "",
221+
"organization": str(org.id),
222+
"title": "Some playlist",
223+
},
224+
HTTP_AUTHORIZATION=f"Bearer {jwt_token}",
225+
)
226+
self.assertEqual(models.Playlist.objects.count(), 1)
227+
228+
self.assertEqual(response.status_code, 201)
229+
created_playlist = models.Playlist.objects.first()
230+
self.assertEqual(
231+
response.json(),
232+
{
233+
"consumer_site": None,
234+
"created_by": str(user.id),
235+
"created_on": created_playlist.created_on.isoformat().replace(
236+
"+00:00", "Z"
237+
),
238+
"duplicated_from": None,
239+
"id": str(created_playlist.id),
240+
"is_portable_to_playlist": False,
241+
"is_portable_to_consumer_site": False,
242+
"is_public": False,
243+
"is_claimable": False,
244+
"lti_id": None,
245+
"organization": {
246+
"id": str(org.id),
247+
"name": org.name,
248+
},
249+
"portable_to": [],
250+
"retention_duration": None,
251+
"title": "Some playlist",
252+
"users": [str(user.id)],
253+
},
254+
)
255+
256+
created_permission = models.PlaylistAccess.objects.first()
257+
self.assertEqual(created_permission.user, user)
258+
self.assertEqual(created_permission.playlist, created_playlist)
259+
self.assertEqual(created_permission.role, ADMINISTRATOR)

src/backend/marsha/core/tests/api/playlists/test_update.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ def test_update_playlist_by_random_logged_in_user(self):
4949
def test_update_playlist_by_playlist_admin(self):
5050
"""Playlist administrators can update playlists."""
5151
user = factories.UserFactory()
52-
playlist = factories.PlaylistFactory(title="existing title")
52+
org_1 = factories.OrganizationFactory()
53+
playlist = factories.PlaylistFactory(
54+
title="existing title", organization=org_1, lti_id=None, consumer_site=None
55+
)
5356
factories.PlaylistAccessFactory(
5457
user=user, playlist=playlist, role=models.ADMINISTRATOR
5558
)
@@ -70,7 +73,13 @@ def test_update_playlist_by_playlist_admin(self):
7073
def test_update_playlist_by_playlist_instructor(self):
7174
"""Playlist instructors can update playlists."""
7275
user = factories.UserFactory()
73-
playlist = factories.PlaylistFactory(title="title for instructor")
76+
org_1 = factories.OrganizationFactory()
77+
playlist = factories.PlaylistFactory(
78+
title="title for instructor",
79+
organization=org_1,
80+
lti_id=None,
81+
consumer_site=None,
82+
)
7483
factories.PlaylistAccessFactory(
7584
user=user, playlist=playlist, role=models.INSTRUCTOR
7685
)
@@ -96,7 +105,10 @@ def test_update_playlist_by_orga_administrator(self):
96105
user=user, organization=org_1, role=models.ADMINISTRATOR
97106
)
98107
playlist = factories.PlaylistFactory(
99-
title="title for orga admin", organization=org_1
108+
title="title for orga admin",
109+
organization=org_1,
110+
lti_id=None,
111+
consumer_site=None,
100112
)
101113

102114
jwt_token = UserAccessTokenFactory(user=user)

0 commit comments

Comments
 (0)