AP: add profile to Content-Type: application/ld+json

for #895
pull/905/head
Ryan Barrett 2024-02-27 11:38:00 -08:00
rodzic fce24c0645
commit 9489204d64
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
8 zmienionych plików z 40 dodań i 38 usunięć

Wyświetl plik

@ -41,7 +41,7 @@ import webfinger
logger = logging.getLogger(__name__)
CONNEG_HEADERS_AS2_HTML = {
'Accept': f'{as2.CONNEG_HEADERS["Accept"]}, {CONTENT_TYPE_HTML}; q=0.7'
'Accept': f'{as2.CONNEG_HEADERS["Accept"]}, {CONTENT_TYPE_HTML}; q=0.5'
}
HTTP_SIG_HEADERS = ('Date', 'Host', 'Digest', '(request-target)')
@ -67,7 +67,7 @@ class ActivityPub(User, Protocol):
ABBREV = 'ap'
PHRASE = 'the fediverse'
LOGO_HTML = '<img src="/static/fediverse_logo.svg">'
CONTENT_TYPE = as2.CONTENT_TYPE
CONTENT_TYPE = as2.CONTENT_TYPE_LD_PROFILE
HAS_FOLLOW_ACCEPTS = True
def _pre_put_hook(self):
@ -516,7 +516,7 @@ def signed_request(fn, url, data=None, headers=None, from_user=None, **kwargs):
# required by Mastodon
# https://github.com/tootsuite/mastodon/pull/14556#issuecomment-674077648
'Host': util.domain_from_link(url, minimize=False),
'Content-Type': as2.CONTENT_TYPE,
'Content-Type': as2.CONTENT_TYPE_LD_PROFILE,
# required for HTTP Signature and Mastodon
'Digest': f'SHA-256={b64encode(sha256(data or b"").digest()).decode()}',
}
@ -849,7 +849,7 @@ def actor(handle_or_id):
logger.info(f'Returning: {json_dumps(actor, indent=2)}')
return actor, {
'Content-Type': as2.CONTENT_TYPE,
'Content-Type': as2.CONTENT_TYPE_LD_PROFILE,
'Access-Control-Allow-Origin': '*',
}
@ -952,7 +952,7 @@ def follower_collection(id, collection):
return f'{protocol} user {id} not found', 404
if request.method == 'HEAD':
return '', {'Content-Type': as2.CONTENT_TYPE}
return '', {'Content-Type': as2.CONTENT_TYPE_LD_PROFILE}
# page
followers, new_before, new_after = Follower.fetch_page(collection, user=user)
@ -973,7 +973,7 @@ def follower_collection(id, collection):
'id': request.url,
})
logger.info(f'Returning {json_dumps(page, indent=2)}')
return page, {'Content-Type': as2.CONTENT_TYPE}
return page, {'Content-Type': as2.CONTENT_TYPE_LD_PROFILE}
# collection
num_followers, num_following = user.count_followers()
@ -986,7 +986,7 @@ def follower_collection(id, collection):
'first': page,
}
logger.info(f'Returning {json_dumps(collection, indent=2)}')
return collection, {'Content-Type': as2.CONTENT_TYPE}
return collection, {'Content-Type': as2.CONTENT_TYPE_LD_PROFILE}
# protocol in subdomain
@ -1010,7 +1010,7 @@ def outbox(id):
error(f'User {id} not found', status=404)
if request.method == 'HEAD':
return '', {'Content-Type': as2.CONTENT_TYPE}
return '', {'Content-Type': as2.CONTENT_TYPE_LD_PROFILE}
query = Object.query(Object.users == user.key)
objects, new_before, new_after = fetch_objects(query, by=Object.updated,
@ -1034,7 +1034,7 @@ def outbox(id):
'id': request.url,
})
logger.info(f'Returning {json_dumps(page, indent=2)}')
return page, {'Content-Type': as2.CONTENT_TYPE}
return page, {'Content-Type': as2.CONTENT_TYPE_LD_PROFILE}
# collection
return {
@ -1044,4 +1044,4 @@ def outbox(id):
'summary': f"{id}'s outbox",
'totalItems': query.count(),
'first': page,
}, {'Content-Type': as2.CONTENT_TYPE}
}, {'Content-Type': as2.CONTENT_TYPE_LD_PROFILE}

Wyświetl plik

@ -109,7 +109,9 @@ def redir(to):
ret = ActivityPub.convert(obj, from_user=user)
logger.info(f'Returning: {json_dumps(ret, indent=2)}')
return ret, {
'Content-Type': accept_type,
'Content-Type': (as2.CONTENT_TYPE_LD_PROFILE
if accept_type == as2.CONTENT_TYPE_LD
else accept_type),
'Access-Control-Allow-Origin': '*',
**VARY_HEADER,
}

Wyświetl plik

