From e5abdc097fc57da3a9c4f58654f1c31bc92e5e6b Mon Sep 17 00:00:00 2001 From: Ryan Barrett Date: Wed, 22 Nov 2023 21:40:36 -0800 Subject: [PATCH] implement outbox only first page. for #383 --- activitypub.py | 19 +++++++++++++++---- tests/test_activitypub.py | 36 +++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/activitypub.py b/activitypub.py index 0fffb26..485ef41 100644 --- a/activitypub.py +++ b/activitypub.py @@ -33,7 +33,7 @@ from common import ( subdomain_wrap, unwrap, ) -from models import Follower, Object, User +from models import fetch_objects, Follower, Object, User from protocol import Protocol import webfinger @@ -932,18 +932,29 @@ def follower_collection(id, collection): @app.get(f'/ap/web//outbox') # special case Web users without /ap/web/ prefix, for backward compatibility @app.get(f'//outbox') +@flask_util.cached(cache, CACHE_TIME) def outbox(id): protocol = Protocol.for_request(fed='web') - assert protocol + if not protocol: + error(f"Couldn't determine protocol", status=404) + + user = protocol.get_by_id(id) + if not user: + error(f'User {id} not found', status=404) + + query = Object.query(Object.users == user.key) + objects, before, after = fetch_objects(query, by=Object.updated, user=user) + return { '@context': 'https://www.w3.org/ns/activitystreams', 'id': request.url, 'summary': f"{id}'s outbox", 'type': 'OrderedCollection', - 'totalItems': 0, + # TODO. needs to handle deleted + # 'totalItems': query.count(), 'first': { 'type': 'CollectionPage', 'partOf': request.base_url, - 'items': [], + 'items': [ActivityPub.convert(obj) for obj in objects], }, }, {'Content-Type': as2.CONTENT_TYPE} diff --git a/tests/test_activitypub.py b/tests/test_activitypub.py index c4d3eba..07b70e3 100644 --- a/tests/test_activitypub.py +++ b/tests/test_activitypub.py @@ -1550,25 +1550,44 @@ class ActivityPubTest(TestCase): 'items': [ACTOR], }, resp.json) - def test_outbox_fake(self, *_): - self.make_user('foo.com', cls=Fake) - resp = self.client.get(f'/ap/foo.com/outbox', + def test_outbox_fake_empty(self, *_): + self.make_user('fake:foo', cls=Fake) + resp = self.client.get(f'/ap/fake:foo/outbox', base_url='https://fa.brid.gy') self.assertEqual(200, resp.status_code) self.assertEqual({ '@context': 'https://www.w3.org/ns/activitystreams', - 'id': 'https://fa.brid.gy/ap/foo.com/outbox', - 'summary': "foo.com's outbox", + 'id': 'https://fa.brid.gy/ap/fake:foo/outbox', + 'summary': "fake:foo's outbox", 'type': 'OrderedCollection', - 'totalItems': 0, 'first': { 'type': 'CollectionPage', - 'partOf': 'https://fa.brid.gy/ap/foo.com/outbox', + 'partOf': 'https://fa.brid.gy/ap/fake:foo/outbox', 'items': [], }, }, resp.json) - def test_outbox_web(self, *_): + def test_outbox_fake_objects(self, *_): + user = self.make_user('fake:foo', cls=Fake) + for i, obj in enumerate([REPLY, MENTION, LIKE, DELETE]): + self.store_object(id=str(i), users=[user.key], as2=obj) + + resp = self.client.get(f'/ap/fake:foo/outbox', + base_url='https://fa.brid.gy') + self.assertEqual(200, resp.status_code) + self.assertEqual({ + '@context': 'https://www.w3.org/ns/activitystreams', + 'id': 'https://fa.brid.gy/ap/fake:foo/outbox', + 'summary': "fake:foo's outbox", + 'type': 'OrderedCollection', + 'first': { + 'type': 'CollectionPage', + 'partOf': 'https://fa.brid.gy/ap/fake:foo/outbox', + 'items': [DELETE, LIKE, MENTION, REPLY], + }, + }, resp.json) + + def test_outbox_web_empty(self, *_): resp = self.client.get(f'/user.com/outbox') self.assertEqual(200, resp.status_code) self.assertEqual({ @@ -1576,7 +1595,6 @@ class ActivityPubTest(TestCase): 'id': 'http://localhost/user.com/outbox', 'summary': "user.com's outbox", 'type': 'OrderedCollection', - 'totalItems': 0, 'first': { 'type': 'CollectionPage', 'partOf': 'http://localhost/user.com/outbox',