Rejecting media files on an instance or account now purge existing media

merge-requests/552/head
Eliot Berriot 2019-01-10 11:02:09 +01:00
rodzic cb3dacedbe
commit 377f237fdb
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: DD6965E2476E5C27
5 zmienionych plików z 102 dodań i 32 usunięć

Wyświetl plik

@ -198,27 +198,34 @@ def delete_qs(qs):
)
def handle_purge_actors(ids):
def handle_purge_actors(ids, only=[]):
"""
Empty only means we purge everything
Otherwise, we purge only the requested bits: media
"""
# purge follows (received emitted)
if not only:
delete_qs(models.LibraryFollow.objects.filter(target__actor_id__in=ids))
delete_qs(models.LibraryFollow.objects.filter(actor_id__in=ids))
delete_qs(models.Follow.objects.filter(target_id__in=ids))
delete_qs(models.Follow.objects.filter(actor_id__in=ids))
# purge audio content
if not only or "media" in only:
delete_qs(models.LibraryFollow.objects.filter(actor_id__in=ids))
delete_qs(models.Follow.objects.filter(target_id__in=ids))
delete_qs(music_models.Upload.objects.filter(library__actor_id__in=ids))
delete_qs(music_models.Library.objects.filter(actor_id__in=ids))
# purge remaining activities / deliveries
if not only:
delete_qs(models.InboxItem.objects.filter(actor_id__in=ids))
delete_qs(models.Activity.objects.filter(actor_id__in=ids))
@celery.app.task(name="federation.purge_actors")
def purge_actors(ids=[], domains=[]):
def purge_actors(ids=[], domains=[], only=[]):
actors = models.Actor.objects.filter(
Q(id__in=ids) | Q(domain_id__in=domains)
).order_by("id")
found_ids = list(actors.values_list("id", flat=True))
logger.info("Starting purging %s accounts", len(found_ids))
handle_purge_actors(ids=found_ids)
handle_purge_actors(ids=found_ids, only=only)

Wyświetl plik

@ -317,17 +317,25 @@ class ManageInstancePolicySerializer(serializers.ModelSerializer):
@transaction.atomic
def save(self, *args, **kwargs):
instance = super().save(*args, **kwargs)
need_purge = self.instance.is_active and self.instance.block_all
need_purge = self.instance.is_active and (
self.instance.block_all or self.instance.reject_media
)
if need_purge:
only = []
if self.instance.reject_media:
only.append("media")
target = instance.target
if target["type"] == "domain":
common_utils.on_commit(
federation_tasks.purge_actors.delay, domains=[target["obj"].pk]
federation_tasks.purge_actors.delay,
domains=[target["obj"].pk],
only=only,
)
if target["type"] == "actor":
common_utils.on_commit(
federation_tasks.purge_actors.delay, ids=[target["obj"].pk]
federation_tasks.purge_actors.delay,
ids=[target["obj"].pk],
only=only,
)
return instance

Wyświetl plik

@ -223,11 +223,46 @@ def test_handle_purge_actors(factories, mocker):
d.refresh_from_db()
def test_handle_purge_actors_restrict_media(factories, mocker):
to_purge = factories["federation.Actor"]()
keeped = [
factories["music.Upload"](),
factories["federation.Activity"](),
factories["federation.InboxItem"](),
factories["federation.Follow"](),
factories["federation.LibraryFollow"](),
factories["federation.Activity"](actor=to_purge),
factories["federation.InboxItem"](actor=to_purge),
factories["federation.Follow"](actor=to_purge),
]
library = factories["music.Library"](actor=to_purge)
deleted = [
library,
factories["music.Upload"](library=library),
factories["federation.LibraryFollow"](actor=to_purge),
]
tasks.handle_purge_actors([to_purge.pk], only=["media"])
for k in keeped:
# this should not be deleted
k.refresh_from_db()
for d in deleted:
with pytest.raises(d.__class__.DoesNotExist):
d.refresh_from_db()
def test_purge_actors(factories, mocker):
handle_purge_actors = mocker.spy(tasks, "handle_purge_actors")
factories["federation.Actor"]()
to_delete = factories["federation.Actor"]()
to_delete_domain = factories["federation.Actor"]()
tasks.purge_actors(ids=[to_delete.pk], domains=[to_delete_domain.domain.name])
tasks.purge_actors(
ids=[to_delete.pk], domains=[to_delete_domain.domain.name], only=["hello"]
)
handle_purge_actors.assert_called_once_with(ids=[to_delete.pk, to_delete_domain.pk])
handle_purge_actors.assert_called_once_with(
ids=[to_delete.pk, to_delete_domain.pk], only=["hello"]
)

