diff --git a/protocol.py b/protocol.py index cd489cf..49dddb5 100644 --- a/protocol.py +++ b/protocol.py @@ -603,6 +603,8 @@ class Protocol: if authed_as: assert isinstance(authed_as, str) + # TODO: handle domain vs URL for web users, eg + # "actor https://tiffwhite.me/ isn't authed user tiffwhite.me" if actor != authed_as: logger.warning(f"actor {actor} isn't authed user {authed_as}") diff --git a/tests/test_follow.py b/tests/test_follow.py index e5aeac9..d98f425 100644 --- a/tests/test_follow.py +++ b/tests/test_follow.py @@ -170,7 +170,8 @@ class FollowTest(TestCase): ) state = util.encode_oauth_state(self.state) - resp = self.client.get(f'/follow/callback?code=my_code&state={state}') + resp = self.client.get(f'/follow/callback?code=my_code&state={state}', + base_url='https://fed.brid.gy/') self.check('@foo@ba.r', resp, FOLLOW_ADDRESS, mock_get, mock_post) mock_get.assert_has_calls(( self.req('https://ba.r/.well-known/webfinger?resource=acct:foo@ba.r'), @@ -189,7 +190,8 @@ class FollowTest(TestCase): self.state['state'] = 'https://ba.r/actor' state = util.encode_oauth_state(self.state) - resp = self.client.get(f'/follow/callback?code=my_code&state={state}') + resp = self.client.get(f'/follow/callback?code=my_code&state={state}', + base_url='https://fed.brid.gy/') self.check('https://ba.r/actor', resp, FOLLOW_URL, mock_get, mock_post) def test_callback_stored_followee_with_our_as1(self, mock_get, mock_post): @@ -206,7 +208,8 @@ class FollowTest(TestCase): self.state['state'] = 'https://ba.r/id' state = util.encode_oauth_state(self.state) - resp = self.client.get(f'/follow/callback?code=my_code&state={state}') + resp = self.client.get(f'/follow/callback?code=my_code&state={state}', + base_url='https://fed.brid.gy/') follow_with_profile_link = { **FOLLOW_URL, @@ -236,7 +239,8 @@ class FollowTest(TestCase): self.state['state'] = 'https://ba.r/actor' state = util.encode_oauth_state(self.state) - resp = self.client.get(f'/follow/callback?code=my_code&state={state}') + resp = self.client.get(f'/follow/callback?code=my_code&state={state}', + base_url='https://fed.brid.gy/') self.check('https://ba.r/actor', resp, FOLLOW_URL, mock_get, mock_post, expected_follow_as1={ @@ -272,7 +276,8 @@ class FollowTest(TestCase): self.state['state'] = 'https://ba.r/actor' state = util.encode_oauth_state(self.state) - resp = self.client.get(f'/follow/callback?code=my_code&state={state}') + resp = self.client.get(f'/follow/callback?code=my_code&state={state}', + base_url='https://fed.brid.gy/') self.check('https://ba.r/actor', resp, FOLLOW_URL, mock_get, mock_post) @@ -350,7 +355,7 @@ class FollowTest(TestCase): sig_template.startswith('keyId="http://localhost/alice.com#key"'), sig_template) - follow_id = f'http://localhost/web/alice.com/following#2022-01-02T03:04:05-{input}' + follow_id = f'https://fed.brid.gy/web/alice.com/following#2022-01-02T03:04:05-{input}' followers = Follower.query().fetch() followee = ActivityPub(id='https://ba.r/id').key @@ -400,7 +405,8 @@ class FollowTest(TestCase): self.state['state'] = 'https://ba.r/actor' state = util.encode_oauth_state(self.state) - resp = self.client.get(f'/follow/callback?code=my_code&state={state}') + resp = self.client.get(f'/follow/callback?code=my_code&state={state}', + base_url='https://fed.brid.gy/') self.assertEqual(302, resp.status_code) self.assertEqual('/web/www.alice.com/following', resp.headers['Location']) @@ -413,7 +419,7 @@ class FollowTest(TestCase): del expected_follow_as1['to'] followee = ActivityPub(id='https://ba.r/id').key follow_obj = self.assert_object( - f'http://localhost/web/{id}', + f'https://fed.brid.gy/web/{id}', users=[user.key], notify=[followee], status='complete', @@ -450,7 +456,8 @@ class FollowTest(TestCase): self.state['state'] = 'https://ba.r/actor' state = util.encode_oauth_state(self.state) - resp = self.client.get(f'/follow/callback?code=my_code&state={state}') + resp = self.client.get(f'/follow/callback?code=my_code&state={state}', + base_url='https://fed.brid.gy/') self.check('https://ba.r/actor', resp, FOLLOW_URL, mock_get, mock_post) self.assertEqual( @@ -466,13 +473,14 @@ class FollowTest(TestCase): requests_response('OK'), # AP Follow to inbox ) - with self.client.session_transaction() as ctx_session: + with self.client.session_transaction(base_url='https://fed.brid.gy/') \ + as ctx_session: ctx_session['indieauthed-me'] = 'https://alice.com' resp = self.client.post('/follow/start', data={ 'me': 'https://alice.com', 'address': 'https://ba.r/actor', - }) + }, base_url='https://fed.brid.gy/') self.check('https://ba.r/actor', resp, FOLLOW_URL, mock_get, mock_post) def test_indieauthed_session_wrong_me(self, mock_get, mock_post): @@ -480,7 +488,8 @@ class FollowTest(TestCase): requests_response(''), # IndieAuth endpoint discovery ) - with self.client.session_transaction() as ctx_session: + with self.client.session_transaction(base_url='https://fed.brid.gy/') \ + as ctx_session: ctx_session['indieauthed-me'] = 'https://eve.com' resp = self.client.post('/follow/start', data={ @@ -544,7 +553,8 @@ class UnfollowTest(TestCase): requests_response('OK'), # AP Undo Follow to inbox ) - resp = self.client.get(f'/unfollow/callback?code=my_code&state={self.state}') + resp = self.client.get(f'/unfollow/callback?code=my_code&state={self.state}', + base_url='https://fed.brid.gy/') self.check(resp, UNDO_FOLLOW, mock_get, mock_post) def test_callback_last_follow_object_str(self, mock_get, mock_post): @@ -570,7 +580,8 @@ class UnfollowTest(TestCase): undo = copy.deepcopy(UNDO_FOLLOW) undo['object']['object'] = FOLLOWEE['id'] - resp = self.client.get(f'/unfollow/callback?code=my_code&state={self.state}') + resp = self.client.get(f'/unfollow/callback?code=my_code&state={self.state}', + base_url='https://fed.brid.gy/') self.check(resp, undo, mock_get, mock_post) def check(self, resp, expected_undo, mock_get, mock_post): @@ -596,7 +607,7 @@ class UnfollowTest(TestCase): self.assertEqual('inactive', follower.status) self.assert_object( - 'http://localhost/web/alice.com/following#undo-2022-01-02T03:04:05-https://ba.r/id', + 'https://fed.brid.gy/web/alice.com/following#undo-2022-01-02T03:04:05-https://ba.r/id', users=[self.user.key], notify=[ActivityPub(id='https://ba.r/id').key], status='complete', @@ -630,7 +641,8 @@ class UnfollowTest(TestCase): 'me': 'https://alice.com', 'state': self.follower.key.id(), }) - resp = self.client.get(f'/unfollow/callback?code=my_code&state={state}') + resp = self.client.get(f'/unfollow/callback?code=my_code&state={state}', + base_url='https://fed.brid.gy/') self.assertEqual(302, resp.status_code) self.assertEqual('/web/www.alice.com/following', resp.headers['Location']) @@ -658,7 +670,7 @@ class UnfollowTest(TestCase): self.assertEqual('inactive', follower.status) self.assert_object( - 'http://localhost/web/www.alice.com/following#undo-2022-01-02T03:04:05-https://ba.r/id', + 'https://fed.brid.gy/web/www.alice.com/following#undo-2022-01-02T03:04:05-https://ba.r/id', users=[user.key], notify=[ActivityPub(id='https://ba.r/id').key], status='complete', @@ -686,7 +698,8 @@ class UnfollowTest(TestCase): requests_response('OK'), # AP Undo Follow to inbox ) - resp = self.client.get(f'/unfollow/callback?code=my_code&state={self.state}') + resp = self.client.get(f'/unfollow/callback?code=my_code&state={self.state}', + base_url='https://fed.brid.gy/') self.assertEqual([f'Unfollowed ba.r/url.'], get_flashed_messages()) self.check(resp, UNDO_FOLLOW, mock_get, mock_post) @@ -698,13 +711,14 @@ class UnfollowTest(TestCase): requests_response('OK'), # AP Undo Follow to inbox ) - with self.client.session_transaction() as ctx_session: + with self.client.session_transaction(base_url='https://fed.brid.gy/') \ + as ctx_session: ctx_session['indieauthed-me'] = 'https://alice.com' resp = self.client.post('/unfollow/start', data={ 'me': 'https://alice.com', 'key': self.follower.key.id(), - }) + }, base_url='https://fed.brid.gy/') self.check(resp, UNDO_FOLLOW, mock_get, mock_post) def test_indieauthed_session_wrong_me(self, mock_get, mock_post): @@ -712,7 +726,8 @@ class UnfollowTest(TestCase): requests_response(''), # IndieAuth endpoint discovery ) - with self.client.session_transaction() as ctx_session: + with self.client.session_transaction(base_url='https://fed.brid.gy/') \ + as ctx_session: ctx_session['indieauthed-me'] = 'https://eve.com' resp = self.client.post('/unfollow/start', data={ diff --git a/tests/test_ids.py b/tests/test_ids.py index 11a9d92..85f432c 100644 --- a/tests/test_ids.py +++ b/tests/test_ids.py @@ -125,7 +125,7 @@ class IdsTest(TestCase): handle=handle, from_proto=from_, to_proto=to, enhanced=True)) def test_translate_object_id(self): - self.store_object(id='http://post', + self.store_object(id='http://po.st', copies=[Target(uri='at://did/web/post', protocol='atproto')]) self.store_object(id='https://inst/post', copies=[Target(uri='at://did/ap/post', protocol='atproto')]) @@ -140,7 +140,7 @@ class IdsTest(TestCase): Web, 'https://ap.brid.gy/convert/web/https://inst/post'), (ATProto, 'at://did/atp/post', ATProto, 'at://did/atp/post'), # copies - (ATProto, 'at://did/web/post', Web, 'http://post'), + (ATProto, 'at://did/web/post', Web, 'http://po.st'), (ATProto, 'at://did/ap/post', ActivityPub, 'https://inst/post'), (ATProto, 'at://did/fa/post', Fake, 'fake:post'), # no copies @@ -152,10 +152,10 @@ class IdsTest(TestCase): (Fake, 'fake:post', ATProto, 'at://did/fa/post'), (Fake, 'fake:post', Fake, 'fake:post'), (Fake, 'fake:post', Web, 'https://fa.brid.gy/convert/web/fake:post'), - (Web, 'http://post', ActivityPub, 'http://localhost/r/http://post'), - (Web, 'http://post', ATProto, 'at://did/web/post'), - (Web, 'http://post', Fake, 'fake:o:web:http://post'), - (Web, 'http://post', Web, 'http://post'), + (Web, 'http://po.st', ActivityPub, 'http://localhost/r/http://po.st'), + (Web, 'http://po.st', ATProto, 'at://did/web/post'), + (Web, 'http://po.st', Fake, 'fake:o:web:http://po.st'), + (Web, 'http://po.st', Web, 'http://po.st'), ]: with self.subTest(from_=from_.LABEL, to=to.LABEL): self.assertEqual(expected, translate_object_id( diff --git a/tests/test_models.py b/tests/test_models.py index 4151c17..2d451ce 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -683,6 +683,13 @@ class ObjectTest(TestCase): with self.assertRaises(AssertionError): Object(id='not a fake', source_protocol='fake').put() + def test_put_blocklisted_id(self): + Object(id='asdf foo').put() # ok, no source protocol + Object(id='fake:foo', source_protocol='fake').put() # ok, valid id + + with self.assertRaises(AssertionError): + Object(id='not a fake', source_protocol='fake').put() + def test_resolve_ids_empty(self): obj = Object() obj.resolve_ids() diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 74c02df..1f3eeb7 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -105,24 +105,24 @@ class ProtocolTest(TestCase): self.assertEqual(Greedy, Protocol.for_id('https://bar/baz')) def test_for_id_object(self): - self.store_object(id='http://ui/obj', source_protocol='ui') - self.assertEqual(UIProtocol, Protocol.for_id('http://ui/obj')) + self.store_object(id='http://u.i/obj', source_protocol='ui') + self.assertEqual(UIProtocol, Protocol.for_id('http://u.i/obj')) def test_for_id_object_missing_source_protocol(self): - self.store_object(id='http://bad/obj') - self.assertIsNone(Protocol.for_id('http://bad/obj')) + self.store_object(id='http://ba.d/obj') + self.assertIsNone(Protocol.for_id('http://ba.d/obj')) @patch('requests.get') def test_for_id_activitypub_fetch(self, mock_get): mock_get.return_value = self.as2_resp(ACTOR) - self.assertEqual(ActivityPub, Protocol.for_id('http://ap/actor')) - self.assertIn(self.as2_req('http://ap/actor'), mock_get.mock_calls) + self.assertEqual(ActivityPub, Protocol.for_id('http://a.p/actor')) + self.assertIn(self.as2_req('http://a.p/actor'), mock_get.mock_calls) @patch('requests.get') def test_for_id_activitypub_fetch_fails(self, mock_get): mock_get.return_value = requests_response('', status=403) - self.assertIsNone(Protocol.for_id('http://ap/actor')) - self.assertIn(self.as2_req('http://ap/actor'), mock_get.mock_calls) + self.assertIsNone(Protocol.for_id('http://a.p/actor')) + self.assertIn(self.as2_req('http://a.p/actor'), mock_get.mock_calls) mock_get.assert_called_once() @patch('requests.get') @@ -272,7 +272,7 @@ class ProtocolTest(TestCase): @patch('requests.get', return_value=ACTOR_HTML_RESP) def test_load_remote_true_clear_our_as1(self, _): - self.store_object(id='https://foo', our_as1={'should': 'disappear'}, + self.store_object(id='https://fo.o', our_as1={'should': 'disappear'}, source_protocol='web') expected_mf2 = { @@ -280,7 +280,7 @@ class ProtocolTest(TestCase): 'url': 'https://user.com/', } - loaded = Web.load('https://foo', remote=True) + loaded = Web.load('https://fo.o', remote=True) self.assertEqual(expected_mf2, loaded.mf2) self.assertIsNone(loaded.our_as1) self.assertEqual(ACTOR_AS1_UNWRAPPED_URLS, loaded.as1) diff --git a/tests/test_web.py b/tests/test_web.py index 14610e8..85fcb1e 100644 --- a/tests/test_web.py +++ b/tests/test_web.py @@ -195,7 +195,7 @@ REPLY_HTML = """\