From 4320fc77b2229d87956a95d44ae4bb83085d6f96 Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Sat, 7 Apr 2018 17:18:54 +0200
Subject: [PATCH] Added validation on collection serializers

---
 api/funkwhale_api/federation/serializers.py | 14 ++++++
 api/tests/federation/test_serializers.py    | 51 ++++++++++++++++++++-
 api/tests/federation/test_views.py          |  1 +
 3 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/api/funkwhale_api/federation/serializers.py b/api/funkwhale_api/federation/serializers.py
index 17541c50..d8e5ddb2 100644
--- a/api/funkwhale_api/federation/serializers.py
+++ b/api/funkwhale_api/federation/serializers.py
@@ -21,6 +21,7 @@ AP_CONTEXT = [
     {},
 ]
 
+
 class ActorSerializer(serializers.ModelSerializer):
     # left maps to activitypub fields, right to our internal models
     id = serializers.URLField(source='url')
@@ -206,6 +207,11 @@ OBJECT_SERIALIZERS = {
 
 
 class PaginatedCollectionSerializer(serializers.Serializer):
+    type = serializers.ChoiceField(choices=['Collection'])
+    totalItems = serializers.IntegerField(min_value=0)
+    items = serializers.ListField()
+    actor = serializers.URLField()
+    id = serializers.URLField()
 
     def to_representation(self, conf):
         paginator = Paginator(
@@ -230,6 +236,14 @@ class PaginatedCollectionSerializer(serializers.Serializer):
 
 
 class CollectionPageSerializer(serializers.Serializer):
+    type = serializers.ChoiceField(choices=['CollectionPage'])
+    totalItems = serializers.IntegerField(min_value=0)
+    items = serializers.ListField()
+    actor = serializers.URLField()
+    id = serializers.URLField()
+    prev = serializers.URLField(required=False)
+    next = serializers.URLField(required=False)
+    partOf = serializers.URLField()
 
     def to_representation(self, conf):
         page = conf['page']
diff --git a/api/tests/federation/test_serializers.py b/api/tests/federation/test_serializers.py
index 71407dc4..8c76bb44 100644
--- a/api/tests/federation/test_serializers.py
+++ b/api/tests/federation/test_serializers.py
@@ -34,7 +34,7 @@ def test_actor_serializer_from_ap(db):
     }
 
     serializer = serializers.ActorSerializer(data=payload)
-    assert serializer.is_valid()
+    assert serializer.is_valid(raise_exception=True)
 
     actor = serializer.build()
 
@@ -65,7 +65,7 @@ def test_actor_serializer_only_mandatory_field_from_ap(db):
     }
 
     serializer = serializers.ActorSerializer(data=payload)
-    assert serializer.is_valid()
+    assert serializer.is_valid(raise_exception=True)
 
     actor = serializer.build()
 
@@ -201,6 +201,53 @@ def test_paginated_collection_serializer(factories):
     assert serializer.data == expected
 
 
+def test_paginated_collection_serializer_validation():
+    data = {
+        'type': 'Collection',
+        'id': 'https://test.federation/test',
+        'totalItems': 5,
+        'actor': 'http://test.actor',
+        'items': []
+    }
+
+    serializer = serializers.PaginatedCollectionSerializer(
+        data=data
+    )
+
+    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['items'] == []
+
+
+def test_collection_page_serializer_validdation():
+    base = 'https://test.federation/test'
+    data = {
+        'type': 'CollectionPage',
+        'id': base + '?page=2',
+        'totalItems': 5,
+        'actor': 'https://test.actor',
+        'items': [],
+        'prev': base + '?page=1',
+        'next': base + '?page=3',
+        'partOf': base,
+    }
+
+    serializer = serializers.CollectionPageSerializer(
+        data=data
+    )
+
+    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['items'] == []
+    assert serializer.validated_data['prev'] == data['prev']
+    assert serializer.validated_data['next'] == data['next']
+    assert serializer.validated_data['partOf'] == data['partOf']
+
+
 def test_collection_page_serializer(factories):
     tfs = factories['music.TrackFile'].create_batch(size=5)
     actor = factories['federation.Actor'](local=True)
diff --git a/api/tests/federation/test_views.py b/api/tests/federation/test_views.py
index c5d651dc..b3fd8591 100644
--- a/api/tests/federation/test_views.py
+++ b/api/tests/federation/test_views.py
@@ -116,6 +116,7 @@ def test_audio_file_list_actor_page(
     assert response.status_code == 200
     assert response.data == expected
 
+
 def test_audio_file_list_actor_page_exclude_federated_files(
         db, settings, api_client, factories):
     settings.FEDERATION_MUSIC_NEEDS_APPROVAL = False
-- 
GitLab