forked from mirrors/bookwyrm
Merge pull request #979 from bookwyrm-social/allow-refollow
Allow refollow
This commit is contained in:
commit
9c87c91c62
2 changed files with 46 additions and 10 deletions
|
@ -101,12 +101,15 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship):
|
||||||
|
|
||||||
def save(self, *args, broadcast=True, **kwargs):
|
def save(self, *args, broadcast=True, **kwargs):
|
||||||
""" make sure the follow or block relationship doesn't already exist """
|
""" make sure the follow or block relationship doesn't already exist """
|
||||||
# don't create a request if a follow already exists
|
# if there's a request for a follow that already exists, accept it
|
||||||
|
# without changing the local database state
|
||||||
if UserFollows.objects.filter(
|
if UserFollows.objects.filter(
|
||||||
user_subject=self.user_subject,
|
user_subject=self.user_subject,
|
||||||
user_object=self.user_object,
|
user_object=self.user_object,
|
||||||
).exists():
|
).exists():
|
||||||
raise IntegrityError()
|
self.accept(broadcast_only=True)
|
||||||
|
return
|
||||||
|
|
||||||
# blocking in either direction is a no-go
|
# blocking in either direction is a no-go
|
||||||
if UserBlocks.objects.filter(
|
if UserBlocks.objects.filter(
|
||||||
Q(
|
Q(
|
||||||
|
@ -141,9 +144,9 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship):
|
||||||
""" get id for sending an accept or reject of a local user """
|
""" get id for sending an accept or reject of a local user """
|
||||||
|
|
||||||
base_path = self.user_object.remote_id
|
base_path = self.user_object.remote_id
|
||||||
return "%s#%s/%d" % (base_path, status, self.id)
|
return "%s#%s/%d" % (base_path, status, self.id or 0)
|
||||||
|
|
||||||
def accept(self):
|
def accept(self, broadcast_only=False):
|
||||||
""" turn this request into the real deal"""
|
""" turn this request into the real deal"""
|
||||||
user = self.user_object
|
user = self.user_object
|
||||||
if not self.user_subject.local:
|
if not self.user_subject.local:
|
||||||
|
@ -153,6 +156,9 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship):
|
||||||
object=self.to_activity(),
|
object=self.to_activity(),
|
||||||
).serialize()
|
).serialize()
|
||||||
self.broadcast(activity, user)
|
self.broadcast(activity, user)
|
||||||
|
if broadcast_only:
|
||||||
|
return
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
UserFollows.from_request(self)
|
UserFollows.from_request(self)
|
||||||
self.delete()
|
self.delete()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
""" tests incoming activities"""
|
""" tests incoming activities"""
|
||||||
|
import json
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
@ -34,7 +35,7 @@ class InboxRelationships(TestCase):
|
||||||
|
|
||||||
models.SiteSettings.objects.create()
|
models.SiteSettings.objects.create()
|
||||||
|
|
||||||
def test_handle_follow(self):
|
def test_follow(self):
|
||||||
""" remote user wants to follow local user """
|
""" remote user wants to follow local user """
|
||||||
activity = {
|
activity = {
|
||||||
"@context": "https://www.w3.org/ns/activitystreams",
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
@ -48,6 +49,8 @@ class InboxRelationships(TestCase):
|
||||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
|
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
|
||||||
views.inbox.activity_task(activity)
|
views.inbox.activity_task(activity)
|
||||||
self.assertEqual(mock.call_count, 1)
|
self.assertEqual(mock.call_count, 1)
|
||||||
|
response_activity = json.loads(mock.call_args[0][1])
|
||||||
|
self.assertEqual(response_activity["type"], "Accept")
|
||||||
|
|
||||||
# notification created
|
# notification created
|
||||||
notification = models.Notification.objects.get()
|
notification = models.Notification.objects.get()
|
||||||
|
@ -61,7 +64,34 @@ class InboxRelationships(TestCase):
|
||||||
follow = models.UserFollows.objects.get(user_object=self.local_user)
|
follow = models.UserFollows.objects.get(user_object=self.local_user)
|
||||||
self.assertEqual(follow.user_subject, self.remote_user)
|
self.assertEqual(follow.user_subject, self.remote_user)
|
||||||
|
|
||||||
def test_handle_follow_manually_approved(self):
|
def test_follow_duplicate(self):
|
||||||
|
""" remote user wants to follow local user twice """
|
||||||
|
activity = {
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
"id": "https://example.com/users/rat/follows/123",
|
||||||
|
"type": "Follow",
|
||||||
|
"actor": "https://example.com/users/rat",
|
||||||
|
"object": "https://example.com/user/mouse",
|
||||||
|
}
|
||||||
|
|
||||||
|
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||||
|
views.inbox.activity_task(activity)
|
||||||
|
|
||||||
|
# the follow relationship should exist
|
||||||
|
follow = models.UserFollows.objects.get(user_object=self.local_user)
|
||||||
|
self.assertEqual(follow.user_subject, self.remote_user)
|
||||||
|
|
||||||
|
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") as mock:
|
||||||
|
views.inbox.activity_task(activity)
|
||||||
|
self.assertEqual(mock.call_count, 1)
|
||||||
|
response_activity = json.loads(mock.call_args[0][1])
|
||||||
|
self.assertEqual(response_activity["type"], "Accept")
|
||||||
|
|
||||||
|
# the follow relationship should STILL exist
|
||||||
|
follow = models.UserFollows.objects.get(user_object=self.local_user)
|
||||||
|
self.assertEqual(follow.user_subject, self.remote_user)
|
||||||
|
|
||||||
|
def test_follow_manually_approved(self):
|
||||||
""" needs approval before following """
|
""" needs approval before following """
|
||||||
activity = {
|
activity = {
|
||||||
"@context": "https://www.w3.org/ns/activitystreams",
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
@ -91,7 +121,7 @@ class InboxRelationships(TestCase):
|
||||||
follow = models.UserFollows.objects.all()
|
follow = models.UserFollows.objects.all()
|
||||||
self.assertEqual(list(follow), [])
|
self.assertEqual(list(follow), [])
|
||||||
|
|
||||||
def test_handle_undo_follow_request(self):
|
def test_undo_follow_request(self):
|
||||||
""" the requester cancels a follow request """
|
""" the requester cancels a follow request """
|
||||||
self.local_user.manually_approves_followers = True
|
self.local_user.manually_approves_followers = True
|
||||||
self.local_user.save(broadcast=False)
|
self.local_user.save(broadcast=False)
|
||||||
|
@ -121,7 +151,7 @@ class InboxRelationships(TestCase):
|
||||||
|
|
||||||
self.assertFalse(self.local_user.follower_requests.exists())
|
self.assertFalse(self.local_user.follower_requests.exists())
|
||||||
|
|
||||||
def test_handle_unfollow(self):
|
def test_unfollow(self):
|
||||||
""" remove a relationship """
|
""" remove a relationship """
|
||||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||||
rel = models.UserFollows.objects.create(
|
rel = models.UserFollows.objects.create(
|
||||||
|
@ -146,7 +176,7 @@ class InboxRelationships(TestCase):
|
||||||
views.inbox.activity_task(activity)
|
views.inbox.activity_task(activity)
|
||||||
self.assertIsNone(self.local_user.followers.first())
|
self.assertIsNone(self.local_user.followers.first())
|
||||||
|
|
||||||
def test_handle_follow_accept(self):
|
def test_follow_accept(self):
|
||||||
""" a remote user approved a follow request from local """
|
""" a remote user approved a follow request from local """
|
||||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||||
rel = models.UserFollowRequest.objects.create(
|
rel = models.UserFollowRequest.objects.create(
|
||||||
|
@ -177,7 +207,7 @@ class InboxRelationships(TestCase):
|
||||||
self.assertEqual(follows.count(), 1)
|
self.assertEqual(follows.count(), 1)
|
||||||
self.assertEqual(follows.first(), self.local_user)
|
self.assertEqual(follows.first(), self.local_user)
|
||||||
|
|
||||||
def test_handle_follow_reject(self):
|
def test_follow_reject(self):
|
||||||
""" turn down a follow request """
|
""" turn down a follow request """
|
||||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||||
rel = models.UserFollowRequest.objects.create(
|
rel = models.UserFollowRequest.objects.create(
|
||||||
|
|
Loading…
Reference in a new issue