Merge branch '170-subscriptions-api-list' into 'develop'
See #170: added missing /api/v1/subscriptions endpoint See merge request funkwhale/funkwhale!996
This commit is contained in:
commit
f96b8e2dcf
|
@ -23,6 +23,7 @@ router.register(r"libraries", views.LibraryViewSet, "libraries")
|
|||
router.register(r"listen", views.ListenViewSet, "listen")
|
||||
router.register(r"artists", views.ArtistViewSet, "artists")
|
||||
router.register(r"channels", audio_views.ChannelViewSet, "channels")
|
||||
router.register(r"subscriptions", audio_views.SubscriptionsViewSet, "subscriptions")
|
||||
router.register(r"albums", views.AlbumViewSet, "albums")
|
||||
router.register(r"licenses", views.LicenseViewSet, "licenses")
|
||||
router.register(r"playlists", playlists_views.PlaylistViewSet, "playlists")
|
||||
|
|
|
@ -10,6 +10,7 @@ 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.users.oauth import permissions as oauth_permissions
|
||||
|
||||
from . import filters, models, serializers
|
||||
|
@ -66,10 +67,12 @@ class ChannelViewSet(
|
|||
)
|
||||
def subscribe(self, request, *args, **kwargs):
|
||||
object = self.get_object()
|
||||
subscription = federation_models.Follow(
|
||||
target=object.actor, approved=True, actor=request.user.actor,
|
||||
)
|
||||
subscription.fid = subscription.get_federation_id()
|
||||
try:
|
||||
subscription = object.actor.received_follows.create(
|
||||
approved=True, actor=request.user.actor,
|
||||
)
|
||||
subscription.save()
|
||||
except IntegrityError:
|
||||
# there's already a subscription for this actor/channel
|
||||
subscription = object.actor.received_follows.filter(
|
||||
|
@ -88,3 +91,48 @@ class ChannelViewSet(
|
|||
object = self.get_object()
|
||||
request.user.actor.emitted_follows.filter(target=object.actor).delete()
|
||||
return response.Response(status=204)
|
||||
|
||||
|
||||
class SubscriptionsViewSet(
|
||||
ChannelsMixin,
|
||||
mixins.RetrieveModelMixin,
|
||||
mixins.ListModelMixin,
|
||||
viewsets.GenericViewSet,
|
||||
):
|
||||
lookup_field = "uuid"
|
||||
serializer_class = serializers.SubscriptionSerializer
|
||||
queryset = (
|
||||
federation_models.Follow.objects.exclude(target__channel__isnull=True)
|
||||
.prefetch_related(
|
||||
"target__channel__library",
|
||||
"target__channel__attributed_to",
|
||||
"target__channel__artist__description",
|
||||
"actor",
|
||||
)
|
||||
.order_by("-creation_date")
|
||||
)
|
||||
permission_classes = [
|
||||
oauth_permissions.ScopePermission,
|
||||
rest_permissions.IsAuthenticated,
|
||||
]
|
||||
required_scope = "libraries"
|
||||
anonymous_policy = False
|
||||
|
||||
def get_queryset(self):
|
||||
qs = super().get_queryset()
|
||||
return qs.filter(actor=self.request.user.actor)
|
||||
|
||||
@decorators.action(methods=["get"], detail=False)
|
||||
def all(self, request, *args, **kwargs):
|
||||
"""
|
||||
Return all the subscriptions of the current user, with only limited data
|
||||
to have a performant endpoint and avoid lots of queries just to display
|
||||
subscription status in the UI
|
||||
"""
|
||||
subscriptions = list(self.get_queryset().values_list("uuid", flat=True))
|
||||
|
||||
payload = {
|
||||
"results": [str(u) for u in subscriptions],
|
||||
"count": len(subscriptions),
|
||||
}
|
||||
return response.Response(payload, status=200)
|
||||
|
|
|
@ -140,6 +140,7 @@ def test_channel_subscribe(factories, logged_in_api_client):
|
|||
subscription = actor.emitted_follows.select_related(
|
||||
"target__channel__artist__description"
|
||||
).latest("id")
|
||||
assert subscription.fid == subscription.get_federation_id()
|
||||
expected = serializers.SubscriptionSerializer(subscription).data
|
||||
assert response.data == expected
|
||||
assert subscription.target == channel.actor
|
||||
|
@ -157,3 +158,34 @@ def test_channel_unsubscribe(factories, logged_in_api_client):
|
|||
|
||||
with pytest.raises(subscription.DoesNotExist):
|
||||
subscription.refresh_from_db()
|
||||
|
||||
|
||||
def test_subscriptions_list(factories, logged_in_api_client):
|
||||
actor = logged_in_api_client.user.create_actor()
|
||||
channel = factories["audio.Channel"](artist__description=None)
|
||||
subscription = factories["audio.Subscription"](target=channel.actor, actor=actor)
|
||||
factories["audio.Subscription"](target=channel.actor)
|
||||
url = reverse("api:v1:subscriptions-list")
|
||||
expected = serializers.SubscriptionSerializer(subscription).data
|
||||
response = logged_in_api_client.get(url)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.data["results"][0] == expected
|
||||
assert response.data == {
|
||||
"results": [expected],
|
||||
"count": 1,
|
||||
"next": None,
|
||||
"previous": None,
|
||||
}
|
||||
|
||||
|
||||
def test_subscriptions_all(factories, logged_in_api_client):
|
||||
actor = logged_in_api_client.user.create_actor()
|
||||
channel = factories["audio.Channel"](artist__description=None)
|
||||
subscription = factories["audio.Subscription"](target=channel.actor, actor=actor)
|
||||
factories["audio.Subscription"](target=channel.actor)
|
||||
url = reverse("api:v1:subscriptions-all")
|
||||
response = logged_in_api_client.get(url)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.data == {"results": [subscription.uuid], "count": 1}
|
||||
|
|
Loading…
Reference in New Issue