activitypub: store Create inner objects in their own Objects

pull/438/head
Ryan Barrett 2023-03-03 15:12:51 -08:00
rodzic fa03958d89
commit fa2a9a1afe
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
2 zmienionych plików z 41 dodań i 26 usunięć

Wyświetl plik

@ -135,9 +135,7 @@ def inbox(domain=None):
elif obj.type not in SUPPORTED_TYPES:
error(f'Sorry, {obj.type} activities are not supported yet.', status=501)
inner_obj = obj.as1.get('object') or {}
if isinstance(inner_obj, str):
inner_obj = {'id': inner_obj}
inner_obj = as1.get_object(obj.as1)
inner_obj_id = inner_obj.get('id')
# load user
@ -149,6 +147,20 @@ def inbox(domain=None):
verify_signature(user)
# check that this activity is public. only do this check for creates, not
# like, follow, or other activity types, since Mastodon doesn't currently
# mark those as explicitly public. Use as2's is_public instead of as1's
# because as1's interprets unlisted as true.
if obj.type in ('post', 'create') and not as2.is_public(obj.as2):
logger.info('Dropping non-public activity')
return 'OK'
# store inner object
if obj.type in ('post', 'create', 'update') and inner_obj.keys() > set(['id']):
to_update = Object.get_by_id(inner_obj_id) or Object(id=inner_obj_id)
to_update.populate(as2=obj.as2['object'], source_protocol='activitypub')
to_update.put()
# handle activity!
if obj.type == 'stop-following':
# granary doesn't yet handle three-actor undo follows, eg Eve undoes
@ -179,10 +191,6 @@ def inbox(domain=None):
if not inner_obj_id:
error("Couldn't find id of object to update")
to_update = Object.get_by_id(inner_obj_id) or Object(id=inner_obj_id)
to_update.populate(as2=obj.as2.get('object'), source_protocol='activitypub')
to_update.put()
obj.status = 'complete'
obj.put()
return 'OK'
@ -224,25 +232,16 @@ def inbox(domain=None):
common.send_webmentions(as2.to_as1(activity), obj, proxy=True)
# deliver original posts and reposts to followers
if obj.type in ('share', 'create', 'post'):
# check that this activity is public. only do this check for Creates,
# not Like, Follow, or other activity types, since Mastodon doesn't
# currently mark those as explicitly public.
if not as1.is_public(obj.as1):
logger.info('Dropping non-public activity')
return 'OK'
if obj.type in ('share', 'create', 'post') and actor and actor_id:
logger.info(f'Delivering to followers of {actor_id}')
for f in Follower.query(Follower.dest == actor_id,
projection=[Follower.src]):
if f.src not in obj.domains:
obj.domains.append(f.src)
if obj.domains and 'feed' not in obj.labels:
obj.labels.append('feed')
if actor and actor_id:
logger.info(f'Delivering to followers of {actor_id}')
for f in Follower.query(Follower.dest == actor_id,
projection=[Follower.src]):
if f.src not in obj.domains:
obj.domains.append(f.src)
if obj.domains and 'feed' not in obj.labels:
obj.labels.append('feed')
if (obj.as1.get('objectType') == 'activity'
and 'activity' not in obj.labels):
if obj.as1.get('objectType') == 'activity' and 'activity' not in obj.labels:
obj.labels.append('activity')
obj.put()

Wyświetl plik

@ -303,6 +303,10 @@ class ActivityPubTest(testutil.TestCase):
'labels': ['notification', 'activity'],
},
*mocks)
self.assert_object(REPLY_OBJECT['id'],
source_protocol='activitypub',
as2=REPLY_OBJECT,
type='comment')
def _test_inbox_reply(self, reply, expected_props, mock_head, mock_get, mock_post):
mock_head.return_value = requests_response(url='http://or.ig/post')
@ -380,6 +384,10 @@ class ActivityPubTest(testutil.TestCase):
type='post',
labels=['activity', 'feed'],
object_ids=[NOTE_OBJECT['id']])
self.assert_object(NOTE_OBJECT['id'],
source_protocol='activitypub',
as2=NOTE_OBJECT,
type='note')
def test_repost_of_federated_post(self, mock_head, mock_get, mock_post):
mock_head.return_value = requests_response(url='https://foo.com/orig')
@ -480,7 +488,7 @@ class ActivityPubTest(testutil.TestCase):
self.assertEqual(200, got.status_code, got.get_data(as_text=True))
obj = Object.get_by_id(not_public['id'])
self.assertEqual(['activity'], obj.labels)
self.assertEqual([], obj.labels)
self.assertEqual([], obj.domains)
self.assertIsNone(Object.get_by_id(not_public['object']['id']))
@ -506,6 +514,14 @@ class ActivityPubTest(testutil.TestCase):
*mocks,
)
# redirect unwrap
expected_as2 = copy.deepcopy(MENTION_OBJECT)
expected_as2['tag'][1]['href'] = 'https://tar.get/'
self.assert_object(MENTION_OBJECT['id'],
source_protocol='activitypub',
as2=expected_as2,
type='note')
def _test_inbox_mention(self, mention, expected_props, mock_head, mock_get, mock_post):
mock_get.return_value = requests_response(
'<html><head><link rel="webmention" href="/webmention"></html>')