Closes #2292: Remove the deprecated UserAction model

This commit is contained in:
Jeremy Stretch 2018-08-14 12:13:43 -04:00
parent 980d62d579
commit 5f66710fcd
11 changed files with 27 additions and 200 deletions

View File

@ -1,13 +1,8 @@
from django import forms
from django.contrib import admin
from django.utils.safestring import mark_safe
from utilities.forms import LaxURLField
from .constants import OBJECTCHANGE_ACTION_CREATE, OBJECTCHANGE_ACTION_DELETE, OBJECTCHANGE_ACTION_UPDATE
from .models import (
ConfigContext, CustomField, CustomFieldChoice, Graph, ExportTemplate, ObjectChange, TopologyMap, UserAction,
Webhook,
)
from .models import CustomField, CustomFieldChoice, Graph, ExportTemplate, TopologyMap, Webhook
def order_content_types(field):
@ -123,16 +118,3 @@ class TopologyMapAdmin(admin.ModelAdmin):
prepopulated_fields = {
'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)

View File

@ -8,7 +8,7 @@ from dcim.api.serializers import (
)
from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site
from extras.models import (
ConfigContext, ExportTemplate, Graph, ImageAttachment, ObjectChange, ReportResult, TopologyMap, UserAction,
ConfigContext, ExportTemplate, Graph, ImageAttachment, ObjectChange, ReportResult, TopologyMap,
)
from extras.constants import *
from tenancy.api.serializers import NestedTenantSerializer, NestedTenantGroupSerializer
@ -238,16 +238,3 @@ class ObjectChangeSerializer(serializers.ModelSerializer):
context = {'request': self.context['request']}
data = serializer(obj.changed_object, context=context).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']

View File

@ -41,8 +41,5 @@ router.register(r'reports', views.ReportViewSet, base_name='report')
# Change logging
router.register(r'object-changes', views.ObjectChangeViewSet)
# Recent activity
router.register(r'recent-activity', views.RecentActivityViewSet)
app_name = 'extras-api'
urlpatterns = router.urls

View File

@ -11,7 +11,6 @@ from taggit.models import Tag
from extras import filters
from extras.models import (
ConfigContext, CustomField, ExportTemplate, Graph, ImageAttachment, ObjectChange, ReportResult, TopologyMap,
UserAction,
)
from extras.reports import get_report, get_reports
from utilities.api import FieldChoicesViewSet, IsAuthenticatedOrLoginNotRequired, ModelViewSet
@ -230,16 +229,3 @@ class ObjectChangeViewSet(ReadOnlyModelViewSet):
queryset = ObjectChange.objects.select_related('user')
serializer_class = serializers.ObjectChangeSerializer
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

View File

@ -1,5 +1,4 @@
import django_filters
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from taggit.models import Tag
@ -7,7 +6,7 @@ from taggit.models import Tag
from dcim.models import DeviceRole, Platform, Region, Site
from tenancy.models import Tenant, TenantGroup
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):
@ -227,15 +226,3 @@ class ObjectChangeFilter(django_filters.FilterSet):
Q(user_name__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']

View 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',
),
]

View File

@ -12,7 +12,6 @@ from django.db.models import Q
from django.http import HttpResponse
from django.template import Template, Context
from django.urls import reverse
from django.utils.safestring import mark_safe
from dcim.constants import CONNECTION_STATUS_CONNECTED
from utilities.utils import foreground_color
@ -842,100 +841,3 @@ class ObjectChange(models.Model):
self.object_repr,
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 ''

View File

@ -21,9 +21,6 @@
<li{% ifequal active_tab "userkey" %} class="active"{% endifequal %}>
<a href="{% url 'user:userkey' %}">User Key</a>
</li>
<li{% ifequal active_tab "recent_activity" %} class="active"{% endifequal %}>
<a href="{% url 'user:recent_activity' %}">Recent Activity</a>
</li>
</ul>
</div>
<div class="col-sm-9 col-md-6">

View File

@ -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 %}

View File

@ -14,6 +14,5 @@ urlpatterns = [
url(r'^user-key/$', views.UserKeyView.as_view(), name='userkey'),
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'^recent-activity/$', views.RecentActivityView.as_view(), name='recent_activity'),
]

View File

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