bugfix: Do not send HTTP request when creating a local notification

This commit is contained in:
Christophe 2019-12-13 15:51:36 +01:00
parent 9416c27971
commit 8946dbf78f
3 changed files with 70 additions and 18 deletions

View File

@ -32,7 +32,18 @@ An object allowing a User to be notified of any change on a resource or a contai
| `object` | `URLField` | | ID of the resource or the container to watch | | `object` | `URLField` | | ID of the resource or the container to watch |
| `inbox` | `URLField` | | ID of the inbox to notify when the resource or the container change | | `inbox` | `URLField` | | ID of the inbox to notify when the resource or the container change |
# Middlewares
There is a `CurrentUserMiddleware` that catches the connected user of the last performed HTTP request and adds
to every model before it is saved. This is useful if you need to get the connected user that performed
the last HTTP request in a `pre_saved` signal. You can get it by using the following line :
```python
getattr(instance, MODEL_MODIFICATION_USER_FIELD, "Unknown user")
```
`MODEL_MODIFICATION_USER_FIELD` is a constant that lies in `djangoldp_notification.middlewares` and
`instance` is the instance of your model before save in DB.
# Signals # Signals
@ -40,8 +51,6 @@ An object allowing a User to be notified of any change on a resource or a contai
When an object is saved, a notification is created for all the subscriptions related to this object. When an object is saved, a notification is created for all the subscriptions related to this object.
## Send email when new notification ## Send email when new notification
When a notification is created, an email is sent to the user. When a notification is created, an email is sent to the user.

View File

@ -0,0 +1,31 @@
from django.db.models import signals
MODEL_MODIFICATION_USER_FIELD = 'modification_user'
class CurrentUserMiddleware:
def __init__(self, get_response=None):
self.get_response = get_response
def __call__(self, request):
self.process_request(request)
response = self.get_response(request)
signals.pre_save.disconnect(dispatch_uid=request)
return response
def process_request(self, request):
if request.method in ('GET', 'HEAD', 'OPTION'):
# this request shouldn't update anything
# so no signal handler should be attached
return
if hasattr(request, 'user') and request.user.is_authenticated():
user = request.user
else:
user = None
def _update_users(sender, instance, **kwargs):
setattr(instance, MODEL_MODIFICATION_USER_FIELD, user)
signals.pre_save.connect(_update_users, dispatch_uid=request, weak=False)

View File

@ -16,6 +16,8 @@ from djangoldp.fields import LDPUrlField
from djangoldp.models import Model from djangoldp.models import Model
from django.template import loader from django.template import loader
from djangoldp_notification.middlewares import MODEL_MODIFICATION_USER_FIELD
from .permissions import InboxPermissions from .permissions import InboxPermissions
@ -47,32 +49,42 @@ class Subscription(Model):
def __str__(self): def __str__(self):
return '{}'.format(self.object) return '{}'.format(self.object)
# --- SUBSCRIPTION SYSTEM --- # --- SUBSCRIPTION SYSTEM ---
@receiver(post_save, dispatch_uid="callback_notif") @receiver(post_save, dispatch_uid="callback_notif")
def send_notification(sender, instance, **kwargs): def send_notification(sender, instance, created, **kwargs):
if sender != Notification: if sender != Notification:
threads = [] threads = []
try: try:
urlContainer = settings.BASE_URL + Model.container_id(instance) url_container = settings.BASE_URL + Model.container_id(instance)
urlResource = settings.BASE_URL + Model.resource_id(instance) url_resource = settings.BASE_URL + Model.resource_id(instance)
except NoReverseMatch: except NoReverseMatch:
return return
for subscription in Subscription.objects.filter(models.Q(object=urlResource)|models.Q(object=urlContainer)): for subscription in Subscription.objects.filter(models.Q(object=url_resource) | models.Q(object=url_container)):
process = Thread(target=send_request, args=[subscription.inbox, urlResource]) process = Thread(target=send_request, args=[subscription.inbox, url_resource, instance, created])
process.start() process.start()
threads.append(process) threads.append(process)
def send_request(target, object_iri): def send_request(target, object_iri, instance, created):
unknown = _("Unknown author")
author = getattr(getattr(instance, MODEL_MODIFICATION_USER_FIELD, unknown), "urlid", unknown)
request_type = "creation" if created else "update"
try: try:
req = requests.post(target, if target.startswith(settings.SITE_URL):
json={"@context": "https://cdn.happy-dev.fr/owl/hdcontext.jsonld", user = Model.resolve_parent(target.replace(settings.SITE_URL, ''))
"object": object_iri, "type": "update"}, Notification.objects.create(user=user, object=object_iri, type=request_type, author=author)
headers={"Content-Type": "application/ld+json"}) else:
except: json = {
logging.error('Djangoldp_notifications: Error with request') "@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 return True
@ -81,7 +93,7 @@ def send_email_on_notification(sender, instance, created, **kwargs):
if created and instance.summary and settings.JABBER_DEFAULT_HOST and instance.user.email: if created and instance.summary and settings.JABBER_DEFAULT_HOST and instance.user.email:
try: try:
if instance.author.startswith(settings.SITE_URL): if instance.author.startswith(settings.SITE_URL):
who = str(Model.resolve_id(instance.author.replace(settings.SITE_URL,''))) who = str(Model.resolve_id(instance.author.replace(settings.SITE_URL, '')))
else: else:
who = requests.get(instance.author).json()['name'] who = requests.get(instance.author).json()['name']
except: except:
@ -89,13 +101,13 @@ def send_email_on_notification(sender, instance, created, **kwargs):
try: try:
if instance.object.startswith(settings.SITE_URL): if instance.object.startswith(settings.SITE_URL):
where = str(Model.resolve_id(instance.object.replace(settings.SITE_URL,''))) where = str(Model.resolve_id(instance.object.replace(settings.SITE_URL, '')))
else: else:
where = requests.get(instance.object).json()['name'] where = requests.get(instance.object).json()['name']
except: except:
where = "Unknown place" where = "Unknown place"
if(who == where): if who == where:
where = "has sent you a private message" where = "has sent you a private message"
else: else:
where = "mention you on " + where where = "mention you on " + where