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

Test bot can now unfollow

parent 81e7f03f
No related branches found
No related tags found
No related merge requests found
......@@ -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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment