diff --git a/activitypub.py b/activitypub.py index f79992a9..5a008df5 100644 --- a/activitypub.py +++ b/activitypub.py @@ -4,7 +4,7 @@ from hashlib import sha256 import itertools import logging import re -from urllib.parse import quote_plus, urljoin +from urllib.parse import quote_plus, urljoin, urlparse from flask import abort, g, request from google.cloud import ndb @@ -117,7 +117,12 @@ class ActivityPub(User, Protocol): https://www.w3.org/TR/activitypub/#obj-id """ - if util.is_web(id) and not cls.is_blocklisted(id): + if (util.is_web(id) + and not cls.is_blocklisted(id) + # heuristic: assume no actor is the root path on its host. this + # lets us assume home pages are Web users without making any + # network requests. + and urlparse(id).path not in ('', '/')): return None return False diff --git a/tests/test_activitypub.py b/tests/test_activitypub.py index 27c0d8ae..00785099 100644 --- a/tests/test_activitypub.py +++ b/tests/test_activitypub.py @@ -1587,13 +1587,12 @@ class ActivityPubUtilsTest(TestCase): ActivityPub(id=bad).put() def test_owns_id(self): - self.assertIsNone(ActivityPub.owns_id('http://foo')) - self.assertIsNone(ActivityPub.owns_id('https://bar/baz')) - self.assertFalse(ActivityPub.owns_id('at://did:plc:foo/bar/123')) - self.assertFalse(ActivityPub.owns_id('e45fab982')) - - self.assertFalse(ActivityPub.owns_id('https://twitter.com/foo')) - self.assertFalse(ActivityPub.owns_id('https://fed.brid.gy/foo')) + self.assertIsNone(ActivityPub.owns_id('http://foo/bar')) + self.assertEqual(False, ActivityPub.owns_id('at://did:plc:foo/bar/123')) + self.assertEqual(False, ActivityPub.owns_id('e45fab982')) + self.assertEqual(False, ActivityPub.owns_id('https://example.com/')) + self.assertEqual(False, ActivityPub.owns_id('https://twitter.com/foo')) + self.assertEqual(False, ActivityPub.owns_id('https://fed.brid.gy/foo')) def test_owns_handle(self): for handle in ('@user@instance', 'user@instance.com', 'user.com@instance.com', diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 70c9d268..e7694cfe 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -124,16 +124,10 @@ class ProtocolTest(TestCase): mock_get.assert_called_once() @patch('requests.get') - def test_for_id_web_fetch(self, mock_get): - mock_get.return_value = requests_response(ACTOR_HTML) - self.assertEqual(Web, Protocol.for_id('http://web.site/')) - self.assertIn(self.req('http://web.site/'), mock_get.mock_calls) - - @patch('requests.get') - def test_for_id_web_fetch_no_mf2(self, mock_get): - mock_get.return_value = requests_response('') - self.assertIsNone(Protocol.for_id('http://web.site/')) - self.assertIn(self.req('http://web.site/'), mock_get.mock_calls) + def test_for_id_web_no_fetch(self, mock_get): + self.assertEqual(Web, Protocol.for_id('http://web/')) + # we don't allow ActivityPub actors on root paths, so Web must be it + mock_get.assert_not_called() def test_for_handle_deterministic(self): for handle, expected in [