diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 387af4b61..49b1af969 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -25,6 +25,7 @@ from utilities.views import ( BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ComponentDeleteView, ComponentEditView, ObjectDeleteView, ObjectEditView, ObjectListView, ) +from utilities.utils import get_ip_address from . import filters, forms, tables from .models import ( CONNECTION_STATUS_CONNECTED, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, @@ -1030,7 +1031,7 @@ def consoleport_connect(request, pk): escape(consoleport.cs_port.name), ) messages.success(request, mark_safe(msg)) - UserAction.objects.log_edit(request.user, consoleport, msg) + UserAction.objects.log_edit(request.user, consoleport, msg, get_ip_address(request)) return redirect('dcim:device', pk=consoleport.device.pk) else: @@ -1075,7 +1076,7 @@ def consoleport_disconnect(request, pk): escape(cs_port.name), ) messages.success(request, mark_safe(msg)) - UserAction.objects.log_edit(request.user, consoleport, msg) + UserAction.objects.log_edit(request.user, consoleport, msg, get_ip_address(request)) return redirect('dcim:device', pk=consoleport.device.pk) else: @@ -1150,7 +1151,7 @@ def consoleserverport_connect(request, pk): escape(consoleserverport.name), ) messages.success(request, mark_safe(msg)) - UserAction.objects.log_edit(request.user, consoleport, msg) + UserAction.objects.log_edit(request.user, consoleport, msg, get_ip_address(request)) return redirect('dcim:device', pk=consoleserverport.device.pk) else: @@ -1195,7 +1196,7 @@ def consoleserverport_disconnect(request, pk): escape(consoleserverport.name), ) messages.success(request, mark_safe(msg)) - UserAction.objects.log_edit(request.user, consoleport, msg) + UserAction.objects.log_edit(request.user, consoleport, msg, get_ip_address(request)) return redirect('dcim:device', pk=consoleserverport.device.pk) else: @@ -1269,7 +1270,7 @@ def powerport_connect(request, pk): escape(powerport.power_outlet.name), ) messages.success(request, mark_safe(msg)) - UserAction.objects.log_edit(request.user, powerport, msg) + UserAction.objects.log_edit(request.user, powerport, msg, get_ip_address(request)) return redirect('dcim:device', pk=powerport.device.pk) else: @@ -1314,7 +1315,7 @@ def powerport_disconnect(request, pk): escape(power_outlet.name), ) messages.success(request, mark_safe(msg)) - UserAction.objects.log_edit(request.user, powerport, msg) + UserAction.objects.log_edit(request.user, powerport, msg, get_ip_address(request)) return redirect('dcim:device', pk=powerport.device.pk) else: @@ -1389,7 +1390,7 @@ def poweroutlet_connect(request, pk): escape(poweroutlet.name), ) messages.success(request, mark_safe(msg)) - UserAction.objects.log_edit(request.user, powerport, msg) + UserAction.objects.log_edit(request.user, powerport, msg, get_ip_address(request)) return redirect('dcim:device', pk=poweroutlet.device.pk) else: @@ -1434,7 +1435,7 @@ def poweroutlet_disconnect(request, pk): escape(poweroutlet.name), ) messages.success(request, mark_safe(msg)) - UserAction.objects.log_edit(request.user, powerport, msg) + UserAction.objects.log_edit(request.user, powerport, msg, get_ip_address(request)) return redirect('dcim:device', pk=poweroutlet.device.pk) else: @@ -1709,7 +1710,7 @@ def interfaceconnection_add(request, pk): escape(interfaceconnection.interface_b.name), ) messages.success(request, mark_safe(msg)) - UserAction.objects.log_edit(request.user, interfaceconnection, msg) + UserAction.objects.log_edit(request.user, interfaceconnection, msg, get_ip_address(request)) if '_addanother' in request.POST: base_url = reverse('dcim:interfaceconnection_add', kwargs={'pk': device.pk}) @@ -1757,7 +1758,7 @@ def interfaceconnection_delete(request, pk): escape(interfaceconnection.interface_b.name), ) messages.success(request, mark_safe(msg)) - UserAction.objects.log_edit(request.user, interfaceconnection, msg) + UserAction.objects.log_edit(request.user, interfaceconnection, msg, get_ip_address(request)) if form.cleaned_data['device']: return redirect('dcim:device', pk=form.cleaned_data['device'].pk) else: diff --git a/netbox/extras/migrations/0009_useraction_ip_address.py b/netbox/extras/migrations/0009_useraction_ip_address.py new file mode 100755 index 000000000..c492449b3 --- /dev/null +++ b/netbox/extras/migrations/0009_useraction_ip_address.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.1 on 2017-10-12 07:53 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0008_reports'), + ] + + operations = [ + migrations.AddField( + model_name='useraction', + name='ip_address', + field=models.GenericIPAddressField(null=True, unpack_ipv4=True), + ), + ] diff --git a/netbox/extras/models.py b/netbox/extras/models.py index 5181e88e9..ea7dad614 100644 --- a/netbox/extras/models.py +++ b/netbox/extras/models.py @@ -414,44 +414,46 @@ class ReportResult(models.Model): class UserActionManager(models.Manager): # Actions affecting a single object - def log_action(self, user, obj, action, message): + def log_action(self, user, obj, action, message, ip_address): self.model.objects.create( content_type=ContentType.objects.get_for_model(obj), object_id=obj.pk, user=user, action=action, message=message, + ip_address=ip_address, ) - def log_create(self, user, obj, message=''): - self.log_action(user, obj, ACTION_CREATE, message) + def log_create(self, user, obj, message, ip_address): + self.log_action(user, obj, ACTION_CREATE, message, ip_address) - def log_edit(self, user, obj, message=''): - self.log_action(user, obj, ACTION_EDIT, message) + def log_edit(self, user, obj, message, ip_address): + self.log_action(user, obj, ACTION_EDIT, message, ip_address) - def log_delete(self, user, obj, message=''): - self.log_action(user, obj, ACTION_DELETE, message) + def log_delete(self, user, obj, message, ip_address): + self.log_action(user, obj, ACTION_DELETE, message, ip_address) # Actions affecting multiple objects - def log_bulk_action(self, user, content_type, action, message): + def log_bulk_action(self, user, content_type, action, message, ip_address): self.model.objects.create( content_type=content_type, user=user, action=action, message=message, + ip_address=ip_address, ) - def log_import(self, user, content_type, message=''): - self.log_bulk_action(user, content_type, ACTION_IMPORT, message) + def log_import(self, user, content_type, message, ip_address): + self.log_bulk_action(user, content_type, ACTION_IMPORT, message, ip_address) - def log_bulk_create(self, user, content_type, message=''): - self.log_bulk_action(user, content_type, ACTION_BULK_CREATE, message) + def log_bulk_create(self, user, content_type, message, ip_address): + self.log_bulk_action(user, content_type, ACTION_BULK_CREATE, message, ip_address) - def log_bulk_edit(self, user, content_type, message=''): - self.log_bulk_action(user, content_type, ACTION_BULK_EDIT, message) + def log_bulk_edit(self, user, content_type, message, ip_address): + self.log_bulk_action(user, content_type, ACTION_BULK_EDIT, message, ip_address) - def log_bulk_delete(self, user, content_type, message=''): - self.log_bulk_action(user, content_type, ACTION_BULK_DELETE, message) + def log_bulk_delete(self, user, content_type, message, ip_address): + self.log_bulk_action(user, content_type, ACTION_BULK_DELETE, message, ip_address) @python_2_unicode_compatible @@ -465,6 +467,7 @@ class UserAction(models.Model): object_id = models.PositiveIntegerField(blank=True, null=True) action = models.PositiveSmallIntegerField(choices=ACTION_CHOICES) message = models.TextField(blank=True) + ip_address = models.GenericIPAddressField(null=True, unpack_ipv4=True) objects = UserActionManager() diff --git a/netbox/extras/views.py b/netbox/extras/views.py index e92b28187..a1f10db16 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -9,6 +9,7 @@ from django.views.generic import View from utilities.forms import ConfirmationForm from utilities.views import ObjectDeleteView, ObjectEditView +from utilities.utils import get_ip_address from .forms import ImageAttachmentForm from .models import ImageAttachment, ReportResult, UserAction from .reports import get_report, get_reports @@ -113,6 +114,6 @@ class ReportRunView(PermissionRequiredMixin, View): result = 'failed' if report.failed else 'passed' msg = "Ran report {} ({})".format(report.full_name, result) messages.success(request, mark_safe(msg)) - UserAction.objects.log_create(request.user, report.result, msg) + UserAction.objects.log_create(request.user, report.result, msg, get_ip_address(request)) return redirect('extras:report', name=report.full_name) diff --git a/netbox/templates/users/recent_activity.html b/netbox/templates/users/recent_activity.html index 92933d78b..6f05ea7db 100644 --- a/netbox/templates/users/recent_activity.html +++ b/netbox/templates/users/recent_activity.html @@ -8,6 +8,7 @@