diff --git a/api/funkwhale_api/federation/library.py b/api/funkwhale_api/federation/library.py index 6fa3c7183fd73d40f8b8dacf09ee92173bf368a6..f19a7a29145b229d3be71e7a616376a3157000b1 100644 --- a/api/funkwhale_api/federation/library.py +++ b/api/funkwhale_api/federation/library.py @@ -1,3 +1,4 @@ +import json import requests from django.conf import settings @@ -5,6 +6,7 @@ from django.conf import settings from funkwhale_api.common import session from . import actors +from . import models from . import serializers from . import signing from . import webfinger @@ -22,6 +24,39 @@ def scan_from_account_name(account_name): """ data = {} + try: + username, domain = webfinger.clean_acct( + account_name, ensure_local=False) + except serializers.ValidationError: + return { + 'webfinger': { + 'errors': ['Invalid account string'] + } + } + system_library = actors.SYSTEM_ACTORS['library'].get_actor_instance() + library = models.Library.objects.filter( + actor__domain=domain, + actor__preferred_username=username + ).select_related('actor').first() + follow_request = None + if library: + data['local']['following'] = True + data['local']['awaiting_approval'] = True + + else: + follow_request = models.FollowRequest.objects.filter( + target__preferred_username=username, + target__domain=username, + actor=system_library, + ).first() + data['local'] = { + 'following': False, + 'awaiting_approval': False, + } + if follow_request: + data['awaiting_approval'] = follow_request.approved is None + + follow_request = models.Follow try: data['webfinger'] = webfinger.get_resource( 'acct:{}'.format(account_name)) @@ -39,6 +74,12 @@ def scan_from_account_name(account_name): e.response.status_code)] } } + except json.JSONDecodeError as e: + return { + 'webfinger': { + 'errors': ['Could not process webfinger response'] + } + } try: data['actor'] = actors.get_actor_data(data['webfinger']['actor_url']) @@ -56,7 +97,11 @@ def scan_from_account_name(account_name): return data serializer = serializers.LibraryActorSerializer(data=data['actor']) - serializer.is_valid(raise_exception=True) + if not serializer.is_valid(): + data['actor'] = { + 'errors': ['Invalid ActivityPub actor'] + } + return data data['library'] = get_library_data( serializer.validated_data['library_url']) diff --git a/api/tests/federation/test_library.py b/api/tests/federation/test_library.py index 714a0c306d582eb79a7305906b3bab825be6924c..7a3abf5d8375ee63598998b40a3b8977b2942198 100644 --- a/api/tests/federation/test_library.py +++ b/api/tests/federation/test_library.py @@ -39,6 +39,10 @@ def test_library_scan_from_account_name(mocker, factories): 'webfinger': get_resource_result, 'actor': actor_data, 'library': get_library_data_result, + 'local': { + 'following': False, + 'awaiting_approval': False, + }, } @@ -63,4 +67,4 @@ def test_get_library_data_requires_authentication(r_mock, factories): url = 'https://test.library' r_mock.get(url, status_code=403) result = library.get_library_data(url) - assert result['errors'] == ['This library requires authentication'] + assert result['errors'] == ['Permission denied while scanning library'] diff --git a/api/tests/federation/test_serializers.py b/api/tests/federation/test_serializers.py index e4fb88040b5653e5497017b05b4b288085e89642..7b7dda33cbffc46eb32199c86d2a8976f3fb8198 100644 --- a/api/tests/federation/test_serializers.py +++ b/api/tests/federation/test_serializers.py @@ -218,7 +218,6 @@ def test_paginated_collection_serializer_validation(): assert serializer.validated_data['totalItems'] == 5 assert serializer.validated_data['id'] == data['id'] assert serializer.validated_data['actor'] == data['actor'] - assert serializer.validated_data['items'] == [] def test_collection_page_serializer_validation():