Wyświetl plik

@ -175,65 +175,85 @@ def test_manage_domain_action_purge(factories, mocker):
)
def test_instance_policy_serializer_purges_target_domain(factories, mocker):
policy = factories["moderation.InstancePolicy"](for_domain=True, block_all=False)
@pytest.mark.parametrize(
"param,expected_only", [("block_all", []), ("reject_media", ["media"])]
)
def test_instance_policy_serializer_purges_target_domain(
factories, mocker, param, expected_only
):
params = {param: False}
if param != "block_all":
params["block_all"] = False
policy = factories["moderation.InstancePolicy"](for_domain=True, **params)
on_commit = mocker.patch("funkwhale_api.common.utils.on_commit")
serializer = serializers.ManageInstancePolicySerializer(
policy, data={"block_all": True}, partial=True
policy, data={param: True}, partial=True
)
serializer.is_valid(raise_exception=True)
serializer.save()
policy.refresh_from_db()
assert policy.block_all is True
assert getattr(policy, param) is True
on_commit.assert_called_once_with(
federation_tasks.purge_actors.delay, domains=[policy.target_domain_id]
federation_tasks.purge_actors.delay,
domains=[policy.target_domain_id],
only=expected_only,
)
on_commit.reset_mock()
# setting to false should have no effect
serializer = serializers.ManageInstancePolicySerializer(
policy, data={"block_all": False}, partial=True
policy, data={param: False}, partial=True
)
serializer.is_valid(raise_exception=True)
serializer.save()
policy.refresh_from_db()
assert policy.block_all is False
assert getattr(policy, param) is False
assert on_commit.call_count == 0
def test_instance_policy_serializer_purges_target_actor(factories, mocker):
policy = factories["moderation.InstancePolicy"](for_actor=True, block_all=False)
@pytest.mark.parametrize(
"param,expected_only", [("block_all", []), ("reject_media", ["media"])]
)
def test_instance_policy_serializer_purges_target_actor(
factories, mocker, param, expected_only
):
params = {param: False}
if param != "block_all":
params["block_all"] = False
policy = factories["moderation.InstancePolicy"](for_actor=True, **params)
on_commit = mocker.patch("funkwhale_api.common.utils.on_commit")
serializer = serializers.ManageInstancePolicySerializer(
policy, data={"block_all": True}, partial=True
policy, data={param: True}, partial=True
)
serializer.is_valid(raise_exception=True)
serializer.save()
policy.refresh_from_db()
assert policy.block_all is True
assert getattr(policy, param) is True
on_commit.assert_called_once_with(
federation_tasks.purge_actors.delay, ids=[policy.target_actor_id]
federation_tasks.purge_actors.delay,
ids=[policy.target_actor_id],
only=expected_only,
)
on_commit.reset_mock()
# setting to false should have no effect
serializer = serializers.ManageInstancePolicySerializer(
policy, data={"block_all": False}, partial=True
policy, data={param: False}, partial=True
)
serializer.is_valid(raise_exception=True)
serializer.save()
policy.refresh_from_db()
assert policy.block_all is False
assert getattr(policy, param) is False
assert on_commit.call_count == 0

Wyświetl plik

@ -119,7 +119,7 @@ export default {
label: this.$gettext("Silence notifications"),
},
rejectMedia: {
help: this.$gettext("Do not download any media file (audio, album cover, account avatar…) from this account or domain."),
help: this.$gettext("Do not download any media file (audio, album cover, account avatar…) from this account or domain. This will purge existing content as well."),
label: this.$gettext("Reject media"),
}
}