@ -357,8 +357,7 @@ class ActivityPubTest(TestCase):
self.make_user('fake:user', cls=Fake)
got = self.client.get('/ap/fake:user', base_url='https://fa.brid.gy/')
self.assertEqual(200, got.status_code, got.get_data(as_text=True))
type = got.headers['Content-Type']
self.assertTrue(type.startswith(as2.CONTENT_TYPE), type)
self.assertEqual(as2.CONTENT_TYPE_LD_PROFILE, got.headers['Content-Type'])
self.assertEqual(ACTOR_FAKE, got.json)
def test_actor_fake_protocol_subdomain(self, *_):
@ -371,8 +370,7 @@ class ActivityPubTest(TestCase):
"""Web users are special cased to drop the /web/ prefix."""
got = self.client.get('/user.com')
self.assertEqual(200, got.status_code)
type = got.headers['Content-Type']
self.assertTrue(type.startswith(as2.CONTENT_TYPE), type)
self.assertEqual(as2.CONTENT_TYPE_LD_PROFILE, got.headers['Content-Type'])
self.assertEqual({
**ACTOR_BASE,
'type': 'Person',

Wyświetl plik

@ -79,7 +79,7 @@ class RedirectTest(testutil.TestCase):
self._test_as2(as2.CONTENT_TYPE)
def test_as2_ld(self):
self._test_as2(as2.CONTENT_TYPE_LD)
self._test_as2(as2.CONTENT_TYPE_LD_PROFILE)
def test_as2_creates_user(self):
Object(id='https://user.com/repost', as2=REPOST_AS2).put()
@ -87,7 +87,7 @@ class RedirectTest(testutil.TestCase):
self.user.key.delete()
resp = self.client.get('/r/https://user.com/repost',
headers={'Accept': as2.CONTENT_TYPE})
headers={'Accept': as2.CONTENT_TYPE_LD_PROFILE})
self.assertEqual(200, resp.status_code, resp.get_data(as_text=True))
self.assert_equals(REPOST_AS2, resp.json)
self.assertEqual('Accept', resp.headers['Vary'])
@ -102,7 +102,7 @@ class RedirectTest(testutil.TestCase):
]
resp = self.client.get('/r/https://user.com/repost',
headers={'Accept': as2.CONTENT_TYPE})
headers={'Accept': as2.CONTENT_TYPE_LD_PROFILE})
self.assertEqual(200, resp.status_code, resp.get_data(as_text=True))
self.assert_equals(REPOST_AS2, resp.json)
self.assertEqual('Accept', resp.headers['Vary'])
@ -116,7 +116,7 @@ class RedirectTest(testutil.TestCase):
]
resp = self.client.get('/r/https://user.com/repost',
headers={'Accept': as2.CONTENT_TYPE})
headers={'Accept': as2.CONTENT_TYPE_LD_PROFILE})
self.assertEqual(200, resp.status_code, resp.get_data(as_text=True))
self.assert_equals(REPOST_AS2, resp.json)
self.assertEqual('Accept', resp.headers['Vary'])
@ -129,7 +129,7 @@ class RedirectTest(testutil.TestCase):
protocol.objects_cache.clear()
resp = self.client.get('/r/https://user.com/',
headers={'Accept': as2.CONTENT_TYPE})
headers={'Accept': as2.CONTENT_TYPE_LD_PROFILE})
self.assertEqual(200, resp.status_code, resp.get_data(as_text=True))
self.assertEqual('Accept', resp.headers['Vary'])
@ -157,7 +157,7 @@ class RedirectTest(testutil.TestCase):
cache.init_app(app)
self.client = app.test_client()
self._test_as2(as2.CONTENT_TYPE)
self._test_as2(as2.CONTENT_TYPE_LD_PROFILE)
resp = self.client.get('/r/https://user.com/bar')
self.assertEqual(301, resp.status_code)
@ -166,7 +166,7 @@ class RedirectTest(testutil.TestCase):
# delete stored Object to make sure we're serving from cache
self.obj.delete()
self._test_as2(as2.CONTENT_TYPE)
self._test_as2(as2.CONTENT_TYPE_LD_PROFILE)
resp = self.client.get('/r/https://user.com/bar',
headers={'Accept': 'text/html'})
@ -186,7 +186,7 @@ class RedirectTest(testutil.TestCase):
Object(id='https://user.com/bar', as2={}, deleted=True).put()
resp = self.client.get('/r/https://user.com/bar',
headers={'Accept': as2.CONTENT_TYPE})
headers={'Accept': as2.CONTENT_TYPE_LD_PROFILE})
self.assertEqual(404, resp.status_code, resp.get_data(as_text=True))
def test_as2_opted_out(self):
@ -194,5 +194,5 @@ class RedirectTest(testutil.TestCase):
self.user.put()
resp = self.client.get('/r/https://user.com/',
headers={'Accept': as2.CONTENT_TYPE})
headers={'Accept': as2.CONTENT_TYPE_LD_PROFILE})
self.assertEqual(404, resp.status_code, resp.get_data(as_text=True))

