add webfinger.fetch_actor_url, use it in follow

also add a basic test for webfinger.fetch
pull/646/head
Ryan Barrett 2023-09-22 12:48:00 -07:00
rodzic 0d33b6422d
commit e97270b344
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
3 zmienionych plików z 48 dodań i 19 usunięć

Wyświetl plik

@ -96,19 +96,8 @@ class FollowCallback(indieauth.Callback):
addr = state
if not state:
error('Missing state')
elif util.is_web(state):
as2_url = state
else:
resp = webfinger.fetch(addr)
if resp is None:
return redirect(g.user.user_page_path('following'))
as2_url = None
for link in resp.get('links', []):
type = link.get('type', '').split(';')[0]
if link.get('rel') == 'self' and type in as2.CONTENT_TYPES:
as2_url = link.get('href')
as2_url = state if util.is_web(state) else webfinger.fetch_actor_url(addr)
if not as2_url:
flash(f"Couldn't find ActivityPub profile link for {addr}")
return redirect(g.user.user_page_path('following'))

Wyświetl plik

@ -10,6 +10,7 @@ from oauth_dropins.webutil.testutil import requests_response
from .testutil import Fake, TestCase
from web import Web
from webfinger import fetch, fetch_actor_url
from .test_web import ACTOR_HTML
@ -261,7 +262,7 @@ class WebfingerTest(TestCase):
self.assertEqual(400, got.status_code, got.get_data(as_text=True))
@patch('requests.get')
def test_fetch_create_user(self, mock_get):
def test_serve_create_user(self, mock_get):
self.user.key.delete()
mock_get.return_value = requests_response(ACTOR_HTML)
@ -282,3 +283,22 @@ class WebfingerTest(TestCase):
got = self.client.get('/.well-known/webfinger?resource=acct%3A%40localhost')
self.assertEqual(400, got.status_code, got.get_data(as_text=True))
@patch('requests.get', return_value=requests_response(
WEBFINGER, content_type='application/jrd+json'))
def test_fetch(self, mock_get):
self.assertEqual(WEBFINGER, fetch('@foo@bar'))
self.assert_req(mock_get,
'https://bar/.well-known/webfinger?resource=acct:foo@bar')
@patch('requests.get', return_value=requests_response(WEBFINGER))
def test_fetch_actor_url(self, mock_get):
self.assertEqual('http://localhost/user.com', fetch_actor_url('@foo@bar'))
self.assert_req(mock_get,
'https://bar/.well-known/webfinger?resource=acct:foo@bar')
@patch('requests.get', return_value=requests_response({'links': []}))
def test_fetch_actor_url_not_found(self, mock_get):
self.assertIsNone(fetch_actor_url('@foo@bar'))
self.assert_req(mock_get,
'https://bar/.well-known/webfinger?resource=acct:foo@bar')

Wyświetl plik

@ -1,7 +1,7 @@
"""Handles requests for WebFinger endpoints.
https://webfinger.net/
https://tools.ietf.org/html/rfc7033
* https://webfinger.net/
* https://tools.ietf.org/html/rfc7033
"""
import logging
import urllib.parse
@ -172,17 +172,15 @@ def fetch(addr):
On failure, flashes a message and returns None.
TODO: unit tests. right now it's only tested indirectly, in test_follow.
TODO: switch to raising exceptions instead of flashing messages and
returning None
Args:
addr: str, a Webfinger-compatible address, eg @x@y, acct:x@y, or
addr (str): a Webfinger-compatible address, eg @x@y, acct:x@y, or
https://x/y
Returns:
dict, fetched Webfinger data, or None on error
dict: fetched Webfinger data, or None on error
"""
addr = addr.strip().strip('@')
split = addr.split('@')
@ -220,6 +218,28 @@ def fetch(addr):
return data
def fetch_actor_url(addr):
"""Fetches and returns a WebFinger address's ActivityPub actor URL.
On failure, flashes a message and returns None.
Args:
addr (str): a Webfinger-compatible address, eg ``@x@y``, ``acct:x@y``, or
``https://x/y``
Returns:
str: ActivityPub actor URL, or None on error or not fouund
"""
data = fetch(addr)
if not data:
return None
for link in data.get('links', []):
type = link.get('type', '').split(';')[0]
if link.get('rel') == 'self' and type in as2.CONTENT_TYPES:
return link.get('href')
app.add_url_rule('/.well-known/webfinger', view_func=Webfinger.as_view('webfinger'))
app.add_url_rule('/.well-known/host-meta', view_func=HostMeta.as_view('hostmeta'))
app.add_url_rule('/.well-known/host-meta.json', view_func=HostMeta.as_view('hostmeta-json'))