kopia lustrzana https://github.com/snarfed/bridgy-fed
add Web.ap_subdomain property, use it in webfinger
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.pull/741/head
rodzic
c617e9ad7b
commit
d33832be1c
|
@ -1916,6 +1916,8 @@ http://this/404s
|
|||
self.assertFalse(self.user.is_web_url('https://other.com/'))
|
||||
|
||||
def test_handle_as(self, *_):
|
||||
self.user.ap_subdomain = 'web'
|
||||
|
||||
self.assertEqual('@user.com@user.com', self.user.handle_as(ActivityPub))
|
||||
|
||||
self.user.obj = Object(id='a', as2={'type': 'Person'})
|
||||
|
@ -1937,6 +1939,9 @@ http://this/404s
|
|||
self.assertEqual('fake:handle:user.com', self.user.handle_as(Fake))
|
||||
self.assertEqual('user.com.web.brid.gy', self.user.handle_as('atproto'))
|
||||
|
||||
self.user.ap_subdomain = 'fed'
|
||||
self.assertEqual('@user.com@fed.brid.gy', self.user.handle_as(ActivityPub))
|
||||
|
||||
def test_ap_actor(self, *_):
|
||||
self.assertEqual('http://localhost/user.com', self.user.ap_actor())
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ WEBFINGER = {
|
|||
'href': 'https://web.brid.gy/ap/sharedInbox',
|
||||
}, {
|
||||
'rel': 'http://ostatus.org/schema/1.0/subscribe',
|
||||
# TODO: genericize
|
||||
'template': 'https://fed.brid.gy/web/user.com?url={uri}',
|
||||
}],
|
||||
}
|
||||
|
@ -66,11 +67,11 @@ WEBFINGER_NO_HCARD = {
|
|||
}, {
|
||||
'rel': 'self',
|
||||
'type': 'application/activity+json',
|
||||
'href': 'http://localhost/user.com',
|
||||
'href': 'https://web.brid.gy/user.com',
|
||||
}, {
|
||||
'rel': 'inbox',
|
||||
'type': 'application/activity+json',
|
||||
'href': 'http://localhost/user.com/inbox',
|
||||
'href': 'https://web.brid.gy/user.com/inbox',
|
||||
}, {
|
||||
'rel': 'sharedInbox',
|
||||
'type': 'application/activity+json',
|
||||
|
@ -162,6 +163,20 @@ class WebfingerTest(TestCase):
|
|||
self.assertEqual('application/jrd+json', got.headers['Content-Type'])
|
||||
self.assert_equals(WEBFINGER, got.json)
|
||||
|
||||
def test_webfinger_web_subdomain_redirects(self):
|
||||
path = '/.well-known/webfinger?resource=user.com@user.com'
|
||||
|
||||
got = self.client.get(path, base_url='https://fed.brid.gy/')
|
||||
self.assertEqual(302, got.status_code)
|
||||
self.assertEqual(f'https://web.brid.gy{path}', got.headers['Location'])
|
||||
|
||||
self.user.ap_subdomain = 'fed'
|
||||
self.user.put()
|
||||
|
||||
got = self.client.get(path, base_url='https://web.brid.gy/')
|
||||
self.assertEqual(302, got.status_code)
|
||||
self.assertEqual(f'https://fed.brid.gy{path}', got.headers['Location'])
|
||||
|
||||
def test_user_infer_protocol_from_resource_subdomain(self):
|
||||
got = self.client.get(
|
||||
'/.well-known/webfinger?resource=acct:fake:handle:user@fake.brid.gy',
|
||||
|
@ -298,8 +313,10 @@ class WebfingerTest(TestCase):
|
|||
expected = copy.deepcopy(WEBFINGER_NO_HCARD)
|
||||
expected['subject'] = 'acct:user.com@web.brid.gy'
|
||||
|
||||
got = self.client.get('/.well-known/webfinger?resource=acct:user.com@fed.brid.gy',
|
||||
headers={'Accept': 'application/json'})
|
||||
got = self.client.get(
|
||||
'/.well-known/webfinger?resource=acct:user.com@web.brid.gy',
|
||||
headers={'Accept': 'application/json'},
|
||||
base_url='https://web.brid.gy/')
|
||||
self.assertEqual(200, got.status_code)
|
||||
self.assertEqual(expected, got.json)
|
||||
|
||||
|
|
9
web.py
9
web.py
|
@ -76,6 +76,13 @@ class Web(User, Protocol):
|
|||
redirects_error = ndb.TextProperty()
|
||||
has_hcard = ndb.BooleanProperty()
|
||||
|
||||
# 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')
|
||||
|
||||
@classmethod
|
||||
def _get_kind(cls):
|
||||
return 'MagicKey'
|
||||
|
@ -114,7 +121,7 @@ class Web(User, Protocol):
|
|||
"""Special case ActivityPub to use custom username."""
|
||||
if to_proto in ('activitypub', 'ap', PROTOCOLS['ap']):
|
||||
return (f'@{self.username()}@{self.key.id()}' if self.has_redirects
|
||||
else f'@{self.key.id()}@{self.ABBREV}{SUPERDOMAIN}')
|
||||
else f'@{self.key.id()}@{self.ap_subdomain}{SUPERDOMAIN}')
|
||||
|
||||
return super().handle_as(to_proto)
|
||||
|
||||
|
|
18
webfinger.py
18
webfinger.py
|
@ -4,16 +4,17 @@
|
|||
* https://tools.ietf.org/html/rfc7033
|
||||
"""
|
||||
import logging
|
||||
import urllib.parse
|
||||
from urllib.parse import urljoin, urlparse
|
||||
|
||||
from flask import g, render_template, request
|
||||
from flask import g, redirect, render_template, request
|
||||
from granary import as2
|
||||
from oauth_dropins.webutil import flask_util, util
|
||||
from oauth_dropins.webutil.flask_util import error, flash
|
||||
from oauth_dropins.webutil.flask_util import error, flash, Found
|
||||
from oauth_dropins.webutil.util import json_dumps, json_loads
|
||||
|
||||
import activitypub
|
||||
import common
|
||||
from common import LOCAL_DOMAINS, SUPERDOMAIN
|
||||
from flask_app import app, cache
|
||||
from protocol import Protocol
|
||||
|
||||
|
@ -55,7 +56,7 @@ class Webfinger(flask_util.XrdOrJrd):
|
|||
id = user
|
||||
allow_indirect = True
|
||||
except ValueError:
|
||||
id = urllib.parse.urlparse(resource).netloc or resource
|
||||
id = urlparse(resource).netloc or resource
|
||||
|
||||
if not cls:
|
||||
cls = Protocol.for_request(fed='web')
|
||||
|
@ -89,6 +90,15 @@ class Webfinger(flask_util.XrdOrJrd):
|
|||
if not user:
|
||||
error(f'No {cls.LABEL} user found for {id}', status=404)
|
||||
|
||||
# backward compatibility for initial Web users whose AP actor ids are on
|
||||
# fed.brid.gy, not web.brid.gy
|
||||
subdomain = request.host.split('.')[0]
|
||||
if (user.LABEL == 'web'
|
||||
and subdomain not in (LOCAL_DOMAINS + (user.ap_subdomain,))):
|
||||
url = urljoin(f'https://{user.ap_subdomain}{common.SUPERDOMAIN}/',
|
||||
request.full_path)
|
||||
raise Found(location=url)
|
||||
|
||||
actor = user.obj.as1 if user.obj and user.obj.as1 else {}
|
||||
logger.info(f'Generating WebFinger data for {user.key}')
|
||||
logger.info(f'AS1 actor: {actor}')
|
||||
|
|
Ładowanie…
Reference in New Issue