fix(front):search fetch federation object was expecting a music object but got a activitypub obj
This commit is contained in:
parent
1be4b5204a
commit
7f6d066acc
|
@ -2462,6 +2462,9 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
content:
|
content:
|
||||||
|
application/activity+json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Fetch'
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Fetch'
|
$ref: '#/components/schemas/Fetch'
|
||||||
|
@ -2484,6 +2487,9 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
content:
|
content:
|
||||||
|
application/activity+json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Fetch'
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Fetch'
|
$ref: '#/components/schemas/Fetch'
|
||||||
|
@ -11972,6 +11978,9 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
content:
|
content:
|
||||||
|
application/activity+json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Fetch'
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Fetch'
|
$ref: '#/components/schemas/Fetch'
|
||||||
|
@ -11994,6 +12003,9 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
content:
|
content:
|
||||||
|
application/activity+json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Fetch'
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Fetch'
|
$ref: '#/components/schemas/Fetch'
|
||||||
|
|
|
@ -13,7 +13,9 @@ from funkwhale_api.audio import models as audio_models
|
||||||
from funkwhale_api.audio import serializers as audio_serializers
|
from funkwhale_api.audio import serializers as audio_serializers
|
||||||
from funkwhale_api.common import serializers as common_serializers
|
from funkwhale_api.common import serializers as common_serializers
|
||||||
from funkwhale_api.music import models as music_models
|
from funkwhale_api.music import models as music_models
|
||||||
|
from funkwhale_api.music import serializers as music_serializers
|
||||||
from funkwhale_api.playlists import models as playlists_models
|
from funkwhale_api.playlists import models as playlists_models
|
||||||
|
from funkwhale_api.playlists import serializers as playlist_serializers
|
||||||
from funkwhale_api.users import serializers as users_serializers
|
from funkwhale_api.users import serializers as users_serializers
|
||||||
|
|
||||||
from . import filters, models
|
from . import filters, models
|
||||||
|
@ -197,10 +199,19 @@ OBJECT_SERIALIZER_MAPPING = {
|
||||||
music_models.Artist: federation_serializers.ArtistSerializer,
|
music_models.Artist: federation_serializers.ArtistSerializer,
|
||||||
music_models.Album: federation_serializers.AlbumSerializer,
|
music_models.Album: federation_serializers.AlbumSerializer,
|
||||||
music_models.Track: federation_serializers.TrackSerializer,
|
music_models.Track: federation_serializers.TrackSerializer,
|
||||||
|
music_models.Library: federation_serializers.LibrarySerializer,
|
||||||
models.Actor: federation_serializers.APIActorSerializer,
|
models.Actor: federation_serializers.APIActorSerializer,
|
||||||
audio_models.Channel: audio_serializers.ChannelSerializer,
|
audio_models.Channel: audio_serializers.ChannelSerializer,
|
||||||
playlists_models.Playlist: federation_serializers.PlaylistSerializer,
|
playlists_models.Playlist: federation_serializers.PlaylistSerializer,
|
||||||
}
|
}
|
||||||
|
OBJECT_MUSIC_SERIALIZER_MAPPING = {
|
||||||
|
music_models.Artist: music_serializers.ArtistSerializer,
|
||||||
|
music_models.Album: music_serializers.AlbumSerializer,
|
||||||
|
music_models.Track: music_serializers.TrackSerializer,
|
||||||
|
models.Actor: federation_serializers.APIActorSerializer,
|
||||||
|
audio_models.Channel: audio_serializers.ChannelSerializer,
|
||||||
|
playlists_models.Playlist: playlist_serializers.PlaylistSerializer,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def convert_url_to_webfinger(url):
|
def convert_url_to_webfinger(url):
|
||||||
|
@ -283,6 +294,9 @@ class FetchSerializer(serializers.ModelSerializer):
|
||||||
return value
|
return value
|
||||||
return f"webfinger://{value}"
|
return f"webfinger://{value}"
|
||||||
|
|
||||||
|
# to do : this is incomplete, schema conflict because
|
||||||
|
# federation serializers have the same name than musi serializer -> upgrade fed serializers to new names
|
||||||
|
# and add the new object here
|
||||||
@extend_schema_field(
|
@extend_schema_field(
|
||||||
{
|
{
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
|
@ -300,7 +314,12 @@ class FetchSerializer(serializers.ModelSerializer):
|
||||||
if obj is None:
|
if obj is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
serializer_class = OBJECT_SERIALIZER_MAPPING.get(type(obj))
|
media_type = self.context.get("media_type")
|
||||||
|
|
||||||
|
if media_type == "application/activity+json":
|
||||||
|
serializer_class = OBJECT_SERIALIZER_MAPPING.get(type(obj))
|
||||||
|
else:
|
||||||
|
serializer_class = OBJECT_MUSIC_SERIALIZER_MAPPING.get(type(obj))
|
||||||
if serializer_class:
|
if serializer_class:
|
||||||
return serializer_class(obj).data
|
return serializer_class(obj).data
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -7,10 +7,13 @@ from django.db.models import Count, Q
|
||||||
from drf_spectacular.utils import extend_schema, extend_schema_view
|
from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||||
from rest_framework import decorators, mixins, permissions, response, viewsets
|
from rest_framework import decorators, mixins, permissions, response, viewsets
|
||||||
from rest_framework.exceptions import NotFound as RestNotFound
|
from rest_framework.exceptions import NotFound as RestNotFound
|
||||||
|
from rest_framework.negotiation import DefaultContentNegotiation
|
||||||
|
from rest_framework.renderers import JSONRenderer
|
||||||
|
|
||||||
from funkwhale_api.common import preferences
|
from funkwhale_api.common import preferences
|
||||||
from funkwhale_api.common import utils as common_utils
|
from funkwhale_api.common import utils as common_utils
|
||||||
from funkwhale_api.common.permissions import ConditionalAuthentication
|
from funkwhale_api.common.permissions import ConditionalAuthentication
|
||||||
|
from funkwhale_api.common.renderers import ActivityStreamRenderer
|
||||||
from funkwhale_api.music import models as music_models
|
from funkwhale_api.music import models as music_models
|
||||||
from funkwhale_api.music import serializers as music_serializers
|
from funkwhale_api.music import serializers as music_serializers
|
||||||
from funkwhale_api.music import views as music_views
|
from funkwhale_api.music import views as music_views
|
||||||
|
@ -245,10 +248,24 @@ class FetchViewSet(
|
||||||
serializer_class = api_serializers.FetchSerializer
|
serializer_class = api_serializers.FetchSerializer
|
||||||
permission_classes = [permissions.IsAuthenticated]
|
permission_classes = [permissions.IsAuthenticated]
|
||||||
throttling_scopes = {"create": {"authenticated": "fetch"}}
|
throttling_scopes = {"create": {"authenticated": "fetch"}}
|
||||||
|
renderer_classes = [ActivityStreamRenderer, JSONRenderer]
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super().get_queryset().filter(actor=self.request.user.actor)
|
return super().get_queryset().filter(actor=self.request.user.actor)
|
||||||
|
|
||||||
|
def get_serializer_context(self):
|
||||||
|
context = super().get_serializer_context()
|
||||||
|
|
||||||
|
negotiator = DefaultContentNegotiation()
|
||||||
|
try:
|
||||||
|
renderer, media_type = negotiator.select_renderer(
|
||||||
|
self.request, self.get_renderers()
|
||||||
|
)
|
||||||
|
context["media_type"] = media_type
|
||||||
|
except Exception:
|
||||||
|
context["media_type"] = None
|
||||||
|
return context
|
||||||
|
|
||||||
def perform_create(self, serializer):
|
def perform_create(self, serializer):
|
||||||
fetch = serializer.save(actor=self.request.user.actor)
|
fetch = serializer.save(actor=self.request.user.actor)
|
||||||
if fetch.status == "finished":
|
if fetch.status == "finished":
|
||||||
|
|
|
@ -1066,6 +1066,7 @@ class LibrarySerializer(PaginatedCollectionSerializer):
|
||||||
privacy = {"": "me", "./": "me", None: "me", contexts.AS.Public: "everyone"}
|
privacy = {"": "me", "./": "me", None: "me", contexts.AS.Public: "everyone"}
|
||||||
library, created = music_models.Library.objects.update_or_create(
|
library, created = music_models.Library.objects.update_or_create(
|
||||||
fid=validated_data["id"],
|
fid=validated_data["id"],
|
||||||
|
uuid=validated_data["id"].rstrip("/").split("/")[-1],
|
||||||
actor=actor,
|
actor=actor,
|
||||||
defaults={
|
defaults={
|
||||||
"uploads_count": validated_data["totalItems"],
|
"uploads_count": validated_data["totalItems"],
|
||||||
|
@ -1449,7 +1450,7 @@ class AlbumSerializer(MusicEntitySerializer):
|
||||||
acs.append(
|
acs.append(
|
||||||
utils.retrieve_ap_object(
|
utils.retrieve_ap_object(
|
||||||
ac["id"],
|
ac["id"],
|
||||||
actor=self.context.get("fetch_actor"),
|
actor=self.context.get("_actor"),
|
||||||
queryset=music_models.ArtistCredit,
|
queryset=music_models.ArtistCredit,
|
||||||
serializer_class=ArtistCreditSerializer,
|
serializer_class=ArtistCreditSerializer,
|
||||||
)
|
)
|
||||||
|
|
|
@ -454,7 +454,6 @@ def fetch(fetch_obj):
|
||||||
max_pages=settings.FEDERATION_COLLECTION_MAX_PAGES - 1,
|
max_pages=settings.FEDERATION_COLLECTION_MAX_PAGES - 1,
|
||||||
is_page=True,
|
is_page=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
fetch_obj.object = obj
|
fetch_obj.object = obj
|
||||||
fetch_obj.status = "finished"
|
fetch_obj.status = "finished"
|
||||||
fetch_obj.fetch_date = timezone.now()
|
fetch_obj.fetch_date = timezone.now()
|
||||||
|
|
|
@ -173,7 +173,12 @@ def test_fetch_serializer_with_object(
|
||||||
"actor": serializers.APIActorSerializer(fetch.actor).data,
|
"actor": serializers.APIActorSerializer(fetch.actor).data,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert api_serializers.FetchSerializer(fetch).data == expected
|
assert (
|
||||||
|
api_serializers.FetchSerializer(
|
||||||
|
fetch, context={"media_type": "application/activity+json"}
|
||||||
|
).data
|
||||||
|
== expected
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_fetch_serializer_unhandled_obj(factories, to_api_date):
|
def test_fetch_serializer_unhandled_obj(factories, to_api_date):
|
||||||
|
|
|
@ -210,13 +210,19 @@ export default (props: PlayOptionsProps) => {
|
||||||
if (!id) {
|
if (!id) {
|
||||||
throw new Error("Library id not found in response.");
|
throw new Error("Library id not found in response.");
|
||||||
}
|
}
|
||||||
const fetchResponse = await axios.post('federation/fetches',
|
const fetchResponse = await axios.post(
|
||||||
{ object: id }
|
'federation/fetches',
|
||||||
|
{ object_uri: id },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/activity+json'
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const response = await axios.post(
|
const response = await axios.post(
|
||||||
'federation/follows/library',
|
'federation/follows/library',
|
||||||
{ target: fetchResponse.data.object.uuid }
|
{ target: fetchResponse.data.object.id.split('/').pop() }
|
||||||
);
|
);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
|
|
@ -10590,6 +10590,7 @@ export interface operations {
|
||||||
[name: string]: unknown;
|
[name: string]: unknown;
|
||||||
};
|
};
|
||||||
content: {
|
content: {
|
||||||
|
"application/activity+json": components["schemas"]["Fetch"];
|
||||||
"application/json": components["schemas"]["Fetch"];
|
"application/json": components["schemas"]["Fetch"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -10612,6 +10613,7 @@ export interface operations {
|
||||||
[name: string]: unknown;
|
[name: string]: unknown;
|
||||||
};
|
};
|
||||||
content: {
|
content: {
|
||||||
|
"application/activity+json": components["schemas"]["Fetch"];
|
||||||
"application/json": components["schemas"]["Fetch"];
|
"application/json": components["schemas"]["Fetch"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -17537,6 +17539,7 @@ export interface operations {
|
||||||
[name: string]: unknown;
|
[name: string]: unknown;
|
||||||
};
|
};
|
||||||
content: {
|
content: {
|
||||||
|
"application/activity+json": components["schemas"]["Fetch"];
|
||||||
"application/json": components["schemas"]["Fetch"];
|
"application/json": components["schemas"]["Fetch"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -17559,6 +17562,7 @@ export interface operations {
|
||||||
[name: string]: unknown;
|
[name: string]: unknown;
|
||||||
};
|
};
|
||||||
content: {
|
content: {
|
||||||
|
"application/activity+json": components["schemas"]["Fetch"];
|
||||||
"application/json": components["schemas"]["Fetch"];
|
"application/json": components["schemas"]["Fetch"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue