Verified Commit 3ad1fe17 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Test bot can now unfollow

parent 81e7f03f
......@@ -130,7 +130,7 @@ class SystemActor(object):
'No handler for activity %s', ac['type'])
return
return handler(ac, actor)
return handler(data, actor)
class LibraryActor(SystemActor):
......@@ -269,6 +269,40 @@ class TestActor(SystemActor):
to=[ac['actor']],
on_behalf_of=test_actor)
def handle_undo(self, ac, sender):
if ac['object']['type'] != 'Follow':
return
if ac['object']['actor'] != sender.url:
# not the same actor, permission issue
return
test_actor = self.get_actor_instance()
models.Follow.objects.filter(
actor=sender,
target=test_actor,
).delete()
# we also unfollow the sender, if possible
try:
follow = models.Follow.objects.get(
target=sender,
actor=test_actor,
)
except models.Follow.DoesNotExist:
return
undo = {
'@context': serializers.AP_CONTEXT,
'type': 'Undo',
'id': follow.get_federation_url() + '/undo',
'actor': test_actor.url,
'object': serializers.FollowSerializer(follow).data,
}
follow.delete()
activity.deliver(
undo,
to=[sender.url],
on_behalf_of=test_actor)
SYSTEM_ACTORS = {
'library': LibraryActor(),
'test': TestActor(),
......
......@@ -3,6 +3,7 @@ import requests
import requests_http_signature
from django.utils import timezone
from django.conf import settings
from funkwhale_api.factories import registry
......@@ -65,6 +66,12 @@ class ActorFactory(factory.DjangoModelFactory):
class Meta:
model = models.Actor
class Params:
local = factory.Trait(
domain=factory.LazyAttribute(
lambda o: settings.FEDERATION_HOSTNAME)
)
@classmethod
def _generate(cls, create, attrs):
has_public = attrs.get('public_key') is not None
......@@ -84,6 +91,11 @@ class FollowFactory(factory.DjangoModelFactory):
class Meta:
model = models.Follow
class Params:
local = factory.Trait(
actor=factory.SubFactory(ActorFactory, local=True)
)
@registry.register(name='federation.Note')
class NoteFactory(factory.Factory):
......
......@@ -14,6 +14,8 @@ TYPE_CHOICES = [
class Actor(models.Model):
ap_type = 'Actor'
url = models.URLField(unique=True, max_length=500, db_index=True)
outbox_url = models.URLField(max_length=500)
inbox_url = models.URLField(max_length=500)
......@@ -79,6 +81,8 @@ class Actor(models.Model):
class Follow(models.Model):
ap_type = 'Follow'
uuid = models.UUIDField(default=uuid.uuid4, unique=True)
actor = models.ForeignKey(
Actor,
......@@ -96,3 +100,6 @@ class Follow(models.Model):
class Meta:
unique_together = ['actor', 'target']
def get_federation_url(self):
return '{}#follows/{}'.format(self.actor.url, self.uuid)
......@@ -169,11 +169,7 @@ def test_test_post_inbox_handles_create_note(
}]
)
expected_activity = {
'@context': [
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1',
{}
],
'@context': serializers.AP_CONTEXT,
'actor': test_actor.url,
'id': 'https://{}/activities/note/{}/activity'.format(
settings.FEDERATION_HOSTNAME, now.timestamp()
......@@ -288,11 +284,7 @@ def test_test_actor_handles_follow(
},
}
expected_follow = {
'@context': [
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1',
{}
],
'@context': serializers.AP_CONTEXT,
'actor': test_actor.url,
'id': test_actor.url + '#follows/{}'.format(uid),
'object': actor.url,
......@@ -317,3 +309,38 @@ def test_test_actor_handles_follow(
follow = test_actor.received_follows.first()
assert follow.actor == actor
assert follow.target == test_actor
def test_test_actor_handles_undo_follow(
settings, mocker, factories):
deliver = mocker.patch(
'funkwhale_api.federation.activity.deliver')
test_actor = actors.SYSTEM_ACTORS['test'].get_actor_instance()
follow = factories['federation.Follow'](target=test_actor)
reverse_follow = factories['federation.Follow'](
actor=test_actor, target=follow.actor)
follow_serializer = serializers.FollowSerializer(follow)
reverse_follow_serializer = serializers.FollowSerializer(
reverse_follow)
undo = {
'@context': serializers.AP_CONTEXT,
'type': 'Undo',
'id': follow_serializer.data['id'] + '/undo',
'actor': follow.actor.url,
'object': follow_serializer.data,
}
expected_undo = {
'@context': serializers.AP_CONTEXT,
'type': 'Undo',
'id': reverse_follow_serializer.data['id'] + '/undo',
'actor': reverse_follow.actor.url,
'object': reverse_follow_serializer.data,
}
actors.SYSTEM_ACTORS['test'].post_inbox(undo, actor=follow.actor)
deliver.assert_called_once_with(
expected_undo,
to=[follow.actor.url],
on_behalf_of=test_actor,)
assert models.Follow.objects.count() == 0
......@@ -3,7 +3,7 @@ from funkwhale_api.federation import keys
from funkwhale_api.federation import signing
def test_authenticate(nodb_factories, mocker, api_request):
def test_authenticate(factories, mocker, api_request):
private, public = keys.get_key_pair()
actor_url = 'https://test.federation/actor'
mocker.patch(
......@@ -18,7 +18,7 @@ def test_authenticate(nodb_factories, mocker, api_request):
'id': actor_url + '#main-key',
}
})
signed_request = nodb_factories['federation.SignedRequest'](
signed_request = factories['federation.SignedRequest'](
auth__key=private,
auth__key_id=actor_url + '#main-key',
auth__headers=[
......
......@@ -23,3 +23,10 @@ def test_cannot_duplicate_follow(factories):
target=follow.target,
actor=follow.actor,
)
def test_follow_federation_url(factories):
follow = factories['federation.Follow'](local=True)
expected = '{}#follows/{}'.format(
follow.actor.url, follow.uuid)
assert follow.get_federation_url() == expected
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