See #890: freeze more data in reports, fixed some failing tests

This commit is contained in:
Eliot Berriot 2019-08-29 14:53:20 +02:00
parent ca7178d1d1
commit 2ad5b9e9f3
No known key found for this signature in database
GPG Key ID: DD6965E2476E5C27
8 changed files with 58 additions and 23 deletions

View File

@ -91,7 +91,11 @@ def get_boolean_filter(name):
def get_generic_relation_filter(relation_name, choices): def get_generic_relation_filter(relation_name, choices):
return {"handler": lambda v: fields.get_generic_filter_query(v, relation_name=relation_name, choices=choices)} return {
"handler": lambda v: fields.get_generic_filter_query(
v, relation_name=relation_name, choices=choices
)
}
class DummyTypedMultipleChoiceField(forms.TypedMultipleChoiceField): class DummyTypedMultipleChoiceField(forms.TypedMultipleChoiceField):

View File

@ -358,7 +358,9 @@ class ManageReportFilterSet(filters.FilterSet):
"assigned_to": get_actor_filter("assigned_to"), "assigned_to": get_actor_filter("assigned_to"),
"target_owner": get_actor_filter("target_owner"), "target_owner": get_actor_filter("target_owner"),
"submitter_email": {"to": "submitter_email"}, "submitter_email": {"to": "submitter_email"},
"target": common_filters.get_generic_relation_filter("target", moderation_serializers.TARGET_CONFIG), "target": common_filters.get_generic_relation_filter(
"target", moderation_serializers.TARGET_CONFIG
),
}, },
) )
) )
@ -375,7 +377,9 @@ class ManageNoteFilterSet(filters.FilterSet):
filter_fields={ filter_fields={
"uuid": {"to": "uuid"}, "uuid": {"to": "uuid"},
"author": get_actor_filter("author"), "author": get_actor_filter("author"),
"target": common_filters.get_generic_relation_filter("target", moderation_utils.NOTE_TARGET_FIELDS), "target": common_filters.get_generic_relation_filter(
"target", moderation_utils.NOTE_TARGET_FIELDS
),
}, },
) )
) )

View File

@ -651,12 +651,10 @@ class ManageBaseNoteSerializer(serializers.ModelSerializer):
class ManageNoteSerializer(ManageBaseNoteSerializer): class ManageNoteSerializer(ManageBaseNoteSerializer):
target = common_fields.GenericRelation( target = common_fields.GenericRelation(moderation_utils.NOTE_TARGET_FIELDS)
moderation_utils.NOTE_TARGET_FIELDS
)
class Meta(ManageBaseNoteSerializer.Meta): class Meta(ManageBaseNoteSerializer.Meta):
fields = ManageBaseNoteSerializer.Meta.fields + ['target'] fields = ManageBaseNoteSerializer.Meta.fields + ["target"]
class ManageReportSerializer(serializers.ModelSerializer): class ManageReportSerializer(serializers.ModelSerializer):
@ -701,5 +699,5 @@ class ManageReportSerializer(serializers.ModelSerializer):
] ]
def get_notes(self, o): def get_notes(self, o):
notes = getattr(o, '_prefetched_notes', []) notes = getattr(o, "_prefetched_notes", [])
return ManageBaseNoteSerializer(notes, many=True).data return ManageBaseNoteSerializer(notes, many=True).data

View File

@ -470,10 +470,18 @@ class ManageReportViewSet(
queryset = ( queryset = (
moderation_models.Report.objects.all() moderation_models.Report.objects.all()
.order_by("-creation_date") .order_by("-creation_date")
.select_related('submitter', 'target_owner', 'assigned_to', 'target_content_type') .select_related(
.prefetch_related('target') "submitter", "target_owner", "assigned_to", "target_content_type"
)
.prefetch_related("target")
.prefetch_related( .prefetch_related(
Prefetch('notes', queryset=moderation_models.Note.objects.order_by('creation_date').select_related('author'), to_attr="_prefetched_notes") Prefetch(
"notes",
queryset=moderation_models.Note.objects.order_by(
"creation_date"
).select_related("author"),
to_attr="_prefetched_notes",
)
) )
) )
serializer_class = serializers.ManageReportSerializer serializer_class = serializers.ManageReportSerializer
@ -491,9 +499,10 @@ class ManageNoteViewSet(
): ):
lookup_field = "uuid" lookup_field = "uuid"
queryset = ( queryset = (
moderation_models.Note.objects.all().order_by("-creation_date") moderation_models.Note.objects.all()
.select_related('author', 'target_content_type') .order_by("-creation_date")
.prefetch_related('target') .select_related("author", "target_content_type")
.prefetch_related("target")
) )
serializer_class = serializers.ManageNoteSerializer serializer_class = serializers.ManageNoteSerializer
filterset_class = filters.ManageNoteFilterSet filterset_class = filters.ManageNoteFilterSet

