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

WIP

parent 71b31027
No related branches found
No related tags found
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