Verified Commit 4ab9dd59 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

WIP

parent 71b31027
......@@ -53,6 +53,8 @@ class JsonLdField(serializers.ListField):
self.id_only = kwargs.pop("id_only", False)
self.base_field = kwargs.pop("base_field")
super().__init__(*args, **kwargs)
self.child = self.base_field
self.child.parent = self
if self.single:
self.validators = [
v
......@@ -105,12 +107,17 @@ class Serializer(serializers.Serializer):
)
def run_validation(self, initial_data):
initial_data.setdefault("@context", ns.CONTEXTS)
import ipdb
ipdb.set_trace()
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):
......
......@@ -367,18 +367,37 @@ class APILibraryTrackSerializer(serializers.ModelSerializer):
return "not_imported"
class FollowSerializer(serializers.Serializer):
id = serializers.URLField(max_length=500)
object = serializers.URLField(max_length=500)
actor = serializers.URLField(max_length=500)
type = serializers.ChoiceField(choices=["Follow"])
class FollowSerializer(jsonld.Serializer):
valid_types = [ns.SHORT["as:Follow"]]
jsonld_fields = [
(
ns.SHORT["as:actor"],
ActorSerializer(required=True),
{"source": "actor", "single": True},
),
(
ns.SHORT["as:object"],
ActorSerializer(required=True),
{"source": "object", "single": True},
),
]
def validate(self, validated_data):
validated_data = super().validate(validated_data)
validated_data[ns.SHORT["as:object"]] = self.validate_object(
validated_data[ns.SHORT["as:object"]]
)
validated_data[ns.SHORT["as:actor"]] = self.validate_actor(
validated_data[ns.SHORT["as:actor"]]
)
return validated_data
def validate_object(self, v):
expected = self.context.get("follow_target")
if expected and expected.url != v:
raise serializers.ValidationError("Invalid target")
try:
return models.Actor.objects.get(url=v)
return models.Actor.objects.get(url=v["@id"])
except models.Actor.DoesNotExist:
raise serializers.ValidationError("Target not found")
......@@ -387,20 +406,20 @@ class FollowSerializer(serializers.Serializer):
if expected and expected.url != v:
raise serializers.ValidationError("Invalid actor")
try:
return models.Actor.objects.get(url=v)
return models.Actor.objects.get(url=v["@id"])
except models.Actor.DoesNotExist:
raise serializers.ValidationError("Actor not found")
def save(self, **kwargs):
return models.Follow.objects.get_or_create(
actor=self.validated_data["actor"],
target=self.validated_data["object"],
actor=self.validated_data[ns.SHORT["as:actor"]],
target=self.validated_data[ns.SHORT["as:object"]],
**kwargs, # noqa
)[0]
def to_representation(self, instance):
return {
"@context": AP_CONTEXT,
"@context": ns.CONTEXTS,
"actor": instance.actor.url,
"id": instance.get_federation_url(),
"object": instance.target.url,
......@@ -425,30 +444,45 @@ class APIFollowSerializer(serializers.ModelSerializer):
]
class AcceptFollowSerializer(serializers.Serializer):
id = serializers.URLField(max_length=500)
actor = serializers.URLField(max_length=500)
object = FollowSerializer()
type = serializers.ChoiceField(choices=["Accept"])
class AcceptFollowSerializer(jsonld.Serializer):
valid_types = [ns.SHORT["as:Accept"]]
jsonld_fields = [
(
ns.SHORT["as:actor"],
ActorSerializer(required=True),
{"source": "actor", "single": True},
),
(
ns.SHORT["as:object"],
FollowSerializer(required=True),
{"source": "object", "single": True},
),
]
def validate_actor(self, v):
expected = self.context.get("follow_target")
if expected and expected.url != v:
raise serializers.ValidationError("Invalid actor")
try:
return models.Actor.objects.get(url=v)
return models.Actor.objects.get(url=v["@id"])
except models.Actor.DoesNotExist:
raise serializers.ValidationError("Actor not found")
def validate(self, validated_data):
import ipdb; ipdb.set_trace()
validated_data = super().validate(validated_data)
validated_data[ns.SHORT["as:actor"]] = self.validate_actor(
validated_data[ns.SHORT["as:actor"]]
)
follow_target = validated_data[ns.SHORT["as:object"]][ns.SHORT["as:object"]]
follow_actor = validated_data[ns.SHORT["as:object"]][ns.SHORT["as:actor"]]
# we ensure the accept actor actually match the follow target
if validated_data["actor"] != validated_data["object"]["object"]:
if validated_data[ns.SHORT["as:actor"]].url != follow_target["@id"]:
raise serializers.ValidationError("Actor mismatch")
try:
validated_data["follow"] = (
models.Follow.objects.filter(
target=validated_data["actor"],
actor=validated_data["object"]["actor"],
target=validated_data[ns.SHORT["as:actor"]], actor=follow_actor
)
.exclude(approved=True)
.get()
......
......@@ -142,11 +142,7 @@ def test_follow_serializer_to_ap(factories):
serializer = serializers.FollowSerializer(follow)
expected = {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{},
],
"@context": ns.CONTEXTS,
"id": follow.get_federation_url(),
"type": "Follow",
"actor": follow.actor.url,
......@@ -161,6 +157,7 @@ def test_follow_serializer_save(factories):
target = factories["federation.Actor"]()
data = {
"@context": ns.CONTEXTS,
"id": "https://test.follow",
"type": "Follow",
"actor": actor.url,
......@@ -184,6 +181,7 @@ def test_follow_serializer_save_validates_on_context(factories):
impostor = factories["federation.Actor"]()
data = {
"@context": ns.CONTEXTS,
"id": "https://test.follow",
"type": "Follow",
"actor": actor.url,
......@@ -203,11 +201,7 @@ def test_accept_follow_serializer_representation(factories):
follow = factories["federation.Follow"](approved=None)
expected = {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{},
],
"@context": ns.CONTEXTS,
"id": follow.get_federation_url() + "/accept",
"type": "Accept",
"actor": follow.target.url,
......@@ -223,11 +217,7 @@ def test_accept_follow_serializer_save(factories):
follow = factories["federation.Follow"](approved=None)
data = {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{},
],
"@context": ns.CONTEXTS,
"id": follow.get_federation_url() + "/accept",
"type": "Accept",
"actor": follow.target.url,
......@@ -247,11 +237,7 @@ def test_accept_follow_serializer_validates_on_context(factories):
follow = factories["federation.Follow"](approved=None)
impostor = factories["federation.Actor"]()
data = {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{},
],
"@context": ns.CONTEXTS,
"id": follow.get_federation_url() + "/accept",
"type": "Accept",
"actor": impostor.url,
......@@ -271,11 +257,7 @@ def test_undo_follow_serializer_representation(factories):
follow = factories["federation.Follow"](approved=True)
expected = {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{},
],
"@context": ns.CONTEXTS,
"id": follow.get_federation_url() + "/undo",
"type": "Undo",
"actor": follow.actor.url,
......@@ -291,11 +273,7 @@ def test_undo_follow_serializer_save(factories):
follow = factories["federation.Follow"](approved=True)
data = {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{},
],
"@context": ns.CONTEXTS,
"id": follow.get_federation_url() + "/undo",
"type": "Undo",
"actor": follow.actor.url,
......@@ -314,11 +292,7 @@ def test_undo_follow_serializer_validates_on_context(factories):
follow = factories["federation.Follow"](approved=True)
impostor = factories["federation.Actor"]()
data = {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{},
],
"@context": ns.CONTEXTS,
"id": follow.get_federation_url() + "/undo",
"type": "Undo",
"actor": impostor.url,
......
Supports Markdown
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