don't strip www, m, and mobile subdomains from user domains

fixes #267
accept-fails-store-response
Ryan Barrett 2022-11-07 16:26:33 -08:00
rodzic cfb6653d77
commit 8e60346dc4
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
4 zmienionych plików z 26 dodań i 21 usunięć

Wyświetl plik

@ -73,7 +73,7 @@ def send(activity, inbox_url, user_domain):
# required by Mastodon
# https://github.com/tootsuite/mastodon/pull/14556#issuecomment-674077648
'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,
headers=headers)
@ -204,7 +204,7 @@ def accept_follow(follow, follow_unwrapped):
error('Follow actor requires id and inbox. Got: %s', 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))
# send AP Accept
@ -220,6 +220,8 @@ def accept_follow(follow, follow_unwrapped):
'object': followee,
}
}
# STATE: this fails, then we don't create a Response, since that happens in
# send_webmentions
resp = send(accept, inbox, user_domain)
# send webmention
@ -231,7 +233,7 @@ def accept_follow(follow, follow_unwrapped):
@ndb.transactional()
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:
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)
# 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))
if follower_obj:
logger.info(f'Marking {follower_obj.key} as inactive')

Wyświetl plik

@ -189,7 +189,8 @@ def send_webmentions(activity_wrapped, proxy=None, **response_props):
# send webmentions and store Responses
errors = [] # stores (code, body) tuples
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}')
continue
@ -398,7 +399,8 @@ def redirect_unwrap(val):
if val.startswith(prefix):
return util.follow_redirects(val[len(prefix):]).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 val

Wyświetl plik

@ -47,7 +47,8 @@ def redir(to):
error(f'Expected fully qualified URL; got {to}')
# 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))
for domain in domains:
if domain and MagicKey.get_by_id(domain):

Wyświetl plik

@ -89,10 +89,10 @@ FOLLOW = {
'id': 'https://mastodon.social/6d1a',
'type': 'Follow',
'actor': 'https://mastodon.social/users/swentel',
'object': 'https://realize.be/',
'object': 'https://www.realize.be/',
}
FOLLOW_WRAPPED = copy.deepcopy(FOLLOW)
FOLLOW_WRAPPED['object'] = 'http://localhost/realize.be'
FOLLOW_WRAPPED['object'] = 'http://localhost/www.realize.be'
ACTOR = {
'@context': 'https://www.w3.org/ns/activitystreams',
'id': FOLLOW['actor'],
@ -112,12 +112,12 @@ FOLLOW_WRAPPED_WITH_ACTOR['actor'] = FOLLOW_WITH_ACTOR['actor']
ACCEPT = {
'@context': 'https://www.w3.org/ns/activitystreams',
'type': 'Accept',
'id': 'tag:localhost:accept/realize.be/https://mastodon.social/6d1a',
'actor': 'http://localhost/realize.be',
'id': 'tag:localhost:accept/www.realize.be/https://mastodon.social/6d1a',
'actor': 'http://localhost/www.realize.be',
'object': {
'type': 'Follow',
'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))
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 = [
# source actor
requests_response(FOLLOW_WITH_ACTOR['actor'],
@ -349,32 +349,32 @@ class ActivityPubTest(testutil.TestCase):
# check webmention
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({
'source': 'http://localhost/render?source=https%3A%2F%2Fmastodon.social%2F6d1a&target=https%3A%2F%2Frealize.be%2F',
'target': 'https://realize.be/',
'source': 'http://localhost/render?source=https%3A%2F%2Fmastodon.social%2F6d1a&target=https%3A%2F%2Fwww.realize.be%2F',
'target': 'https://www.realize.be/',
}, 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('activitypub', resp.protocol)
self.assertEqual('complete', resp.status)
self.assertEqual(FOLLOW_WITH_ACTOR, json_loads(resp.source_as2))
# 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(FOLLOW_WRAPPED_WITH_ACTOR, json_loads(follower.last_follow))
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)
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)
def test_inbox_undo_follow_doesnt_exist(self, mock_head, mock_get, mock_post):