mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-06 12:07:30 -06:00
Compare commits
4 Commits
20923-dcim
...
b0f7024dcb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0f7024dcb | ||
|
|
f0507d00bf | ||
|
|
77b389f105 | ||
|
|
605c61ef5b |
@@ -3,7 +3,7 @@ from threading import local
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
||||
from django.db.models import CASCADE
|
||||
from django.db.models import CASCADE, RESTRICT
|
||||
from django.db.models.fields.reverse_related import ManyToManyRel, ManyToOneRel
|
||||
from django.db.models.signals import m2m_changed, post_migrate, post_save, pre_delete
|
||||
from django.dispatch import receiver, Signal
|
||||
@@ -47,6 +47,7 @@ clear_events = Signal()
|
||||
# Object types
|
||||
#
|
||||
|
||||
|
||||
@receiver(post_migrate)
|
||||
def update_object_types(sender, **kwargs):
|
||||
"""
|
||||
@@ -133,7 +134,7 @@ def handle_changed_object(sender, instance, **kwargs):
|
||||
prev_change := ObjectChange.objects.filter(
|
||||
changed_object_type=ContentType.objects.get_for_model(instance),
|
||||
changed_object_id=instance.pk,
|
||||
request_id=request.id
|
||||
request_id=request.id,
|
||||
).first()
|
||||
):
|
||||
prev_change.postchange_data = objectchange.postchange_data
|
||||
@@ -172,9 +173,7 @@ def handle_deleted_object(sender, instance, **kwargs):
|
||||
try:
|
||||
run_validators(instance, validators)
|
||||
except ValidationError as e:
|
||||
raise AbortRequest(
|
||||
_("Deletion is prevented by a protection rule: {message}").format(message=e)
|
||||
)
|
||||
raise AbortRequest(_("Deletion is prevented by a protection rule: {message}").format(message=e))
|
||||
|
||||
# Get the current request, or bail if not set
|
||||
request = current_request.get()
|
||||
@@ -221,7 +220,12 @@ def handle_deleted_object(sender, instance, **kwargs):
|
||||
obj.snapshot() # Ensure the change record includes the "before" state
|
||||
if type(relation) is ManyToManyRel:
|
||||
getattr(obj, related_field_name).remove(instance)
|
||||
elif type(relation) is ManyToOneRel and relation.null and relation.on_delete is not CASCADE:
|
||||
elif (
|
||||
type(relation) is ManyToOneRel
|
||||
and relation.null
|
||||
and relation.on_delete is not CASCADE
|
||||
and relation.on_delete is not RESTRICT
|
||||
):
|
||||
setattr(obj, related_field_name, None)
|
||||
obj.save()
|
||||
|
||||
@@ -256,6 +260,7 @@ def clear_events_queue(sender, **kwargs):
|
||||
# DataSource handlers
|
||||
#
|
||||
|
||||
|
||||
@receiver(post_save, sender=DataSource)
|
||||
def enqueue_sync_job(instance, created, **kwargs):
|
||||
"""
|
||||
@@ -267,9 +272,10 @@ def enqueue_sync_job(instance, created, **kwargs):
|
||||
SyncDataSourceJob.enqueue_once(instance, interval=instance.sync_interval)
|
||||
elif not created:
|
||||
# Delete any previously scheduled recurring jobs for this DataSource
|
||||
for job in SyncDataSourceJob.get_jobs(instance).defer('data').filter(
|
||||
interval__isnull=False,
|
||||
status=JobStatusChoices.STATUS_SCHEDULED
|
||||
for job in (
|
||||
SyncDataSourceJob.get_jobs(instance)
|
||||
.defer('data')
|
||||
.filter(interval__isnull=False, status=JobStatusChoices.STATUS_SCHEDULED)
|
||||
):
|
||||
# Call delete() per instance to ensure the associated background task is deleted as well
|
||||
job.delete()
|
||||
|
||||
@@ -119,7 +119,9 @@ def process_event_rules(event_rules, object_type, event_type, data, username=Non
|
||||
if snapshots:
|
||||
params["snapshots"] = snapshots
|
||||
if request:
|
||||
params["request"] = copy_safe_request(request)
|
||||
# Exclude FILES - webhooks don't need uploaded files,
|
||||
# which can cause pickle errors with Pillow.
|
||||
params["request"] = copy_safe_request(request, include_files=False)
|
||||
|
||||
# Enqueue the task
|
||||
rq_queue.enqueue(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,27 +35,34 @@ class NetBoxFakeRequest:
|
||||
# Utility functions
|
||||
#
|
||||
|
||||
def copy_safe_request(request):
|
||||
def copy_safe_request(request, include_files=True):
|
||||
"""
|
||||
Copy selected attributes from a request object into a new fake request object. This is needed in places where
|
||||
thread safe pickling of the useful request data is needed.
|
||||
|
||||
Args:
|
||||
request: The original request object
|
||||
include_files: Whether to include request.FILES.
|
||||
"""
|
||||
meta = {
|
||||
k: request.META[k]
|
||||
for k in HTTP_REQUEST_META_SAFE_COPY
|
||||
if k in request.META and isinstance(request.META[k], str)
|
||||
}
|
||||
return NetBoxFakeRequest({
|
||||
data = {
|
||||
'META': meta,
|
||||
'COOKIES': request.COOKIES,
|
||||
'POST': request.POST,
|
||||
'GET': request.GET,
|
||||
'FILES': request.FILES,
|
||||
'user': request.user,
|
||||
'method': request.method,
|
||||
'path': request.path,
|
||||
'id': getattr(request, 'id', None), # UUID assigned by middleware
|
||||
})
|
||||
}
|
||||
if include_files:
|
||||
data['FILES'] = request.FILES
|
||||
|
||||
return NetBoxFakeRequest(data)
|
||||
|
||||
|
||||
def get_client_ip(request, additional_headers=()):
|
||||
|
||||
Reference in New Issue
Block a user