Skip to content
Snippets Groups Projects
Verified Commit 4ab9dd59 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

WIP

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