mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 12:06:53 -06:00
Closes #2292: Remove the deprecated UserAction model
This commit is contained in:
parent
980d62d579
commit
5f66710fcd
@ -1,13 +1,8 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.utils.safestring import mark_safe
|
|
||||||
|
|
||||||
from utilities.forms import LaxURLField
|
from utilities.forms import LaxURLField
|
||||||
from .constants import OBJECTCHANGE_ACTION_CREATE, OBJECTCHANGE_ACTION_DELETE, OBJECTCHANGE_ACTION_UPDATE
|
from .models import CustomField, CustomFieldChoice, Graph, ExportTemplate, TopologyMap, Webhook
|
||||||
from .models import (
|
|
||||||
ConfigContext, CustomField, CustomFieldChoice, Graph, ExportTemplate, ObjectChange, TopologyMap, UserAction,
|
|
||||||
Webhook,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def order_content_types(field):
|
def order_content_types(field):
|
||||||
@ -123,16 +118,3 @@ class TopologyMapAdmin(admin.ModelAdmin):
|
|||||||
prepopulated_fields = {
|
prepopulated_fields = {
|
||||||
'slug': ['name'],
|
'slug': ['name'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# User actions
|
|
||||||
#
|
|
||||||
|
|
||||||
@admin.register(UserAction)
|
|
||||||
class UserActionAdmin(admin.ModelAdmin):
|
|
||||||
actions = None
|
|
||||||
list_display = ['user', 'action', 'content_type', 'object_id', '_message']
|
|
||||||
|
|
||||||
def _message(self, obj):
|
|
||||||
return mark_safe(obj.message)
|
|
||||||
|
@ -8,7 +8,7 @@ from dcim.api.serializers import (
|
|||||||
)
|
)
|
||||||
from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site
|
from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site
|
||||||
from extras.models import (
|
from extras.models import (
|
||||||
ConfigContext, ExportTemplate, Graph, ImageAttachment, ObjectChange, ReportResult, TopologyMap, UserAction,
|
ConfigContext, ExportTemplate, Graph, ImageAttachment, ObjectChange, ReportResult, TopologyMap,
|
||||||
)
|
)
|
||||||
from extras.constants import *
|
from extras.constants import *
|
||||||
from tenancy.api.serializers import NestedTenantSerializer, NestedTenantGroupSerializer
|
from tenancy.api.serializers import NestedTenantSerializer, NestedTenantGroupSerializer
|
||||||
@ -238,16 +238,3 @@ class ObjectChangeSerializer(serializers.ModelSerializer):
|
|||||||
context = {'request': self.context['request']}
|
context = {'request': self.context['request']}
|
||||||
data = serializer(obj.changed_object, context=context).data
|
data = serializer(obj.changed_object, context=context).data
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# User actions
|
|
||||||
#
|
|
||||||
|
|
||||||
class UserActionSerializer(serializers.ModelSerializer):
|
|
||||||
user = NestedUserSerializer()
|
|
||||||
action = ChoiceField(choices=ACTION_CHOICES)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = UserAction
|
|
||||||
fields = ['id', 'time', 'user', 'action', 'message']
|
|
||||||
|
@ -41,8 +41,5 @@ router.register(r'reports', views.ReportViewSet, base_name='report')
|
|||||||
# Change logging
|
# Change logging
|
||||||
router.register(r'object-changes', views.ObjectChangeViewSet)
|
router.register(r'object-changes', views.ObjectChangeViewSet)
|
||||||
|
|
||||||
# Recent activity
|
|
||||||
router.register(r'recent-activity', views.RecentActivityViewSet)
|
|
||||||
|
|
||||||
app_name = 'extras-api'
|
app_name = 'extras-api'
|
||||||
urlpatterns = router.urls
|
urlpatterns = router.urls
|
||||||
|
@ -11,7 +11,6 @@ from taggit.models import Tag
|
|||||||
from extras import filters
|
from extras import filters
|
||||||
from extras.models import (
|
from extras.models import (
|
||||||
ConfigContext, CustomField, ExportTemplate, Graph, ImageAttachment, ObjectChange, ReportResult, TopologyMap,
|
ConfigContext, CustomField, ExportTemplate, Graph, ImageAttachment, ObjectChange, ReportResult, TopologyMap,
|
||||||
UserAction,
|
|
||||||
)
|
)
|
||||||
from extras.reports import get_report, get_reports
|
from extras.reports import get_report, get_reports
|
||||||
from utilities.api import FieldChoicesViewSet, IsAuthenticatedOrLoginNotRequired, ModelViewSet
|
from utilities.api import FieldChoicesViewSet, IsAuthenticatedOrLoginNotRequired, ModelViewSet
|
||||||
@ -230,16 +229,3 @@ class ObjectChangeViewSet(ReadOnlyModelViewSet):
|
|||||||
queryset = ObjectChange.objects.select_related('user')
|
queryset = ObjectChange.objects.select_related('user')
|
||||||
serializer_class = serializers.ObjectChangeSerializer
|
serializer_class = serializers.ObjectChangeSerializer
|
||||||
filter_class = filters.ObjectChangeFilter
|
filter_class = filters.ObjectChangeFilter
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# User activity
|
|
||||||
#
|
|
||||||
|
|
||||||
class RecentActivityViewSet(ReadOnlyModelViewSet):
|
|
||||||
"""
|
|
||||||
DEPRECATED: List all UserActions to provide a log of recent activity.
|
|
||||||
"""
|
|
||||||
queryset = UserAction.objects.all()
|
|
||||||
serializer_class = serializers.UserActionSerializer
|
|
||||||
filter_class = filters.UserActionFilter
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import django_filters
|
import django_filters
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from taggit.models import Tag
|
from taggit.models import Tag
|
||||||
@ -7,7 +6,7 @@ from taggit.models import Tag
|
|||||||
from dcim.models import DeviceRole, Platform, Region, Site
|
from dcim.models import DeviceRole, Platform, Region, Site
|
||||||
from tenancy.models import Tenant, TenantGroup
|
from tenancy.models import Tenant, TenantGroup
|
||||||
from .constants import CF_FILTER_DISABLED, CF_FILTER_EXACT, CF_TYPE_BOOLEAN, CF_TYPE_SELECT
|
from .constants import CF_FILTER_DISABLED, CF_FILTER_EXACT, CF_TYPE_BOOLEAN, CF_TYPE_SELECT
|
||||||
from .models import ConfigContext, CustomField, Graph, ExportTemplate, ObjectChange, TopologyMap, UserAction
|
from .models import ConfigContext, CustomField, Graph, ExportTemplate, ObjectChange, TopologyMap
|
||||||
|
|
||||||
|
|
||||||
class CustomFieldFilter(django_filters.Filter):
|
class CustomFieldFilter(django_filters.Filter):
|
||||||
@ -227,15 +226,3 @@ class ObjectChangeFilter(django_filters.FilterSet):
|
|||||||
Q(user_name__icontains=value) |
|
Q(user_name__icontains=value) |
|
||||||
Q(object_repr__icontains=value)
|
Q(object_repr__icontains=value)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UserActionFilter(django_filters.FilterSet):
|
|
||||||
username = django_filters.ModelMultipleChoiceFilter(
|
|
||||||
name='user__username',
|
|
||||||
queryset=User.objects.all(),
|
|
||||||
to_field_name='username',
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = UserAction
|
|
||||||
fields = ['user']
|
|
||||||
|
24
netbox/extras/migrations/0015_remove_useraction.py
Normal file
24
netbox/extras/migrations/0015_remove_useraction.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 2.0.8 on 2018-08-14 16:10
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('extras', '0014_configcontexts'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='useraction',
|
||||||
|
name='content_type',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='useraction',
|
||||||
|
name='user',
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='UserAction',
|
||||||
|
),
|
||||||
|
]
|
@ -12,7 +12,6 @@ from django.db.models import Q
|
|||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.template import Template, Context
|
from django.template import Template, Context
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.safestring import mark_safe
|
|
||||||
|
|
||||||
from dcim.constants import CONNECTION_STATUS_CONNECTED
|
from dcim.constants import CONNECTION_STATUS_CONNECTED
|
||||||
from utilities.utils import foreground_color
|
from utilities.utils import foreground_color
|
||||||
@ -842,100 +841,3 @@ class ObjectChange(models.Model):
|
|||||||
self.object_repr,
|
self.object_repr,
|
||||||
self.object_data,
|
self.object_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# User actions
|
|
||||||
#
|
|
||||||
|
|
||||||
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_create(self, user, content_type, message=''):
|
|
||||||
self.log_bulk_action(user, content_type, ACTION_BULK_CREATE, 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)
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: Remove UserAction, which has been replaced by ObjectChange.
|
|
||||||
class UserAction(models.Model):
|
|
||||||
"""
|
|
||||||
DEPRECATED: 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(
|
|
||||||
to=User,
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
related_name='actions'
|
|
||||||
)
|
|
||||||
content_type = models.ForeignKey(
|
|
||||||
to=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']
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.message:
|
|
||||||
return '{} {}'.format(self.user, self.message)
|
|
||||||
return '{} {} {}'.format(self.user, self.get_action_display(), self.content_type)
|
|
||||||
|
|
||||||
def icon(self):
|
|
||||||
if self.action in [ACTION_CREATE, ACTION_BULK_CREATE, ACTION_IMPORT]:
|
|
||||||
return mark_safe('<i class="glyphicon glyphicon-plus text-success"></i>')
|
|
||||||
elif self.action in [ACTION_EDIT, ACTION_BULK_EDIT]:
|
|
||||||
return mark_safe('<i class="glyphicon glyphicon-pencil text-warning"></i>')
|
|
||||||
elif self.action in [ACTION_DELETE, ACTION_BULK_DELETE]:
|
|
||||||
return mark_safe('<i class="glyphicon glyphicon-remove text-danger"></i>')
|
|
||||||
else:
|
|
||||||
return ''
|
|
||||||
|
@ -21,9 +21,6 @@
|
|||||||
<li{% ifequal active_tab "userkey" %} class="active"{% endifequal %}>
|
<li{% ifequal active_tab "userkey" %} class="active"{% endifequal %}>
|
||||||
<a href="{% url 'user:userkey' %}">User Key</a>
|
<a href="{% url 'user:userkey' %}">User Key</a>
|
||||||
</li>
|
</li>
|
||||||
<li{% ifequal active_tab "recent_activity" %} class="active"{% endifequal %}>
|
|
||||||
<a href="{% url 'user:recent_activity' %}">Recent Activity</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-9 col-md-6">
|
<div class="col-sm-9 col-md-6">
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
{% extends 'users/_user.html' %}
|
|
||||||
|
|
||||||
{% block title %}Recent Activity{% endblock %}
|
|
||||||
|
|
||||||
{% block usercontent %}
|
|
||||||
<table class="table table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Time</th>
|
|
||||||
<th>Action</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for action in recent_activity %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ action.time|date:'SHORT_DATETIME_FORMAT' }}</td>
|
|
||||||
<td>{{ action.icon }} {{ action.message|safe }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{% endblock %}
|
|
@ -14,6 +14,5 @@ urlpatterns = [
|
|||||||
url(r'^user-key/$', views.UserKeyView.as_view(), name='userkey'),
|
url(r'^user-key/$', views.UserKeyView.as_view(), name='userkey'),
|
||||||
url(r'^user-key/edit/$', views.UserKeyEditView.as_view(), name='userkey_edit'),
|
url(r'^user-key/edit/$', views.UserKeyEditView.as_view(), name='userkey_edit'),
|
||||||
url(r'^session-key/delete/$', views.SessionKeyDeleteView.as_view(), name='sessionkey_delete'),
|
url(r'^session-key/delete/$', views.SessionKeyDeleteView.as_view(), name='sessionkey_delete'),
|
||||||
url(r'^recent-activity/$', views.RecentActivityView.as_view(), name='recent_activity'),
|
|
||||||
|
|
||||||
]
|
]
|
||||||
|
@ -196,18 +196,6 @@ class SessionKeyDeleteView(LoginRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(login_required, name='dispatch')
|
|
||||||
class RecentActivityView(View):
|
|
||||||
template_name = 'users/recent_activity.html'
|
|
||||||
|
|
||||||
def get(self, request):
|
|
||||||
|
|
||||||
return render(request, self.template_name, {
|
|
||||||
'recent_activity': request.user.actions.all()[:50],
|
|
||||||
'active_tab': 'recent_activity',
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# API tokens
|
# API tokens
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user