Make JSON webfinger support webfinger profile url

merge-requests/130/head
Jason Robinson 2018-02-21 19:20:46 +02:00
rodzic 065d9e4d2b
commit 3730a3d9b8
7 zmienionych plików z 43 dodań i 18 usunięć

Wyświetl plik

@ -111,11 +111,14 @@ Some settings need to be set in Django settings. An example is below:
FEDERATION = { FEDERATION = {
"base_url": "https://myserver.domain.tld, "base_url": "https://myserver.domain.tld,
"profile_id_function": "myproject.utils.get_profile_id_by_handle", "get_profile_function": "myproject.utils.get_profile_by_handle",
} }
* ``base_url`` is the base URL of the server, ie protocol://domain.tld. * ``base_url`` is the base URL of the server, ie protocol://domain.tld.
* ``profile_id_function`` should be the full path to a function that given a handle will return the Diaspora URI format profile ID. * ``profile_id_function`` should be the full path to a function that given a handle will return a dictionary with information that will be used to generate the webfinger document. The dict should contain the following elements:
* ``id`` - Diaspora URI format ID.
* ``profile_path`` - profile path for generating an absolute URL to the profile page of the user.
Protocols Protocols
--------- ---------

Wyświetl plik

@ -19,7 +19,7 @@ def get_configuration():
} }
configuration.update(settings.FEDERATION) configuration.update(settings.FEDERATION)
if not all([ if not all([
"profile_id_function" in configuration, "get_profile_function" in configuration,
"base_url" in configuration, "base_url" in configuration,
"hcard_path" in configuration, "hcard_path" in configuration,
]): ]):
@ -27,12 +27,12 @@ def get_configuration():
return configuration return configuration
def get_profile_id_func(): def get_profile_func():
""" """
Import the function to get profile ID by handle. Import the function to get profile by handle.
""" """
config = get_configuration() config = get_configuration()
profile_func_path = config.get("profile_id_function") profile_func_path = config.get("get_profile_function")
module_path, func_name = profile_func_path.rsplit(".", 1) module_path, func_name = profile_func_path.rsplit(".", 1)
module = importlib.import_module(module_path) module = importlib.import_module(module_path)
profile_func = getattr(module, func_name) profile_func = getattr(module, func_name)
@ -50,18 +50,19 @@ def rfc3033_webfinger_view(request, *args, **kwargs):
return HttpResponseBadRequest("Invalid resource") return HttpResponseBadRequest("Invalid resource")
handle = resource.replace("acct:", "") handle = resource.replace("acct:", "")
profile_id_func = get_profile_id_func() profile_func = get_profile_func()
try: try:
profile_id = profile_id_func(handle) profile = profile_func(handle)
except Exception as exc: except Exception as exc:
logger.warning("rfc3033_webfinger_view - Failed to get profile ID by handle %s: %s", handle, exc) logger.warning("rfc3033_webfinger_view - Failed to get profile by handle %s: %s", handle, exc)
return HttpResponseNotFound() return HttpResponseNotFound()
config = get_configuration() config = get_configuration()
webfinger = RFC3033Webfinger( webfinger = RFC3033Webfinger(
id=profile_id, id=profile.get('id'),
base_url=config.get('base_url'), base_url=config.get('base_url'),
profile_path=profile.get('profile_path'),
hcard_path=config.get('hcard_path'), hcard_path=config.get('hcard_path'),
) )

Wyświetl plik

