Commit ec13adf3 authored by Agate's avatar Agate 💬

Merge branch '619-attributed-to' into 'develop'

Fix #619: Use attributedTo instead of actor in library ActivityPub payload

Closes #619

See merge request funkwhale/funkwhale!737
parents f9a9899e 99378319
Pipeline #4025 passed with stages
in 9 minutes and 40 seconds
......@@ -556,6 +556,7 @@ def get_additional_fields(data):
PAGINATED_COLLECTION_JSONLD_MAPPING = {
"totalItems": jsonld.first_val(contexts.AS.totalItems),
"actor": jsonld.first_id(contexts.AS.actor),
"attributedTo": jsonld.first_id(contexts.AS.attributedTo),
"first": jsonld.first_id(contexts.AS.first),
"last": jsonld.first_id(contexts.AS.last),
"partOf": jsonld.first_id(contexts.AS.partOf),
......@@ -565,7 +566,8 @@ PAGINATED_COLLECTION_JSONLD_MAPPING = {
class PaginatedCollectionSerializer(jsonld.JsonLdSerializer):
type = serializers.ChoiceField(choices=[contexts.AS.Collection])
totalItems = serializers.IntegerField(min_value=0)
actor = serializers.URLField(max_length=500)
actor = serializers.URLField(max_length=500, required=False)
attributedTo = serializers.URLField(max_length=500, required=False)
id = serializers.URLField(max_length=500)
first = serializers.URLField(max_length=500)
last = serializers.URLField(max_length=500)
......@@ -573,6 +575,18 @@ class PaginatedCollectionSerializer(jsonld.JsonLdSerializer):
class Meta:
jsonld_mapping = PAGINATED_COLLECTION_JSONLD_MAPPING
def validate(self, validated_data):
d = super().validate(validated_data)
actor = d.get("actor")
attributed_to = d.get("attributedTo")
if not actor and not attributed_to:
raise serializers.ValidationError(
"You need to provide at least actor or attributedTo"
)
d["attributedTo"] = attributed_to or actor
return d
def to_representation(self, conf):
paginator = Paginator(conf["items"], conf.get("page_size", 20))
first = funkwhale_utils.set_query_parameter(conf["id"], page=1)
......@@ -580,7 +594,9 @@ class PaginatedCollectionSerializer(jsonld.JsonLdSerializer):
last = funkwhale_utils.set_query_parameter(conf["id"], page=paginator.num_pages)
d = {
"id": conf["id"],
# XXX Stable release: remove the obsolete actor field
"actor": conf["actor"].fid,
"attributedTo": conf["actor"].fid,
"totalItems": paginator.count,
"type": conf.get("type", "Collection"),
"current": current,
......@@ -624,7 +640,9 @@ class LibrarySerializer(PaginatedCollectionSerializer):
"name": library.name,
"summary": library.description,
"page_size": 100,
# XXX Stable release: remove the obsolete actor field
"actor": library.actor,
"attributedTo": library.actor,
"items": library.uploads.for_federation(),
"type": "Library",
}
......@@ -637,7 +655,7 @@ class LibrarySerializer(PaginatedCollectionSerializer):
def create(self, validated_data):
actor = utils.retrieve_ap_object(
validated_data["actor"],
validated_data["attributedTo"],
actor=self.context.get("fetch_actor"),
queryset=models.Actor,
serializer_class=ActorSerializer,
......@@ -661,7 +679,8 @@ class CollectionPageSerializer(jsonld.JsonLdSerializer):
type = serializers.ChoiceField(choices=[contexts.AS.CollectionPage])
totalItems = serializers.IntegerField(min_value=0)
items = serializers.ListField()
actor = serializers.URLField(max_length=500)
actor = serializers.URLField(max_length=500, required=False)
attributedTo = serializers.URLField(max_length=500, required=False)
id = serializers.URLField(max_length=500)
first = serializers.URLField(max_length=500)
last = serializers.URLField(max_length=500)
......@@ -674,6 +693,7 @@ class CollectionPageSerializer(jsonld.JsonLdSerializer):
"totalItems": jsonld.first_val(contexts.AS.totalItems),
"items": jsonld.raw(contexts.AS.items),
"actor": jsonld.first_id(contexts.AS.actor),
"attributedTo": jsonld.first_id(contexts.AS.attributedTo),
"first": jsonld.first_id(contexts.AS.first),
"last": jsonld.first_id(contexts.AS.last),
"next": jsonld.first_id(contexts.AS.next),
......@@ -706,7 +726,9 @@ class CollectionPageSerializer(jsonld.JsonLdSerializer):
d = {
"id": id,
"partOf": conf["id"],
# XXX Stable release: remove the obsolete actor field
"actor": conf["actor"].fid,
"attributedTo": conf["actor"].fid,
"totalItems": page.paginator.count,
"type": "CollectionPage",
"first": first,
......
......@@ -334,6 +334,7 @@ def test_paginated_collection_serializer(factories):
"type": "Collection",
"id": conf["id"],
"actor": actor.fid,
"attributedTo": actor.fid,
"totalItems": len(uploads),
"current": conf["id"] + "?page=1",
"last": conf["id"] + "?page=3",
......@@ -352,6 +353,7 @@ def test_paginated_collection_serializer_validation():
"id": "https://test.federation/test",
"totalItems": 5,
"actor": "http://test.actor",
"attributedTo": "http://test.actor",
"first": "https://test.federation/test?page=1",
"last": "https://test.federation/test?page=1",
"items": [],
......@@ -362,7 +364,7 @@ def test_paginated_collection_serializer_validation():
assert serializer.is_valid(raise_exception=True) is True
assert serializer.validated_data["totalItems"] == 5
assert serializer.validated_data["id"] == data["id"]
assert serializer.validated_data["actor"] == data["actor"]
assert serializer.validated_data["attributedTo"] == data["actor"]
def test_collection_page_serializer_validation():
......@@ -373,6 +375,7 @@ def test_collection_page_serializer_validation():
"id": base + "?page=2",
"totalItems": 5,
"actor": "https://test.actor",
"attributedTo": "https://test.actor",
"items": [],
"first": "https://test.federation/test?page=1",
"last": "https://test.federation/test?page=3",
......@@ -386,7 +389,7 @@ def test_collection_page_serializer_validation():
assert serializer.is_valid(raise_exception=True) is True
assert serializer.validated_data["totalItems"] == 5
assert serializer.validated_data["id"] == data["id"]
assert serializer.validated_data["actor"] == data["actor"]
assert serializer.validated_data["attributedTo"] == data["actor"]
assert serializer.validated_data["items"] == []
assert serializer.validated_data["prev"] == data["prev"]
assert serializer.validated_data["next"] == data["next"]
......@@ -398,7 +401,7 @@ def test_collection_page_serializer_can_validate_child():
"@context": jsonld.get_default_context(),
"type": "CollectionPage",
"id": "https://test.page?page=2",
"actor": "https://test.actor",
"attributedTo": "https://test.actor",
"first": "https://test.page?page=1",
"last": "https://test.page?page=3",
"partOf": "https://test.page",
......@@ -430,6 +433,7 @@ def test_collection_page_serializer(factories):
"type": "CollectionPage",
"id": conf["id"] + "?page=2",
"actor": actor.fid,
"attributedTo": actor.fid,
"totalItems": len(uploads),
"partOf": conf["id"],
"prev": conf["id"] + "?page=1",
......@@ -464,6 +468,7 @@ def test_music_library_serializer_to_ap(factories):
"name": library.name,
"summary": library.description,
"actor": library.actor.fid,
"attributedTo": library.actor.fid,
"totalItems": 0,
"current": library.fid + "?page=1",
"last": library.fid + "?page=1",
......@@ -487,7 +492,7 @@ def test_music_library_serializer_from_public(factories, mocker):
"type": "Library",
"id": "https://library.id",
"followers": "https://library.id/followers",
"actor": actor.fid,
"attributedTo": actor.fid,
"totalItems": 12,
"first": "https://library.id?page=1",
"last": "https://library.id?page=2",
......@@ -527,7 +532,7 @@ def test_music_library_serializer_from_private(factories, mocker):
"type": "Library",
"id": "https://library.id",
"followers": "https://library.id/followers",
"actor": actor.fid,
"attributedTo": actor.fid,
"totalItems": 12,
"first": "https://library.id?page=1",
"last": "https://library.id?page=2",
......
Use attributedTo instead of actor in library ActivityPub payload (#619)
......@@ -585,7 +585,7 @@ Example
{
"type": "Library",
"id": "https://awesome.music/federation/music/libraries/dc702491-f6ce-441b-9da0-cecbed08bcc6",
"actor": "https://awesome.music/federation/actors/MyNameIsTroll",
"attributedTo": "https://awesome.music/federation/actors/Alice",
"name": "My awesome library",
"followers": "https://awesome.music/federation/music/libraries/dc702491-f6ce-441b-9da0-cecbed08bcc6/followers",
"summary": "This library is for restricted use only",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment