Now validate incoming webfinger
This commit is contained in:
parent
314587e2eb
commit
b8c7e960c3
|
@ -116,10 +116,27 @@ class FollowSerializer(serializers.ModelSerializer):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class ActorWebfingerSerializer(serializers.ModelSerializer):
|
class ActorWebfingerSerializer(serializers.Serializer):
|
||||||
class Meta:
|
subject = serializers.CharField()
|
||||||
model = models.Actor
|
aliases = serializers.ListField(child=serializers.URLField())
|
||||||
fields = ['url']
|
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):
|
def to_representation(self, instance):
|
||||||
data = {}
|
data = {}
|
||||||
|
|
|
@ -2,8 +2,11 @@ from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from funkwhale_api.common import session
|
||||||
|
|
||||||
from . import actors
|
from . import actors
|
||||||
from . import utils
|
from . import utils
|
||||||
|
from . import serializers
|
||||||
|
|
||||||
VALID_RESOURCE_TYPES = ['acct']
|
VALID_RESOURCE_TYPES = ['acct']
|
||||||
|
|
||||||
|
@ -23,13 +26,13 @@ def clean_resource(resource_string):
|
||||||
return resource_type, resource
|
return resource_type, resource
|
||||||
|
|
||||||
|
|
||||||
def clean_acct(acct_string):
|
def clean_acct(acct_string, ensure_local=True):
|
||||||
try:
|
try:
|
||||||
username, hostname = acct_string.split('@')
|
username, hostname = acct_string.split('@')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise forms.ValidationError('Invalid format')
|
raise forms.ValidationError('Invalid format')
|
||||||
|
|
||||||
if hostname.lower() != settings.FEDERATION_HOSTNAME:
|
if ensure_local and hostname.lower() != settings.FEDERATION_HOSTNAME:
|
||||||
raise forms.ValidationError(
|
raise forms.ValidationError(
|
||||||
'Invalid hostname {}'.format(hostname))
|
'Invalid hostname {}'.format(hostname))
|
||||||
|
|
||||||
|
@ -37,3 +40,15 @@ def clean_acct(acct_string):
|
||||||
raise forms.ValidationError('Invalid username')
|
raise forms.ValidationError('Invalid username')
|
||||||
|
|
||||||
return username, hostname
|
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
|
||||||
|
|
|
@ -40,3 +40,29 @@ def test_webfinger_clean_acct_errors(resource, message, settings):
|
||||||
webfinger.clean_resource(resource)
|
webfinger.clean_resource(resource)
|
||||||
|
|
||||||
assert message == str(excinfo)
|
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
|
||||||
|
|
Loading…
Reference in New Issue