1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Record a unique request ID with each ObjectChange

This commit is contained in:
Jeremy Stretch
2018-06-19 15:45:15 -04:00
parent 23f91274d6
commit a8b11e45c1
6 changed files with 20 additions and 8 deletions

View File

@ -132,12 +132,12 @@ class TopologyMapAdmin(admin.ModelAdmin):
@admin.register(ObjectChange) @admin.register(ObjectChange)
class ObjectChangeAdmin(admin.ModelAdmin): class ObjectChangeAdmin(admin.ModelAdmin):
actions = None actions = None
fields = ['time', 'content_type', 'display_object', 'action', 'display_user', 'object_data'] fields = ['time', 'content_type', 'display_object', 'action', 'display_user', 'request_id', 'object_data']
list_display = ['time', 'content_type', 'display_object', 'display_action', 'display_user'] list_display = ['time', 'content_type', 'display_object', 'display_action', 'display_user', 'request_id']
list_filter = ['time', 'action', 'user__username'] list_filter = ['time', 'action', 'user__username']
list_select_related = ['content_type', 'user'] list_select_related = ['content_type', 'user']
readonly_fields = fields readonly_fields = fields
search_fields = ['user_name', 'object_repr'] search_fields = ['user_name', 'object_repr', 'request_id']
def has_add_permission(self, request): def has_add_permission(self, request):
return False return False

View File

@ -167,12 +167,16 @@ class ObjectChangeSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = ObjectChange model = ObjectChange
fields = ['id', 'time', 'user', 'user_name', 'action', 'content_type', 'changed_object', 'object_data'] fields = [
'id', 'time', 'user', 'user_name', 'request_id', 'action', 'content_type', 'changed_object', 'object_data',
]
def get_changed_object(self, obj): def get_changed_object(self, obj):
""" """
Serialize a nested representation of the changed object. Serialize a nested representation of the changed object.
""" """
if obj.changed_object is None:
return None
serializer = get_serializer_for_model(obj.changed_object, prefix='Nested') serializer = get_serializer_for_model(obj.changed_object, prefix='Nested')
if serializer is None: if serializer is None:
return obj.object_repr return obj.object_repr

View File

@ -132,7 +132,7 @@ class ObjectChangeFilter(django_filters.FilterSet):
class Meta: class Meta:
model = ObjectChange model = ObjectChange
fields = ['user_name', 'action', 'content_type', 'object_repr'] fields = ['user', 'user_name', 'request_id', 'action', 'content_type', 'object_repr']
def search(self, queryset, name, value): def search(self, queryset, name, value):
if not value.strip(): if not value.strip():

View File

@ -1,6 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import json import json
import uuid
from django.core.serializers import serialize from django.core.serializers import serialize
from django.db.models.signals import post_delete, post_save from django.db.models.signals import post_delete, post_save
@ -11,7 +12,7 @@ from .constants import OBJECTCHANGE_ACTION_CREATE, OBJECTCHANGE_ACTION_DELETE, O
from .models import ObjectChange from .models import ObjectChange
def record_object_change(user, instance, **kwargs): def record_object_change(user, request_id, instance, **kwargs):
""" """
Create an ObjectChange in response to an object being created or deleted. Create an ObjectChange in response to an object being created or deleted.
""" """
@ -31,6 +32,7 @@ def record_object_change(user, instance, **kwargs):
ObjectChange( ObjectChange(
user=user, user=user,
request_id=request_id,
changed_object=instance, changed_object=instance,
action=action, action=action,
object_data=object_data object_data=object_data
@ -53,9 +55,11 @@ class ChangeLoggingMiddleware(object):
# detail, see https://stackoverflow.com/questions/26240832/ # detail, see https://stackoverflow.com/questions/26240832/
user = SimpleLazyObject(lambda: get_user(request)) user = SimpleLazyObject(lambda: get_user(request))
request_id = uuid.uuid4()
# Django doesn't provide any request context with the post_save/post_delete signals, so we curry # Django doesn't provide any request context with the post_save/post_delete signals, so we curry
# record_object_change() to include the user associated with the current request. # record_object_change() to include the user associated with the current request.
_record_object_change = curry(record_object_change, user) _record_object_change = curry(record_object_change, user, request_id)
post_save.connect(_record_object_change, dispatch_uid='record_object_saved') post_save.connect(_record_object_change, dispatch_uid='record_object_saved')
post_delete.connect(_record_object_change, dispatch_uid='record_object_deleted') post_delete.connect(_record_object_change, dispatch_uid='record_object_deleted')

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-06-13 20:05 # Generated by Django 1.11.12 on 2018-06-19 19:34
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
@ -23,6 +23,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('time', models.DateTimeField(auto_now_add=True)), ('time', models.DateTimeField(auto_now_add=True)),
('user_name', models.CharField(editable=False, max_length=150)), ('user_name', models.CharField(editable=False, max_length=150)),
('request_id', models.UUIDField(editable=False)),
('action', models.PositiveSmallIntegerField(choices=[(1, 'Created'), (2, 'Updated'), (3, 'Deleted')])), ('action', models.PositiveSmallIntegerField(choices=[(1, 'Created'), (2, 'Updated'), (3, 'Deleted')])),
('object_id', models.PositiveIntegerField()), ('object_id', models.PositiveIntegerField()),
('object_repr', models.CharField(editable=False, max_length=200)), ('object_repr', models.CharField(editable=False, max_length=200)),

View File

@ -681,6 +681,9 @@ class ObjectChange(models.Model):
max_length=150, max_length=150,
editable=False editable=False
) )
request_id = models.UUIDField(
editable=False
)
action = models.PositiveSmallIntegerField( action = models.PositiveSmallIntegerField(
choices=OBJECTCHANGE_ACTION_CHOICES choices=OBJECTCHANGE_ACTION_CHOICES
) )