def _record_object_deleted(request, instance, **kwargs): # Record that the object was deleted. if hasattr(instance, 'log_change'): instance.log_change(request.user, request.id, OBJECTCHANGE_ACTION_DELETE) enqueue_webhooks(instance, OBJECTCHANGE_ACTION_DELETE)
def _record_object_deleted(request, instance, **kwargs): # Force resolution of request.user in case it's still a SimpleLazyObject. This seems to happen # occasionally during tests, but haven't been able to determine why. assert request.user.is_authenticated # Record that the object was deleted if hasattr(instance, 'log_change'): instance.log_change(request.user, request.id, OBJECTCHANGE_ACTION_DELETE) enqueue_webhooks(instance, request.user, request.id, OBJECTCHANGE_ACTION_DELETE)
def _record_object_deleted(request, instance, **kwargs): # Force resolution of request.user in case it's still a SimpleLazyObject. This seems to happen # occasionally during tests, but haven't been able to determine why. assert request.user.is_authenticated # Record that the object was deleted if hasattr(instance, 'log_change'): instance.log_change(request.user, request.id, OBJECTCHANGE_ACTION_DELETE) enqueue_webhooks(instance, OBJECTCHANGE_ACTION_DELETE)
def _record_object_deleted(request, instance, **kwargs): # Record that the object was deleted if hasattr(instance, 'log_change'): instance.log_change(request.user, request.id, OBJECTCHANGE_ACTION_DELETE) # Enqueue webhooks enqueue_webhooks(instance, request.user, request.id, OBJECTCHANGE_ACTION_DELETE) # Increment metric counters model_deletes.labels(instance._meta.model_name).inc()
def __call__(self, request): # Initialize an empty list to cache objects being saved. _thread_locals.changed_objects = [] # Assign a random unique ID to the request. This will be used to associate multiple object changes made during # the same request. request.id = uuid.uuid4() # Signals don't include the request context, so we're currying it into the post_delete function ahead of time. record_object_deleted = curry(_record_object_deleted, request) # Connect our receivers to the post_save and post_delete signals. post_save.connect(cache_changed_object, dispatch_uid='record_object_saved') post_delete.connect(record_object_deleted, dispatch_uid='record_object_deleted') # Process the request response = self.get_response(request) # Create records for any cached objects that were created/updated. for obj, action in _thread_locals.changed_objects: # Record the change if hasattr(obj, 'log_change'): obj.log_change(request.user, request.id, action) # Enqueue webhooks enqueue_webhooks(obj, request.user, request.id, action) # Increment metric counters if action == OBJECTCHANGE_ACTION_CREATE: model_inserts.labels(obj._meta.model_name).inc() elif action == OBJECTCHANGE_ACTION_UPDATE: model_updates.labels(obj._meta.model_name).inc() # Housekeeping: 1% chance of clearing out expired ObjectChanges if _thread_locals.changed_objects and settings.CHANGELOG_RETENTION and random.randint( 1, 100) == 1: cutoff = timezone.now() - timedelta( days=settings.CHANGELOG_RETENTION) purged_count, _ = ObjectChange.objects.filter( time__lt=cutoff).delete() return response
def _record_object_deleted(request, instance, **kwargs): # Force resolution of request.user in case it's still a SimpleLazyObject. This seems to happen # occasionally during tests, but haven't been able to determine why. # Note: We exclude SAML2 login flow deletions, as the call to request.session.flush() throws this assertion if request.path_info != '/saml2_auth/acs/': assert request.user.is_authenticated # Record that the object was deleted if hasattr(instance, 'log_change'): instance.log_change(request.user, request.id, OBJECTCHANGE_ACTION_DELETE) # Enqueue webhooks enqueue_webhooks(instance, request.user, request.id, OBJECTCHANGE_ACTION_DELETE) # Increment metric counters model_deletes.labels(instance._meta.model_name).inc()
def test_webhooks_worker(self): request_id = uuid.uuid4() def dummy_send(_, request, **kwargs): """ A dummy implementation of Session.send() to be used for testing. Always returns a 200 HTTP response. """ webhook = Webhook.objects.get(type_create=True) signature = generate_signature(request.body, webhook.secret) # Validate the outgoing request headers self.assertEqual(request.headers['Content-Type'], webhook.http_content_type) self.assertEqual(request.headers['X-Hook-Signature'], signature) self.assertEqual(request.headers['X-Foo'], 'Bar') # Validate the outgoing request body body = json.loads(request.body) self.assertEqual(body['event'], 'created') self.assertEqual(body['timestamp'], job.args[4]) self.assertEqual(body['model'], 'site') self.assertEqual(body['username'], 'testuser') self.assertEqual(body['request_id'], str(request_id)) self.assertEqual(body['data']['name'], 'Site 1') return HttpResponse() # Enqueue a webhook for processing site = Site.objects.create(name='Site 1', slug='site-1') enqueue_webhooks( instance=site, user=self.user, request_id=request_id, action=ObjectChangeActionChoices.ACTION_CREATE ) # Retrieve the job from queue job = self.queue.jobs[0] # Patch the Session object with our dummy_send() method, then process the webhook for sending with patch.object(Session, 'send', dummy_send) as mock_send: process_webhook(*job.args)
def __call__(self, request): # Initialize an empty list to cache objects being saved. _thread_locals.changed_objects = [] # Assign a random unique ID to the request. This will be used to associate multiple object changes made during # the same request. request.id = uuid.uuid4() # Signals don't include the request context, so we're currying it into the pre_delete function ahead of time. record_object_deleted = curry(_record_object_deleted, request) # Connect our receivers to the post_save and pre_delete signals. post_save.connect(cache_changed_object, dispatch_uid='record_object_saved') post_delete.connect(record_object_deleted, dispatch_uid='record_object_deleted') # Process the request response = self.get_response(request) # Create records for any cached objects that were created/updated. for obj, action in _thread_locals.changed_objects: # Record the change if hasattr(obj, 'log_change'): obj.log_change(request.user, request.id, action) # Enqueue webhooks enqueue_webhooks(obj, request.user, request.id, action) # Housekeeping: 1% chance of clearing out expired ObjectChanges if _thread_locals.changed_objects and settings.CHANGELOG_RETENTION and random.randint(1, 100) == 1: cutoff = timezone.now() - timedelta(days=settings.CHANGELOG_RETENTION) purged_count, _ = ObjectChange.objects.filter( time__lt=cutoff ).delete() return response