Merge branch 'activity-queue' into 'master'

minor: Notifications sent using ActivityQueueService

See merge request djangoldp-packages/djangoldp-notification!33
This commit is contained in:
Jean-Baptiste Pasquier 2020-10-23 12:29:26 +00:00
commit 78b22cbe9f
2 changed files with 41 additions and 28 deletions

View File

@ -1,5 +1,3 @@
import logging
import requests
from django.conf import settings
from django.contrib.auth import get_user_model
@ -13,10 +11,14 @@ from django.urls import NoReverseMatch, get_resolver
from django.utils.translation import ugettext_lazy as _
from djangoldp.fields import LDPUrlField
from djangoldp.models import Model
from threading import Thread
from djangoldp.activities.services import ActivityQueueService, ActivityPubService, activity_sending_finished
from djangoldp_notification.middlewares import MODEL_MODIFICATION_USER_FIELD
from djangoldp_notification.permissions import InboxPermissions, SubscriptionsPermissions
from djangoldp_notification.views import LDPNotificationsViewSet
import logging
logger = logging.getLogger('djangoldp')
class Notification(Model):
@ -115,7 +117,10 @@ def create_nested_subscribers(sender, instance, created, **kwargs):
@receiver(post_delete, dispatch_uid="delete_callback_notif")
def send_notification(sender, instance, **kwargs):
if sender != Notification:
threads = []
# don't send notifications for foreign resources
if hasattr(instance, 'urlid') and Model.is_external(instance.urlid):
return
recipients = []
try:
url_container = settings.BASE_URL + Model.container_id(instance)
@ -125,47 +130,55 @@ def send_notification(sender, instance, **kwargs):
# dispatch a notification for every Subscription on this resource
for subscription in Subscription.objects.filter(models.Q(object=url_resource) | models.Q(object=url_container)):
if not instance.is_backlink and subscription.inbox not in recipients and \
(not subscription.is_backlink or not kwargs.get("created")):
if subscription.inbox not in recipients and (not subscription.is_backlink or not kwargs.get("created")):
# I may have configured to send the subscription to a foreign key
if subscription.field is not None and len(subscription.field) > 1:
try:
instance = getattr(instance, subscription.field, instance)
# don't send notifications for foreign resources
if hasattr(instance, 'urlid') and Model.is_external(instance.urlid):
continue
url_resource = settings.BASE_URL + Model.resource_id(instance)
except NoReverseMatch:
continue
except ObjectDoesNotExist:
continue
process = Thread(target=send_request, args=[subscription.inbox, url_resource, instance,
kwargs.get("created", False)])
process.start()
threads.append(process)
send_request(subscription.inbox, url_resource, instance, kwargs.get("created", False))
recipients.append(subscription.inbox)
@receiver(activity_sending_finished, sender=ActivityQueueService)
def _handle_prosody_response(sender, response, saved_activity, **kwargs):
'''callback function for handling a response from Prosody on a notification'''
# if text is defined in the response body then it's an error
if saved_activity is not None:
response_body = saved_activity.response_to_json()
if 'condition' in response_body:
logger.error("[DjangoLDP-Notification.models._handle_prosody_response] error in Prosody response " +
str(response_body))
def send_request(target, object_iri, instance, created):
unknown = str(_("Auteur inconnu"))
author = getattr(getattr(instance, MODEL_MODIFICATION_USER_FIELD, unknown), "urlid", unknown)
request_type = "creation" if created else "update"
try:
# local inbox
if target.startswith(settings.SITE_URL):
user = Model.resolve_parent(target.replace(settings.SITE_URL, ''))
Notification.objects.create(user=user, object=object_iri, type=request_type, author=author)
# external inbox
else:
json = {
"@context": settings.LDP_RDF_CONTEXT,
"object": object_iri,
"author": author,
"type": request_type
}
requests.post(target, json=json, headers={"Content-Type": "application/ld+json"})
except Exception as e:
logging.error('Djangoldp_notifications: Error with request: {}'.format(e))
return True
# local inbox
if target.startswith(settings.SITE_URL):
user = Model.resolve_parent(target.replace(settings.SITE_URL, ''))
Notification.objects.create(user=user, object=object_iri, type=request_type, author=author)
# external inbox
else:
json = {
"@context": settings.LDP_RDF_CONTEXT,
"object": object_iri,
"author": author,
"type": request_type
}
ActivityQueueService.send_activity(target, json)
@receiver(post_save, sender=Notification)

View File

@ -10,7 +10,7 @@ license = MIT
[options]
packages = find:
install_requires =
djangoldp>=1.0.0
djangoldp>=1.2.0
[options.extras_require]
include_package_data = True