kopia lustrzana https://github.com/snarfed/bridgy-fed
rodzic
7e2fbd1ed0
commit
3feb44e414
|
@ -83,9 +83,9 @@ def inbox(domain=None):
|
|||
actor_id = actor.get('id') if isinstance(actor, dict) else actor
|
||||
logger.info(f'Got {type} activity from {actor_id}: {json_dumps(activity, indent=2)}')
|
||||
|
||||
obj = activity.get('object') or {}
|
||||
if isinstance(obj, str):
|
||||
obj = {'id': obj}
|
||||
obj_as2 = activity.get('object') or {}
|
||||
if isinstance(obj_as2, str):
|
||||
obj_as2 = {'id': obj_as2}
|
||||
|
||||
if type == 'Accept': # eg in response to a Follow
|
||||
return '' # noop
|
||||
|
@ -94,25 +94,29 @@ def inbox(domain=None):
|
|||
|
||||
# TODO: verify signature if there is one
|
||||
|
||||
if type == 'Undo' and obj.get('type') == 'Follow':
|
||||
if type == 'Undo' and obj_as2.get('type') == 'Follow':
|
||||
# skip actor fetch below; we don't need it to undo a follow
|
||||
undo_follow(redirect_unwrap(activity))
|
||||
return ''
|
||||
elif type == 'Update':
|
||||
if obj.get('type') == 'Person':
|
||||
return '' # noop
|
||||
else:
|
||||
error(f'Sorry, {type} activities are not supported yet.', status=501)
|
||||
elif type == 'Delete':
|
||||
# we currently only actually delete followers for Deletes that are sent
|
||||
# to the shared inbox, not individual users' inboxes, to help scaling
|
||||
# background: https://github.com/snarfed/bridgy-fed/issues/284
|
||||
if domain:
|
||||
logger.info('Skipping Delete sent to individual user inbox')
|
||||
return 'OK'
|
||||
|
||||
id = obj.get('id') if isinstance(obj, dict) else obj
|
||||
if not isinstance(id, str):
|
||||
elif type == 'Update':
|
||||
id = obj_as2.get('id')
|
||||
if not id:
|
||||
error("Couldn't find id of object to update")
|
||||
|
||||
logger.info(f'updating Object {id}')
|
||||
obj = Object.get_by_id(id) or Object(id=id)
|
||||
obj.as2 = json_dumps(obj_as2)
|
||||
obj_as1 = as2.to_as1(obj_as2)
|
||||
obj.as1 = json_dumps(obj_as1)
|
||||
obj.type = as1.object_type(obj_as1)
|
||||
obj.source_protocol = 'activitypub'
|
||||
obj.put()
|
||||
return 'OK'
|
||||
|
||||
elif type == 'Delete':
|
||||
id = obj_as2.get('id')
|
||||
if not id:
|
||||
error("Couldn't find id of object to delete")
|
||||
|
||||
obj = Object.get_by_id(id)
|
||||
|
@ -138,7 +142,7 @@ def inbox(domain=None):
|
|||
|
||||
# fetch object if necessary so we can render it in feeds
|
||||
if type in FETCH_OBJECT_TYPES and isinstance(activity.get('object'), str):
|
||||
obj = activity['object'] = common.get_as2(activity['object'], user=user).json()
|
||||
obj_as2 = activity['object'] = common.get_as2(activity['object'], user=user).json()
|
||||
|
||||
activity_unwrapped = redirect_unwrap(activity)
|
||||
if type == 'Follow':
|
||||
|
@ -155,7 +159,7 @@ def inbox(domain=None):
|
|||
object_ids=as1.get_ids(activity_as1, 'object'))
|
||||
|
||||
# deliver original posts and reposts to followers
|
||||
if ((type == 'Create' and not activity.get('inReplyTo') and not obj.get('inReplyTo'))
|
||||
if ((type == 'Create' and not activity.get('inReplyTo') and not obj_as2.get('inReplyTo'))
|
||||
or type == 'Announce'):
|
||||
# check that this activity is public. only do this check for Creates,
|
||||
# not Like, Follow, or other activity types, since Mastodon doesn't
|
||||
|
|
|
@ -543,9 +543,8 @@ class ActivityPubTest(testutil.TestCase):
|
|||
labels=['notification', 'activity'],
|
||||
object_ids=[LIKE['object']])
|
||||
|
||||
def test_inbox_follow_accept_with_id(self, mock_head, mock_get, mock_post):
|
||||
self._test_inbox_follow_accept(FOLLOW_WRAPPED, ACCEPT,
|
||||
mock_head, mock_get, mock_post)
|
||||
def test_inbox_follow_accept_with_id(self, *mocks):
|
||||
self._test_inbox_follow_accept(FOLLOW_WRAPPED, ACCEPT, *mocks)
|
||||
|
||||
follow = copy.deepcopy(FOLLOW_WITH_ACTOR)
|
||||
follow['url'] = 'https://mastodon.social/users/swentel#followed-https://foo.com/'
|
||||
|
@ -564,7 +563,7 @@ class ActivityPubTest(testutil.TestCase):
|
|||
follower = Follower.query().get()
|
||||
self.assertEqual(FOLLOW_WRAPPED_WITH_ACTOR, json_loads(follower.last_follow))
|
||||
|
||||
def test_inbox_follow_accept_with_object(self, mock_head, mock_get, mock_post):
|
||||
def test_inbox_follow_accept_with_object(self, *mocks):
|
||||
wrapped_user = {
|
||||
'id': FOLLOW_WRAPPED['object'],
|
||||
'url': FOLLOW_WRAPPED['object'],
|
||||
|
@ -580,7 +579,7 @@ class ActivityPubTest(testutil.TestCase):
|
|||
accept = copy.deepcopy(ACCEPT)
|
||||
accept['actor'] = accept['object']['object'] = wrapped_user
|
||||
|
||||
self._test_inbox_follow_accept(follow, accept, mock_head, mock_get, mock_post)
|
||||
self._test_inbox_follow_accept(follow, accept, *mocks)
|
||||
|
||||
follower = Follower.query().get()
|
||||
follow.update({
|
||||
|
@ -746,22 +745,7 @@ class ActivityPubTest(testutil.TestCase):
|
|||
mock_post.assert_not_called()
|
||||
self.assertEqual(0, Object.query().count())
|
||||
|
||||
def test_individual_inbox_delete_actor_noop(self, mock_head, mock_get, mock_post):
|
||||
"""Deletes sent to individual users' inboxes do nothing."""
|
||||
follower = Follower.get_or_create('foo.com', DELETE['actor'])
|
||||
followee = Follower.get_or_create(DELETE['actor'], 'snarfed.org')
|
||||
# other unrelated follower
|
||||
other = Follower.get_or_create('foo.com', 'https://mas.to/users/other')
|
||||
self.assertEqual(3, Follower.query().count())
|
||||
|
||||
got = self.client.post('/foo.com/inbox', json=DELETE)
|
||||
self.assertEqual(200, got.status_code)
|
||||
self.assertEqual('active', follower.key.get().status)
|
||||
self.assertEqual('active', followee.key.get().status)
|
||||
self.assertEqual('active', other.key.get().status)
|
||||
|
||||
def test_shared_inbox_delete_actor(self, mock_head, mock_get, mock_post):
|
||||
"""Deletes sent to the shared inbox actually deactivate followers."""
|
||||
def test_delete_actor(self, _, __, ___):
|
||||
follower = Follower.get_or_create('foo.com', DELETE['actor'])
|
||||
followee = Follower.get_or_create(DELETE['actor'], 'snarfed.org')
|
||||
# other unrelated follower
|
||||
|
@ -774,7 +758,7 @@ class ActivityPubTest(testutil.TestCase):
|
|||
self.assertEqual('inactive', followee.key.get().status)
|
||||
self.assertEqual('active', other.key.get().status)
|
||||
|
||||
def test_delete_note(self, mock_head, mock_get, mock_post):
|
||||
def test_delete_note(self, _, __, ___):
|
||||
key = Object(id='http://an/obj', as1='{}').put()
|
||||
|
||||
resp = self.client.post('/inbox', json={
|
||||
|
@ -784,15 +768,23 @@ class ActivityPubTest(testutil.TestCase):
|
|||
self.assertEqual(200, resp.status_code)
|
||||
self.assertTrue(key.get().deleted)
|
||||
|
||||
def test_update_person_noop(self, _, __, ___):
|
||||
"""Updates to Person objects do nothing."""
|
||||
got = self.client.post('/inbox', json=UPDATE_PERSON)
|
||||
self.assertEqual(200, got.status_code)
|
||||
def test_update_note(self, _, __, ___):
|
||||
key = Object(id='https://a/note', as1='{}').put()
|
||||
|
||||
def test_update_note_not_implemented(self, _, __, ___):
|
||||
"""Updates to non-Person objects are not implemented."""
|
||||
got = self.client.post('/inbox', json=UPDATE_NOTE)
|
||||
self.assertEqual(501, got.status_code)
|
||||
resp = self.client.post('/inbox', json=UPDATE_NOTE)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
obj = UPDATE_NOTE['object']
|
||||
self.assert_object('https://a/note', type='note', as2=obj,
|
||||
as1=as2.to_as1(obj), source_protocol='activitypub')
|
||||
|
||||
def test_update_unknown(self, _, __, ___):
|
||||
resp = self.client.post('/inbox', json=UPDATE_NOTE)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
obj = UPDATE_NOTE['object']
|
||||
self.assert_object('https://a/note', type='note', as2=obj,
|
||||
as1=as2.to_as1(obj), source_protocol='activitypub')
|
||||
|
||||
def test_inbox_webmention_discovery_connection_fails(self, mock_head,
|
||||
mock_get, mock_post):
|
||||
|
|
Ładowanie…
Reference in New Issue