Verified Commit e0dcb87f authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Follow request approve/refuse logic

parent cb9309c2
......@@ -97,6 +97,15 @@ class FollowFactory(factory.DjangoModelFactory):
)
@registry.register
class FollowRequestFactory(factory.DjangoModelFactory):
target = factory.SubFactory(ActorFactory)
actor = factory.SubFactory(ActorFactory)
class Meta:
model = models.FollowRequest
@registry.register(name='federation.Note')
class NoteFactory(factory.Factory):
type = 'Note'
......
......@@ -35,6 +35,13 @@ class Actor(models.Model):
last_fetch_date = models.DateTimeField(
default=timezone.now)
manually_approves_followers = models.NullBooleanField(default=None)
followers = models.ManyToManyField(
to='self',
symmetrical=False,
through='Follow',
through_fields=('target', 'actor'),
related_name='following',
)
class Meta:
unique_together = ['domain', 'preferred_username']
......@@ -65,6 +72,10 @@ class Actor(models.Model):
super().save(**kwargs)
@property
def is_local(self):
return self.domain == settings.FEDERATION_HOSTNAME
@property
def is_system(self):
from . import actors
......@@ -121,3 +132,28 @@ class FollowRequest(models.Model):
last_modification_date = models.DateTimeField(
default=timezone.now)
approved = models.NullBooleanField(default=None)
def approve(self):
from . import activity
from . import serializers
self.approved = True
self.save(update_fields=['approved'])
Follow.objects.get_or_create(
target=self.target,
actor=self.actor
)
if self.target.is_local:
follow = {
'@context': serializers.AP_CONTEXT,
'actor': self.actor.url,
'id': self.actor.url + '#follows/{}'.format(uuid.uuid4()),
'object': self.target.url,
'type': 'Follow'
}
activity.accept_follow(
self.target, follow, self.actor
)
def refuse(self):
self.approved = False
self.save(update_fields=['approved'])
......@@ -351,7 +351,7 @@ def test_library_actor_handles_follow_manual_approval(
def test_library_actor_handles_follow_auto_approval(
settings, mocker, factories):
settings.FEDERATION_MUSIC_NEEDS_APPROVAL = True
settings.FEDERATION_MUSIC_NEEDS_APPROVAL = False
actor = factories['federation.Actor']()
accept_follow = mocker.patch(
'funkwhale_api.federation.activity.accept_follow')
......@@ -363,3 +363,8 @@ def test_library_actor_handles_follow_auto_approval(
'object': library_actor.url,
}
library_actor.system_conf.post_inbox(data, actor=actor)
assert library_actor.received_follow_requests.count() == 0
accept_follow.assert_called_once_with(
library_actor, data, actor
)
import pytest
import uuid
from django import db
from funkwhale_api.federation import models
from funkwhale_api.federation import serializers
def test_cannot_duplicate_actor(factories):
......@@ -30,3 +32,47 @@ def test_follow_federation_url(factories):
follow.actor.url, follow.uuid)
assert follow.get_federation_url() == expected
def test_follow_request_approve(mocker, factories):
uid = uuid.uuid4()
mocker.patch('uuid.uuid4', return_value=uid)
accept_follow = mocker.patch(
'funkwhale_api.federation.activity.accept_follow')
fr = factories['federation.FollowRequest'](target__local=True)
fr.approve()
follow = {
'@context': serializers.AP_CONTEXT,
'actor': fr.actor.url,
'id': fr.actor.url + '#follows/{}'.format(uid),
'object': fr.target.url,
'type': 'Follow'
}
assert fr.approved is True
assert list(fr.target.followers.all()) == [fr.actor]
accept_follow.assert_called_once_with(
fr.target, follow, fr.actor
)
def test_follow_request_approve_non_local(mocker, factories):
uid = uuid.uuid4()
mocker.patch('uuid.uuid4', return_value=uid)
accept_follow = mocker.patch(
'funkwhale_api.federation.activity.accept_follow')
fr = factories['federation.FollowRequest']()
fr.approve()
assert fr.approved is True
assert list(fr.target.followers.all()) == [fr.actor]
accept_follow.assert_not_called()
def test_follow_request_refused(mocker, factories):
fr = factories['federation.FollowRequest']()
fr.refuse()
assert fr.approved is False
assert fr.target.followers.count() == 0
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