From a5fe105b6cef1049119c1fbeec2bf15a4966c1fd Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Tue, 6 Aug 2019 23:56:55 +0300 Subject: [PATCH] Support incoming retraction of ActivityPub shares --- federation/entities/activitypub/mappers.py | 11 +++++++++-- .../entities/activitypub/test_mappers.py | 11 ++++++++++- .../tests/fixtures/payloads/activitypub.py | 19 +++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/federation/entities/activitypub/mappers.py b/federation/entities/activitypub/mappers.py index a3eb952..7757ea9 100644 --- a/federation/entities/activitypub/mappers.py +++ b/federation/entities/activitypub/mappers.py @@ -21,7 +21,6 @@ MAPPINGS = { "Note": ActivitypubPost, "Page": ActivitypubPost, "Person": ActivitypubProfile, - "Undo": ActivitypubFollow, # Technically not correct, but for now we support only undoing a follow of a profile } OBJECTS = ( @@ -31,15 +30,23 @@ OBJECTS = ( "Person", ) +UNDO_MAPPINGS = { + "Follow": ActivitypubFollow, + "Announce": ActivitypubRetraction, +} def element_to_objects(payload: Dict) -> List: """ Transform an Element to a list of entities. """ + cls = None entities = [] is_object = True if payload.get('type') in OBJECTS else False if payload.get('type') == "Delete": cls = ActivitypubRetraction + elif payload.get('type') == "Undo": + if isinstance(payload.get('object'), dict): + cls = UNDO_MAPPINGS.get(payload["object"]["type"]) elif isinstance(payload.get('object'), dict) and payload["object"].get('type'): if payload["object"]["type"] == "Note" and payload["object"].get("inReplyTo"): cls = ActivitypubComment @@ -233,7 +240,7 @@ def transform_attribute(key: str, value: Union[str, Dict, int], transformed: Dic transformed["target_id"] = value elif key == "name": transformed["name"] = value - elif key == "object": + elif key == "object" and not is_object: if isinstance(value, dict): if cls == ActivitypubAccept: transformed["target_id"] = value.get("id") diff --git a/federation/tests/entities/activitypub/test_mappers.py b/federation/tests/entities/activitypub/test_mappers.py index 3b254cb..f3a4350 100644 --- a/federation/tests/entities/activitypub/test_mappers.py +++ b/federation/tests/entities/activitypub/test_mappers.py @@ -9,7 +9,7 @@ from federation.entities.activitypub.mappers import message_to_objects, get_outb from federation.entities.base import Accept, Follow, Profile, Post, Comment from federation.tests.fixtures.payloads import ( ACTIVITYPUB_FOLLOW, ACTIVITYPUB_PROFILE, ACTIVITYPUB_PROFILE_INVALID, ACTIVITYPUB_UNDO_FOLLOW, ACTIVITYPUB_POST, - ACTIVITYPUB_COMMENT, ACTIVITYPUB_RETRACTION, ACTIVITYPUB_SHARE) + ACTIVITYPUB_COMMENT, ACTIVITYPUB_RETRACTION, ACTIVITYPUB_SHARE, ACTIVITYPUB_RETRACTION_SHARE) from federation.types import UserType, ReceiverVariant @@ -180,6 +180,15 @@ class TestActivitypubEntityMappersReceive: assert entity.target_id == "https://friendica.feneas.org/objects/76158462-165d-3386-aa23-ba2090614385" assert entity.entity_type == "Object" + def test_message_to_objects_retraction__share(self): + entities = message_to_objects(ACTIVITYPUB_RETRACTION_SHARE, "https://mastodon.social/users/jaywink") + assert len(entities) == 1 + entity = entities[0] + assert isinstance(entity, ActivitypubRetraction) + assert entity.actor_id == "https://mastodon.social/users/jaywink" + assert entity.target_id == "https://mastodon.social/users/jaywink/statuses/102571932479036987/activity" + assert entity.entity_type == "Object" + @pytest.mark.skip def test_message_to_objects_reshare_extra_properties(self): entities = message_to_objects(DIASPORA_RESHARE_WITH_EXTRA_PROPERTIES, "alice@example.org") diff --git a/federation/tests/fixtures/payloads/activitypub.py b/federation/tests/fixtures/payloads/activitypub.py index 409a562..1cf6de9 100644 --- a/federation/tests/fixtures/payloads/activitypub.py +++ b/federation/tests/fixtures/payloads/activitypub.py @@ -183,6 +183,25 @@ ACTIVITYPUB_RETRACTION = { }, } +ACTIVITYPUB_RETRACTION_SHARE = {'@context': 'https://www.w3.org/ns/activitystreams', + 'id': 'https://mastodon.social/users/jaywink#announces/102571932479036987/undo', + 'type': 'Undo', + 'actor': 'https://mastodon.social/users/jaywink', + 'to': ['https://www.w3.org/ns/activitystreams#Public'], + 'object': {'id': 'https://mastodon.social/users/jaywink/statuses/102571932479036987/activity', + 'type': 'Announce', + 'actor': 'https://mastodon.social/users/jaywink', + 'published': '2019-08-06T20:31:21Z', + 'to': ['https://www.w3.org/ns/activitystreams#Public'], + 'cc': ['https://mastodon.art/users/asterii', + 'https://mastodon.social/users/jaywink/followers'], + 'object': 'https://mastodon.art/users/asterii/statuses/102571181579804095', + 'atomUri': 'https://mastodon.social/users/jaywink/statuses/102571932479036987/activity'}, + 'signature': {'type': 'RsaSignature2017', + 'creator': 'https://mastodon.social/users/jaywink#main-key', + 'created': '2019-08-06T20:32:23Z', + 'signatureValue': 'erI90OrrLqK1DiTqb4OO72XLcE7m74Fs4cH6s0plKKELHa7BZFQmtQYXKEgA9LwIUdSRrIurAUiaDWAw2sQZDg7opYo9x3z+GJDMZ3KxhBND7iHO8ZeGhV1ZBBKUMuBb3BfhOkd3ADp+RQ/fHcw6kOcViV2VsQduinAgQRpiutmGCLd/7eshqSF/aL4tFoAOyCskkm/5JDMNp2nnHNoXXJ+SZf7a8C6YPNDxWd7GzyQNeWkTBBdCJBPvS4HI0wQrTWemBvy6uP8k5QQ7FnqrrRrk/7zrcibFSInuYxiRTRV++rQ3irIbXNtoLhWQd36Iu5U22BclmkS1AAVBDUIj8w=='}} + ACTIVITYPUB_SHARE = { '@context': 'https://www.w3.org/ns/activitystreams', 'id': 'https://mastodon.social/users/jaywink/statuses/102560701449465612/activity',