/render: hydrate author/actor if necessary

fixes semi-blank authors in outgoing webmentions
pull/475/head
Ryan Barrett 2023-04-05 07:16:31 -07:00
rodzic d7f2455d69
commit 0ba43561fa
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
2 zmienionych plików z 47 dodań i 5 usunięć

Wyświetl plik

@ -9,6 +9,7 @@ from oauth_dropins.webutil import flask_util
from oauth_dropins.webutil.flask_util import error
from oauth_dropins.webutil import util
import activitypub
from app import app, cache
import common
from models import Object
@ -27,9 +28,9 @@ def render():
elif not obj.as1:
error(f'Stored object for {id} has no AS1', status=404)
# redirect creates, updates, etc to inner object
type = as1.object_type(obj.as1)
if type in ('post', 'update', 'delete'):
# redirect to inner object
obj_id = as1.get_object(obj.as1).get('id')
if obj_id:
obj_obj = Object.get_by_id(obj_id)
@ -41,11 +42,21 @@ def render():
if obj.deleted or type == 'delete':
return '', 410
# fill in author/actor if available
obj_as1 = obj.as1
for field in 'author', 'actor':
val = as1.get_object(obj.as1, field)
if val.keys() == set(['id']) and val['id']:
# TODO: abstract on obj.source_protocol
loaded = activitypub.ActivityPub.load(val['id'])
if loaded and loaded.as1:
obj_as1 = {**obj_as1, field: loaded.as1}
# add HTML meta redirect to source page. should trigger for end users in
# browsers but not for webmention receivers (hopefully).
html = microformats2.activities_to_html([obj.as1])
html = microformats2.activities_to_html([obj_as1])
utf8 = '<meta charset="utf-8">'
url = util.get_url(obj.as1)
url = util.get_url(obj_as1)
if url:
refresh = f'<meta http-equiv="refresh" content="0;url={url}">'
html = html.replace(utf8, utf8 + '\n' + refresh)

Wyświetl plik

@ -2,7 +2,7 @@
import copy
from granary import as2
from granary.tests.test_as1 import COMMENT, DELETE_OF_ID, UPDATE
from granary.tests.test_as1 import ACTOR, COMMENT, DELETE_OF_ID, UPDATE
from app import app
import common
@ -28,6 +28,29 @@ EXPECTED_HTML = """\
</body>
</html>
"""
EXPECTED_AUTHOR_HTML = """\
<!DOCTYPE html>
<html>
<head><meta charset="utf-8">
<meta http-equiv="refresh" content="0;url=https://fake.com/123456"></head>
<body class="">
<article class="h-entry">
<span class="p-uid">tag:fake.com:123456</span>
<time class="dt-published" datetime="2012-12-05T00:58:26+00:00">2012-12-05T00:58:26+00:00</time>
<span class="p-author h-card">
<data class="p-uid" value="tag:fake.com:444"></data>
<a class="p-name u-url" href="https://plus.google.com/bob">Bob</a>
<img class="u-photo" src="https://bob/picture" alt="" />
</span>
<a class="u-url" href="https://fake.com/123456">fake.com/123456</a>
<div class="e-content p-name">
A reply
</div>
<a class="u-in-reply-to" href="https://fake.com/123"></a>
</article>
</body>
</html>
"""
class RenderTest(testutil.TestCase):
@ -49,6 +72,15 @@ class RenderTest(testutil.TestCase):
self.assertEqual(200, resp.status_code)
self.assert_multiline_equals(EXPECTED_HTML, resp.get_data(as_text=True), ignore_blanks=True)
def test_render_with_author(self):
with app.test_request_context('/'):
Object(id='abc', as2=as2.from_as1({**COMMENT, 'author': 'def'})).put()
Object(id='def', as2=as2.from_as1(ACTOR)).put()
resp = self.client.get('/render?id=abc')
self.assertEqual(200, resp.status_code)
self.assert_multiline_equals(
EXPECTED_AUTHOR_HTML, resp.get_data(as_text=True), ignore_blanks=True)
def test_render_no_url(self):
comment = copy.deepcopy(COMMENT)
del comment['url']
@ -113,7 +145,6 @@ A ☕ reply
<a class="u-in-reply-to" href="https://fake.com/123"></a>
""", resp.get_data(as_text=True), ignore_blanks=True)
def test_render_update_inner_obj_too_minimal_serve_as_is(self):
with app.test_request_context('/'):
# UPDATE's object field is a full object