Skip to content
Snippets Groups Projects
Commit c3383bc7 authored by Calum Mackervoy's avatar Calum Mackervoy
Browse files

feature: automatic followers removal

parent bd08385b
No related branches found
No related tags found
1 merge request!164feature: external resources auto-follow and unfollow local ones on activity reception
Pipeline #7751 passed with stage
in 45 seconds
......@@ -260,6 +260,15 @@ class ActivityPubService(object):
Follower.objects.create(object=obj_id, inbox=ActivityPubService.discover_inbox(urlid),
follower=urlid, is_backlink=True)
@classmethod
def remove_followers_for_resource(cls, external_urlid, obj_id):
'''removes all followers which match the follower urlid, obj urlid combination'''
inbox = ActivityPubService.discover_inbox(external_urlid)
for follower in Follower.objects.filter(object=obj_id, follower=external_urlid,
inbox=inbox, is_backlink=True):
follower.delete()
@receiver([post_save])
def check_save_for_backlinks(sender, instance, created, **kwargs):
......@@ -362,7 +371,4 @@ def check_m2m_for_backlinks(sender, instance, action, *args, **kwargs):
elif action == "post_remove" or action == "pre_clear":
for target in targets:
ActivityPubService.send_remove_activity(BACKLINKS_ACTOR, obj, target)
inbox = ActivityPubService.discover_inbox(target['@id'])
for follower in Follower.objects.filter(object=obj['@id'], follower=target['@id'],
inbox=inbox, is_backlink=True):
follower.delete()
ActivityPubService.remove_followers_for_resource(target['@id'], obj['@id'])
......@@ -306,9 +306,13 @@ class TestsInbox(APITestCase):
# REMOVE & DELETE ACTIVITIES
#
# project model has a direct many-to-many with User
@override_settings(SEND_BACKLINKS=True, DISABLE_OUTBOX=True)
def test_remove_activity_project_using_origin(self):
project = Project.objects.create(urlid="https://distant.com/projects/1/")
self.user.projects.add(project)
Follower.objects.create(object=self.user.urlid, inbox='https://distant.com/inbox/',
follower=project.urlid, is_backlink=True)
prior_activity_count = Activity.objects.count()
obj = {
"@type": "hd:project",
......@@ -326,7 +330,8 @@ class TestsInbox(APITestCase):
self.assertEquals(len(projects), 1)
self.assertEquals(len(user_projects), 0)
self.assertIn("https://distant.com/projects/1/", projects.values_list('urlid', flat=True))
self._assert_activity_created(response)
self._assert_activity_created(response, prior_activity_count + 2)
self.assertEqual(Follower.objects.count(), 0)
# TODO: test_remove_activity_project_using_target
......@@ -374,9 +379,12 @@ class TestsInbox(APITestCase):
self.assertEqual(Activity.objects.all().count(), prior_count + 1)
# Delete CircleMember
@override_settings(SEND_BACKLINKS=True, DISABLE_OUTBOX=True)
def test_delete_activity_circle_using_origin(self):
circle = Circle.objects.create(urlid="https://distant.com/circles/1/", allow_create_backlink=False)
CircleMember.objects.create(urlid="https://distant.com/circle-members/1/",circle=circle, user=self.user)
cm = CircleMember.objects.create(urlid="https://distant.com/circle-members/1/",circle=circle, user=self.user)
Follower.objects.create(object=self.user.urlid, inbox='https://distant.com/inbox/',
follower=cm.urlid, is_backlink=True)
obj = {
"@type": "hd:circlemember",
......@@ -400,9 +408,11 @@ class TestsInbox(APITestCase):
circles = Circle.objects.all()
user_circles = self.user.circles.all()
self.assertEquals(len(circles), 1)
self.assertEquals(CircleMember.objects.count(), 0)
self.assertEquals(len(user_circles), 0)
self.assertIn("https://distant.com/circles/1/", circles.values_list('urlid', flat=True))
self._assert_activity_created(response)
self.assertEqual(Follower.objects.count(), 0)
# TODO: test_delete_activity_circle_using_target
......
......@@ -239,6 +239,7 @@ class InboxView(APIView):
attr = getattr(origin, field_name)
if attr.filter(urlid=object_instance.urlid).exists():
attr.remove(object_instance)
ActivityPubService.remove_followers_for_resource(origin.urlid, object_instance.urlid)
def handle_create_or_update_activity(self, activity, **kwargs):
'''
......@@ -264,6 +265,10 @@ class InboxView(APIView):
object_instance.allow_create_backlink = False
object_instance.save()
object_instance.delete()
urlid = getattr(object_instance, 'urlid', None)
if urlid is not None:
for follower in Follower.objects.filter(follower=urlid):
follower.delete()
def handle_follow_activity(self, activity, **kwargs):
'''
......
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