Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Auri
funkwhale
Commits
4ab9dd59
Verified
Commit
4ab9dd59
authored
Jul 11, 2018
by
Eliot Berriot
Browse files
WIP
parent
71b31027
Changes
3
Hide whitespace changes
Inline
Side-by-side
api/funkwhale_api/federation/jsonld.py
View file @
4ab9dd59
...
...
@@ -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
):
...
...
api/funkwhale_api/federation/serializers.py
View file @
4ab9dd59
...
...
@@ -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
.
CONTEXT
S
,
"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
()
...
...
api/tests/federation/test_serializers.py
View file @
4ab9dd59
...
...
@@ -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
,
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment