티스토리 수익 글 보기

티스토리 수익 글 보기

[1.5.x] Checked object permissions on admin history view. · django/django@0e46c7f · GitHub
Skip to content

Commit 0e46c7f

Browse files
committed
[1.5.x] Checked object permissions on admin history view.
This is a security fix. Disclosure and advisory coming shortly. Patch by Russell Keith-Magee.
1 parent 2d0c22e commit 0e46c7f

File tree

2 files changed

+50
4
lines changed

2 files changed

+50
4
lines changed

django/contrib/admin/options.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,15 +1369,21 @@ def delete_view(self, request, object_id, extra_context=None):
13691369
def history_view(self, request, object_id, extra_context=None):
13701370
"The 'history' admin view for this model."
13711371
from django.contrib.admin.models import LogEntry
1372+
# First check if the user can see this history.
13721373
model = self.model
1374+
obj = get_object_or_404(model, pk=unquote(object_id))
1375+
1376+
if not self.has_change_permission(request, obj):
1377+
raise PermissionDenied
1378+
1379+
# Then get the history for this object.
13731380
opts = model._meta
13741381
app_label = opts.app_label
13751382
action_list = LogEntry.objects.filter(
1376-
object_id = unquote(object_id),
1377-
content_type__id__exact = ContentType.objects.get_for_model(model).id
1383+
object_id=unquote(object_id),
1384+
content_type__id__exact=ContentType.objects.get_for_model(model).id
13781385
).select_related().order_by('action_time')
1379-
# If no history was found, see whether this object even exists.
1380-
obj = get_object_or_404(model, pk=unquote(object_id))
1386+
13811387
context = {
13821388
'title': _('Change history: %s') % force_text(obj),
13831389
'action_list': action_list,

tests/regressiontests/admin_views/tests.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,46 @@ def testChangeView(self):
11031103
self.assertContains(response, 'login-form')
11041104
self.client.get('/test_admin/admin/logout/')
11051105

1106+
def testHistoryView(self):
1107+
"""History view should restrict access."""
1108+
1109+
# add user shoud not be able to view the list of article or change any of them
1110+
self.client.get('/test_admin/admin/')
1111+
self.client.post('/test_admin/admin/', self.adduser_login)
1112+
response = self.client.get('/test_admin/admin/admin_views/article/1/history/')
1113+
self.assertEqual(response.status_code, 403)
1114+
self.client.get('/test_admin/admin/logout/')
1115+
1116+
# change user can view all items and edit them
1117+
self.client.get('/test_admin/admin/')
1118+
self.client.post('/test_admin/admin/', self.changeuser_login)
1119+
response = self.client.get('/test_admin/admin/admin_views/article/1/history/')
1120+
self.assertEqual(response.status_code, 200)
1121+
1122+
# Test redirection when using row-level change permissions. Refs #11513.
1123+
RowLevelChangePermissionModel.objects.create(id=1, name="odd id")
1124+
RowLevelChangePermissionModel.objects.create(id=2, name="even id")
1125+
for login_dict in [self.super_login, self.changeuser_login, self.adduser_login, self.deleteuser_login]:
1126+
self.client.post('/test_admin/admin/', login_dict)
1127+
response = self.client.get('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/1/history/')
1128+
self.assertEqual(response.status_code, 403)
1129+
1130+
response = self.client.get('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/2/history/')
1131+
self.assertEqual(response.status_code, 200)
1132+
1133+
self.client.get('/test_admin/admin/logout/')
1134+
1135+
for login_dict in [self.joepublic_login, self.no_username_login]:
1136+
self.client.post('/test_admin/admin/', login_dict)
1137+
response = self.client.get('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/1/history/')
1138+
self.assertEqual(response.status_code, 200)
1139+
self.assertContains(response, 'login-form')
1140+
response = self.client.get('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/2/history/')
1141+
self.assertEqual(response.status_code, 200)
1142+
self.assertContains(response, 'login-form')
1143+
1144+
self.client.get('/test_admin/admin/logout/')
1145+
11061146
def testConditionallyShowAddSectionLink(self):
11071147
"""
11081148
The foreign key widget should only show the "add related" button if the

0 commit comments

Comments
 (0)