kopia lustrzana https://github.com/snarfed/bridgy-fed
rodzic
cfb6653d77
commit
8e60346dc4
|
@ -73,7 +73,7 @@ def send(activity, inbox_url, user_domain):
|
||||||
# required by Mastodon
|
# required by Mastodon
|
||||||
# https://github.com/tootsuite/mastodon/pull/14556#issuecomment-674077648
|
# https://github.com/tootsuite/mastodon/pull/14556#issuecomment-674077648
|
||||||
'Digest': 'SHA-256=' + b64encode(sha256(body).digest()).decode(),
|
'Digest': 'SHA-256=' + b64encode(sha256(body).digest()).decode(),
|
||||||
'Host': util.domain_from_link(inbox_url),
|
'Host': util.domain_from_link(inbox_url, minimize=False),
|
||||||
}
|
}
|
||||||
return common.requests_post(inbox_url, data=body, auth=auth,
|
return common.requests_post(inbox_url, data=body, auth=auth,
|
||||||
headers=headers)
|
headers=headers)
|
||||||
|
@ -204,7 +204,7 @@ def accept_follow(follow, follow_unwrapped):
|
||||||
error('Follow actor requires id and inbox. Got: %s', follower)
|
error('Follow actor requires id and inbox. Got: %s', follower)
|
||||||
|
|
||||||
# store Follower
|
# store Follower
|
||||||
user_domain = util.domain_from_link(followee_unwrapped)
|
user_domain = util.domain_from_link(followee_unwrapped, minimize=False)
|
||||||
Follower.get_or_create(user_domain, follower_id, last_follow=json_dumps(follow))
|
Follower.get_or_create(user_domain, follower_id, last_follow=json_dumps(follow))
|
||||||
|
|
||||||
# send AP Accept
|
# send AP Accept
|
||||||
|
@ -220,6 +220,8 @@ def accept_follow(follow, follow_unwrapped):
|
||||||
'object': followee,
|
'object': followee,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# STATE: this fails, then we don't create a Response, since that happens in
|
||||||
|
# send_webmentions
|
||||||
resp = send(accept, inbox, user_domain)
|
resp = send(accept, inbox, user_domain)
|
||||||
|
|
||||||
# send webmention
|
# send webmention
|
||||||
|
@ -231,7 +233,7 @@ def accept_follow(follow, follow_unwrapped):
|
||||||
|
|
||||||
@ndb.transactional()
|
@ndb.transactional()
|
||||||
def undo_follow(undo_unwrapped):
|
def undo_follow(undo_unwrapped):
|
||||||
"""Replies to an AP Follow request with an Accept request.
|
"""Handles an AP Undo Follow request by deactivating the Follower entity.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
undo_unwrapped: dict, AP Undo activity with redirect URLs unwrapped
|
undo_unwrapped: dict, AP Undo activity with redirect URLs unwrapped
|
||||||
|
@ -245,7 +247,7 @@ def undo_follow(undo_unwrapped):
|
||||||
error('Undo of Follow requires object with actor and object. Got: %s' % follow)
|
error('Undo of Follow requires object with actor and object. Got: %s' % follow)
|
||||||
|
|
||||||
# deactivate Follower
|
# deactivate Follower
|
||||||
user_domain = util.domain_from_link(followee)
|
user_domain = util.domain_from_link(followee, minimize=False)
|
||||||
follower_obj = Follower.get_by_id(Follower._id(user_domain, follower))
|
follower_obj = Follower.get_by_id(Follower._id(user_domain, follower))
|
||||||
if follower_obj:
|
if follower_obj:
|
||||||
logger.info(f'Marking {follower_obj.key} as inactive')
|
logger.info(f'Marking {follower_obj.key} as inactive')
|
||||||
|
|
|
@ -189,7 +189,8 @@ def send_webmentions(activity_wrapped, proxy=None, **response_props):
|
||||||
# send webmentions and store Responses
|
# send webmentions and store Responses
|
||||||
errors = [] # stores (code, body) tuples
|
errors = [] # stores (code, body) tuples
|
||||||
for target in targets:
|
for target in targets:
|
||||||
if util.domain_from_link(target) == util.domain_from_link(source):
|
if (util.domain_from_link(target, minimize=False) ==
|
||||||
|
util.domain_from_link(source, minimize=False)):
|
||||||
logger.info(f'Skipping same-domain webmention from {source} to {target}')
|
logger.info(f'Skipping same-domain webmention from {source} to {target}')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -398,7 +399,8 @@ def redirect_unwrap(val):
|
||||||
if val.startswith(prefix):
|
if val.startswith(prefix):
|
||||||
return util.follow_redirects(val[len(prefix):]).url
|
return util.follow_redirects(val[len(prefix):]).url
|
||||||
elif val.startswith(request.host_url):
|
elif val.startswith(request.host_url):
|
||||||
domain = util.domain_from_link(urllib.parse.urlparse(val).path.strip('/'))
|
domain = util.domain_from_link(urllib.parse.urlparse(val).path.strip('/'),
|
||||||
|
minimize=False)
|
||||||
return util.follow_redirects(domain).url
|
return util.follow_redirects(domain).url
|
||||||
|
|
||||||
return val
|
return val
|
||||||
|
|
|
@ -47,7 +47,8 @@ def redir(to):
|
||||||
error(f'Expected fully qualified URL; got {to}')
|
error(f'Expected fully qualified URL; got {to}')
|
||||||
|
|
||||||
# check that we've seen this domain before so we're not an open redirect
|
# check that we've seen this domain before so we're not an open redirect
|
||||||
domains = set((util.domain_from_link(to),
|
domains = set((util.domain_from_link(to, minimize=True),
|
||||||
|
util.domain_from_link(to, minimize=False),
|
||||||
urllib.parse.urlparse(to).hostname))
|
urllib.parse.urlparse(to).hostname))
|
||||||
for domain in domains:
|
for domain in domains:
|
||||||
if domain and MagicKey.get_by_id(domain):
|
if domain and MagicKey.get_by_id(domain):
|
||||||
|
|
|
@ -89,10 +89,10 @@ FOLLOW = {
|
||||||
'id': 'https://mastodon.social/6d1a',
|
'id': 'https://mastodon.social/6d1a',
|
||||||
'type': 'Follow',
|
'type': 'Follow',
|
||||||
'actor': 'https://mastodon.social/users/swentel',
|
'actor': 'https://mastodon.social/users/swentel',
|
||||||
'object': 'https://realize.be/',
|
'object': 'https://www.realize.be/',
|
||||||
}
|
}
|
||||||
FOLLOW_WRAPPED = copy.deepcopy(FOLLOW)
|
FOLLOW_WRAPPED = copy.deepcopy(FOLLOW)
|
||||||
FOLLOW_WRAPPED['object'] = 'http://localhost/realize.be'
|
FOLLOW_WRAPPED['object'] = 'http://localhost/www.realize.be'
|
||||||
ACTOR = {
|
ACTOR = {
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
'id': FOLLOW['actor'],
|
'id': FOLLOW['actor'],
|
||||||
|
@ -112,12 +112,12 @@ FOLLOW_WRAPPED_WITH_ACTOR['actor'] = FOLLOW_WITH_ACTOR['actor']
|
||||||
ACCEPT = {
|
ACCEPT = {
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
'type': 'Accept',
|
'type': 'Accept',
|
||||||
'id': 'tag:localhost:accept/realize.be/https://mastodon.social/6d1a',
|
'id': 'tag:localhost:accept/www.realize.be/https://mastodon.social/6d1a',
|
||||||
'actor': 'http://localhost/realize.be',
|
'actor': 'http://localhost/www.realize.be',
|
||||||
'object': {
|
'object': {
|
||||||
'type': 'Follow',
|
'type': 'Follow',
|
||||||
'actor': 'https://mastodon.social/users/swentel',
|
'actor': 'https://mastodon.social/users/swentel',
|
||||||
'object': 'http://localhost/realize.be',
|
'object': 'http://localhost/www.realize.be',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ class ActivityPubTest(testutil.TestCase):
|
||||||
self.assertEqual(LIKE_WITH_ACTOR, json_loads(resp.source_as2))
|
self.assertEqual(LIKE_WITH_ACTOR, json_loads(resp.source_as2))
|
||||||
|
|
||||||
def test_inbox_follow_accept(self, mock_head, mock_get, mock_post):
|
def test_inbox_follow_accept(self, mock_head, mock_get, mock_post):
|
||||||
mock_head.return_value = requests_response(url='https://realize.be/')
|
mock_head.return_value = requests_response(url='https://www.realize.be/')
|
||||||
mock_get.side_effect = [
|
mock_get.side_effect = [
|
||||||
# source actor
|
# source actor
|
||||||
requests_response(FOLLOW_WITH_ACTOR['actor'],
|
requests_response(FOLLOW_WITH_ACTOR['actor'],
|
||||||
|
@ -349,32 +349,32 @@ class ActivityPubTest(testutil.TestCase):
|
||||||
|
|
||||||
# check webmention
|
# check webmention
|
||||||
args, kwargs = mock_post.call_args_list[1]
|
args, kwargs = mock_post.call_args_list[1]
|
||||||
self.assertEqual(('https://realize.be/webmention',), args)
|
self.assertEqual(('https://www.realize.be/webmention',), args)
|
||||||
self.assertEqual({
|
self.assertEqual({
|
||||||
'source': 'http://localhost/render?source=https%3A%2F%2Fmastodon.social%2F6d1a&target=https%3A%2F%2Frealize.be%2F',
|
'source': 'http://localhost/render?source=https%3A%2F%2Fmastodon.social%2F6d1a&target=https%3A%2F%2Fwww.realize.be%2F',
|
||||||
'target': 'https://realize.be/',
|
'target': 'https://www.realize.be/',
|
||||||
}, kwargs['data'])
|
}, kwargs['data'])
|
||||||
|
|
||||||
resp = Response.get_by_id('https://mastodon.social/6d1a https://realize.be/')
|
resp = Response.get_by_id('https://mastodon.social/6d1a https://www.realize.be/')
|
||||||
self.assertEqual('in', resp.direction)
|
self.assertEqual('in', resp.direction)
|
||||||
self.assertEqual('activitypub', resp.protocol)
|
self.assertEqual('activitypub', resp.protocol)
|
||||||
self.assertEqual('complete', resp.status)
|
self.assertEqual('complete', resp.status)
|
||||||
self.assertEqual(FOLLOW_WITH_ACTOR, json_loads(resp.source_as2))
|
self.assertEqual(FOLLOW_WITH_ACTOR, json_loads(resp.source_as2))
|
||||||
|
|
||||||
# check that we stored a Follower object
|
# check that we stored a Follower object
|
||||||
follower = Follower.get_by_id('realize.be %s' % (FOLLOW['actor']))
|
follower = Follower.get_by_id('www.realize.be %s' % (FOLLOW['actor']))
|
||||||
self.assertEqual('active', follower.status)
|
self.assertEqual('active', follower.status)
|
||||||
self.assertEqual(FOLLOW_WRAPPED_WITH_ACTOR, json_loads(follower.last_follow))
|
self.assertEqual(FOLLOW_WRAPPED_WITH_ACTOR, json_loads(follower.last_follow))
|
||||||
|
|
||||||
def test_inbox_undo_follow(self, mock_head, mock_get, mock_post):
|
def test_inbox_undo_follow(self, mock_head, mock_get, mock_post):
|
||||||
mock_head.return_value = requests_response(url='https://realize.be/')
|
mock_head.return_value = requests_response(url='https://www.realize.be/')
|
||||||
|
|
||||||
Follower(id=Follower._id('realize.be', FOLLOW['actor'])).put()
|
Follower(id=Follower._id('www.realize.be', FOLLOW['actor'])).put()
|
||||||
|
|
||||||
got = self.client.post('/foo.com/inbox', json=UNDO_FOLLOW_WRAPPED)
|
got = self.client.post('/foo.com/inbox', json=UNDO_FOLLOW_WRAPPED)
|
||||||
self.assertEqual(200, got.status_code)
|
self.assertEqual(200, got.status_code)
|
||||||
|
|
||||||
follower = Follower.get_by_id('realize.be %s' % FOLLOW['actor'])
|
follower = Follower.get_by_id('www.realize.be %s' % FOLLOW['actor'])
|
||||||
self.assertEqual('inactive', follower.status)
|
self.assertEqual('inactive', follower.status)
|
||||||
|
|
||||||
def test_inbox_undo_follow_doesnt_exist(self, mock_head, mock_get, mock_post):
|
def test_inbox_undo_follow_doesnt_exist(self, mock_head, mock_get, mock_post):
|
||||||
|
|
Ładowanie…
Reference in New Issue