From aa8b1b5f83c3394561593acdd9fc6cc90543b237 Mon Sep 17 00:00:00 2001 From: Agate Date: Fri, 5 Jun 2020 11:21:10 +0200 Subject: [PATCH] Fix #1151: Updated the /api/v1/libraries endpoint to support listing public libraries of a pod --- api/funkwhale_api/music/filters.py | 9 +++++++++ api/funkwhale_api/music/views.py | 7 ++++++- api/tests/music/test_views.py | 17 +++++++++++++++-- changes/changelog.d/1151.enhancement | 1 + changes/notes.rst | 13 +++++++++++++ front/src/views/content/libraries/Home.vue | 2 +- 6 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 changes/changelog.d/1151.enhancement diff --git a/api/funkwhale_api/music/filters.py b/api/funkwhale_api/music/filters.py index 79b2d2c63..d69dd13a3 100644 --- a/api/funkwhale_api/music/filters.py +++ b/api/funkwhale_api/music/filters.py @@ -218,3 +218,12 @@ class AlbumFilter( def filter_playable(self, queryset, name, value): actor = utils.get_actor_from_request(self.request) return queryset.playable_by(actor, value) + + +class LibraryFilter(filters.FilterSet): + q = fields.SearchFilter(search_fields=["name"],) + scope = common_filters.ActorScopeFilter(actor_field="actor", distinct=True) + + class Meta: + model = models.Library + fields = ["privacy_level", "q", "scope"] diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index 93635c11b..6c9f7e41c 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -273,6 +273,7 @@ class LibraryViewSet( oauth_permissions.ScopePermission, common_permissions.OwnerPermission, ] + filterset_class = filters.LibraryFilter required_scope = "libraries" anonymous_policy = "setting" owner_field = "actor.user" @@ -282,8 +283,12 @@ class LibraryViewSet( qs = super().get_queryset() # allow retrieving a single library by uuid if request.user isn't # the owner. Any other get should be from the owner only - if self.action != "retrieve": + if self.action not in ["retrieve", "list"]: qs = qs.filter(actor=self.request.user.actor) + if self.action == "list": + actor = utils.get_actor_from_request(self.request) + qs = qs.viewable_by(actor) + return qs def perform_create(self, serializer): diff --git a/api/tests/music/test_views.py b/api/tests/music/test_views.py index 2a362a536..66f80d8fe 100644 --- a/api/tests/music/test_views.py +++ b/api/tests/music/test_views.py @@ -631,10 +631,10 @@ def test_user_can_create_library(factories, logged_in_api_client): def test_user_can_list_their_library(factories, logged_in_api_client): actor = logged_in_api_client.user.create_actor() library = factories["music.Library"](actor=actor) - factories["music.Library"]() + factories["music.Library"](privacy_level="everyone") url = reverse("api:v1:libraries-list") - response = logged_in_api_client.get(url) + response = logged_in_api_client.get(url, {"scope": "me"}) assert response.status_code == 200 assert response.data["count"] == 1 @@ -651,6 +651,19 @@ def test_user_can_retrieve_another_user_library(factories, logged_in_api_client) assert response.data["uuid"] == str(library.uuid) +def test_user_can_list_public_libraries(factories, api_client, preferences): + preferences["common__api_authentication_required"] = False + library = factories["music.Library"](privacy_level="everyone") + factories["music.Library"](privacy_level="me") + + url = reverse("api:v1:libraries-list") + response = api_client.get(url) + + assert response.status_code == 200 + assert response.data["count"] == 1 + assert response.data["results"][0]["uuid"] == str(library.uuid) + + def test_library_list_excludes_channel_library(factories, logged_in_api_client): actor = logged_in_api_client.user.create_actor() factories["audio.Channel"](attributed_to=actor) diff --git a/changes/changelog.d/1151.enhancement b/changes/changelog.d/1151.enhancement new file mode 100644 index 000000000..c9b867a30 --- /dev/null +++ b/changes/changelog.d/1151.enhancement @@ -0,0 +1 @@ +Updated the /api/v1/libraries endpoint to support listing public libraries from other users/pods (#1151) diff --git a/changes/notes.rst b/changes/notes.rst index 96ac3d765..3dc81fda8 100644 --- a/changes/notes.rst +++ b/changes/notes.rst @@ -5,3 +5,16 @@ Next release notes Those release notes refer to the current development branch and are reset after each release. + +Small API breaking change in ``/api/v1/libraries`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To allow easier crawling of public libraries on a pod,we had to make a slight breaking change +to the behaviour of ``GET /api/v1/libraries``. + +Before, it returned only libraries owned by the current user. + +Now, it returns all the accessible libraries (including ones from other users and pods). + +If you are consuming the API via a third-party client and need to retrieve your libraries, +use the ``scope`` parameter, like this: ``GET /api/v1/libraries?scope=me`` diff --git a/front/src/views/content/libraries/Home.vue b/front/src/views/content/libraries/Home.vue index 2e5e39498..e3e71995e 100644 --- a/front/src/views/content/libraries/Home.vue +++ b/front/src/views/content/libraries/Home.vue @@ -53,7 +53,7 @@ export default { fetch() { this.isLoading = true let self = this - axios.get("libraries/").then(response => { + axios.get("libraries/", {params: {scope: 'me'}}).then(response => { self.isLoading = false self.libraries = response.data.results if (self.libraries.length === 0) {