From 93275650957983b294323ec0702f159e321e1db4 Mon Sep 17 00:00:00 2001 From: Ryan Barrett Date: Tue, 7 Nov 2023 14:02:29 -0800 Subject: [PATCH] /convert/: drop req't that ids are web URLs for abstracting across protocols. also other minor tweaks. --- convert.py | 20 +++++++------------- tests/test_convert.py | 16 +++++++++++----- tests/testutil.py | 3 ++- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/convert.py b/convert.py index d4011f4..4379196 100644 --- a/convert.py +++ b/convert.py @@ -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}') diff --git a/tests/test_convert.py b/tests/test_convert.py index 1f6345c..bd5f047 100644 --- a/tests/test_convert.py +++ b/tests/test_convert.py @@ -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' diff --git a/tests/testutil.py b/tests/testutil.py index 6638f54..71a0343 100644 --- a/tests/testutil.py +++ b/tests/testutil.py @@ -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 = []