@ -287,13 +287,15 @@ class RFC3033Webfinger:
:param id: Diaspora ID in URI format :param id: Diaspora ID in URI format
:param base_url: The base URL of the server (protocol://domain.tld) :param base_url: The base URL of the server (protocol://domain.tld)
:param profile_path: Profile path for the user (for example `/profile/johndoe/`)
:param hcard_path: (Optional) hCard path, defaults to ``/hcard/users/``. :param hcard_path: (Optional) hCard path, defaults to ``/hcard/users/``.
:returns: dict :returns: dict
""" """
def __init__(self, id, base_url, hcard_path="/hcard/users/"): def __init__(self, id, base_url, profile_path, hcard_path="/hcard/users/"):
self.handle, self.guid = parse_profile_diaspora_id(id) self.handle, self.guid = parse_profile_diaspora_id(id)
self.base_url = base_url self.base_url = base_url
self.hcard_path = hcard_path self.hcard_path = hcard_path
self.profile_path = profile_path
def render(self): def render(self):
return { return {
@ -309,5 +311,10 @@ class RFC3033Webfinger:
"type": "text/html", "type": "text/html",
"href": self.base_url, "href": self.base_url,
}, },
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "%s%s" % (self.base_url, self.profile_path),
},
], ],
} }

Wyświetl plik

@ -4,5 +4,5 @@ INSTALLED_APPS = tuple()
FEDERATION = { FEDERATION = {
"base_url": "https://example.com", "base_url": "https://example.com",
"profile_id_function": "federation.tests.hostmeta.django.utils.get_profile_id_by_handle", "get_profile_function": "federation.tests.hostmeta.django.utils.get_profile_by_handle",
} }

Wyświetl plik

@ -4,11 +4,11 @@ from unittest.mock import patch, Mock
from django.test import RequestFactory from django.test import RequestFactory
from federation.hostmeta.django import rfc3033_webfinger_view from federation.hostmeta.django import rfc3033_webfinger_view
from federation.hostmeta.django.generators import get_profile_id_func from federation.hostmeta.django.generators import get_profile_func
def test_get_profile_id_func(): def test_get_profile_func():
func = get_profile_id_func() func = get_profile_func()
assert callable(func) assert callable(func)
@ -23,7 +23,7 @@ class TestRFC3033WebfingerView:
response = rfc3033_webfinger_view(request) response = rfc3033_webfinger_view(request)
assert response.status_code == 400 assert response.status_code == 400
@patch("federation.hostmeta.django.generators.get_profile_id_func") @patch("federation.hostmeta.django.generators.get_profile_func")
def test_unknown_handle_returns_not_found(self, mock_get_func): def test_unknown_handle_returns_not_found(self, mock_get_func):
mock_get_func.return_value = Mock(side_effect=Exception) mock_get_func.return_value = Mock(side_effect=Exception)
request = RequestFactory().get("/.well-known/webfinger?resource=acct:foobar@domain.tld") request = RequestFactory().get("/.well-known/webfinger?resource=acct:foobar@domain.tld")
@ -48,5 +48,10 @@ class TestRFC3033WebfingerView:
"type": "text/html", "type": "text/html",
"href": "https://example.com", "href": "https://example.com",
}, },
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://example.com/profile/1234/",
},
], ],
} }

Wyświetl plik

@ -1,5 +1,8 @@
from federation.utils.diaspora import generate_diaspora_profile_id from federation.utils.diaspora import generate_diaspora_profile_id
def get_profile_id_by_handle(handle): def get_profile_by_handle(handle):
return generate_diaspora_profile_id(handle, "1234") return {
"id": generate_diaspora_profile_id(handle, "1234"),
"profile_path": "/profile/1234/",
}

Wyświetl plik

@ -182,6 +182,7 @@ def test_rfc3033_webfinger():
webfinger = RFC3033Webfinger( webfinger = RFC3033Webfinger(
"diaspora://foobar@example.com/profile/1234", "diaspora://foobar@example.com/profile/1234",
"https://example.com", "https://example.com",
profile_path="/profile/1234/",
).render() ).render()
assert webfinger == { assert webfinger == {
"subject": "acct:foobar@example.com", "subject": "acct:foobar@example.com",
@ -196,5 +197,10 @@ def test_rfc3033_webfinger():
"type": "text/html", "type": "text/html",
"href": "https://example.com", "href": "https://example.com",
}, },
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://example.com/profile/1234/",
},
], ],
} }