From 04d710e690a0ef4fc1cbc18a2af95d9cd3a7349b Mon Sep 17 00:00:00 2001 From: Eliot Berriot <contact@eliotberriot.com> Date: Fri, 6 Apr 2018 14:45:06 +0200 Subject: [PATCH] Library can now receive import info from followed instances --- api/funkwhale_api/federation/activity.py | 2 + api/funkwhale_api/federation/actors.py | 29 ++++++++++++ api/tests/federation/test_actors.py | 57 ++++++++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/api/funkwhale_api/federation/activity.py b/api/funkwhale_api/federation/activity.py index b253955c..db71bd4f 100644 --- a/api/funkwhale_api/federation/activity.py +++ b/api/funkwhale_api/federation/activity.py @@ -44,10 +44,12 @@ ACTIVITY_TYPES = [ OBJECT_TYPES = [ 'Article', 'Audio', + 'Collection', 'Document', 'Event', 'Image', 'Note', + 'OrderedCollection', 'Page', 'Place', 'Profile', diff --git a/api/funkwhale_api/federation/actors.py b/api/funkwhale_api/federation/actors.py index 0da78fdb..fa1b5628 100644 --- a/api/funkwhale_api/federation/actors.py +++ b/api/funkwhale_api/federation/actors.py @@ -176,6 +176,35 @@ class LibraryActor(SystemActor): def manually_approves_followers(self): return settings.FEDERATION_MUSIC_NEEDS_APPROVAL + def handle_create(self, ac, sender): + from funkwhale_api.music.serializers import ( + AudioCollectionImportSerializer) + + library = self.get_actor_instance() + if not library.following.filter(url=sender.url).exists(): + logger.info( + 'Skipping import, we\'re not following %s', sender.url) + return + + if ac['object']['type'] != 'Collection': + return + + if ac['object']['totalItems'] <= 0: + return + + items = ac['object']['items'] + + serializer = AudioCollectionImportSerializer( + data=ac['object'], + context={'sender': sender}) + + if not serializer.is_valid(): + logger.error( + 'Cannot import audio collection: %s', serializer.errors) + return + + serializer.save() + class TestActor(SystemActor): id = 'test' diff --git a/api/tests/federation/test_actors.py b/api/tests/federation/test_actors.py index be24a536..7a5e0d31 100644 --- a/api/tests/federation/test_actors.py +++ b/api/tests/federation/test_actors.py @@ -10,6 +10,7 @@ from funkwhale_api.federation import actors from funkwhale_api.federation import models from funkwhale_api.federation import serializers from funkwhale_api.federation import utils +from funkwhale_api.music import models as music_models def test_actor_fetching(r_mock): @@ -368,3 +369,59 @@ def test_library_actor_handles_follow_auto_approval( accept_follow.assert_called_once_with( library_actor, data, actor ) + + +def test_library_actor_handle_create_audio_not_following(mocker, factories): + # when we receive inbox create audio, we should not do anything + # if we're not actually following the sender + mocked_create = mocker.patch( + 'funkwhale_api.music.serializers.AudioCollectionImportSerializer.create' + ) + actor = factories['federation.Actor']() + library_actor = actors.SYSTEM_ACTORS['library'].get_actor_instance() + data = { + 'actor': actor.url, + 'type': 'Create', + 'id': 'http://test.federation/audio/create', + 'object': { + 'id': 'https://batch.import', + 'type': 'Collection', + 'totalItems': 2, + 'items': factories['federation.Audio'].create_batch(size=2) + }, + } + library_actor.system_conf.post_inbox(data, actor=actor) + + mocked_create.assert_not_called() + music_models.ImportBatch.objects.count() == 0 + + +def test_library_actor_handle_create_audio(mocker, factories): + library_actor = actors.SYSTEM_ACTORS['library'].get_actor_instance() + follow = factories['federation.Follow'](actor=library_actor) + + data = { + 'actor': follow.target.url, + 'type': 'Create', + 'id': 'http://test.federation/audio/create', + 'object': { + 'id': 'https://batch.import', + 'type': 'Collection', + 'totalItems': 2, + 'items': factories['federation.Audio'].create_batch(size=2) + }, + } + + library_actor.system_conf.post_inbox(data, actor=follow.target) + + batch = follow.target.import_batches.latest('id') + + assert batch.federation_source == data['object']['id'] + assert batch.federation_actor == follow.target + assert batch.jobs.count() == 2 + + jobs = list(batch.jobs.order_by('id')) + for i, a in enumerate(data['object']['items']): + job = jobs[i] + assert job.federation_source == a['id'] + assert job.source == a['url']['href'] -- GitLab