Skip to content
Snippets Groups Projects
Commit 907b0b66 authored by Calum Mackervoy's avatar Calum Mackervoy Committed by Benoit Alessandroni
Browse files

bugfix: infinite loop on remove activity

parent 82048cb7
No related branches found
No related tags found
No related merge requests found
......@@ -15,6 +15,10 @@ import logging
logger = logging.getLogger('djangoldp')
BACKLINKS_ACTOR = {
"type": "Service",
"name": "Backlinks Service"
}
class ActivityPubService(object):
......@@ -174,7 +178,7 @@ class ActivityPubService(object):
def _save_sent_activity(cls, activity):
'''Auxiliary function saves a record of parameterised activity'''
payload = bytes(json.dumps(activity), "utf-8")
local_id = settings.SITE_URL + "outbox/"
local_id = settings.SITE_URL + "/outbox/"
obj = ActivityModel.objects.create(local_id=local_id, payload=payload)
obj.aid = Model.absolute_url(obj)
obj.save()
......@@ -247,10 +251,7 @@ def check_save_for_backlinks(sender, instance, created, **kwargs):
if len(targets) > 0:
obj = ActivityPubService.build_object_tree(instance)
actor = {
"type": "Service",
"name": "Backlinks Service"
}
actor = BACKLINKS_ACTOR
# Create Activity
if created:
for target in targets:
......@@ -276,10 +277,7 @@ def check_delete_for_backlinks(sender, instance, **kwargs):
if len(targets) > 0:
for target in targets:
ActivityPubService.send_delete_activity({
"type": "Service",
"name": "Backlinks Service"
}, {
ActivityPubService.send_delete_activity(BACKLINKS_ACTOR, {
"@id": instance.urlid,
"@type": Model.get_model_rdf_type(sender)
}, target)
......@@ -341,10 +339,7 @@ def check_m2m_for_backlinks(sender, instance, action, *args, **kwargs):
}
if action == 'post_add':
for target in targets:
ActivityPubService.send_add_activity({
"type": "Service",
"name": "Backlinks Service"
}, obj, target)
ActivityPubService.send_add_activity(BACKLINKS_ACTOR, obj, target)
inbox = ActivityPubService.discover_inbox(target['@id'])
if not Follower.objects.filter(object=obj['@id'], follower=target['@id']).exists():
Follower.objects.create(object=obj['@id'], inbox=inbox, follower=target['@id'],
......@@ -352,10 +347,8 @@ 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({
"type": "Service",
"name": "Backlinks Service"
}, obj, target)
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'],
is_backlink=True):
inbox=inbox, is_backlink=True):
follower.delete()
......@@ -301,9 +301,7 @@ class Activity(Model):
rdf_type = 'as:Activity'
def to_activitystream(self):
payload = self.payload.decode("utf-8")
data = json.loads(payload)
return data
return json.loads(self.payload.tobytes())
class Follower(Model):
......
......@@ -81,7 +81,6 @@ class TestsBacklinksService(APITestCase):
@override_settings(SEND_BACKLINKS=True, DISABLE_OUTBOX=True)
def test_local_object_with_external_m2m_delete_parent(self):
# a local project with three distant users
project = Project.objects.create(description='Test')
external_a = self._get_random_external_user()
project.team.add(external_a)
......
......@@ -2,6 +2,7 @@ import json
from django.contrib.auth import get_user_model
from django.conf import settings
from django.db import IntegrityError
from django.test import override_settings
from rest_framework.test import APIClient, APITestCase
from djangoldp.tests.models import Circle, CircleMember, Project, UserProfile, DateModel, DateChild
from djangoldp.models import Activity, Follower
......@@ -153,6 +154,7 @@ class TestsInbox(APITestCase):
self._assert_activity_created(response)
# test sending an add activity when the backlink already exists
@override_settings(SEND_BACKLINKS=True, DISABLE_OUTBOX=True)
def test_add_activity_object_already_added(self):
circle = Circle.objects.create(urlid="https://distant.com/circles/1/")
CircleMember.objects.create(urlid="https://distant.com/circle-members/1/", circle=circle, user=self.user)
......@@ -170,6 +172,7 @@ class TestsInbox(APITestCase):
}
}
payload = self._get_activity_request_template("Add", obj, self._build_target_from_user(self.user))
prior_count = Activity.objects.count()
response = self.client.post('/inbox/',
data=json.dumps(payload),
......@@ -184,6 +187,7 @@ class TestsInbox(APITestCase):
self.assertIn("https://distant.com/circles/1/", circles.values_list('urlid', flat=True))
self.assertIn("https://distant.com/circle-members/1/", user_circles.values_list('urlid', flat=True))
self._assert_activity_created(response)
self.assertEqual(Activity.objects.count(), prior_count + 1)
# TODO: https://git.startinblox.com/djangoldp-packages/djangoldp/issues/250
def test_add_activity_str_parameter(self):
......@@ -315,6 +319,34 @@ class TestsInbox(APITestCase):
self.assertEqual(response.status_code, 201)
self._assert_activity_created(response)
@override_settings(SEND_BACKLINKS=True, DISABLE_OUTBOX=True)
def test_removing_object_twice(self):
project = Project.objects.create(urlid="https://distant.com/projects/1/")
self.user.projects.add(project)
prior_count = Activity.objects.all().count()
# remove once via activity
obj = {
"@type": "hd:project",
"@id": "https://distant.com/projects/1/"
}
payload = self._get_activity_request_template("Remove", obj, origin=self._build_target_from_user(self.user))
response = self.client.post('/inbox/',
data=json.dumps(payload),
content_type='application/ld+json;profile="https://www.w3.org/ns/activitystreams"')
self.assertEqual(response.status_code, 201)
# received and then sent
self.assertEqual(Activity.objects.all().count(), prior_count + 2)
prior_count = Activity.objects.all().count()
# sending remove activity again
payload = self._get_activity_request_template("Remove", obj, origin=self._build_target_from_user(self.user))
response = self.client.post('/inbox/',
data=json.dumps(payload),
content_type='application/ld+json;profile="https://www.w3.org/ns/activitystreams"')
# just received, did not send
self.assertEqual(Activity.objects.all().count(), prior_count + 1)
# Delete CircleMember
def test_delete_activity_circle_using_origin(self):
circle = Circle.objects.create(urlid="https://distant.com/circles/1/", allow_create_backlink=False)
......
......@@ -190,7 +190,9 @@ class InboxView(APIView):
for field_name, relation_info in target_info.relations.items():
if relation_info.related_model == object_model:
getattr(target, field_name).add(backlink)
attr = getattr(target, field_name)
if not attr.filter(urlid=backlink.urlid).exists():
attr.add(backlink)
def handle_remove_activity(self, activity, **kwargs):
'''
......@@ -215,7 +217,9 @@ class InboxView(APIView):
for field_name, relation_info in origin_info.relations.items():
if relation_info.related_model == object_model:
getattr(origin, field_name).remove(object_instance)
attr = getattr(origin, field_name)
if attr.filter(urlid=object_instance.urlid).exists():
attr.remove(object_instance)
def handle_create_or_update_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