From e793f8365ffc4154cb15b557ec943e197a09ae18 Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Thu, 29 Mar 2018 00:00:20 +0200
Subject: [PATCH] Webfinger utils

---
 api/funkwhale_api/federation/webfinger.py | 52 ++++++++++++++++++
 api/tests/federation/test_webfinger.py    | 66 +++++++++++++++++++++++
 2 files changed, 118 insertions(+)
 create mode 100644 api/funkwhale_api/federation/webfinger.py
 create mode 100644 api/tests/federation/test_webfinger.py

diff --git a/api/funkwhale_api/federation/webfinger.py b/api/funkwhale_api/federation/webfinger.py
new file mode 100644
index 00000000..a9281c2b
--- /dev/null
+++ b/api/funkwhale_api/federation/webfinger.py
@@ -0,0 +1,52 @@
+from django import forms
+from django.conf import settings
+from django.urls import reverse
+
+from . import utils
+VALID_RESOURCE_TYPES = ['acct']
+
+
+def clean_resource(resource_string):
+    if not resource_string:
+        raise forms.ValidationError('Invalid resource string')
+
+    try:
+        resource_type, resource = resource_string.split(':', 1)
+    except ValueError:
+        raise forms.ValidationError('Missing webfinger resource type')
+
+    if resource_type not in VALID_RESOURCE_TYPES:
+        raise forms.ValidationError('Invalid webfinger resource type')
+
+    return resource_type, resource
+
+
+def clean_acct(acct_string):
+    try:
+        username, hostname = acct_string.split('@')
+    except ValueError:
+        raise forms.ValidationError('Invalid format')
+
+    if hostname != settings.FEDERATION_HOSTNAME:
+        raise forms.ValidationError('Invalid hostname')
+
+    if username != 'service':
+        raise forms.ValidationError('Invalid username')
+
+    return username, hostname
+
+
+def serialize_system_acct():
+    return {
+        'subject': 'acct:service@{}'.format(settings.FEDERATION_HOSTNAME),
+        'aliases': [
+            utils.full_url(reverse('federation:instance-actor'))
+        ],
+        'links': [
+            {
+                'rel': 'self',
+                'type': 'application/activity+json',
+                'href': utils.full_url(reverse('federation:instance-actor')),
+            }
+        ]
+    }
diff --git a/api/tests/federation/test_webfinger.py b/api/tests/federation/test_webfinger.py
new file mode 100644
index 00000000..4cee9c8c
--- /dev/null
+++ b/api/tests/federation/test_webfinger.py
@@ -0,0 +1,66 @@
+import pytest
+
+from django import forms
+from django.urls import reverse
+
+from funkwhale_api.federation import webfinger
+
+
+def test_webfinger_clean_resource():
+    t, r = webfinger.clean_resource('acct:service@test.federation')
+    assert t == 'acct'
+    assert r == 'service@test.federation'
+
+
+@pytest.mark.parametrize('resource,message', [
+    ('', 'Invalid resource string'),
+    ('service@test.com', 'Missing webfinger resource type'),
+    ('noop:service@test.com', 'Invalid webfinger resource type'),
+])
+def test_webfinger_clean_resource_errors(resource, message):
+    with pytest.raises(forms.ValidationError) as excinfo:
+        webfinger.clean_resource(resource)
+
+        assert message == str(excinfo)
+
+
+def test_webfinger_clean_acct(settings):
+    settings.FEDERATION_HOSTNAME = 'test.federation'
+    username, hostname = webfinger.clean_acct('service@test.federation')
+    assert username == 'service'
+    assert hostname == 'test.federation'
+
+
+@pytest.mark.parametrize('resource,message', [
+    ('service', 'Invalid format'),
+    ('service@test.com', 'Invalid hostname'),
+    ('noop@test.federation', 'Invalid account'),
+])
+def test_webfinger_clean_acct_errors(resource, message, settings):
+    settings.FEDERATION_HOSTNAME = 'test.federation'
+
+    with pytest.raises(forms.ValidationError) as excinfo:
+        webfinger.clean_resource(resource)
+
+        assert message == str(excinfo)
+
+
+def test_service_serializer(settings):
+    settings.FEDERATION_HOSTNAME = 'test.federation'
+    settings.FUNKWHALE_URL = 'https://test.federation'
+
+    expected = {
+        'subject': 'acct:service@test.federation',
+        'links': [
+            {
+                'rel': 'self',
+                'href': 'https://test.federation/instance/actor',
+                'type': 'application/activity+json',
+            }
+        ],
+        'aliases': [
+            'https://test.federation/instance/actor',
+        ]
+    }
+
+    assert expected == webfinger.serialize_system_acct()
-- 
GitLab