Add `federation.hostmeta` generators for Matrix client and server well-known files.

Django views and url configuration also included for convenience.
matrix-appservice
Jason Robinson 2020-12-20 17:55:01 +02:00
rodzic 34d04f01f1
commit 48be2cbb6e
5 zmienionych plików z 103 dodań i 2 usunięć

Wyświetl plik

@ -2,6 +2,11 @@
## [unreleased] ## [unreleased]
### Added
* Add `federation.hostmeta` generators for Matrix client and server well-known files.
Django views and url configuration also included for convenience.
## [0.21.0] - 2020-12-20 ## [0.21.0] - 2020-12-20
### Added ### Added

Wyświetl plik

@ -149,6 +149,8 @@ Generator classes
.. autoclass:: federation.hostmeta.generators.DiasporaHostMeta .. autoclass:: federation.hostmeta.generators.DiasporaHostMeta
.. autoclass:: federation.hostmeta.generators.DiasporaWebFinger .. autoclass:: federation.hostmeta.generators.DiasporaWebFinger
.. autoclass:: federation.hostmeta.generators.DiasporaHCard .. autoclass:: federation.hostmeta.generators.DiasporaHCard
.. autoclass:: federation.hostmeta.generators.MatrixClientWellKnown
.. autoclass:: federation.hostmeta.generators.MatrixServerWellKnown
.. autoclass:: federation.hostmeta.generators.NodeInfo .. autoclass:: federation.hostmeta.generators.NodeInfo
.. autoclass:: federation.hostmeta.generators.RFC7033Webfinger .. autoclass:: federation.hostmeta.generators.RFC7033Webfinger
.. autoclass:: federation.hostmeta.generators.SocialRelayWellKnown .. autoclass:: federation.hostmeta.generators.SocialRelayWellKnown
@ -189,6 +191,8 @@ It must be installed separately.
.. autofunction:: federation.entities.activitypub.django.views.activitypub_object_view .. autofunction:: federation.entities.activitypub.django.views.activitypub_object_view
.. autofunction:: federation.hostmeta.django.generators.rfc7033_webfinger_view .. autofunction:: federation.hostmeta.django.generators.rfc7033_webfinger_view
.. autofunction:: federation.hostmeta.django.generators.matrix_client_wellknown_view
.. autofunction:: federation.hostmeta.django.generators.matrix_server_wellknown_view
.. autofunction:: federation.hostmeta.django.generators.nodeinfo2_view .. autofunction:: federation.hostmeta.django.generators.nodeinfo2_view
Configuration Configuration
@ -209,6 +213,7 @@ Some settings need to be set in Django settings. An example is below:
"get_object_function": "myproject.utils.get_object", "get_object_function": "myproject.utils.get_object",
"get_private_key_function": "myproject.utils.get_private_key", "get_private_key_function": "myproject.utils.get_private_key",
"get_profile_function": "myproject.utils.get_profile", "get_profile_function": "myproject.utils.get_profile",
"matrix_config_function": "myproject.utils.matrix_config_funct",
"nodeinfo2_function": "myproject.utils.get_nodeinfo2_data", "nodeinfo2_function": "myproject.utils.get_nodeinfo2_data",
"process_payload_function": "myproject.utils.process_payload", "process_payload_function": "myproject.utils.process_payload",
"search_path": "/search/?q=", "search_path": "/search/?q=",
@ -219,6 +224,23 @@ Some settings need to be set in Django settings. An example is below:
* ``get_object_function`` should be the full path to a function that will return the object matching the ActivityPub ID for the request object passed to this function. * ``get_object_function`` should be the full path to a function that will return the object matching the ActivityPub ID for the request object passed to this function.
* ``get_private_key_function`` should be the full path to a function that will accept a federation ID (url, handle or guid) and return the private key of the user (as an RSA object). Required for example to sign outbound messages in some cases. * ``get_private_key_function`` should be the full path to a function that will accept a federation ID (url, handle or guid) and return the private key of the user (as an RSA object). Required for example to sign outbound messages in some cases.
* ``get_profile_function`` should be the full path to a function that should return a ``Profile`` entity. The function should take one or more keyword arguments: ``fid``, ``handle``, ``guid`` or ``request``. It should look up a profile with one or more of the provided parameters. * ``get_profile_function`` should be the full path to a function that should return a ``Profile`` entity. The function should take one or more keyword arguments: ``fid``, ``handle``, ``guid`` or ``request``. It should look up a profile with one or more of the provided parameters.
* ``matrix_config_function`` (optional) function that returns a Matrix configuration dictionary, with the following objects:
::
{
# Location of the homeserver (not server name)
"homeserver_base_url": "https://matrix.domain.tld",
# Homeserver domain and port (not server domain)
"homeserver_domain_with_port": "matrix.domain.tld:443",
# (Optional) location of identity server
"identity_server_base_url": "https://id.domain.tld",
# (Optional) other keys to include in the client well-known (must be a dictionary)
"client_wellknown_other_keys": {
"org.foo.key" "barfoo",
},
}
* ``nodeinfo2_function`` (optional) function that returns data for generating a `NodeInfo2 document <https://github.com/jaywink/nodeinfo2>`_. Once configured the path ``/.well-known/x-nodeinfo2`` will automatically generate a NodeInfo2 document. The function should return a ``dict`` corresponding to the NodeInfo2 schema, with the following minimum items: * ``nodeinfo2_function`` (optional) function that returns data for generating a `NodeInfo2 document <https://github.com/jaywink/nodeinfo2>`_. Once configured the path ``/.well-known/x-nodeinfo2`` will automatically generate a NodeInfo2 document. The function should return a ``dict`` corresponding to the NodeInfo2 schema, with the following minimum items:
:: ::