Wyświetl plik

@ -428,7 +428,8 @@ class WebTest(TestCase):
calls = {} # maps inbox URL to JSON data
for args, kwargs in mock_post.call_args_list:
self.assertEqual(as2.CONTENT_TYPE, kwargs['headers']['Content-Type'])
self.assertEqual(as2.CONTENT_TYPE_LD_PROFILE,
kwargs['headers']['Content-Type'])
rsa_key = kwargs['auth'].header_signer._rsa._key
self.assertEqual(self.user.private_pem(), rsa_key.exportKey())
calls[args[0]] = json_loads(kwargs['data'])

Wyświetl plik

@ -3,6 +3,7 @@ import copy
from unittest.mock import patch
import urllib.parse
from granary.as2 import CONTENT_TYPE_LD_PROFILE
from oauth_dropins.webutil.testutil import requests_response
# import first so that Fake is defined before URL routes are registered
@ -39,15 +40,15 @@ WEBFINGER = {
'href': 'https://user.com/about-me',
}, {
'rel': 'self',
'type': 'application/activity+json',
'type': CONTENT_TYPE_LD_PROFILE,
'href': 'http://localhost/user.com',
}, {
'rel': 'inbox',
'type': 'application/activity+json',
'type': CONTENT_TYPE_LD_PROFILE,
'href': 'http://localhost/user.com/inbox'
}, {
'rel': 'sharedInbox',
'type': 'application/activity+json',
'type': CONTENT_TYPE_LD_PROFILE,
'href': 'https://web.brid.gy/ap/sharedInbox',
}, {
'rel': 'http://ostatus.org/schema/1.0/subscribe',
@ -68,15 +69,15 @@ WEBFINGER_NO_HCARD = {
'href': 'https://user.com/',
}, {
'rel': 'self',
'type': 'application/activity+json',
'type': CONTENT_TYPE_LD_PROFILE,
'href': 'https://web.brid.gy/user.com',
}, {
'rel': 'inbox',
'type': 'application/activity+json',
'type': CONTENT_TYPE_LD_PROFILE,
'href': 'https://web.brid.gy/user.com/inbox',
}, {
'rel': 'sharedInbox',
'type': 'application/activity+json',
'type': CONTENT_TYPE_LD_PROFILE,
'href': 'https://web.brid.gy/ap/sharedInbox',
}, {
'rel': 'http://ostatus.org/schema/1.0/subscribe',
@ -92,15 +93,15 @@ WEBFINGER_FAKE = {
'href': 'fake:user',
}, {
'rel': 'self',
'type': 'application/activity+json',
'type': CONTENT_TYPE_LD_PROFILE,
'href': 'http://localhost/ap/fa/fake:user',
}, {
'rel': 'inbox',
'type': 'application/activity+json',
'type': CONTENT_TYPE_LD_PROFILE,
'href': 'http://localhost/ap/fa/fake:user/inbox',
}, {
'rel': 'sharedInbox',
'type': 'application/activity+json',
'type': CONTENT_TYPE_LD_PROFILE,
'href': 'https://web.brid.gy/ap/sharedInbox',
}, {
'rel': 'http://ostatus.org/schema/1.0/subscribe',

Wyświetl plik

@ -392,7 +392,7 @@ class TestCase(unittest.TestCase, testutil.Asserts):
headers = {
'Date': 'Sun, 02 Jan 2022 03:04:05 GMT',
'Host': util.domain_from_link(url, minimize=False),
'Content-Type': 'application/activity+json',
'Content-Type': as2.CONTENT_TYPE_LD_PROFILE,
'Digest': ANY,
**CONNEG_HEADERS_AS2_HTML,
**kwargs.pop('headers', {}),

Wyświetl plik

@ -138,7 +138,7 @@ class Webfinger(flask_util.XrdOrJrd):
# ActivityPub
{
'rel': 'self',
'type': as2.CONTENT_TYPE,
'type': as2.CONTENT_TYPE_LD_PROFILE,
# WARNING: in python 2 sometimes request.host_url lost port,
# http://localhost:8080 would become just http://localhost. no
# clue how or why. pay attention here if that happens again.
@ -147,12 +147,12 @@ class Webfinger(flask_util.XrdOrJrd):
# AP reads this and sharedInbox from the AS2 actor, not
# webfinger, so strictly speaking, it's probably not needed here.
'rel': 'inbox',
'type': as2.CONTENT_TYPE,
'type': as2.CONTENT_TYPE_LD_PROFILE,
'href': actor_id + '/inbox',
}, {
# https://www.w3.org/TR/activitypub/#sharedInbox
'rel': 'sharedInbox',
'type': as2.CONTENT_TYPE,
'type': as2.CONTENT_TYPE_LD_PROFILE,
'href': common.subdomain_wrap(cls, '/ap/sharedInbox'),
},