1
0
mirror of https://github.com/django/django.git synced 2025-04-04 21:46:40 +00:00

added change that checks permissions when displaying url for recent changes

This commit is contained in:
AP Jama 2023-08-05 12:33:06 +01:00
parent 519087819e
commit d8cb58ada8
3 changed files with 45 additions and 4 deletions

View File

@ -31,10 +31,10 @@
{% for entry in admin_log %}
<li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">
<span class="visually-hidden">{% if entry.is_addition %}{% translate 'Added:' %}{% elif entry.is_change %}{% translate 'Changed:' %}{% elif entry.is_deletion %}{% translate 'Deleted:' %}{% endif %}</span>
{% if entry.is_deletion or not entry.get_admin_url %}
{% if entry.is_deletion or not entry.url %}
{{ entry.object_repr }}
{% else %}
<a href="{{ entry.get_admin_url }}">{{ entry.object_repr }}</a>
<a href="{{ entry.url }}">{{ entry.object_repr }}</a>
{% endif %}
<br>
{% if entry.content_type %}

View File

@ -19,7 +19,22 @@ class AdminLogNode(template.Node):
if not user_id.isdigit():
user_id = context[self.user].pk
entries = entries.filter(user__pk=user_id)
context[self.varname] = entries[: int(self.limit)]
filtered_context = entries.select_related("content_type", "user")[
: int(self.limit)
]
for entry in filtered_context:
content_type = entry.content_type
if not content_type:
entry.url = entry.get_admin_url()
continue
user = entry.user
view_permission_name = f"{content_type.app_label}.view_{content_type.model}"
user_has_permission = user.has_perm(view_permission_name)
if user_has_permission:
entry.url = entry.get_admin_url()
else:
entry.url = None
context[self.varname] = filtered_context
return ""

View File

@ -3,7 +3,7 @@ from datetime import datetime
from django.contrib.admin.models import ADDITION, CHANGE, DELETION, LogEntry
from django.contrib.admin.utils import quote
from django.contrib.auth.models import User
from django.contrib.auth.models import User, Permission
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase, override_settings
from django.urls import reverse
@ -351,6 +351,32 @@ class LogEntryTests(TestCase):
counted_presence_after = response.content.count(should_contain)
self.assertEqual(counted_presence_before - 1, counted_presence_after)
def test_recent_actions_user_lacks_view_permission(self):
# No permission to view articles. Log is a span with no link.
response = self.client.get(reverse("admin:index"))
should_contain = """<span class="mini quiet">Article</span>"""
self.assertContains(response, should_contain)
# Add permission to view articles. Log is a link.
logentry = LogEntry.objects.get(content_type__model__iexact="article")
view_permission_name = f"{logentry.content_type.app_label}.view_{logentry.content_type.model}"
view_article_permission = Permission.objects.create(
name=f"Can view {logentry.content_type.model}",
content_type=logentry.content_type,
codename=view_permission_name,
)
self.user.user_permissions.add(view_article_permission)
response = self.client.get(reverse("admin:index"))
expected_log_entry_link = reverse(
"admin:admin_utils_article_change", args=(quote(self.a1.pk),)
)
should_contain = """<a href="%s">%s</a>""" % (
escape(expected_log_entry_link),
escape(repr(self.a1)),
)
self.assertContains(response, should_contain)
def test_proxy_model_content_type_is_used_for_log_entries(self):
"""
Log entries for proxy models should have the proxy model's contenttype