Wyświetl plik

@ -1,8 +1,11 @@
import logging import logging
# noinspection PyPackageRequirements
from django.http import HttpResponseBadRequest, JsonResponse, HttpResponseNotFound from django.http import HttpResponseBadRequest, JsonResponse, HttpResponseNotFound
from federation.hostmeta.generators import RFC7033Webfinger, generate_nodeinfo2_document from federation.hostmeta.generators import (
RFC7033Webfinger, generate_nodeinfo2_document, MatrixClientWellKnown, MatrixServerWellKnown,
)
from federation.utils.django import get_configuration, get_function_from_config from federation.utils.django import get_configuration, get_function_from_config
from federation.utils.text import get_path_from_url from federation.utils.text import get_path_from_url
@ -19,6 +22,34 @@ def nodeinfo2_view(request, *args, **kwargs):
return JsonResponse(generate_nodeinfo2_document(**nodeinfo2)) return JsonResponse(generate_nodeinfo2_document(**nodeinfo2))
def matrix_client_wellknown_view(request, *args, **kwargs):
try:
matrix_config_func = get_function_from_config("matrix_config_function")
except AttributeError:
return HttpResponseBadRequest("Not configured")
matrix_config = matrix_config_func()
wellknown = MatrixClientWellKnown(
homeserver_base_url=matrix_config["homeserver_base_url"],
identity_server_base_url=matrix_config.get("identity_server_base_url"),
other_keys=matrix_config.get("client_wellknown_other_keys"),
)
return JsonResponse(wellknown.render())
def matrix_server_wellknown_view(request, *args, **kwargs):
try:
matrix_config_func = get_function_from_config("matrix_config_function")
except AttributeError:
return HttpResponseBadRequest("Not configured")
matrix_config = matrix_config_func()
wellknown = MatrixServerWellKnown(
homeserver_domain_with_port=matrix_config["homeserver_domain_with_port"],
)
return JsonResponse(wellknown.render())
def rfc7033_webfinger_view(request, *args, **kwargs): def rfc7033_webfinger_view(request, *args, **kwargs):
""" """
Django view to generate an RFC7033 webfinger. Django view to generate an RFC7033 webfinger.

Wyświetl plik

@ -1,9 +1,14 @@
# noinspection PyPackageRequirements
from django.conf.urls import url from django.conf.urls import url
from federation.hostmeta.django import rfc7033_webfinger_view from federation.hostmeta.django import rfc7033_webfinger_view
from federation.hostmeta.django.generators import nodeinfo2_view from federation.hostmeta.django.generators import (
nodeinfo2_view, matrix_client_wellknown_view, matrix_server_wellknown_view,
)
urlpatterns = [ urlpatterns = [
url(r'^.well-known/matrix/client$', matrix_client_wellknown_view, name="matrix-client-wellknown"),
url(r'^.well-known/matrix/server$', matrix_server_wellknown_view, name="matrix-server-wellknown"),
url(r'^.well-known/webfinger$', rfc7033_webfinger_view, name="rfc7033-webfinger"), url(r'^.well-known/webfinger$', rfc7033_webfinger_view, name="rfc7033-webfinger"),
url(r'^.well-known/x-nodeinfo2$', nodeinfo2_view, name="nodeinfo2"), url(r'^.well-known/x-nodeinfo2$', nodeinfo2_view, name="nodeinfo2"),
] ]

Wyświetl plik

@ -3,6 +3,7 @@ import os
import warnings import warnings
from base64 import b64encode from base64 import b64encode
from string import Template from string import Template
from typing import Dict
from jsonschema import validate from jsonschema import validate
from jsonschema.exceptions import ValidationError from jsonschema.exceptions import ValidationError
@ -331,6 +332,43 @@ def get_nodeinfo_well_known_document(url, document_path=None):
} }
class MatrixClientWellKnown:
"""
Matrix Client well-known as per https://matrix.org/docs/spec/client_server/r0.6.1#server-discovery
"""
def __init__(self, homeserver_base_url: str, identity_server_base_url: str = None, other_keys: Dict = None):
self.homeserver_base_url = homeserver_base_url
self.identity_server_base_url = identity_server_base_url
self.other_keys = other_keys
def render(self):
doc = {
"m.homeserver": {
"base_url": self.homeserver_base_url,
}
}
if self.identity_server_base_url:
doc["m.identity_server"] = {
"base_url": self.identity_server_base_url,
}
if self.other_keys:
doc.update(self.other_keys)
return doc
class MatrixServerWellKnown:
"""
Matrix Server well-known as per https://matrix.org/docs/spec/server_server/r0.1.4#server-discovery
"""
def __init__(self, homeserver_domain_with_port: str):
self.homeserver_domain_with_port = homeserver_domain_with_port
def render(self):
return {
"m.server": self.homeserver_domain_with_port,
}
class RFC7033Webfinger: class RFC7033Webfinger:
""" """
RFC 7033 webfinger - see https://tools.ietf.org/html/rfc7033 RFC 7033 webfinger - see https://tools.ietf.org/html/rfc7033