2017-08-19 15:21:05 +00:00
|
|
|
# coding=utf-8
|
2023-02-10 04:00:58 +00:00
|
|
|
"""Unit tests for webfinger.py."""
|
2021-08-06 17:29:25 +00:00
|
|
|
import html
|
2019-12-26 06:20:57 +00:00
|
|
|
import urllib.parse
|
2017-08-19 15:21:05 +00:00
|
|
|
|
2017-08-19 20:10:18 +00:00
|
|
|
import common
|
2023-02-10 04:00:58 +00:00
|
|
|
from models import User
|
2019-12-26 06:20:57 +00:00
|
|
|
from . import testutil
|
2017-08-19 15:21:05 +00:00
|
|
|
|
|
|
|
|
2023-02-10 04:00:58 +00:00
|
|
|
class HostMetaTest(testutil.TestCase):
|
|
|
|
def test_host_meta_xrd(self):
|
|
|
|
got = self.client.get('/.well-known/host-meta')
|
|
|
|
self.assertEqual(200, got.status_code)
|
|
|
|
self.assertEqual('application/xrd+xml; charset=utf-8',
|
|
|
|
got.headers['Content-Type'])
|
|
|
|
body = got.get_data(as_text=True)
|
|
|
|
self.assertTrue(body.startswith('<?xml'), body)
|
|
|
|
|
|
|
|
def test_host_meta_xrds(self):
|
|
|
|
got = self.client.get('/.well-known/host-meta.xrds')
|
|
|
|
self.assertEqual(200, got.status_code)
|
|
|
|
self.assertEqual('application/xrds+xml', got.headers['Content-Type'])
|
|
|
|
body = got.get_data(as_text=True)
|
|
|
|
self.assertTrue(body.startswith('<XRDS'), body)
|
|
|
|
|
|
|
|
def test_host_meta_jrd(self):
|
|
|
|
got = self.client.get('/.well-known/host-meta.json')
|
|
|
|
self.assertEqual(200, got.status_code)
|
|
|
|
self.assertEqual('application/jrd+json', got.headers['Content-Type'])
|
|
|
|
body = got.get_data(as_text=True)
|
|
|
|
self.assertTrue(body.startswith('{'), body)
|
|
|
|
|
|
|
|
|
2020-12-30 18:26:48 +00:00
|
|
|
class WebfingerTest(testutil.TestCase):
|
2017-08-19 16:24:00 +00:00
|
|
|
|
2017-09-03 22:44:01 +00:00
|
|
|
def setUp(self):
|
2021-08-18 14:59:52 +00:00
|
|
|
super().setUp()
|
2021-07-11 20:39:19 +00:00
|
|
|
|
2023-02-10 04:00:58 +00:00
|
|
|
self.actor_as2 = {
|
|
|
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
|
|
|
'type': 'Person',
|
2023-03-19 22:43:55 +00:00
|
|
|
'url': 'https://user.com/about-me',
|
2023-02-10 04:00:58 +00:00
|
|
|
'name': 'Mrs. ☕ Foo',
|
2023-03-19 22:43:55 +00:00
|
|
|
'icon': {'type': 'Image', 'url': 'https://user.com/me.jpg'},
|
2023-02-10 04:00:58 +00:00
|
|
|
}
|
2023-03-19 22:43:55 +00:00
|
|
|
self.user = self.make_user('user.com', has_hcard=True, actor_as2=self.actor_as2)
|
2023-02-10 04:00:58 +00:00
|
|
|
self.user.put()
|
2017-09-03 22:44:01 +00:00
|
|
|
self.expected_webfinger = {
|
2023-03-19 22:43:55 +00:00
|
|
|
'subject': 'acct:user.com@user.com',
|
2017-08-19 16:24:00 +00:00
|
|
|
'aliases': [
|
2023-03-19 22:43:55 +00:00
|
|
|
'https://user.com/about-me',
|
|
|
|
'https://user.com/',
|
2017-08-19 16:24:00 +00:00
|
|
|
],
|
|
|
|
'links': [{
|
|
|
|
'rel': 'http://webfinger.net/rel/profile-page',
|
|
|
|
'type': 'text/html',
|
2023-03-19 22:43:55 +00:00
|
|
|
'href': 'https://user.com/about-me',
|
2017-08-19 16:24:00 +00:00
|
|
|
}, {
|
2017-08-19 20:10:18 +00:00
|
|
|
'rel': 'http://webfinger.net/rel/profile-page',
|
|
|
|
'type': 'text/html',
|
2023-03-19 22:43:55 +00:00
|
|
|
'href': 'https://user.com/',
|
2017-08-20 02:46:53 +00:00
|
|
|
}, {
|
|
|
|
'rel': 'http://webfinger.net/rel/avatar',
|
2023-03-19 22:43:55 +00:00
|
|
|
'href': 'https://user.com/me.jpg',
|
2017-09-03 19:35:18 +00:00
|
|
|
}, {
|
|
|
|
'rel': 'canonical_uri',
|
|
|
|
'type': 'text/html',
|
2023-03-19 22:43:55 +00:00
|
|
|
'href': 'https://user.com/about-me',
|
2017-09-28 14:25:21 +00:00
|
|
|
}, {
|
|
|
|
'rel': 'self',
|
|
|
|
'type': 'application/activity+json',
|
2023-03-19 22:43:55 +00:00
|
|
|
'href': 'http://localhost/user.com',
|
2017-09-28 14:25:21 +00:00
|
|
|
}, {
|
|
|
|
'rel': 'inbox',
|
|
|
|
'type': 'application/activity+json',
|
2023-03-19 22:43:55 +00:00
|
|
|
'href': 'http://localhost/user.com/inbox'
|
2022-11-16 18:09:24 +00:00
|
|
|
}, {
|
|
|
|
'rel': 'sharedInbox',
|
|
|
|
'type': 'application/activity+json',
|
2023-02-10 04:00:58 +00:00
|
|
|
'href': 'http://localhost/inbox',
|
2023-01-26 04:41:29 +00:00
|
|
|
}, {
|
|
|
|
'rel': 'http://ostatus.org/schema/1.0/subscribe',
|
2023-03-19 22:43:55 +00:00
|
|
|
'template': 'http://localhost/user/user.com?url={uri}',
|
2023-01-26 04:59:40 +00:00
|
|
|
}],
|
2017-09-03 22:44:01 +00:00
|
|
|
}
|
|
|
|
|
2023-02-10 04:00:58 +00:00
|
|
|
def test_user(self):
|
2023-03-19 22:43:55 +00:00
|
|
|
got = self.client.get('/acct:user.com', headers={'Accept': 'application/json'})
|
2021-07-11 20:39:19 +00:00
|
|
|
self.assertEqual(200, got.status_code)
|
2021-07-11 23:30:14 +00:00
|
|
|
self.assertEqual('application/jrd+json', got.headers['Content-Type'])
|
2023-03-19 04:45:27 +00:00
|
|
|
self.assert_equals(self.expected_webfinger, got.json)
|
2017-08-19 20:31:06 +00:00
|
|
|
|
2023-02-10 04:00:58 +00:00
|
|
|
def test_user_no_hcard(self):
|
|
|
|
self.user.has_hcard = False
|
|
|
|
self.user.actor_as2 = None
|
|
|
|
self.user.put()
|
|
|
|
|
2023-03-19 22:43:55 +00:00
|
|
|
got = self.client.get('/acct:user.com')
|
2023-01-26 04:41:29 +00:00
|
|
|
self.assertEqual(200, got.status_code)
|
|
|
|
self.assert_equals({
|
2023-03-19 22:43:55 +00:00
|
|
|
'subject': 'acct:user.com@user.com',
|
|
|
|
'aliases': ['https://user.com/'],
|
2023-01-26 04:41:29 +00:00
|
|
|
'links': [{
|
|
|
|
'rel': 'http://webfinger.net/rel/profile-page',
|
|
|
|
'type': 'text/html',
|
2023-03-19 22:43:55 +00:00
|
|
|
'href': 'https://user.com/'
|
2023-01-26 04:41:29 +00:00
|
|
|
}, {
|
|
|
|
'rel': 'canonical_uri',
|
|
|
|
'type': 'text/html',
|
2023-03-19 22:43:55 +00:00
|
|
|
'href': 'https://user.com/'
|
2023-01-26 04:41:29 +00:00
|
|
|
}, {
|
|
|
|
'rel': 'self',
|
|
|
|
'type': 'application/activity+json',
|
2023-03-19 22:43:55 +00:00
|
|
|
'href': 'http://localhost/user.com'
|
2023-01-26 04:41:29 +00:00
|
|
|
}, {
|
|
|
|
'rel': 'inbox',
|
|
|
|
'type': 'application/activity+json',
|
2023-03-19 22:43:55 +00:00
|
|
|
'href': 'http://localhost/user.com/inbox'
|
2023-01-26 04:41:29 +00:00
|
|
|
}, {
|
|
|
|
'rel': 'sharedInbox',
|
|
|
|
'type': 'application/activity+json',
|
|
|
|
'href': 'http://localhost/inbox'
|
|
|
|
}, {
|
|
|
|
'rel': 'http://ostatus.org/schema/1.0/subscribe',
|
2023-03-19 22:43:55 +00:00
|
|
|
'template': 'http://localhost/user/user.com?url={uri}',
|
2023-01-26 04:41:29 +00:00
|
|
|
}]
|
|
|
|
}, got.json)
|
2017-09-03 22:44:01 +00:00
|
|
|
|
2022-11-25 16:00:14 +00:00
|
|
|
def test_user_bad_tld(self):
|
2021-08-18 14:59:52 +00:00
|
|
|
got = self.client.get('/acct:foo.json')
|
2021-07-11 20:39:19 +00:00
|
|
|
self.assertEqual(404, got.status_code)
|
2021-08-06 17:29:25 +00:00
|
|
|
self.assertIn("doesn't look like a domain",
|
|
|
|
html.unescape(got.get_data(as_text=True)))
|
2019-04-19 14:59:44 +00:00
|
|
|
|
2023-01-26 04:00:54 +00:00
|
|
|
def test_user_not_found(self):
|
|
|
|
got = self.client.get('/acct:nope.com', headers={'Accept': 'application/json'})
|
|
|
|
self.assertEqual(404, got.status_code)
|
|
|
|
|
2023-02-10 04:00:58 +00:00
|
|
|
def test_webfinger(self):
|
2023-03-19 22:43:55 +00:00
|
|
|
for resource in ('user.com@user.com', 'acct:user.com@user.com', 'xyz@user.com',
|
|
|
|
'user.com', 'http://user.com/', 'https://user.com/',
|
|
|
|
'http://localhost/user.com'):
|
2022-11-26 14:59:27 +00:00
|
|
|
with self.subTest(resource=resource):
|
2023-01-24 20:17:24 +00:00
|
|
|
url = (f'/.well-known/webfinger?' +
|
|
|
|
urllib.parse.urlencode({'resource': resource}))
|
2022-11-26 14:59:27 +00:00
|
|
|
got = self.client.get(url, headers={'Accept': 'application/json'})
|
|
|
|
self.assertEqual(200, got.status_code, got.get_data(as_text=True))
|
|
|
|
self.assertEqual('application/jrd+json', got.headers['Content-Type'])
|
2023-03-19 04:45:27 +00:00
|
|
|
self.assert_equals(self.expected_webfinger, got.json)
|
2018-04-12 13:25:39 +00:00
|
|
|
|
2023-02-10 04:00:58 +00:00
|
|
|
def test_webfinger_custom_username(self):
|
2023-02-24 13:25:29 +00:00
|
|
|
self.user.actor_as2 = {
|
2023-02-10 04:00:58 +00:00
|
|
|
**self.actor_as2,
|
|
|
|
'url': [
|
2023-03-19 22:43:55 +00:00
|
|
|
'https://user.com/about-me',
|
2023-02-10 04:00:58 +00:00
|
|
|
'acct:notthisuser@boop.org',
|
2023-03-19 22:43:55 +00:00
|
|
|
'acct:customuser@user.com',
|
2023-02-10 04:00:58 +00:00
|
|
|
],
|
2023-02-24 13:25:29 +00:00
|
|
|
}
|
2023-02-10 04:00:58 +00:00
|
|
|
self.user.put()
|
|
|
|
|
2020-12-30 18:26:48 +00:00
|
|
|
self.expected_webfinger.update({
|
2023-03-19 22:43:55 +00:00
|
|
|
'subject': 'acct:customuser@user.com',
|
2020-12-30 18:26:48 +00:00
|
|
|
'aliases': [
|
2023-03-19 22:43:55 +00:00
|
|
|
'https://user.com/about-me',
|
2020-12-30 18:26:48 +00:00
|
|
|
'acct:notthisuser@boop.org',
|
2023-03-19 22:43:55 +00:00
|
|
|
'acct:customuser@user.com',
|
|
|
|
'https://user.com/',
|
2020-12-30 18:26:48 +00:00
|
|
|
],
|
|
|
|
})
|
2018-04-12 13:25:39 +00:00
|
|
|
|
2020-12-30 18:26:48 +00:00
|
|
|
for resource in (
|
2023-03-19 22:43:55 +00:00
|
|
|
'customuser@user.com',
|
|
|
|
'acct:customuser@user.com',
|
|
|
|
'user.com',
|
|
|
|
'http://user.com/',
|
|
|
|
'https://user.com/',
|
2020-12-30 18:26:48 +00:00
|
|
|
# Mastodon requires this as of 3.3.0
|
|
|
|
# https://github.com/snarfed/bridgy-fed/issues/73
|
2023-03-19 22:43:55 +00:00
|
|
|
'acct:user.com@fed.brid.gy',
|
|
|
|
'acct:user.com@bridgy-federated.appspot.com',
|
|
|
|
'acct:user.com@localhost',
|
2020-12-30 18:26:48 +00:00
|
|
|
):
|
2022-11-27 00:05:02 +00:00
|
|
|
with self.subTest(resource=resource):
|
2023-01-24 20:17:24 +00:00
|
|
|
url = (f'/.well-known/webfinger?' +
|
|
|
|
urllib.parse.urlencode({'resource': resource}))
|
2022-11-27 00:05:02 +00:00
|
|
|
got = self.client.get(url, headers={'Accept': 'application/json'})
|
|
|
|
self.assertEqual(200, got.status_code, got.get_data(as_text=True))
|
|
|
|
self.assertEqual('application/jrd+json', got.headers['Content-Type'])
|
2023-03-19 04:45:27 +00:00
|
|
|
self.assert_equals(self.expected_webfinger, got.json)
|
2022-11-25 16:00:14 +00:00
|
|
|
|
|
|
|
def test_webfinger_fed_brid_gy(self):
|
|
|
|
got = self.client.get('/.well-known/webfinger?resource=http://localhost/')
|
|
|
|
self.assertEqual(400, got.status_code, got.get_data(as_text=True))
|
|
|
|
|
2022-11-26 14:59:27 +00:00
|
|
|
got = self.client.get('/.well-known/webfinger?resource=acct%3A%40localhost')
|
|
|
|
self.assertEqual(400, got.status_code, got.get_data(as_text=True))
|