mirror of
https://github.com/netbox-community/netbox.git
synced 2025-12-19 03:42:25 -06:00
Implemented object add/edit/delete logging
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Graph, ExportTemplate, TopologyMap
|
||||
from .models import Graph, ExportTemplate, TopologyMap, UserAction
|
||||
|
||||
|
||||
@admin.register(Graph)
|
||||
@@ -19,3 +19,8 @@ class TopologyMapAdmin(admin.ModelAdmin):
|
||||
prepopulated_fields = {
|
||||
'slug': ['name'],
|
||||
}
|
||||
|
||||
|
||||
@admin.register(UserAction)
|
||||
class UserActionAdmin(admin.ModelAdmin):
|
||||
list_display = ['user', 'action', 'content_type', 'object_id', 'message']
|
||||
|
||||
34
netbox/extras/migrations/0004_useraction.py
Normal file
34
netbox/extras/migrations/0004_useraction.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.5 on 2016-05-23 18:16
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('extras', '0003_auto_20160412_1332'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='UserAction',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('time', models.DateTimeField(auto_now_add=True)),
|
||||
('object_id', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('action', models.PositiveSmallIntegerField(choices=[(1, b'created'), (2, b'imported'), (3, b'modified'), (4, b'bulk edited'), (5, b'deleted'), (6, b'bulk deleted')])),
|
||||
('message', models.TextField(blank=True)),
|
||||
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['-time'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,3 +1,4 @@
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import models
|
||||
from django.http import HttpResponse
|
||||
@@ -21,6 +22,21 @@ EXPORTTEMPLATE_MODELS = [
|
||||
'provider', 'circuit'
|
||||
]
|
||||
|
||||
ACTION_CREATE = 1
|
||||
ACTION_IMPORT = 2
|
||||
ACTION_EDIT = 3
|
||||
ACTION_BULK_EDIT = 4
|
||||
ACTION_DELETE = 5
|
||||
ACTION_BULK_DELETE = 6
|
||||
ACTION_CHOICES = (
|
||||
(ACTION_CREATE, 'created'),
|
||||
(ACTION_IMPORT, 'imported'),
|
||||
(ACTION_EDIT, 'modified'),
|
||||
(ACTION_BULK_EDIT, 'bulk edited'),
|
||||
(ACTION_DELETE, 'deleted'),
|
||||
(ACTION_BULK_DELETE, 'bulk deleted')
|
||||
)
|
||||
|
||||
|
||||
class Graph(models.Model):
|
||||
type = models.PositiveSmallIntegerField(choices=GRAPH_TYPE_CHOICES)
|
||||
@@ -93,3 +109,60 @@ class TopologyMap(models.Model):
|
||||
if not self.device_patterns:
|
||||
return None
|
||||
return [line.strip() for line in self.device_patterns.split('\n')]
|
||||
|
||||
|
||||
class UserActionManager(models.Manager):
|
||||
|
||||
# Actions affecting a single object
|
||||
def log_action(self, user, obj, action, message):
|
||||
self.model.objects.create(
|
||||
content_type = ContentType.objects.get_for_model(obj),
|
||||
object_id = obj.pk,
|
||||
user = user,
|
||||
action = action,
|
||||
message = message,
|
||||
)
|
||||
|
||||
def log_create(self, user, obj, message=''):
|
||||
self.log_action(user, obj, ACTION_CREATE, message)
|
||||
|
||||
def log_edit(self, user, obj, message=''):
|
||||
self.log_action(user, obj, ACTION_EDIT, message)
|
||||
|
||||
def log_delete(self, user, obj, message=''):
|
||||
self.log_action(user, obj, ACTION_DELETE, message)
|
||||
|
||||
# Actions affecting multiple objects
|
||||
def log_bulk_action(self, user, content_type, action, message):
|
||||
self.model.objects.create(
|
||||
content_type=content_type,
|
||||
user=user,
|
||||
action=action,
|
||||
message=message,
|
||||
)
|
||||
|
||||
def log_import(self, user, content_type, message=''):
|
||||
self.log_bulk_action(user, content_type, ACTION_IMPORT, message)
|
||||
|
||||
def log_bulk_edit(self, user, content_type, message=''):
|
||||
self.log_bulk_action(user, content_type, ACTION_BULK_EDIT, message)
|
||||
|
||||
def log_bulk_delete(self, user, content_type, message=''):
|
||||
self.log_bulk_action(user, content_type, ACTION_BULK_DELETE, message)
|
||||
|
||||
|
||||
class UserAction(models.Model):
|
||||
"""
|
||||
A record of an action (add, edit, or delete) performed on an object by a User.
|
||||
"""
|
||||
time = models.DateTimeField(auto_now_add=True, editable=False)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
|
||||
object_id = models.PositiveIntegerField(blank=True, null=True)
|
||||
action = models.PositiveSmallIntegerField(choices=ACTION_CHOICES)
|
||||
message = models.TextField(blank=True)
|
||||
|
||||
objects = UserActionManager()
|
||||
|
||||
class Meta:
|
||||
ordering = ['-time']
|
||||
|
||||
Reference in New Issue
Block a user