Skip to content
Snippets Groups Projects
Verified Commit 75710638 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Url and views for instance actor and webfinger

parent e793f836
No related branches found
No related tags found
No related merge requests found
......@@ -13,6 +13,9 @@ urlpatterns = [
url(settings.ADMIN_URL, admin.site.urls),
url(r'^api/', include(("config.api_urls", 'api'), namespace="api")),
url(r'^', include(
('funkwhale_api.federation.urls', 'federation'),
namespace="federation")),
url(r'^api/v1/auth/', include('rest_auth.urls')),
url(r'^api/v1/auth/registration/', include('funkwhale_api.users.rest_auth_urls')),
url(r'^accounts/', include('allauth.urls')),
......
from django.urls import reverse
from django.conf import settings
from . import utils
def repr_instance_actor():
"""
We do not use a serializer here, since it's pretty static
"""
return {
'@context': [
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1',
{},
],
'id': utils.full_url(reverse('federation:instance-actor')),
'type': 'Service',
'inbox': utils.full_url(reverse('federation:instance-inbox')),
'outbox': utils.full_url(reverse('federation:instance-outbox')),
}
from rest_framework import routers
from . import views
router = routers.SimpleRouter(trailing_slash=False)
router.register(
r'instance',
views.InstanceViewSet,
'instance')
router.register(
r'.well-known',
views.WellKnownViewSet,
'well-known')
urlpatterns = router.urls
from django import forms
from django.conf import settings
from django.http import HttpResponse
from rest_framework import viewsets
from rest_framework import views
from rest_framework import response
from rest_framework.decorators import list_route
from . import serializers
from . import webfinger
class FederationMixin(object):
def dispatch(self, request, *args, **kwargs):
if not settings.FEDERATION_ENABLED:
return HttpResponse(status=405)
return super().dispatch(request, *args, **kwargs)
class InstanceViewSet(FederationMixin, viewsets.GenericViewSet):
authentication_classes = []
permission_classes = []
@list_route(methods=['get'])
def actor(self, request, *args, **kwargs):
return response.Response(serializers.repr_instance_actor())
@list_route(methods=['get'])
def inbox(self, request, *args, **kwargs):
raise NotImplementedError()
@list_route(methods=['get'])
def outbox(self, request, *args, **kwargs):
raise NotImplementedError()
class WellKnownViewSet(FederationMixin, viewsets.GenericViewSet):
authentication_classes = []
permission_classes = []
@list_route(methods=['get'])
def webfinger(self, request, *args, **kwargs):
try:
resource_type, resource = webfinger.clean_resource(
request.GET['resource'])
cleaner = getattr(webfinger, 'clean_{}'.format(resource_type))
result = cleaner(resource)
except forms.ValidationError as e:
return response.Response({
'errors': {
'resource': e.message
}
}, status=400)
except KeyError:
return response.Response({
'errors': {
'resource': 'This field is required',
}
}, status=400)
handler = getattr(self, 'handler_{}'.format(resource_type))
data = handler(result)
return response.Response(
data,
content_type='application/jrd+json; charset=utf-8')
def handler_acct(self, clean_result):
username, hostname = clean_result
if username == 'service':
return webfinger.serialize_system_acct()
return {}
from django.urls import reverse
import pytest
from funkwhale_api.federation import webfinger
def test_instance_actor(db, settings, api_client):
settings.FUNKWHALE_URL = 'http://test.com'
url = reverse('federation:instance-actor')
response = api_client.get(url)
assert response.data['id'] == (
settings.FUNKWHALE_URL + url
)
assert response.data['type'] == 'Service'
assert response.data['inbox'] == (
settings.FUNKWHALE_URL + reverse('federation:instance-inbox')
)
assert response.data['outbox'] == (
settings.FUNKWHALE_URL + reverse('federation:instance-outbox')
)
assert response.data['@context'] == [
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1',
{},
]
@pytest.mark.parametrize('route', [
'instance-outbox',
'instance-inbox',
'instance-actor',
'well-known-webfinger',
])
def test_instance_inbox_405_if_federation_disabled(
db, settings, api_client, route):
settings.FEDERATION_ENABLED = False
url = reverse('federation:{}'.format(route))
response = api_client.get(url)
assert response.status_code == 405
def test_wellknown_webfinger_validates_resource(
db, api_client, settings, mocker):
clean = mocker.spy(webfinger, 'clean_resource')
settings.FEDERATION_ENABLED = True
url = reverse('federation:well-known-webfinger')
response = api_client.get(url, data={'resource': 'something'})
clean.assert_called_once_with('something')
assert url == '/.well-known/webfinger'
assert response.status_code == 400
assert response.data['errors']['resource'] == (
'Missing webfinger resource type'
)
def test_wellknown_webfinger_system(
db, api_client, settings, mocker):
settings.FEDERATION_ENABLED = True
settings.FEDERATION_HOSTNAME = 'test.federation'
url = reverse('federation:well-known-webfinger')
response = api_client.get(
url, data={'resource': 'acct:service@test.federation'})
assert response.status_code == 200
assert response['Content-Type'] == 'application/jrd+json; charset=utf-8'
assert response.data == webfinger.serialize_system_acct()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment