Skip to content

Commit

Permalink
Add "Purge" action to remove all rows in EasyAudit tables
Browse files Browse the repository at this point in the history
  • Loading branch information
morlandi committed Nov 12, 2017
1 parent 5866577 commit b968902
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 39 deletions.
51 changes: 12 additions & 39 deletions easyaudit/admin.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,16 @@
import json
from django.contrib import admin
from django.core import urlresolvers
from django.contrib.auth import get_user_model
from django.utils.safestring import mark_safe
from . import models, settings


def get_user_link(user):
"""
Helper to get admin url for given user
"""
if user is None:
return '-'
try:
user_model = get_user_model()
url = urlresolvers.reverse("admin:%s_%s_change" % (
user_model._meta.app_label,
user_model._meta.model_name,
), args=(user.id,))
html = '<a href="%s">%s</a>' % (url, str(user))
except:
html = str(user)
return html
from . import settings
from .models import CRUDEvent
from .models import LoginEvent
from .models import RequestEvent
from .admin_helpers import EasyAuditModelAdmin


# CRUD events
class CRUDEventAdmin(admin.ModelAdmin):
class CRUDEventAdmin(EasyAuditModelAdmin):
list_display = ['get_event_type_display', 'content_type', 'object_id', 'object_repr_link', 'user_link', 'datetime']
date_hierarchy = 'datetime'
list_filter = ['event_type', 'content_type', 'user', 'datetime', ]
Expand All @@ -34,7 +19,7 @@ class CRUDEventAdmin(admin.ModelAdmin):
'object_json_repr_prettified', 'object_json_repr', 'user', 'user_pk_as_string', 'datetime', ]

def object_repr_link(self, obj):
if obj.event_type == models.CRUDEvent.DELETE:
if obj.event_type == CRUDEvent.DELETE:
html = obj.object_repr
else:
try:
Expand All @@ -48,10 +33,6 @@ def object_repr_link(self, obj):
return mark_safe(html)
object_repr_link.short_description = 'object repr'

def user_link(self, obj):
return mark_safe(get_user_link(obj.user))
user_link.short_description = 'user'

def object_json_repr_prettified(self, obj):
try:
data = json.loads(obj.object_json_repr)
Expand All @@ -63,38 +44,30 @@ def object_json_repr_prettified(self, obj):


if settings.ADMIN_SHOW_MODEL_EVENTS:
admin.site.register(models.CRUDEvent, CRUDEventAdmin)
admin.site.register(CRUDEvent, CRUDEventAdmin)


# Login events
class LoginEventAdmin(admin.ModelAdmin):
class LoginEventAdmin(EasyAuditModelAdmin):
list_display = ['datetime', 'get_login_type_display', 'user_link', 'username', 'remote_ip']
date_hierarchy = 'datetime'
list_filter = ['login_type', 'user', 'datetime', ]
search_fields = ['=remote_ip', 'username', ]
readonly_fields = ['login_type', 'username', 'user', 'remote_ip', 'datetime', ]

def user_link(self, obj):
return mark_safe(get_user_link(obj.user))
user_link.short_description = 'user'


if settings.ADMIN_SHOW_AUTH_EVENTS:
admin.site.register(models.LoginEvent, LoginEventAdmin)
admin.site.register(LoginEvent, LoginEventAdmin)


# Request events
class RequestEventAdmin(admin.ModelAdmin):
class RequestEventAdmin(EasyAuditModelAdmin):
list_display = ['datetime', 'user_link', 'method', 'url', 'remote_ip']
date_hierarchy = 'datetime'
list_filter = ['method', 'user', 'datetime', ]
search_fields = ['=remote_ip', 'username', 'url', 'query_string', ]
readonly_fields = ['url', 'method', 'query_string', 'user', 'remote_ip', 'datetime', ]

def user_link(self, obj):
return mark_safe(get_user_link(obj.user))
user_link.short_description = 'user'


if settings.ADMIN_SHOW_REQUEST_EVENTS:
admin.site.register(models.RequestEvent, RequestEventAdmin)
admin.site.register(RequestEvent, RequestEventAdmin)
87 changes: 87 additions & 0 deletions easyaudit/admin_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from django.contrib import admin
from django.core import urlresolvers
from django.core.exceptions import PermissionDenied
from django.contrib.auth import get_user_model
from django.shortcuts import render
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext_lazy as _
from django.contrib import messages
from django.conf.urls import url
from django.utils.safestring import mark_safe


