diff --git a/api/funkwhale_api/manage/filters.py b/api/funkwhale_api/manage/filters.py index 6a6e7b99d..f4ebb1172 100644 --- a/api/funkwhale_api/manage/filters.py +++ b/api/funkwhale_api/manage/filters.py @@ -339,3 +339,26 @@ class ManageTagFilterSet(filters.FilterSet): class Meta: model = tags_models.Tag fields = ["q"] + + +class ManageReportFilterSet(filters.FilterSet): + q = fields.SmartSearchFilter( + config=search.SearchConfig( + search_fields={"summary": {"to": "summary"}}, + filter_fields={ + "uuid": {"to": "uuid"}, + "id": {"to": "id"}, + "is_handled": {"to": "is_handled"}, + "domain": {"to": "target_owner__domain_id"}, + "type": {"to": "type"}, + "submitter": get_actor_filter("submitter"), + "assigned_to": get_actor_filter("assigned_to"), + "target_owner": get_actor_filter("target_owner"), + "submitter_email": {"to": "submitter_email"}, + }, + ) + ) + + class Meta: + model = moderation_models.Report + fields = ["q", "is_handled", "type", "submitter_email"] diff --git a/api/funkwhale_api/manage/urls.py b/api/funkwhale_api/manage/urls.py index b830f0023..f97fd5e30 100644 --- a/api/funkwhale_api/manage/urls.py +++ b/api/funkwhale_api/manage/urls.py @@ -17,6 +17,7 @@ moderation_router = routers.OptionalSlashRouter() moderation_router.register( r"instance-policies", views.ManageInstancePolicyViewSet, "instance-policies" ) +moderation_router.register(r"reports", views.ManageReportViewSet, "reports") users_router = routers.OptionalSlashRouter() users_router.register(r"users", views.ManageUserViewSet, "users") diff --git a/api/funkwhale_api/manage/views.py b/api/funkwhale_api/manage/views.py index ea3c33f80..70f1b3a27 100644 --- a/api/funkwhale_api/manage/views.py +++ b/api/funkwhale_api/manage/views.py @@ -459,6 +459,25 @@ class ManageInstancePolicyViewSet( serializer.save(actor=self.request.user.actor) +class ManageReportViewSet( + mixins.ListModelMixin, + mixins.RetrieveModelMixin, + mixins.DestroyModelMixin, + mixins.UpdateModelMixin, + viewsets.GenericViewSet, +): + lookup_field = "uuid" + queryset = ( + moderation_models.Report.objects.all() + .order_by("-creation_date") + .select_related() + ) + serializer_class = serializers.ManageReportSerializer + filterset_class = filters.ManageReportFilterSet + required_scope = "instance:reports" + ordering_fields = ["id", "creation_date", "handled_date"] + + class ManageTagViewSet( mixins.ListModelMixin, mixins.RetrieveModelMixin, diff --git a/api/funkwhale_api/moderation/factories.py b/api/funkwhale_api/moderation/factories.py index 3db5d2060..75cec7c7f 100644 --- a/api/funkwhale_api/moderation/factories.py +++ b/api/funkwhale_api/moderation/factories.py @@ -44,7 +44,7 @@ class UserFilterFactory(NoUpdateOnCreate, factory.DjangoModelFactory): @registry.register class ReportFactory(NoUpdateOnCreate, factory.DjangoModelFactory): submitter = factory.SubFactory(federation_factories.ActorFactory) - target = None + target = factory.SubFactory(music_factories.ArtistFactory) summary = factory.Faker("paragraph") type = "other" diff --git a/api/funkwhale_api/moderation/models.py b/api/funkwhale_api/moderation/models.py index 74fa4fd1b..9966cdb56 100644 --- a/api/funkwhale_api/moderation/models.py +++ b/api/funkwhale_api/moderation/models.py @@ -14,6 +14,7 @@ from django.utils import timezone from funkwhale_api.federation import models as federation_models from funkwhale_api.federation import utils as federation_utils + class InstancePolicyQuerySet(models.QuerySet): def active(self): return self.filter(is_active=True) @@ -168,4 +169,4 @@ def set_handled_date(sender, instance, **kwargs): if instance.is_handled is True and not instance.handled_date: instance.handled_date = timezone.now() elif not instance.is_handled: - instance.handled_date = None \ No newline at end of file + instance.handled_date = None diff --git a/api/tests/manage/test_views.py b/api/tests/manage/test_views.py index a164e4012..8bd414db2 100644 --- a/api/tests/manage/test_views.py +++ b/api/tests/manage/test_views.py @@ -417,3 +417,47 @@ def test_tag_delete(factories, superuser_api_client): response = superuser_api_client.delete(url) assert response.status_code == 204 + + +def test_report_detail(factories, superuser_api_client): + report = factories["moderation.Report"]() + url = reverse( + "api:v1:manage:moderation:reports-detail", kwargs={"uuid": report.uuid} + ) + response = superuser_api_client.get(url) + + assert response.status_code == 200 + assert response.data["summary"] == report.summary + + +def test_report_list(factories, superuser_api_client, settings): + report = factories["moderation.Report"]() + url = reverse("api:v1:manage:moderation:reports-list") + response = superuser_api_client.get(url) + + assert response.status_code == 200 + + assert response.data["count"] == 1 + assert response.data["results"][0]["summary"] == report.summary + + +def test_report_update(factories, superuser_api_client): + report = factories["moderation.Report"]() + url = reverse( + "api:v1:manage:moderation:reports-detail", kwargs={"uuid": report.uuid} + ) + response = superuser_api_client.patch(url, {"is_handled": True}) + + assert response.status_code == 200 + report.refresh_from_db() + assert report.is_handled is True + + +def test_report_delete(factories, superuser_api_client): + report = factories["moderation.Report"]() + url = reverse( + "api:v1:manage:moderation:reports-detail", kwargs={"uuid": report.uuid} + ) + response = superuser_api_client.delete(url) + + assert response.status_code == 204