View File

@ -149,9 +149,7 @@ class Report(federation_models.FederationMixin):
target_state = JSONField(null=True) target_state = JSONField(null=True)
notes = GenericRelation( notes = GenericRelation(
"Note", "Note", content_type_field="target_content_type", object_id_field="target_id"
content_type_field="target_content_type",
object_id_field="target_id",
) )
def get_federation_id(self): def get_federation_id(self):

View File

@ -1,6 +1,8 @@
import json
import urllib.parse import urllib.parse
from django.conf import settings from django.conf import settings
from django.core.serializers.json import DjangoJSONEncoder
import persisting_theory import persisting_theory
from rest_framework import serializers from rest_framework import serializers
@ -170,6 +172,7 @@ def get_target_owner(target):
return mapping[target.__class__](target) return mapping[target.__class__](target)
TARGET_CONFIG = { TARGET_CONFIG = {
"artist": {"queryset": music_models.Artist.objects.all()}, "artist": {"queryset": music_models.Artist.objects.all()},
"album": {"queryset": music_models.Album.objects.all()}, "album": {"queryset": music_models.Album.objects.all()},
@ -187,9 +190,7 @@ TARGET_CONFIG = {
"get_query": get_actor_query, "get_query": get_actor_query,
}, },
} }
TARGET_FIELD = common_fields.GenericRelation( TARGET_FIELD = common_fields.GenericRelation(TARGET_CONFIG)
TARGET_CONFIG
)
class ReportSerializer(serializers.ModelSerializer): class ReportSerializer(serializers.ModelSerializer):
@ -239,6 +240,13 @@ class ReportSerializer(serializers.ModelSerializer):
validated_data["target_state"] = target_state_serializer( validated_data["target_state"] = target_state_serializer(
validated_data["target"] validated_data["target"]
).data ).data
# freeze target type/id in JSON so even if the corresponding object is deleted
# we can have the info and display it in the frontend
target_data = self.fields["target"].to_representation(validated_data["target"])
validated_data["target_state"]["_target"] = json.loads(
json.dumps(target_data, cls=DjangoJSONEncoder)
)
if "fid" in validated_data["target_state"]: if "fid" in validated_data["target_state"]:
validated_data["target_state"]["domain"] = urllib.parse.urlparse( validated_data["target_state"]["domain"] = urllib.parse.urlparse(
validated_data["target_state"]["fid"] validated_data["target_state"]["fid"]

View File

@ -1,4 +1,3 @@
from rest_framework import serializers from rest_framework import serializers
from funkwhale_api.federation import models as federation_models from funkwhale_api.federation import models as federation_models

View File

@ -1,4 +1,8 @@
import json
import pytest import pytest
import urllib.parse
from django.core.serializers.json import DjangoJSONEncoder
from funkwhale_api.common import utils as common_utils from funkwhale_api.common import utils as common_utils
from funkwhale_api.federation import models as federation_models from funkwhale_api.federation import models as federation_models
@ -51,7 +55,7 @@ def test_user_filter_serializer_save(factories):
], ],
) )
def test_report_serializer_save( def test_report_serializer_save(
factory_name, target_type, id_field, state_serializer, factories, mocker factory_name, target_type, id_field, state_serializer, factories, mocker, settings
): ):
target = factories[factory_name]() target = factories[factory_name]()
target_owner = factories["federation.Actor"]() target_owner = factories["federation.Actor"]()
@ -72,10 +76,21 @@ def test_report_serializer_save(
report = serializer.save() report = serializer.save()
expected_state = state_serializer(target).data
expected_state["_target"] = json.loads(
json.dumps(target_data, cls=DjangoJSONEncoder)
)
if hasattr(target, "fid"):
expected_state["domain"] = urllib.parse.urlparse(target.fid).hostname
expected_state["is_local"] = (
expected_state["domain"] == settings.FEDERATION_HOSTNAME
)
else:
expected_state["is_local"] = True
assert report.target == target assert report.target == target
assert report.type == payload["type"] assert report.type == payload["type"]
assert report.summary == payload["summary"] assert report.summary == payload["summary"]
assert report.target_state == state_serializer(target).data assert report.target_state == expected_state
assert report.target_owner == target_owner assert report.target_owner == target_owner
get_target_owner.assert_called_once_with(target) get_target_owner.assert_called_once_with(target)