diff --git a/api/funkwhale_api/audio/views.py b/api/funkwhale_api/audio/views.py index 91331d2f2..6d463d369 100644 --- a/api/funkwhale_api/audio/views.py +++ b/api/funkwhale_api/audio/views.py @@ -6,12 +6,14 @@ from rest_framework import response from rest_framework import viewsets from django import http +from django.db import transaction from django.db.models import Count, Prefetch from django.db.utils import IntegrityError from funkwhale_api.common import permissions from funkwhale_api.common import preferences from funkwhale_api.federation import models as federation_models +from funkwhale_api.federation import routes from funkwhale_api.music import models as music_models from funkwhale_api.music import views as music_views from funkwhale_api.users.oauth import permissions as oauth_permissions @@ -109,11 +111,13 @@ class ChannelViewSet( @decorators.action( detail=True, methods=["get"], - permission_classes=[], content_negotiation_class=renderers.PodcastRSSContentNegociation, ) def rss(self, request, *args, **kwargs): object = self.get_object() + if not object.attributed_to.is_local: + return response.Response({"detail": "Not found"}, status=404) + uploads = ( object.library.uploads.playable_by(None) .prefetch_related( @@ -142,6 +146,14 @@ class ChannelViewSet( context["actor"] = self.request.user.actor return context + @transaction.atomic + def perform_destroy(self, instance): + routes.outbox.dispatch( + {"type": "Delete", "object": {"type": instance.actor.type}}, + context={"actor": instance.actor}, + ) + instance.delete() + class SubscriptionsViewSet( ChannelsMixin, diff --git a/api/tests/audio/test_views.py b/api/tests/audio/test_views.py index 9b9cf51f1..335058f85 100644 --- a/api/tests/audio/test_views.py +++ b/api/tests/audio/test_views.py @@ -107,11 +107,13 @@ def test_channel_update_permission(logged_in_api_client, factories): assert response.status_code == 403 -def test_channel_delete(logged_in_api_client, factories): +def test_channel_delete(logged_in_api_client, factories, mocker): + actor = logged_in_api_client.user.create_actor() channel = factories["audio.Channel"](attributed_to=actor) url = reverse("api:v1:channels-detail", kwargs={"uuid": channel.uuid}) + dispatch = mocker.patch("funkwhale_api.federation.routes.outbox.dispatch") response = logged_in_api_client.delete(url) assert response.status_code == 204 @@ -119,6 +121,11 @@ def test_channel_delete(logged_in_api_client, factories): with pytest.raises(channel.DoesNotExist): channel.refresh_from_db() + dispatch.assert_called_once_with( + {"type": "Delete", "object": {"type": channel.actor.type}}, + context={"actor": channel.actor}, + ) + def test_channel_delete_permission(logged_in_api_client, factories): logged_in_api_client.user.create_actor() @@ -212,8 +219,9 @@ def test_subscriptions_all(factories, logged_in_api_client): } -def test_channel_rss_feed(factories, api_client): - channel = factories["audio.Channel"]() +def test_channel_rss_feed(factories, api_client, preferences): + preferences["common__api_authentication_required"] = False + channel = factories["audio.Channel"](local=True) upload1 = factories["music.Upload"](library=channel.library, playable=True) upload2 = factories["music.Upload"](library=channel.library, playable=True) @@ -228,3 +236,25 @@ def test_channel_rss_feed(factories, api_client): assert response.status_code == 200 assert response.data == expected assert response["Content-Type"] == "application/rss+xml" + + +def test_channel_rss_feed_remote(factories, api_client, preferences): + preferences["common__api_authentication_required"] = False + channel = factories["audio.Channel"]() + + url = reverse("api:v1:channels-rss", kwargs={"uuid": channel.uuid}) + + response = api_client.get(url) + + assert response.status_code == 404 + + +def test_channel_rss_feed_authentication_required(factories, api_client, preferences): + preferences["common__api_authentication_required"] = True + channel = factories["audio.Channel"](local=True) + + url = reverse("api:v1:channels-rss", kwargs={"uuid": channel.uuid}) + + response = api_client.get(url) + + assert response.status_code == 401