expand User.ap_subdomain to allow protocol subdomains like bsky

part of setting up per-protocol bot users for #880
pull/968/head
Ryan Barrett 2024-04-22 11:12:03 -07:00
rodzic e1f9021696
commit ed78090d2c
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
6 zmienionych plików z 37 dodań i 20 usunięć

Wyświetl plik

@ -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',

22
ids.py
Wyświetl plik

@ -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}/'

Wyświetl plik

@ -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.

Wyświetl plik

@ -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):

Wyświetl plik

@ -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'))

15
web.py
Wyświetl plik

@ -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)