diff --git a/common.py b/common.py index d5bea16..58b7716 100644 --- a/common.py +++ b/common.py @@ -38,15 +38,12 @@ SUPERDOMAIN = '.brid.gy' # use it to canonicalize most UI routes from these to fed.brid.gy. PROTOCOL_DOMAINS = ( 'ap.brid.gy', - 'atp.brid.gy', 'atproto.brid.gy', - 'bluesky.brid.gy', 'bsky.brid.gy', + 'web.brid.gy', 'eefake.brid.gy', 'fa.brid.gy', 'other.brid.gy', - 'nostr.brid.gy', - 'web.brid.gy', ) OTHER_DOMAINS = ( 'bridgy-federated.appspot.com', diff --git a/ids.py b/ids.py index 14d6181..5cc84e6 100644 --- a/ids.py +++ b/ids.py @@ -21,7 +21,9 @@ COPIES_PROTOCOLS = ('atproto',) # Web user domains whose AP actor ids are on fed.brid.gy, not web.brid.gy, for # historical compatibility. Loaded on first call to web_ap_subdomain(). -_FED_SUBDOMAIN_SITES = None +# +# Maps string domain to string subdomain (bsky, fed, or web). +_NON_WEB_SUBDOMAIN_SITES = None def web_ap_base_domain(user_domain): @@ -40,16 +42,18 @@ def web_ap_base_domain(user_domain): if request.host in LOCAL_DOMAINS: return request.host_url - global _FED_SUBDOMAIN_SITES - if _FED_SUBDOMAIN_SITES is None: - _FED_SUBDOMAIN_SITES = { - key.id() for key in Query('MagicKey', - filters=FilterNode('ap_subdomain', '=', 'fed') - ).fetch(keys_only=True) + global _NON_WEB_SUBDOMAIN_SITES + if _NON_WEB_SUBDOMAIN_SITES is None: + _NON_WEB_SUBDOMAIN_SITES = { + user.key.id(): user.ap_subdomain + for key in Query('MagicKey', + filters=FilterNode('ap_subdomain', '!=', 'web'), + projection=['ap_subdomain'], + ).fetch() } - logger.info(f'Loaded {len(_FED_SUBDOMAIN_SITES)} fed subdomain Web users') + logger.info(f'Loaded {len(_NON_WEB_SUBDOMAIN_SITES)} non-web.brid.gy Web users') - subdomain = 'fed' if user_domain in _FED_SUBDOMAIN_SITES else 'web' + subdomain = _NON_WEB_SUBDOMAIN_SITES.get(user_domain, 'web') return f'https://{subdomain}{SUPERDOMAIN}/' diff --git a/tests/test_activitypub.py b/tests/test_activitypub.py index d03e5cd..b62d421 100644 --- a/tests/test_activitypub.py +++ b/tests/test_activitypub.py @@ -2411,3 +2411,5 @@ class ActivityPubUtilsTest(TestCase): 'actor': 'https://fa.brid.gy/ap/fake:user', 'to': [as2.PUBLIC_AUDIENCE], }, json_loads(kwargs['data'])) + + # TODO: actor fetch and webfinger for @bsky.brid.gy@bsky.brid.gy both don't work. test and fix those. diff --git a/tests/test_ids.py b/tests/test_ids.py index 295894e..8e2733b 100644 --- a/tests/test_ids.py +++ b/tests/test_ids.py @@ -88,7 +88,10 @@ class IdsTest(TestCase): self.assertEqual(expected, translate_user_id( id='https://www.user.com/', from_=Web, to=proto)) - @patch('ids._FED_SUBDOMAIN_SITES', new={'on-fed.com'}) + @patch('ids._NON_WEB_SUBDOMAIN_SITES', new={ + 'on-bsky.com': 'bsky', + 'on-fed.com': 'fed', + }) def test_translate_user_id_web_ap_subdomain_fed(self): for base_url in ['https://web.brid.gy/', 'https://fed.brid.gy/']: with app.test_request_context('/', base_url=base_url): @@ -96,6 +99,8 @@ class IdsTest(TestCase): id='on-web.com', from_=Web, to=ActivityPub)) self.assertEqual('https://fed.brid.gy/on-fed.com', translate_user_id( id='on-fed.com', from_=Web, to=ActivityPub)) + self.assertEqual('https://bsky.brid.gy/on-bsky.com', translate_user_id( + id='on-bsky.com', from_=Web, to=ActivityPub)) def test_translate_handle(self): for from_, handle, to, expected in [ @@ -185,7 +190,7 @@ class IdsTest(TestCase): self.assertEqual(expected, translate_object_id( id=id, from_=from_, to=to)) - @patch('ids._FED_SUBDOMAIN_SITES', new={'on-fed.com'}) + @patch('ids._NON_WEB_SUBDOMAIN_SITES', new={'on-fed.com': 'fed'}) def test_translate_object_id_web_ap_subdomain_fed(self): for base_url in ['https://web.brid.gy/', 'https://fed.brid.gy/']: with app.test_request_context('/', base_url=base_url): diff --git a/tests/test_web.py b/tests/test_web.py index bac0f68..e11aab7 100644 --- a/tests/test_web.py +++ b/tests/test_web.py @@ -2541,6 +2541,8 @@ class WebUtilTest(TestCase): self.assertIs(False, Web.owns_id('http://localhost:8080/foo')) self.assertIs(False, Web.owns_id('https://twitter.com/')) self.assertIs(False, Web.owns_id('https://ap.brid.gy/foo')) + # TODO: this still needs to be false + # special-case PROTOCOL_DOMAINS homepages in Web.owns_id, otherwise False def test_owns_handle(self, *_): self.assertIsNone(Web.owns_handle('foo.com')) @@ -2552,7 +2554,7 @@ class WebUtilTest(TestCase): self.assertEqual(False, Web.owns_handle('@foo@bar.com')) self.assertEqual(False, Web.owns_handle('foo@bar.com')) self.assertEqual(False, Web.owns_handle('localhost')) - self.assertEqual(False, Web.owns_handle('bsky.brid.gy')) + self.assertEqual(True, Web.owns_handle('bsky.brid.gy')) def test_handle_to_id(self, *_): self.assertEqual('foo.com', Web.handle_to_id('foo.com')) diff --git a/web.py b/web.py index 6975ea9..01072d6 100644 --- a/web.py +++ b/web.py @@ -76,7 +76,9 @@ def is_valid_domain(domain): # logger.debug(f"{domain} doesn't look like a domain") return False - if Web.is_blocklisted(domain) and domain != common.PRIMARY_DOMAIN: + if (Web.is_blocklisted(domain) + and domain != PRIMARY_DOMAIN + and domain not in PROTOCOL_DOMAINS): logger.debug(f'{domain} is blocklisted') return False @@ -112,9 +114,14 @@ class Web(User, Protocol): # Originally, BF served Web users' AP actor ids on fed.brid.gy, eg # https://fed.brid.gy/snarfed.org . When we started adding new protocols, we # switched to per-protocol subdomains, eg https://web.brid.gy/snarfed.org . - # However, we need to preserve the old users' actor ids as is. So, this - # property tracks which subdomain a given Web user's AP actor uses. - ap_subdomain = ndb.StringProperty(choices=['fed', 'web'], default='web') + # However, we need to preserve the old users' actor ids as is. + # + # Also, our per-protocol bot accounts in ActivityPub are on their own + # subdomains, eg @bsky.brid.gy@bsky.brid.gy. + # + # So, this property tracks which subdomain a given Web user's AP actor uses. + ap_subdomain = ndb.StringProperty(choices=['bsky', 'fed', 'web'], + default='web') # OLD. some stored entities still have these; do not reuse. # superfeedr_subscribed = ndb.DateTimeProperty(tzinfo=timezone.utc)