Make library drop migration use playlist.library instead of user follow and resolve tests
This commit is contained in:
parent
2d6374747c
commit
bd9f31d50f
|
@ -106,7 +106,7 @@ class PrivacyLevelPermission(BasePermission):
|
|||
elif privacy_level == "me" and obj_actor == request_actor:
|
||||
return True
|
||||
|
||||
elif request_actor in obj.user.actor.get_approved_followers():
|
||||
elif request_actor in obj_actor.get_approved_followers():
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Generated by Django 4.2.9 on 2025-01-03 16:12
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.db import IntegrityError
|
||||
|
||||
from funkwhale_api.federation import utils as federation_utils
|
||||
from django.urls import reverse
|
||||
|
@ -19,7 +18,7 @@ def insert_tracks_to_playlist(apps, playlist, uploads):
|
|||
uuid=(new_uuid := uuid.uuid4()),
|
||||
fid=federation_utils.full_url(
|
||||
reverse(
|
||||
f"federation:music:playlist-tracks-detail",
|
||||
"federation:music:playlist-tracks-detail",
|
||||
kwargs={"uuid": new_uuid},
|
||||
)
|
||||
),
|
||||
|
@ -34,49 +33,36 @@ def insert_tracks_to_playlist(apps, playlist, uploads):
|
|||
def migrate_libraries_to_playlist(apps, schema_editor):
|
||||
Playlist = apps.get_model("playlists", "Playlist")
|
||||
Library = apps.get_model("music", "Library")
|
||||
LibraryFollow = apps.get_model("federation", "LibraryFollow")
|
||||
Follow = apps.get_model("federation", "Follow")
|
||||
User = apps.get_model("users", "User")
|
||||
Actor = apps.get_model("federation", "Actor")
|
||||
|
||||
# library to playlist
|
||||
for library in Library.objects.all():
|
||||
playlist = Playlist.objects.create(
|
||||
name=library.name,
|
||||
actor=library.actor,
|
||||
creation_date=library.creation_date,
|
||||
privacy_level=library.privacy_level,
|
||||
description=library.description,
|
||||
uuid=(new_uuid := uuid.uuid4()),
|
||||
fid=federation_utils.full_url(
|
||||
reverse(
|
||||
f"federation:music:playlists-detail",
|
||||
kwargs={"uuid": new_uuid},
|
||||
)
|
||||
),
|
||||
)
|
||||
playlist.save()
|
||||
try:
|
||||
playlist = Playlist.objects.create(
|
||||
name=library.name,
|
||||
library=library,
|
||||
actor=library.actor,
|
||||
creation_date=library.creation_date,
|
||||
privacy_level=library.privacy_level,
|
||||
description=library.description,
|
||||
uuid=(new_uuid := uuid.uuid4()),
|
||||
fid=federation_utils.full_url(
|
||||
reverse(
|
||||
"federation:music:playlists-detail",
|
||||
kwargs={"uuid": new_uuid},
|
||||
)
|
||||
),
|
||||
)
|
||||
playlist.save()
|
||||
|
||||
if library.uploads.all().exists():
|
||||
insert_tracks_to_playlist(apps, playlist, library.uploads.all())
|
||||
if library.uploads.all().exists():
|
||||
uploads = library.uploads.all()
|
||||
insert_tracks_to_playlist(apps, playlist, uploads)
|
||||
playlist.library.playlist_uploads.set(uploads)
|
||||
except Exception as e:
|
||||
print(f"An error occurred during library.playlist creation {e}")
|
||||
continue
|
||||
|
||||
# library follows to user follow
|
||||
for lib_follow in LibraryFollow.objects.filter(target=library):
|
||||
try:
|
||||
Follow.objects.create(
|
||||
uuid=lib_follow.uuid,
|
||||
target=library.actor,
|
||||
actor=lib_follow.actor,
|
||||
approved=lib_follow.approved,
|
||||
creation_date=lib_follow.creation_date,
|
||||
modification_date=lib_follow.modification_date,
|
||||
)
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
LibraryFollow.objects.all().delete()
|
||||
|
||||
# migrate uploads to new library
|
||||
# migrate uploads to new built-in libraries
|
||||
for actor in Actor.objects.all():
|
||||
privacy_levels = ["me", "instance", "everyone"]
|
||||
for privacy_level in privacy_levels:
|
||||
|
@ -87,23 +73,30 @@ def migrate_libraries_to_playlist(apps, schema_editor):
|
|||
uuid=(new_uuid := uuid.uuid4()),
|
||||
fid=federation_utils.full_url(
|
||||
reverse(
|
||||
f"federation:music:libraries-detail",
|
||||
"federation:music:libraries-detail",
|
||||
kwargs={"uuid": new_uuid},
|
||||
)
|
||||
),
|
||||
)
|
||||
for library in actor.libraries.filter(privacy_level=privacy_level):
|
||||
library.uploads.all().update(library=build_in_lib)
|
||||
if library.pk is not build_in_lib.pk:
|
||||
library.delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("music", "0060_empty_for_test"),
|
||||
("playlists", "0008_playlist_library_drop"),
|
||||
("playlists", "0009_playlist_library"),
|
||||
]
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="upload",
|
||||
name="playlist_libraries",
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
related_name="playlist_uploads",
|
||||
to="music.library",
|
||||
),
|
||||
),
|
||||
migrations.RunPython(
|
||||
migrate_libraries_to_playlist, reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
# Generated by Django 5.1.6 on 2025-03-09 21:58
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("music", "0063_upload_third_party_provider"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="upload",
|
||||
name="playlist_libraries",
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
null=True,
|
||||
related_name="playlist_uploads",
|
||||
to="music.library",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -830,7 +830,6 @@ class Upload(models.Model):
|
|||
playlist_libraries = models.ManyToManyField(
|
||||
"library",
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="playlist_uploads",
|
||||
)
|
||||
|
||||
|
|
|
@ -16,18 +16,21 @@ def create_playlist_libraries(apps, schema_editor):
|
|||
for playlist in Playlist.objects.all():
|
||||
library = playlist.library
|
||||
if library is None:
|
||||
library = Library.objects.create(
|
||||
name=playlist.name, privacy_level="me", actor=playlist.actor
|
||||
)
|
||||
library.save()
|
||||
playlist.library = library
|
||||
playlist.save()
|
||||
add_uploads_to_pl_library(playlist, library)
|
||||
try:
|
||||
library = Library.objects.create(
|
||||
name=playlist.name, privacy_level="me", actor=playlist.actor
|
||||
)
|
||||
library.save()
|
||||
playlist.library = library
|
||||
playlist.save()
|
||||
add_uploads_to_pl_library(playlist, library)
|
||||
except Exception as e:
|
||||
print(f"An error occurred during playlist.library creation {e}")
|
||||
continue
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("music", "0063_upload_third_party_provider"),
|
||||
("playlists", "0008_playlist_library_drop"),
|
||||
]
|
||||
|
||||
|
|
|
@ -98,9 +98,10 @@ def test_privacylevel_permission_me(
|
|||
assert check is expected
|
||||
|
||||
|
||||
# "me" expects true since the object can be private but share with followers
|
||||
@pytest.mark.parametrize(
|
||||
"privacy_level,expected",
|
||||
[("me", False), ("followers", True), ("instance", False), ("everyone", True)],
|
||||
[("me", True), ("followers", True), ("instance", False), ("everyone", True)],
|
||||
)
|
||||
def test_privacylevel_permission_followers(
|
||||
factories, api_request, anonymous_user, privacy_level, expected, mocker
|
||||
|
|
|
@ -107,8 +107,6 @@ def test_migrate_libraries_to_playlist(migrator):
|
|||
domain = Domain.objects.create()
|
||||
domain2 = Domain.objects.create(pk=2)
|
||||
actor = Actor.objects.create(name="Test Actor", domain=domain)
|
||||
existing_urls = Actor.objects.values_list("fid", flat=True)
|
||||
print(existing_urls)
|
||||
target_actor = Actor.objects.create(
|
||||
name="Test Actor 2",
|
||||
domain=domain2,
|
||||
|
@ -152,9 +150,7 @@ def test_migrate_libraries_to_playlist(migrator):
|
|||
new_apps = migrator.loader.project_state([music_final_migration]).apps
|
||||
Playlist = new_apps.get_model("playlists", "Playlist")
|
||||
PlaylistTrack = new_apps.get_model("playlists", "PlaylistTrack")
|
||||
Follow = new_apps.get_model("federation", "Follow")
|
||||
LibraryFollow = new_apps.get_model("federation", "LibraryFollow")
|
||||
Follow = new_apps.get_model("federation", "Follow")
|
||||
|
||||
# Assertions
|
||||
|
||||
|
@ -172,13 +168,17 @@ def test_migrate_libraries_to_playlist(migrator):
|
|||
for i, playlist_track in enumerate(playlist_tracks):
|
||||
assert playlist_track.track.pk == uploads[i].track.pk
|
||||
|
||||
# Verify User Follow creation
|
||||
follow = Follow.objects.get(target__pk=target_actor.pk)
|
||||
# Verify playlist.library Follow creation
|
||||
follow = LibraryFollow.objects.get(target__pk=playlist.library.pk)
|
||||
assert follow.actor.pk == actor.pk
|
||||
assert follow.approved == library_follow.approved
|
||||
assert follow.target == playlist.library
|
||||
|
||||
# Verify LibraryFollow deletion and library creation
|
||||
assert LibraryFollow.objects.count() == 0
|
||||
# Verify uploads are migrated in lib.playlist_uploads
|
||||
for upload in uploads:
|
||||
assert upload.pk in [u.pk for u in playlist.library.playlist_uploads.all()]
|
||||
assert upload.pk not in [u.pk for u in playlist.library.uploads.all()]
|
||||
assert not playlist.library.uploads.all()
|
||||
|
||||
# Test fail but works on real db I don't get why
|
||||
# no library are found in the new app
|
||||
|
|
|
@ -15,14 +15,15 @@ Users will be able to click on a "Request access to playlist audios files" butto
|
|||
|
||||
#### Backend
|
||||
|
||||
- [x] ``PlaylistViewSet` `add` `clear` `remove` update the uploads.playlist_libraries relationships
|
||||
- [x] ``PlaylistViewSet` `add` `clear` `remove` -> `schedule_scan` -> Update activity to remote -> playlist.library scan on remote
|
||||
- [x] `PlaylistViewSet` `add` `clear` `remove` update the uploads.playlist_libraries relationships
|
||||
- [x] `PlaylistViewSet` `add` `clear` `remove` -> `schedule_scan` -> Update activity to remote -> playlist.library scan on remote
|
||||
- [x] library and playlist scan delay are long (24h), force on ap update
|
||||
- [ ] make sure only owned upload are added to the playlist.library
|
||||
- [ ] update the "drop library" migrations to use the playlist.library instead of user follow
|
||||
- [x] make sure only owned upload are added to the playlist.library
|
||||
- [x] update the "drop library" migrations to use the playlist.library instead of user follow
|
||||
- [ ] make sure user get the new libraries created after library drop
|
||||
|
||||
### Follow up
|
||||
|
||||
- [ ] Finish library drop (delete libraries endpoints)
|
||||
- [ ] Playlist discovery : fetch federation endpoint for playlists
|
||||
- [ ] Playlist discovery : add the playlist to my playlist collection = follow request to playlist
|
||||
|
|
|
@ -3201,7 +3201,7 @@
|
|||
},
|
||||
"useErrorHandler": {
|
||||
"errorReportMessage": "To help us understand why it happened, please attach a detailed description of what you did that has triggered the error.",
|
||||
"errorReportTitle": "An unexpected error occured.",
|
||||
"errorReportTitle": "An unexpected error occurred.",
|
||||
"leaveFeedback": "Leave feedback",
|
||||
"unexpectedError": "An unexpected error occurred."
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue