Verified Commit bdd3258b authored by Agate's avatar Agate 💬

See #303: fixed failing tests and improved validation

parent 50b06cc8
......@@ -19,6 +19,7 @@ class SignatureAuthentication(authentication.BaseAuthentication):
try:
actor = actors.get_actor(key_id.split("#")[0])
except Exception as e:
raise
raise exceptions.AuthenticationFailed(str(e))
if not actor.public_key:
......
......@@ -83,6 +83,7 @@ class Serializer(serializers.Serializer):
id_source = None
include_id = True
include_type = True
valid_types = []
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
......@@ -104,9 +105,27 @@ class Serializer(serializers.Serializer):
)
def run_validation(self, initial_data):
document = expand(initial_data)[0]
try:
document = expand(initial_data)[0]
except IndexError:
raise serializers.ValidationError(
"Cannot parse json-ld, maybe you are missing context."
)
return super().run_validation(document)
def validate(self, validated_data):
validated_data = super().validate(validated_data)
if self.valid_types and "@type" in validated_data:
if validated_data["@type"] not in self.valid_types:
raise serializers.ValidationError(
{
"@type": "Invalid type. Allowed types are: {}".format(
", ".join(self.valid_types)
)
}
)
return validated_data
def to_representation(self, data):
data = super().to_representation(data)
compacted = pyld.jsonld.compact(data, {"@context": ns.CONTEXTS})
......
......@@ -52,6 +52,13 @@ class PublicKeyField(jsonld.Serializer):
class ActorSerializer(jsonld.Serializer):
id_source = "url"
type_source = "type_ap"
valid_types = [
ns.SHORT["as:Application"],
ns.SHORT["as:Group"],
ns.SHORT["as:Organization"],
ns.SHORT["as:Person"],
ns.SHORT["as:Service"],
]
jsonld_fields = [
(
ns.SHORT["as:outbox"],
......@@ -119,8 +126,8 @@ class ActorSerializer(jsonld.Serializer):
"url": self.validated_data["url"],
"outbox_url": self.validated_data[ns.SHORT["as:outbox"]],
"inbox_url": self.validated_data[ns.SHORT["ldp:inbox"]],
"following_url": self.validated_data[ns.SHORT["as:following"]],
"followers_url": self.validated_data[ns.SHORT["as:followers"]],
"following_url": self.validated_data.get(ns.SHORT["as:following"]),
"followers_url": self.validated_data.get(ns.SHORT["as:followers"]),
"summary": self.validated_data.get(ns.SHORT["as:summary"]),
"type": self.validated_data["type_ap"].split("#")[-1],
"name": self.validated_data.get(ns.SHORT["as:name"]),
......@@ -178,22 +185,22 @@ class APIActorSerializer(serializers.ModelSerializer):
class LibraryActorSerializer(ActorSerializer):
url = serializers.ListField(child=serializers.JSONField())
# url = serializers.ListField(child=serializers.JSONField())
jsonld_fields = ActorSerializer.jsonld_fields + [
(
ns.SHORT["as:url"],
jsonld.Serializer(required=True),
{"source": "library_url"},
)
]
def validate(self, validated_data):
try:
urls = validated_data["url"]
except KeyError:
raise serializers.ValidationError("Missing URL field")
for u in urls:
try:
if u["name"] != "library":
continue
validated_data["library_url"] = u["href"]
break
except KeyError:
validated_data = super().validate(validated_data)
for url in validated_data[ns.SHORT["as:url"]]:
if url[ns.SHORT["as:name"]][0]["@value"] != "library":
continue
validated_data["library_url"] = url[ns.SHORT["as:href"]][0]["@id"]
break
return validated_data
......
from funkwhale_api.federation import authentication, keys
from funkwhale_api.federation import authentication, keys, ns
def test_authenticate(factories, mocker, api_request):
......@@ -7,10 +7,13 @@ def test_authenticate(factories, mocker, api_request):
mocker.patch(
"funkwhale_api.federation.actors.get_actor_data",
return_value={
"@context": ns.CONTEXTS,
"id": actor_url,
"type": "Person",
"outbox": "https://test.com",
"inbox": "https://test.com",
"following": "https://test.com",
"followers": "https://test.com",
"preferredUsername": "test",
"publicKey": {
"publicKeyPem": public.decode("utf-8"),
......
......@@ -93,6 +93,37 @@ def test_json_ld_serializer_validation_id(field_conf, expected):
}
def test_json_ld_validates_type_failing():
document = {
"@context": ns.NS["as"]["documentUrl"],
"type": "Disallowed",
"outbox": "http://test",
"id": "http://test.document",
}
class Serializer(jsonld.Serializer):
valid_types = [ns.SHORT["as:Person"]]
serializer = Serializer(data=document)
assert serializer.is_valid() is False
assert "@type" in serializer.errors
def test_json_ld_validates_type_success():
document = {
"@context": ns.NS["as"]["documentUrl"],
"type": "Person",
"outbox": "http://test",
"id": "http://test.document",
}
class Serializer(jsonld.Serializer):
valid_types = [ns.SHORT["as:Person"]]
serializer = Serializer(data=document)
assert serializer.is_valid(raise_exception=True) is True
def test_json_ld_serializer_to_representation():
class Serializer(jsonld.Serializer):
jsonld_fields = [
......
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