diff --git a/api/config/api_urls.py b/api/config/api_urls.py index e8a20a8daf11b718ad3225854cd2b91b2df25c39..fd076c8e2304e3314ed067734c9f2d8c7a3ae8f1 100644 --- a/api/config/api_urls.py +++ b/api/config/api_urls.py @@ -65,10 +65,6 @@ v1_patterns += [ r"^users/", include(("funkwhale_api.users.api_urls", "users"), namespace="users"), ), - url( - r"^requests/", - include(("funkwhale_api.requests.api_urls", "requests"), namespace="requests"), - ), url(r"^token/$", jwt_views.obtain_jwt_token, name="token"), url(r"^token/refresh/$", jwt_views.refresh_jwt_token, name="token_refresh"), ] diff --git a/api/funkwhale_api/manage/filters.py b/api/funkwhale_api/manage/filters.py index 5c825b2f6e190c1068fb911477c661a93da661a0..7f6e328db16acce78f6e8ec4947bdcba66ad0a49 100644 --- a/api/funkwhale_api/manage/filters.py +++ b/api/funkwhale_api/manage/filters.py @@ -2,7 +2,6 @@ from django_filters import rest_framework as filters from funkwhale_api.common import fields from funkwhale_api.music import models as music_models -from funkwhale_api.requests import models as requests_models from funkwhale_api.users import models as users_models @@ -51,13 +50,3 @@ class ManageInvitationFilterSet(filters.FilterSet): if value is None: return queryset return queryset.open(value) - - -class ManageImportRequestFilterSet(filters.FilterSet): - q = fields.SearchFilter( - search_fields=["user__username", "albums", "artist_name", "comment"] - ) - - class Meta: - model = requests_models.ImportRequest - fields = ["q", "status"] diff --git a/api/funkwhale_api/manage/serializers.py b/api/funkwhale_api/manage/serializers.py index 5f1e25240fd5a73164bf3f8cbed432a602862eff..9b5e24f662d9f25c39e980108b119f85e67c8470 100644 --- a/api/funkwhale_api/manage/serializers.py +++ b/api/funkwhale_api/manage/serializers.py @@ -1,10 +1,9 @@ from django.db import transaction -from django.utils import timezone + from rest_framework import serializers from funkwhale_api.common import serializers as common_serializers from funkwhale_api.music import models as music_models -from funkwhale_api.requests import models as requests_models from funkwhale_api.users import models as users_models from . import filters @@ -169,69 +168,3 @@ class ManageInvitationActionSerializer(common_serializers.ActionSerializer): @transaction.atomic def handle_delete(self, objects): return objects.delete() - - -class ManageImportRequestSerializer(serializers.ModelSerializer): - user = ManageUserSimpleSerializer(required=False) - - class Meta: - model = requests_models.ImportRequest - fields = [ - "id", - "status", - "creation_date", - "imported_date", - "user", - "albums", - "artist_name", - "comment", - ] - read_only_fields = [ - "id", - "status", - "creation_date", - "imported_date", - "user", - "albums", - "artist_name", - "comment", - ] - - def validate_code(self, value): - if not value: - return value - if users_models.Invitation.objects.filter(code__iexact=value).exists(): - raise serializers.ValidationError( - "An invitation with this code already exists" - ) - return value - - -class ManageImportRequestActionSerializer(common_serializers.ActionSerializer): - actions = [ - common_serializers.Action( - "mark_closed", - allow_all=True, - qs_filter=lambda qs: qs.filter(status__in=["pending", "accepted"]), - ), - common_serializers.Action( - "mark_imported", - allow_all=True, - qs_filter=lambda qs: qs.filter(status__in=["pending", "accepted"]), - ), - common_serializers.Action("delete", allow_all=False), - ] - filterset_class = filters.ManageImportRequestFilterSet - - @transaction.atomic - def handle_delete(self, objects): - return objects.delete() - - @transaction.atomic - def handle_mark_closed(self, objects): - return objects.update(status="closed") - - @transaction.atomic - def handle_mark_imported(self, objects): - now = timezone.now() - return objects.update(status="imported", imported_date=now) diff --git a/api/funkwhale_api/manage/urls.py b/api/funkwhale_api/manage/urls.py index de202a183637d03d2948159501d57d50d9dce56a..9f5503978c435797d012fc0595a8c8b50aa81568 100644 --- a/api/funkwhale_api/manage/urls.py +++ b/api/funkwhale_api/manage/urls.py @@ -5,10 +5,6 @@ from . import views library_router = routers.SimpleRouter() library_router.register(r"uploads", views.ManageUploadViewSet, "uploads") -requests_router = routers.SimpleRouter() -requests_router.register( - r"import-requests", views.ManageImportRequestViewSet, "import-requests" -) users_router = routers.SimpleRouter() users_router.register(r"users", views.ManageUserViewSet, "users") users_router.register(r"invitations", views.ManageInvitationViewSet, "invitations") @@ -16,7 +12,4 @@ users_router.register(r"invitations", views.ManageInvitationViewSet, "invitation urlpatterns = [ url(r"^library/", include((library_router.urls, "instance"), namespace="library")), url(r"^users/", include((users_router.urls, "instance"), namespace="users")), - url( - r"^requests/", include((requests_router.urls, "instance"), namespace="requests") - ), ] diff --git a/api/funkwhale_api/manage/views.py b/api/funkwhale_api/manage/views.py index 0b14bf8a903454caa56607e9be00d08b1797d230..bfd5b2ef21bb3c1854ed711bb52b57f5bdc6a079 100644 --- a/api/funkwhale_api/manage/views.py +++ b/api/funkwhale_api/manage/views.py @@ -3,7 +3,6 @@ from rest_framework.decorators import list_route from funkwhale_api.common import preferences from funkwhale_api.music import models as music_models -from funkwhale_api.requests import models as requests_models from funkwhale_api.users import models as users_models from funkwhale_api.users.permissions import HasUserPermission @@ -93,31 +92,3 @@ class ManageInvitationViewSet( serializer.is_valid(raise_exception=True) result = serializer.save() return response.Response(result, status=200) - - -class ManageImportRequestViewSet( - mixins.ListModelMixin, - mixins.RetrieveModelMixin, - mixins.UpdateModelMixin, - viewsets.GenericViewSet, -): - queryset = ( - requests_models.ImportRequest.objects.all() - .order_by("-id") - .select_related("user") - ) - serializer_class = serializers.ManageImportRequestSerializer - filter_class = filters.ManageImportRequestFilterSet - permission_classes = (HasUserPermission,) - required_permissions = ["library"] - ordering_fields = ["creation_date", "imported_date"] - - @list_route(methods=["post"]) - def action(self, request, *args, **kwargs): - queryset = self.get_queryset() - serializer = serializers.ManageImportRequestActionSerializer( - request.data, queryset=queryset - ) - serializer.is_valid(raise_exception=True) - result = serializer.save() - return response.Response(result, status=200) diff --git a/api/funkwhale_api/requests/admin.py b/api/funkwhale_api/requests/admin.py deleted file mode 100644 index b0f1a7990ef55fe7659073835db4fc6ef48e4c96..0000000000000000000000000000000000000000 --- a/api/funkwhale_api/requests/admin.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.contrib import admin - -from . import models - - -@admin.register(models.ImportRequest) -class ImportRequestAdmin(admin.ModelAdmin): - list_display = ["artist_name", "user", "status", "creation_date"] - list_select_related = ["user"] - list_filter = ["status"] - search_fields = ["artist_name", "comment", "albums"] diff --git a/api/funkwhale_api/requests/api_urls.py b/api/funkwhale_api/requests/api_urls.py deleted file mode 100644 index 403a0953bac9fa4d822466ccc9a286477d57b89b..0000000000000000000000000000000000000000 --- a/api/funkwhale_api/requests/api_urls.py +++ /dev/null @@ -1,8 +0,0 @@ -from rest_framework import routers - -from . import views - -router = routers.SimpleRouter() -router.register(r"import-requests", views.ImportRequestViewSet, "import-requests") - -urlpatterns = router.urls diff --git a/api/funkwhale_api/requests/factories.py b/api/funkwhale_api/requests/factories.py deleted file mode 100644 index d6673aebdc94078b8eba7323a67b8b65f61298cd..0000000000000000000000000000000000000000 --- a/api/funkwhale_api/requests/factories.py +++ /dev/null @@ -1,15 +0,0 @@ -import factory - -from funkwhale_api.factories import registry -from funkwhale_api.users.factories import UserFactory - - -@registry.register -class ImportRequestFactory(factory.django.DjangoModelFactory): - artist_name = factory.Faker("name") - albums = factory.Faker("sentence") - user = factory.SubFactory(UserFactory) - comment = factory.Faker("paragraph") - - class Meta: - model = "requests.ImportRequest" diff --git a/api/funkwhale_api/requests/filters.py b/api/funkwhale_api/requests/filters.py deleted file mode 100644 index 4a06dea1b754f35f830b8cad488fa34ea04e28be..0000000000000000000000000000000000000000 --- a/api/funkwhale_api/requests/filters.py +++ /dev/null @@ -1,20 +0,0 @@ -import django_filters - -from funkwhale_api.common import fields - -from . import models - - -class ImportRequestFilter(django_filters.FilterSet): - - q = fields.SearchFilter( - search_fields=["artist_name", "user__username", "albums", "comment"] - ) - - class Meta: - model = models.ImportRequest - fields = { - "artist_name": ["exact", "iexact", "startswith", "icontains"], - "status": ["exact"], - "user__username": ["exact"], - } diff --git a/api/funkwhale_api/requests/serializers.py b/api/funkwhale_api/requests/serializers.py deleted file mode 100644 index 2a810a9997196e8ad3b0d19477d7f71151cd1253..0000000000000000000000000000000000000000 --- a/api/funkwhale_api/requests/serializers.py +++ /dev/null @@ -1,27 +0,0 @@ -from rest_framework import serializers - -from funkwhale_api.users.serializers import UserBasicSerializer - -from . import models - - -class ImportRequestSerializer(serializers.ModelSerializer): - user = UserBasicSerializer(read_only=True) - - class Meta: - model = models.ImportRequest - fields = ( - "id", - "status", - "albums", - "artist_name", - "user", - "creation_date", - "imported_date", - "comment", - ) - read_only_fields = ("creation_date", "imported_date", "user", "status") - - def create(self, validated_data): - validated_data["user"] = self.context["user"] - return super().create(validated_data) diff --git a/api/funkwhale_api/requests/views.py b/api/funkwhale_api/requests/views.py deleted file mode 100644 index 96d8c89279333b442a7afade7bf53f2022769cd6..0000000000000000000000000000000000000000 --- a/api/funkwhale_api/requests/views.py +++ /dev/null @@ -1,27 +0,0 @@ -from rest_framework import mixins, viewsets - -from . import filters, models, serializers - - -class ImportRequestViewSet( - mixins.CreateModelMixin, - mixins.RetrieveModelMixin, - mixins.ListModelMixin, - viewsets.GenericViewSet, -): - - serializer_class = serializers.ImportRequestSerializer - queryset = ( - models.ImportRequest.objects.all().select_related().order_by("-creation_date") - ) - filter_class = filters.ImportRequestFilter - ordering_fields = ("id", "artist_name", "creation_date", "status") - - def perform_create(self, serializer): - return serializer.save(user=self.request.user) - - def get_serializer_context(self): - context = super().get_serializer_context() - if self.request.user.is_authenticated: - context["user"] = self.request.user - return context diff --git a/api/tests/manage/test_serializers.py b/api/tests/manage/test_serializers.py index d2c29164369c8159fc7ef89afb9f7eb69a15b743..df55ab82393aa28a70ebdbb51c4d8650d08ca9ac 100644 --- a/api/tests/manage/test_serializers.py +++ b/api/tests/manage/test_serializers.py @@ -36,44 +36,3 @@ def test_user_update_permission(factories): assert user.permission_upload is True assert user.permission_library is False assert user.permission_settings is True - - -def test_manage_import_request_mark_closed(factories): - affected = factories["requests.ImportRequest"].create_batch( - size=5, status="pending" - ) - # we do not update imported requests - factories["requests.ImportRequest"].create_batch(size=5, status="imported") - s = serializers.ManageImportRequestActionSerializer( - queryset=affected[0].__class__.objects.all(), - data={"objects": "all", "action": "mark_closed"}, - ) - - assert s.is_valid(raise_exception=True) is True - s.save() - - assert affected[0].__class__.objects.filter(status="imported").count() == 5 - for ir in affected: - ir.refresh_from_db() - assert ir.status == "closed" - - -def test_manage_import_request_mark_imported(factories, now): - affected = factories["requests.ImportRequest"].create_batch( - size=5, status="pending" - ) - # we do not update closed requests - factories["requests.ImportRequest"].create_batch(size=5, status="closed") - s = serializers.ManageImportRequestActionSerializer( - queryset=affected[0].__class__.objects.all(), - data={"objects": "all", "action": "mark_imported"}, - ) - - assert s.is_valid(raise_exception=True) is True - s.save() - - assert affected[0].__class__.objects.filter(status="closed").count() == 5 - for ir in affected: - ir.refresh_from_db() - assert ir.status == "imported" - assert ir.imported_date == now diff --git a/api/tests/manage/test_views.py b/api/tests/manage/test_views.py index 2789c68223b4ddbd0cb674142c2f2cd879be9140..a9920ce0761b655074cba3a1a7e18104fea8ca49 100644 --- a/api/tests/manage/test_views.py +++ b/api/tests/manage/test_views.py @@ -10,7 +10,6 @@ from funkwhale_api.manage import serializers, views (views.ManageUploadViewSet, ["library"], "and"), (views.ManageUserViewSet, ["settings"], "and"), (views.ManageInvitationViewSet, ["settings"], "and"), - (views.ManageImportRequestViewSet, ["library"], "and"), ], ) def test_permissions(assert_user_permission, view, permissions, operator): @@ -65,15 +64,3 @@ def test_invitation_view_create(factories, superuser_api_client, mocker): assert response.status_code == 201 assert superuser_api_client.user.invitations.latest("id") is not None - - -def test_music_requests_view(factories, superuser_api_client, mocker): - invitations = factories["requests.ImportRequest"].create_batch(size=5) - qs = invitations[0].__class__.objects.order_by("-id") - url = reverse("api:v1:manage:requests:import-requests-list") - - response = superuser_api_client.get(url, {"sort": "-id"}) - expected = serializers.ManageImportRequestSerializer(qs, many=True).data - - assert response.data["count"] == len(invitations) - assert response.data["results"] == expected diff --git a/api/tests/requests/__init__.py b/api/tests/requests/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/api/tests/requests/test_views.py b/api/tests/requests/test_views.py deleted file mode 100644 index 0d64336720aaa23abdc6b7ad4cd6d48b604d6ef2..0000000000000000000000000000000000000000 --- a/api/tests/requests/test_views.py +++ /dev/null @@ -1,26 +0,0 @@ -from django.urls import reverse - - -def test_request_viewset_requires_auth(db, api_client): - url = reverse("api:v1:requests:import-requests-list") - response = api_client.get(url) - assert response.status_code == 401 - - -def test_user_can_create_request(logged_in_api_client): - url = reverse("api:v1:requests:import-requests-list") - user = logged_in_api_client.user - data = { - "artist_name": "System of a Down", - "albums": "All please!", - "comment": "Please, they rock!", - } - response = logged_in_api_client.post(url, data) - - assert response.status_code == 201 - - ir = user.import_requests.latest("id") - assert ir.status == "pending" - assert ir.creation_date is not None - for field, value in data.items(): - assert getattr(ir, field) == value diff --git a/front/src/App.vue b/front/src/App.vue index f4ec3b3f831016e86779f0c168a65cd27be09259..16154b130d2d49f9c57b3f35e6daeba7b5688b61 100644 --- a/front/src/App.vue +++ b/front/src/App.vue @@ -34,9 +34,6 @@ <router-link class="item" to="/about"> <translate>About this instance</translate> </router-link> - <router-link class="item" :to="{name: 'library.request'}"> - <translate>Request music</translate> - </router-link> <a href="https://funkwhale.audio" class="item" target="_blank"><translate>Official website</translate></a> <a href="https://docs.funkwhale.audio" class="item" target="_blank"><translate>Documentation</translate></a> <a href="https://code.eliotberriot.com/funkwhale/funkwhale" class="item" target="_blank"> diff --git a/front/src/router/index.js b/front/src/router/index.js index ff7e4469f536da239f8aee9bb6e0658f92319c9e..489ca2242093b731b855057d2ae8f91ed5856626 100644 --- a/front/src/router/index.js +++ b/front/src/router/index.js @@ -27,12 +27,10 @@ import Favorites from '@/components/favorites/List' import AdminSettings from '@/views/admin/Settings' import AdminLibraryBase from '@/views/admin/library/Base' import AdminLibraryFilesList from '@/views/admin/library/FilesList' -import AdminLibraryRequestsList from '@/views/admin/library/RequestsList' import AdminUsersBase from '@/views/admin/users/Base' import AdminUsersDetail from '@/views/admin/users/UsersDetail' import AdminUsersList from '@/views/admin/users/UsersList' import AdminInvitationsList from '@/views/admin/users/InvitationsList' -import MusicRequest from '@/views/library/MusicRequest' import FederationBase from '@/views/federation/Base' import FederationScan from '@/views/federation/Scan' import FederationLibraryDetail from '@/views/federation/LibraryDetail' @@ -257,11 +255,6 @@ export default new Router({ path: 'files', name: 'manage.library.files', component: AdminLibraryFilesList - }, - { - path: 'requests', - name: 'manage.library.requests', - component: AdminLibraryRequestsList } ] }, @@ -292,11 +285,6 @@ export default new Router({ component: Library, children: [ { path: '', component: LibraryHome, name: 'library.index' }, - { - path: 'requests/', - name: 'library.request', - component: MusicRequest - }, { path: 'artists/', name: 'library.artists.browse', diff --git a/front/src/views/admin/library/Base.vue b/front/src/views/admin/library/Base.vue index 114f64ac5954d6ef1d5c33a6e7ba0e13e3d55a1f..22f20452f76ed5a2c244a47774a7709d0c65bcc3 100644 --- a/front/src/views/admin/library/Base.vue +++ b/front/src/views/admin/library/Base.vue @@ -4,15 +4,6 @@ <router-link class="ui item" :to="{name: 'manage.library.files'}"><translate>Files</translate></router-link> - <router-link - class="ui item" - :to="{name: 'manage.library.requests'}"> - <translate>Import requests</translate> - <div - :class="['ui', {'teal': $store.state.ui.notifications.importRequests > 0}, 'label']" - :title="labels.pendingRequests"> - {{ $store.state.ui.notifications.importRequests }}</div> - </router-link> </div> <router-view :key="$route.fullPath"></router-view> </div> @@ -23,10 +14,8 @@ export default { computed: { labels () { let title = this.$gettext('Manage library') - let pendingRequests = this.$gettext('Pending import requests') return { - title, - pendingRequests + title } } } diff --git a/front/src/views/admin/library/RequestsList.vue b/front/src/views/admin/library/RequestsList.vue deleted file mode 100644 index d945fb865ec448f287c8b56a9f39bd6d1905d56d..0000000000000000000000000000000000000000 --- a/front/src/views/admin/library/RequestsList.vue +++ /dev/null @@ -1,30 +0,0 @@ -<template> - <div v-title="labels.importRequests"> - <div class="ui vertical stripe segment"> - <h2 class="ui header"><translate>Import requests</translate></h2> - <div class="ui hidden divider"></div> - <library-requests-table></library-requests-table> - </div> - </div> -</template> - -<script> -import LibraryRequestsTable from '@/components/manage/library/RequestsTable' - -export default { - components: { - LibraryRequestsTable - }, - computed: { - labels () { - return { - importRequests: this.$gettext('Import requests') - } - } - } -} -</script> - -<!-- Add "scoped" attribute to limit CSS to this component only --> -<style scoped> -</style> diff --git a/front/src/views/library/MusicRequest.vue b/front/src/views/library/MusicRequest.vue deleted file mode 100644 index ac2aeafb2c6cb4732c29cdaad275a1bbf69a3363..0000000000000000000000000000000000000000 --- a/front/src/views/library/MusicRequest.vue +++ /dev/null @@ -1,32 +0,0 @@ -<template> - <div class="ui vertical stripe segment" v-title="labels.title"> - <div class="ui small text container"> - <h2 class="ui header"> - <translate>Request some music</translate> - </h2> - <request-form v-if="$store.state.auth.authenticated"></request-form> - </div> - </div> -</template> - -<script> -import RequestForm from '@/components/requests/Form' - -export default { - components: { - RequestForm - }, - computed: { - labels () { - let title = this.$gettext('Request some music') - return { - title - } - } - } -} -</script> - -<!-- Add "scoped" attribute to limit CSS to this component only --> -<style scoped> -</style>