Allow cascade deletion of auditlog entries (#556)

* Allow cascade deletion of auditlog entries

* Cache iteration over self.urls
This commit is contained in:
Aleh Rymašeŭski 2023-08-27 09:12:39 +00:00 committed by GitHub
parent fb1ae7abed
commit c52786855b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 1 deletions

View file

@ -25,6 +25,7 @@
- fix: Always set remote_addr even if the request has no authenticated user. ([#484](https://github.com/jazzband/django-auditlog/pull/484))
- fix: Fix a bug in getting field's `verbose_name` when model is not accessible. ([508](https://github.com/jazzband/django-auditlog/pull/508))
- fix: Fix a bug in `serialized_data` with F expressions. ([508](https://github.com/jazzband/django-auditlog/pull/508))
- fix: Make log entries read-only in the admin. ([#449](https://github.com/jazzband/django-auditlog/pull/449), [#556](https://github.com/jazzband/django-auditlog/pull/556)) (applied again after being reverted in 2.2.2)
## 2.2.2 (2023-01-16)

View file

@ -1,3 +1,5 @@
from functools import cached_property
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.utils.translation import gettext_lazy as _
@ -39,7 +41,17 @@ class LogEntryAdmin(admin.ModelAdmin, LogEntryAdminMixin):
def has_change_permission(self, request, obj=None):
return False
@cached_property
def _own_url_names(self):
return [pattern.name for pattern in self.urls if pattern.name]
def has_delete_permission(self, request, obj=None):
if (
request.resolver_match
and request.resolver_match.url_name not in self._own_url_names
):
# only allow cascade delete to satisfy delete_related flag
return super().has_delete_permission(request, obj)
return False
def get_queryset(self, request):

View file

@ -19,7 +19,7 @@ from django.core import management
from django.db import models
from django.db.models.signals import pre_save
from django.test import RequestFactory, TestCase, override_settings
from django.urls import reverse
from django.urls import resolve, reverse
from django.utils import dateformat, formats
from django.utils import timezone as django_timezone
from django.utils.encoding import smart_str
@ -1549,6 +1549,23 @@ class AdminPanelTest(TestCase):
self.assertEqual(res.status_code, 200)
self.assertIn(expected_response, res.rendered_content)
def test_has_delete_permission(self):
log = self.obj.history.latest()
obj_pk = self.obj.pk
delete_log_request = RequestFactory().post(
f"/admin/auditlog/logentry/{log.pk}/delete/"
)
delete_log_request.resolver_match = resolve(delete_log_request.path)
delete_log_request.user = self.user
delete_object_request = RequestFactory().post(
f"/admin/tests/simplemodel/{obj_pk}/delete/"
)
delete_object_request.resolver_match = resolve(delete_object_request.path)
delete_object_request.user = self.user
self.assertTrue(self.admin.has_delete_permission(delete_object_request, log))
self.assertFalse(self.admin.has_delete_permission(delete_log_request, log))
class DiffMsgTest(TestCase):
def setUp(self):