Skip to content
Snippets Groups Projects
Commit 22c02856 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Merge branch '170-rss-auth' into 'develop'

See #170: support for auth in RSS feed

See merge request !1034
parents 27ada784 dfa8b675
Branches
No related tags found
No related merge requests found
...@@ -6,12 +6,14 @@ from rest_framework import response ...@@ -6,12 +6,14 @@ from rest_framework import response
from rest_framework import viewsets from rest_framework import viewsets
from django import http from django import http
from django.db import transaction
from django.db.models import Count, Prefetch from django.db.models import Count, Prefetch
from django.db.utils import IntegrityError from django.db.utils import IntegrityError
from funkwhale_api.common import permissions from funkwhale_api.common import permissions
from funkwhale_api.common import preferences from funkwhale_api.common import preferences
from funkwhale_api.federation import models as federation_models 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 models as music_models
from funkwhale_api.music import views as music_views from funkwhale_api.music import views as music_views
from funkwhale_api.users.oauth import permissions as oauth_permissions from funkwhale_api.users.oauth import permissions as oauth_permissions
...@@ -109,11 +111,13 @@ class ChannelViewSet( ...@@ -109,11 +111,13 @@ class ChannelViewSet(
@decorators.action( @decorators.action(
detail=True, detail=True,
methods=["get"], methods=["get"],
permission_classes=[],
content_negotiation_class=renderers.PodcastRSSContentNegociation, content_negotiation_class=renderers.PodcastRSSContentNegociation,
) )
def rss(self, request, *args, **kwargs): def rss(self, request, *args, **kwargs):
object = self.get_object() object = self.get_object()
if not object.attributed_to.is_local:
return response.Response({"detail": "Not found"}, status=404)
uploads = ( uploads = (
object.library.uploads.playable_by(None) object.library.uploads.playable_by(None)
.prefetch_related( .prefetch_related(
...@@ -142,6 +146,14 @@ class ChannelViewSet( ...@@ -142,6 +146,14 @@ class ChannelViewSet(
context["actor"] = self.request.user.actor context["actor"] = self.request.user.actor
return context 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( class SubscriptionsViewSet(
ChannelsMixin, ChannelsMixin,
......
...@@ -107,11 +107,13 @@ def test_channel_update_permission(logged_in_api_client, factories): ...@@ -107,11 +107,13 @@ def test_channel_update_permission(logged_in_api_client, factories):
assert response.status_code == 403 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() actor = logged_in_api_client.user.create_actor()
channel = factories["audio.Channel"](attributed_to=actor) channel = factories["audio.Channel"](attributed_to=actor)
url = reverse("api:v1:channels-detail", kwargs={"uuid": channel.uuid}) 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) response = logged_in_api_client.delete(url)
assert response.status_code == 204 assert response.status_code == 204
...@@ -119,6 +121,11 @@ def test_channel_delete(logged_in_api_client, factories): ...@@ -119,6 +121,11 @@ def test_channel_delete(logged_in_api_client, factories):
with pytest.raises(channel.DoesNotExist): with pytest.raises(channel.DoesNotExist):
channel.refresh_from_db() 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): def test_channel_delete_permission(logged_in_api_client, factories):
logged_in_api_client.user.create_actor() logged_in_api_client.user.create_actor()
...@@ -212,8 +219,9 @@ def test_subscriptions_all(factories, logged_in_api_client): ...@@ -212,8 +219,9 @@ def test_subscriptions_all(factories, logged_in_api_client):
} }
def test_channel_rss_feed(factories, api_client): def test_channel_rss_feed(factories, api_client, preferences):
channel = factories["audio.Channel"]() preferences["common__api_authentication_required"] = False
channel = factories["audio.Channel"](local=True)
upload1 = factories["music.Upload"](library=channel.library, playable=True) upload1 = factories["music.Upload"](library=channel.library, playable=True)
upload2 = 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): ...@@ -228,3 +236,25 @@ def test_channel_rss_feed(factories, api_client):
assert response.status_code == 200 assert response.status_code == 200
assert response.data == expected assert response.data == expected
assert response["Content-Type"] == "application/rss+xml" 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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment