Now validate incoming webfinger

This commit is contained in:
Eliot Berriot 2018-04-08 10:42:10 +02:00
parent 314587e2eb
commit b8c7e960c3
No known key found for this signature in database
GPG Key ID: DD6965E2476E5C27
3 changed files with 64 additions and 6 deletions

View File

@ -116,10 +116,27 @@ class FollowSerializer(serializers.ModelSerializer):
return ret
class ActorWebfingerSerializer(serializers.ModelSerializer):
class Meta:
model = models.Actor
fields = ['url']
class ActorWebfingerSerializer(serializers.Serializer):
subject = serializers.CharField()
aliases = serializers.ListField(child=serializers.URLField())
links = serializers.ListField()
actor_url = serializers.URLField(required=False)
def validate(self, validated_data):
validated_data['actor_url'] = None
for l in validated_data['links']:
try:
if not l['rel'] == 'self':
continue
if not l['type'] == 'application/activity+json':
continue
validated_data['actor_url'] = l['href']
break
except KeyError:
pass
if validated_data['actor_url'] is None:
raise serializers.ValidationError('No valid actor url found')
return validated_data
def to_representation(self, instance):
data = {}

View File

@ -2,8 +2,11 @@ from django import forms
from django.conf import settings
from django.urls import reverse
from funkwhale_api.common import session
from . import actors
from . import utils
from . import serializers
VALID_RESOURCE_TYPES = ['acct']
@ -23,13 +26,13 @@ def clean_resource(resource_string):
return resource_type, resource
def clean_acct(acct_string):
def clean_acct(acct_string, ensure_local=True):
try:
username, hostname = acct_string.split('@')
except ValueError:
raise forms.ValidationError('Invalid format')
if hostname.lower() != settings.FEDERATION_HOSTNAME:
if ensure_local and hostname.lower() != settings.FEDERATION_HOSTNAME:
raise forms.ValidationError(
'Invalid hostname {}'.format(hostname))
@ -37,3 +40,15 @@ def clean_acct(acct_string):
raise forms.ValidationError('Invalid username')
return username, hostname
def get_resource(resource_string):
resource_type, resource = clean_resource(resource_string)
username, hostname = clean_acct(resource, ensure_local=False)
url = 'https://{}/.well-known/webfinger?resource={}'.format(
hostname, resource_string)
response = session.get_session().get(url)
response.raise_for_status()
serializer = serializers.ActorWebfingerSerializer(data=response.json())
serializer.is_valid(raise_exception=True)
return serializer.validated_data

View File

@ -40,3 +40,29 @@ def test_webfinger_clean_acct_errors(resource, message, settings):
webfinger.clean_resource(resource)
assert message == str(excinfo)
def test_webfinger_get_resource(r_mock):
resource = 'acct:test@test.webfinger'
payload = {
'subject': resource,
'aliases': ['https://test.webfinger'],
'links': [
{
'rel': 'self',
'type': 'application/activity+json',
'href': 'https://test.webfinger/user/test'
}
]
}
r_mock.get(
'https://test.webfinger/.well-known/webfinger?resource={}'.format(
resource
),
json=payload
)
data = webfinger.get_resource('acct:test@test.webfinger')
assert data['actor_url'] == 'https://test.webfinger/user/test'
assert data['subject'] == resource