From c3383bc78ca111522866373d6a310cec55ac44f5 Mon Sep 17 00:00:00 2001 From: Calum Mackervoy <c.mackervoy@gmail.com> Date: Mon, 28 Sep 2020 22:09:51 +0200 Subject: [PATCH] feature: automatic followers removal --- djangoldp/activities/services.py | 14 ++++++++++---- djangoldp/tests/tests_inbox.py | 14 ++++++++++++-- djangoldp/views.py | 5 +++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/djangoldp/activities/services.py b/djangoldp/activities/services.py index db02400c..94d8e9d5 100644 --- a/djangoldp/activities/services.py +++ b/djangoldp/activities/services.py @@ -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']) diff --git a/djangoldp/tests/tests_inbox.py b/djangoldp/tests/tests_inbox.py index 13f24339..41dadbba 100644 --- a/djangoldp/tests/tests_inbox.py +++ b/djangoldp/tests/tests_inbox.py @@ -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 diff --git a/djangoldp/views.py b/djangoldp/views.py index a110bfff..083c88c5 100644 --- a/djangoldp/views.py +++ b/djangoldp/views.py @@ -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): ''' -- GitLab