diff --git a/api/config/urls/api_v2.py b/api/config/urls/api_v2.py index a5fda5c7c..eceb85ac9 100644 --- a/api/config/urls/api_v2.py +++ b/api/config/urls/api_v2.py @@ -1,8 +1,10 @@ from django.conf.urls import include, url from funkwhale_api.common import routers as common_routers +from funkwhale_api.music.views import UploadGroupViewSet router = common_routers.OptionalSlashRouter() +router.register(r"upload-groups", UploadGroupViewSet, "upload-groups") v2_patterns = router.urls v2_patterns += [ diff --git a/api/funkwhale_api/music/migrations/0058_uploadgroup.py b/api/funkwhale_api/music/migrations/0058_uploadgroup.py new file mode 100644 index 000000000..449415560 --- /dev/null +++ b/api/funkwhale_api/music/migrations/0058_uploadgroup.py @@ -0,0 +1,32 @@ +# Generated by Django 3.2.23 on 2024-01-11 14:34 + +import datetime +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + dependencies = [ + ("music", "0057_auto_20221118_2108"), + ] + + operations = [ + migrations.CreateModel( + name="UploadGroup", + fields=[ + ( + "name", + models.CharField(default=datetime.datetime.now, max_length=255), + ), + ( + "guid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + primary_key=True, + serialize=False, + ), + ), + ], + ), + ] diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py index fca044a16..1e1b61d29 100644 --- a/api/funkwhale_api/music/models.py +++ b/api/funkwhale_api/music/models.py @@ -1431,3 +1431,8 @@ def update_request_status(sender, instance, created, **kwargs): # let's mark the request as imported since the import is over instance.import_request.status = "imported" return instance.import_request.save(update_fields=["status"]) + + +class UploadGroup(models.Model): + name = models.CharField(max_length=255, default=datetime.datetime.now) + guid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) diff --git a/api/funkwhale_api/music/serializers.py b/api/funkwhale_api/music/serializers.py index 46a118817..2dbd65336 100644 --- a/api/funkwhale_api/music/serializers.py +++ b/api/funkwhale_api/music/serializers.py @@ -850,3 +850,15 @@ class SearchResultSerializer(serializers.Serializer): tracks = TrackSerializer(many=True) albums = AlbumSerializer(many=True) tags = tags_serializers.TagSerializer(many=True) + + +class UploadGroupSerializer(serializers.ModelSerializer): + class Meta: + model = models.UploadGroup + fields = "__all__" + + name = serializers.CharField(required=False) + uploadUrl = serializers.SerializerMethodField(read_only=True) + + def get_uploadUrl(self, value): + return f"{settings.FUNKWHALE_URL}/api/v2/upload-groups/{value.guid}/uploads" diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index 282ceca24..0dd323604 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -928,3 +928,10 @@ class OembedView(views.APIView): serializer.is_valid(raise_exception=True) embed_data = serializer.save() return Response(embed_data) + + +class UploadGroupViewSet(viewsets.ModelViewSet): + permission_classes = [oauth_permissions.ScopePermission] + required_scope = "libraries" + queryset = models.UploadGroup.objects.all() + serializer_class = serializers.UploadGroupSerializer diff --git a/api/tests/music/test_urls.py b/api/tests/music/test_urls.py new file mode 100644 index 000000000..103531653 --- /dev/null +++ b/api/tests/music/test_urls.py @@ -0,0 +1,6 @@ +from django.urls import reverse + + +def test_can_resolve_upload_urls(): + url = reverse("api:v2:upload-groups-list") + assert url == "/api/v2/upload-groups" diff --git a/api/tests/music/test_views.py b/api/tests/music/test_views.py index 1e347f4b5..7aad7dac7 100644 --- a/api/tests/music/test_views.py +++ b/api/tests/music/test_views.py @@ -1590,3 +1590,33 @@ def test_fs_import_cancel_already_running( assert response.status_code == 204 assert cache.get("fs-import:status") == "canceled" + + +def test_can_create_upload_group_without_name(logged_in_api_client): + count = models.UploadGroup.objects.count() + + url = reverse("api:v2:upload-groups-list") + response = logged_in_api_client.post(url) + + assert response.status_code == 201 + assert count + 1 == models.UploadGroup.objects.count() + assert response.data.get("guid") != "" + assert response.data.get("name") != "" + assert "https://test.federation/api/v2/upload-groups/" in response.data.get( + "uploadUrl" + ) + + +def test_can_create_upload_group_with_name(logged_in_api_client): + count = models.UploadGroup.objects.count() + + url = reverse("api:v2:upload-groups-list") + response = logged_in_api_client.post(url, {"name": "Test Name"}) + + assert response.status_code == 201 + assert count + 1 == models.UploadGroup.objects.count() + assert response.data.get("guid") != "" + assert response.data.get("name") == "Test Name" + assert "https://test.federation/api/v2/upload-groups/" in response.data.get( + "uploadUrl" + )