class EasyAuditModelAdmin(admin.ModelAdmin):

def user_link(self, obj):
#return mark_safe(get_user_link(obj.user))
user = obj.user
if user is None:
return '-'
try:
user_model = get_user_model()
url = urlresolvers.reverse("admin:%s_%s_change" % (
user_model._meta.app_label,
user_model._meta.model_name,
), args=(user.id,))
html = '<a href="%s">%s</a>' % (url, str(user))
except:
html = str(user)
return mark_safe(html)
user_link.short_description = 'user'

def has_add_permission(self, request, obj=None):
return False

def get_urls(self):
info = self.model._meta.app_label, self.model._meta.model_name
urls = super(EasyAuditModelAdmin, self).get_urls()
my_urls = [
url(r'^purge/$', self.admin_site.admin_view(self.purge), {}, name="%s_%s_purge" % info),
]
return my_urls + urls

def purge(self, request):
return self.purge_objects(request)

# Helper view to remove all rows in a table
def purge_objects(self, request):
"""
Removes all objects in this table.
This action first displays a confirmation page;
next, it deletes all objects and redirects back to the change list.
"""
modeladmin = self
opts = modeladmin.model._meta

# Check that the user has delete permission for the actual model
if not request.user.is_superuser:
raise PermissionDenied
if not modeladmin.has_delete_permission(request):
raise PermissionDenied

# If the user has already confirmed or cancelled the deletion,
# (eventually) do the deletion and return to the change list view again.
if request.method == 'POST':
if 'btn-confirm' in request.POST:
try:
modeladmin.model.objects.all().delete()
modeladmin.message_user(request, _("Successfully removed all objects"), messages.SUCCESS);
except Exception as e:
modeladmin.message_user(request, _(u'ERROR') + ': %r' % e, messages.ERROR)
else:
modeladmin.message_user(request, _("Action cancelled by user"), messages.SUCCESS);
return HttpResponseRedirect(reverse('admin:%s_%s_changelist' % (opts.app_label, opts.model_name)))

context = {
"title": _("Purge all %s ... are you sure?") % opts.verbose_name_plural,
"opts": opts,
"app_label": opts.app_label,
}

# Display the confirmation page
return render(
request,
'admin/easyaudit/purge_confirmation.html',
context
)
15 changes: 15 additions & 0 deletions easyaudit/templates/admin/easyaudit/change_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{% extends "admin/change_list.html" %}
{% load i18n %}

{% block object-tools-items %}
{{ block.super }}
{% if request.user.is_superuser %}
<li>
{% with purge_url='admin:'|add:cl.opts.app_label|add:'_'|add:cl.opts.model_name|add:'_purge' %}
<a href="{% url purge_url %}" class="deletelink">
{% blocktrans with cl.opts.verbose_name_plural as name %}Purge {{ name }}{% endblocktrans %}
</a>
{% endwith %}
</li>
{% endif %}
{% endblock %}
31 changes: 31 additions & 0 deletions easyaudit/templates/admin/easyaudit/purge_confirmation.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_urls static admin_list %}


{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label=app_label %}">{{ app_label|capfirst|escape }}</a>
&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
&rsaquo; {% trans 'Purge' %}
</div>
{% endblock %}


{% block content %}

<form method="post" action="">{% csrf_token %}
<div class="alert alert-block alert-error">
<h4 class="alert-heading">{% trans 'Please confirm deletion' %}.</h4>
<p>{% blocktrans %}This operation is destructive, cannot be undone and may require some minutes.{% endblocktrans %}</p>
<p>{% blocktrans %}Are you sure you want to permanently remove all objects ?{% endblocktrans %}</p>
<br>

<div class="submit-row">
<input type="submit" class="btn btn-danger deletelink" name="btn-confirm" value="{% trans 'Yes, I\'m sure' %}" />
<input type="submit" class="btn" name="btn-cancel" value="{% trans 'Cancel' %}" />
</div>
</div>
</form>

{% endblock %}

0 comments on commit b968902

Please sign in to comment.