/convert/: drop req't that ids are web URLs

for abstracting across protocols. also other minor tweaks.
pull/723/head
Ryan Barrett 2023-11-07 14:02:29 -08:00
rodzic 4b7926b3a8
commit 9327565095
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
3 zmienionych plików z 20 dodań i 19 usunięć

Wyświetl plik

@ -50,30 +50,25 @@ def convert(dest, _, src=None):
# guarantee us the same query param string as in the original URL, and we
# want exactly the same thing since we're looking up the URL's Object by id
path_prefix = f'convert/{dest}/'
url = unquote(request.url.removeprefix(request.root_url).removeprefix(path_prefix))
id = unquote(request.url.removeprefix(request.root_url).removeprefix(path_prefix))
# our redirects evidently collapse :// down to :/ , maybe to prevent URL
# parsing bugs? if that happened to this URL, expand it back to ://
url = re.sub(r'^(https?:/)([^/])', r'\1/\2', url)
id = re.sub(r'^(https?:/)([^/])', r'\1/\2', id)
# STATE: genericize all this below (and above?)
if not util.is_web(url):
error(f'Expected fully qualified URL; got {url}')
logger.info(f'Converting from {src} to {dest}: {url}')
logger.info(f'Converting from {src_cls.LABEL} to {dest}: {id}')
# require g.user for AP since postprocess_as2 currently needs it. ugh
if dest_cls == ActivityPub:
domain = util.domain_from_link(url, minimize=False)
domain = util.domain_from_link(id, minimize=False)
g.user = Web.get_by_id(domain)
if not g.user:
error(f'No web user found for {domain}')
# load, and maybe fetch. if it's a post/update, redirect to inner object.
obj = src_cls.load(url)
obj = src_cls.load(id)
if not obj:
error(f"Couldn't load {url}", status=404)
error(f"Couldn't load {id}", status=404)
elif not obj.as1:
error(f'Stored object for {id} has no data', status=404)
@ -81,8 +76,7 @@ def convert(dest, _, src=None):
if type in ('post', 'update', 'delete'):
obj_id = as1.get_object(obj.as1).get('id')
if obj_id:
# TODO: PROTOCOLS[src].load() this instead?
obj_obj = Object.get_by_id(obj_id)
obj_obj = src_cls.load(obj_id, remote=False)
if (obj_obj and obj_obj.as1
and not obj_obj.as1.keys() <= set(['id', 'url', 'objectType'])):
logger.info(f'{type} activity, redirecting to Object {obj_id}')

Wyświetl plik

@ -7,7 +7,7 @@ from granary import as2
from granary.tests.test_as1 import ACTOR, COMMENT, DELETE_OF_ID, UPDATE
from models import Object
from oauth_dropins.webutil.testutil import requests_response
from oauth_dropins.webutil.util import parse_mf2
from oauth_dropins.webutil.util import json_loads, parse_mf2
# import first so that Fake is defined before URL routes are registered
from . import testutil
@ -84,10 +84,16 @@ class ConvertTest(testutil.TestCase):
base_url='https://ap.brid.gy/')
self.assertEqual(404, resp.status_code)
def test_url_not_web(self):
resp = self.client.get('/convert/web/git+ssh://foo/bar',
base_url='https://ap.brid.gy/')
self.assertEqual(400, resp.status_code)
def test_fake_to_other(self):
self.store_object(id='fake:post', our_as1={'foo': 'bar'})
resp = self.client.get('/convert/other/fake:post',
base_url='https://fa.brid.gy/')
self.assertEqual(200, resp.status_code)
self.assertEqual(OtherFake.CONTENT_TYPE, resp.content_type)
self.assertEqual({
'id': 'other:o:fa:fake:post',
'foo': 'bar',
}, json_loads(resp.get_data()))
def test_activitypub_to_web_object(self):
url = 'https://user.com/bar?baz=baj&biff'

Wyświetl plik

@ -126,7 +126,7 @@ class Fake(User, protocol.Protocol):
@classmethod
def convert(cls, obj):
logger.info(f'{cls.__name__}.convert {obj.key.id()}')
return obj.as1
return cls.translate_ids(obj.as1)
@classmethod
def target_for(cls, obj, shared=False):
@ -147,6 +147,7 @@ class Fake(User, protocol.Protocol):
class OtherFake(Fake):
"""Different class because the same-protocol check special cases Fake."""
LABEL = ABBREV = 'other'
CONTENT_TYPE = 'ot/her'
fetchable = {}
sent = []