This commit is contained in:
huzichunjohn 2017-10-13 14:59:28 +00:00 committed by GitHub
commit 5c77ec2d9f
7 changed files with 71 additions and 34 deletions

View File

@ -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:

View File

@ -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),
),
]

View File

@ -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()

View File

@ -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)

View File

@ -8,6 +8,7 @@
<tr>
<th>Time</th>
<th>Action</th>
<th>IP Address</th>
</tr>
</thead>
<tbody>
@ -15,6 +16,7 @@
<tr>
<td>{{ action.time|date:'SHORT_DATETIME_FORMAT' }}</td>
<td>{{ action.icon }} {{ action.message|safe }}</td>
<td>{% if action.ip_address %}{{ action.ip_address }}{% endif %}</td>
</tr>
{% endfor %}
</tbody>

View File

@ -37,3 +37,12 @@ def foreground_color(bg_color):
return '000000'
else:
return 'ffffff'
def get_ip_address(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip_address = x_forwarded_for.split(',')[0]
else:
ip_address = request.META.get('REMOTE_ADDR')
return ip_address

View File

@ -22,6 +22,7 @@ from django.views.generic import View
from extras.models import CustomField, CustomFieldValue, ExportTemplate, UserAction
from utilities.forms import BootstrapMixin, CSVDataField
from utilities.utils import get_ip_address
from .error_handlers import handle_protectederror
from .forms import ConfirmationForm
from .paginator import EnhancedPaginator
@ -210,9 +211,9 @@ class ObjectEditView(GetReturnURLMixin, View):
msg = '{} {}'.format(msg, escape(obj))
messages.success(request, mark_safe(msg))
if obj_created:
UserAction.objects.log_create(request.user, obj, msg)
UserAction.objects.log_create(request.user, obj, msg, get_ip_address(request))
else:
UserAction.objects.log_edit(request.user, obj, msg)
UserAction.objects.log_edit(request.user, obj, msg, get_ip_address(request))
if '_addanother' in request.POST:
return redirect(request.get_full_path())
@ -275,7 +276,7 @@ class ObjectDeleteView(GetReturnURLMixin, View):
msg = 'Deleted {} {}'.format(self.model._meta.verbose_name, obj)
messages.success(request, msg)
UserAction.objects.log_delete(request.user, obj, msg)
UserAction.objects.log_delete(request.user, obj, msg, get_ip_address(request))
return_url = form.cleaned_data.get('return_url')
if return_url is not None and is_safe_url(url=return_url, host=request.get_host()):
@ -355,7 +356,7 @@ class BulkCreateView(View):
# If we make it to this point, validation has succeeded on all new objects.
msg = "Added {} {}".format(len(new_objs), model._meta.verbose_name_plural)
messages.success(request, msg)
UserAction.objects.log_bulk_create(request.user, ContentType.objects.get_for_model(model), msg)
UserAction.objects.log_bulk_create(request.user, ContentType.objects.get_for_model(model), msg, get_ip_address(request))
if '_addanother' in request.POST:
return redirect(request.path)
@ -440,7 +441,7 @@ class BulkImportView(View):
if new_objs:
msg = 'Imported {} {}'.format(len(new_objs), new_objs[0]._meta.verbose_name_plural)
messages.success(request, msg)
UserAction.objects.log_import(request.user, ContentType.objects.get_for_model(new_objs[0]), msg)
UserAction.objects.log_import(request.user, ContentType.objects.get_for_model(new_objs[0]), msg, get_ip_address(request))
return render(request, "import_success.html", {
'table': obj_table,
@ -536,7 +537,7 @@ class BulkEditView(View):
if updated_count:
msg = 'Updated {} {}'.format(updated_count, self.cls._meta.verbose_name_plural)
messages.success(self.request, msg)
UserAction.objects.log_bulk_edit(request.user, ContentType.objects.get_for_model(self.cls), msg)
UserAction.objects.log_bulk_edit(request.user, ContentType.objects.get_for_model(self.cls), msg, get_ip_address(request))
return redirect(return_url)
else:
@ -671,7 +672,7 @@ class BulkDeleteView(View):
msg = 'Deleted {} {}'.format(deleted_count, self.cls._meta.verbose_name_plural)
messages.success(request, msg)
UserAction.objects.log_bulk_delete(request.user, ContentType.objects.get_for_model(self.cls), msg)
UserAction.objects.log_bulk_delete(request.user, ContentType.objects.get_for_model(self.cls), msg, get_ip_address(request))
return redirect(return_url)
else: