Fixed #21063 -- AdminSite app_index should be fail early if the user has no permissions.

This commit is contained in:
Keryn Knight 2013-09-07 13:32:12 +01:00 committed by Tim Graham
parent fb51c9a0f2
commit 0d74f9553c
2 changed files with 56 additions and 34 deletions

View File

@ -6,7 +6,7 @@ from django.contrib.auth import logout as auth_logout, REDIRECT_FIELD_NAME
from django.contrib.contenttypes import views as contenttype_views from django.contrib.contenttypes import views as contenttype_views
from django.views.decorators.csrf import csrf_protect from django.views.decorators.csrf import csrf_protect
from django.db.models.base import ModelBase from django.db.models.base import ModelBase
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.core.urlresolvers import reverse, NoReverseMatch from django.core.urlresolvers import reverse, NoReverseMatch
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.utils import six from django.utils import six
@ -399,10 +399,11 @@ class AdminSite(object):
def app_index(self, request, app_label, extra_context=None): def app_index(self, request, app_label, extra_context=None):
user = request.user user = request.user
has_module_perms = user.has_module_perms(app_label) has_module_perms = user.has_module_perms(app_label)
if not has_module_perms:
raise PermissionDenied
app_dict = {} app_dict = {}
for model, model_admin in self._registry.items(): for model, model_admin in self._registry.items():
if app_label == model._meta.app_label: if app_label == model._meta.app_label:
if has_module_perms:
perms = model_admin.get_model_perms(request) perms = model_admin.get_model_perms(request)
# Check whether user has any perm for this module. # Check whether user has any perm for this module.
@ -414,12 +415,12 @@ class AdminSite(object):
'object_name': model._meta.object_name, 'object_name': model._meta.object_name,
'perms': perms, 'perms': perms,
} }
if perms.get('change', False): if perms.get('change'):
try: try:
model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name) model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name)
except NoReverseMatch: except NoReverseMatch:
pass pass
if perms.get('add', False): if perms.get('add'):
try: try:
model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=self.name) model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=self.name)
except NoReverseMatch: except NoReverseMatch:

View File

@ -1309,6 +1309,27 @@ class AdminViewPermissionsTest(TestCase):
response = self.client.get('/test_admin/admin/secure-view/') response = self.client.get('/test_admin/admin/secure-view/')
self.assertContains(response, 'id="login-form"') self.assertContains(response, 'id="login-form"')
def testAppIndexFailEarly(self):
"""
If a user has no module perms, avoid iterating over all the modeladmins
in the registry.
"""
opts = Article._meta
change_user = User.objects.get(username='changeuser')
permission = get_perm(Article, get_permission_codename('change', opts))
self.client.post('/test_admin/admin/', self.changeuser_login)
# the user has no module permissions, because this module doesn't exist
change_user.user_permissions.remove(permission)
response = self.client.get('/test_admin/admin/admin_views/')
self.assertEqual(response.status_code, 403)
# the user now has module permissions
change_user.user_permissions.add(permission)
response = self.client.get('/test_admin/admin/admin_views/')
self.assertEqual(response.status_code, 200)
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class AdminViewsNoUrlTest(TestCase): class AdminViewsNoUrlTest(TestCase):