kopia lustrzana https://github.com/snarfed/bridgy-fed
noop identifier renames, key => domain or entity
rodzic
97088da382
commit
e3f1431018
|
@ -58,8 +58,8 @@ def send(activity, inbox_url, user_domain):
|
|||
# https://tools.ietf.org/html/draft-cavage-http-signatures-07
|
||||
# https://github.com/tootsuite/mastodon/issues/4906#issuecomment-328844846
|
||||
key_id = request.host_url + user_domain
|
||||
key = Domain.get_or_create(user_domain)
|
||||
auth = HTTPSignatureAuth(secret=key.private_pem(), key_id=key_id,
|
||||
domain = Domain.get_or_create(user_domain)
|
||||
auth = HTTPSignatureAuth(secret=domain.private_pem(), key_id=key_id,
|
||||
algorithm='rsa-sha256', sign_header='signature',
|
||||
headers=('Date', 'Digest', 'Host'))
|
||||
|
||||
|
@ -94,9 +94,9 @@ def actor(domain):
|
|||
if not hcard:
|
||||
error(f"Couldn't find a representative h-card (http://microformats.org/wiki/representative-hcard-parsing) on {mf2['url']}")
|
||||
|
||||
key = Domain.get_or_create(domain)
|
||||
entity = Domain.get_or_create(domain)
|
||||
obj = common.postprocess_as2(
|
||||
as2.from_as1(microformats2.json_to_object(hcard)), key=key)
|
||||
as2.from_as1(microformats2.json_to_object(hcard)), domain=entity)
|
||||
obj.update({
|
||||
'preferredUsername': domain,
|
||||
'inbox': f'{request.host_url}{domain}/inbox',
|
||||
|
|
|
@ -242,14 +242,14 @@ def send_webmentions(activity_wrapped, proxy=None, **activity_props):
|
|||
error(msg, status=int(errors[0][0] or 502))
|
||||
|
||||
|
||||
def postprocess_as2(activity, target=None, key=None):
|
||||
def postprocess_as2(activity, target=None, domain=None):
|
||||
"""Prepare an AS2 object to be served or sent via ActivityPub.
|
||||
|
||||
Args:
|
||||
activity: dict, AS2 object or activity
|
||||
target: dict, AS2 object, optional. The target of activity's inReplyTo or
|
||||
Like/Announce/etc object, if any.
|
||||
key: :class:`models.Domain`, optional. populated into publicKey field
|
||||
domain: :class:`models.Domain`, optional. populated into publicKey field
|
||||
if provided.
|
||||
"""
|
||||
type = activity.get('type')
|
||||
|
@ -257,7 +257,7 @@ def postprocess_as2(activity, target=None, key=None):
|
|||
# actor objects
|
||||
if type == 'Person':
|
||||
postprocess_as2_actor(activity)
|
||||
if not activity.get('publicKey'):
|
||||
if not activity.get('publicKey') and domain:
|
||||
# underspecified, inferred from this issue and Mastodon's implementation:
|
||||
# https://github.com/w3c/activitypub/issues/203#issuecomment-297553229
|
||||
# https://github.com/tootsuite/mastodon/blob/bc2c263504e584e154384ecc2d804aeb1afb1ba3/app/services/activitypub/process_account_service.rb#L77
|
||||
|
@ -266,7 +266,7 @@ def postprocess_as2(activity, target=None, key=None):
|
|||
'publicKey': {
|
||||
'id': actor_url,
|
||||
'owner': actor_url,
|
||||
'publicKeyPem': key.public_pem().decode(),
|
||||
'publicKeyPem': domain.public_pem().decode(),
|
||||
},
|
||||
'@context': (util.get_list(activity, '@context') +
|
||||
['https://w3id.org/security/v1']),
|
||||
|
|
10
models.py
10
models.py
|
@ -36,17 +36,17 @@ class Domain(StringIdModel):
|
|||
@ndb.transactional()
|
||||
def get_or_create(domain):
|
||||
"""Loads and returns a Domain. Creates it if necessary."""
|
||||
key = Domain.get_by_id(domain)
|
||||
entity = Domain.get_by_id(domain)
|
||||
|
||||
if not key:
|
||||
if not entity:
|
||||
# this uses urandom(), and does nontrivial math, so it can take a
|
||||
# while depending on the amount of randomness available.
|
||||
pubexp, mod, privexp = magicsigs.generate()
|
||||
key = Domain(id=domain, mod=mod, public_exponent=pubexp,
|
||||
entity = Domain(id=domain, mod=mod, public_exponent=pubexp,
|
||||
private_exponent=privexp)
|
||||
key.put()
|
||||
entity.put()
|
||||
|
||||
return key
|
||||
return entity
|
||||
|
||||
def href(self):
|
||||
return 'data:application/magic-public-key,RSA.%s.%s' % (
|
||||
|
|
|
@ -9,29 +9,29 @@ class DomainTest(testutil.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
super(DomainTest, self).setUp()
|
||||
self.key = Domain.get_or_create('y.z')
|
||||
self.domain = Domain.get_or_create('y.z')
|
||||
|
||||
def test_magic_key_get_or_create(self):
|
||||
assert self.key.mod
|
||||
assert self.key.public_exponent
|
||||
assert self.key.private_exponent
|
||||
assert self.domain.mod
|
||||
assert self.domain.public_exponent
|
||||
assert self.domain.private_exponent
|
||||
|
||||
same = Domain.get_or_create('y.z')
|
||||
self.assertEqual(same, self.key)
|
||||
self.assertEqual(same, self.domain)
|
||||
|
||||
def test_href(self):
|
||||
href = self.key.href()
|
||||
href = self.domain.href()
|
||||
self.assertTrue(href.startswith('data:application/magic-public-key,RSA.'), href)
|
||||
self.assertIn(self.key.mod, href)
|
||||
self.assertIn(self.key.public_exponent, href)
|
||||
self.assertIn(self.domain.mod, href)
|
||||
self.assertIn(self.domain.public_exponent, href)
|
||||
|
||||
def test_public_pem(self):
|
||||
pem = self.key.public_pem()
|
||||
pem = self.domain.public_pem()
|
||||
self.assertTrue(pem.decode().startswith('-----BEGIN PUBLIC KEY-----\n'), pem)
|
||||
self.assertTrue(pem.decode().endswith('-----END PUBLIC KEY-----'), pem)
|
||||
|
||||
def test_private_pem(self):
|
||||
pem = self.key.private_pem()
|
||||
pem = self.domain.private_pem()
|
||||
self.assertTrue(pem.decode().startswith('-----BEGIN RSA PRIVATE KEY-----\n'), pem)
|
||||
self.assertTrue(pem.decode().endswith('-----END RSA PRIVATE KEY-----'), pem)
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ class User(flask_util.XrdOrJrd):
|
|||
error(f"didn't find a representative h-card (http://microformats.org/wiki/representative-hcard-parsing) on {resp.url}")
|
||||
|
||||
logger.info(f'Generating WebFinger data for {domain}')
|
||||
key = models.Domain.get_or_create(domain)
|
||||
entity = models.Domain.get_or_create(domain)
|
||||
props = hcard.get('properties', {})
|
||||
urls = util.dedupe_urls(props.get('url', []) + [resp.url])
|
||||
canonical_url = urls[0]
|
||||
|
@ -97,7 +97,7 @@ class User(flask_util.XrdOrJrd):
|
|||
data = util.trim_nulls({
|
||||
'subject': 'acct:' + acct,
|
||||
'aliases': urls,
|
||||
'magic_keys': [{'value': key.href()}],
|
||||
'magic_keys': [{'value': entity.href()}],
|
||||
'links': sum(([{
|
||||
'rel': 'http://webfinger.net/rel/profile-page',
|
||||
'type': 'text/html',
|
||||
|
@ -135,7 +135,7 @@ class User(flask_util.XrdOrJrd):
|
|||
'href': hub,
|
||||
}, {
|
||||
'rel': 'magic-public-key',
|
||||
'href': key.href(),
|
||||
'href': entity.href(),
|
||||
}, {
|
||||
'rel': 'salmon',
|
||||
'href': f'{request.host_url}{domain}/salmon',
|
||||
|
|
|
@ -91,7 +91,7 @@ class Webmention(View):
|
|||
if not targets:
|
||||
return None
|
||||
|
||||
key = Domain.get_or_create(self.source_domain)
|
||||
domain = Domain.get_or_create(self.source_domain)
|
||||
error = None
|
||||
last_success = None
|
||||
|
||||
|
@ -106,7 +106,7 @@ class Webmention(View):
|
|||
for resp, inbox in targets:
|
||||
target_obj = json_loads(resp.target_as2) if resp.target_as2 else None
|
||||
source_activity = common.postprocess_as2(
|
||||
as2.from_as1(self.source_obj), target=target_obj, key=key)
|
||||
as2.from_as1(self.source_obj), target=target_obj, domain=domain)
|
||||
|
||||
if resp.status == 'complete':
|
||||
if resp.source_mf2:
|
||||
|
@ -361,10 +361,10 @@ class Webmention(View):
|
|||
|
||||
# sign reply and wrap in magic envelope
|
||||
domain = urllib.parse.urlparse(self.source_url).netloc
|
||||
key = Domain.get_or_create(domain)
|
||||
logger.info(f'Using key for {domain}: {key}')
|
||||
entity = Domain.get_or_create(domain)
|
||||
logger.info(f'Using key for {domain}: {entity}')
|
||||
magic_envelope = magicsigs.magic_envelope(
|
||||
entry, common.CONTENT_TYPE_ATOM, key).decode()
|
||||
entry, common.CONTENT_TYPE_ATOM, entity).decode()
|
||||
|
||||
logger.info(f'Sending Salmon slap to {endpoint}')
|
||||
common.requests_post(
|
||||
|
|
Ładowanie…
Reference in New Issue