diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py index ca87311cd918a..fc46f030c28a2 100644 --- a/django/contrib/admin/sites.py +++ b/django/contrib/admin/sites.py @@ -4,7 +4,7 @@ from django.conf import settings from django.contrib.admin import ModelAdmin, actions from django.contrib.auth import REDIRECT_FIELD_NAME -from django.core.exceptions import ImproperlyConfigured, PermissionDenied +from django.core.exceptions import ImproperlyConfigured from django.db.models.base import ModelBase from django.http import Http404, HttpResponseRedirect from django.template.response import TemplateResponse @@ -399,8 +399,6 @@ def _build_app_dict(self, request, label=None): has_module_perms = model_admin.has_module_permission(request) if not has_module_perms: - if label: - raise PermissionDenied continue perms = model_admin.get_model_perms(request) diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py index 5a9923848f515..be38a14b03931 100644 --- a/tests/admin_views/admin.py +++ b/tests/admin_views/admin.py @@ -1019,3 +1019,4 @@ def get_formsets_with_inlines(self, request, obj=None): site7 = admin.AdminSite(name="admin7") site7.register(Article, ArticleAdmin2) +site7.register(Section) diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index 3007764b5ded0..0eae2e467ac29 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -1926,10 +1926,9 @@ def test_disabled_staff_permissions_when_logged_in(self): response = self.client.get(reverse('secure_view'), follow=True) self.assertContains(response, 'id="login-form"') - def test_app_index_fail_early(self): + def test_app_list_permissions(self): """ - If a user has no module perms, avoid iterating over all the modeladmins - in the registry. + If a user has no module perms, the app list returns a 404. """ opts = Article._meta change_user = User.objects.get(username='changeuser') @@ -1937,10 +1936,10 @@ def test_app_index_fail_early(self): self.client.force_login(self.changeuser) - # the user has no module permissions, because this module doesn't exist + # the user has no module permissions change_user.user_permissions.remove(permission) response = self.client.get(reverse('admin:app_list', args=('admin_views',))) - self.assertEqual(response.status_code, 403) + self.assertEqual(response.status_code, 404) # the user now has module permissions change_user.user_permissions.add(permission) @@ -2002,30 +2001,38 @@ def test_overriding_has_module_permission(self): In this case, it always returns False, so the module should not be displayed on the admin index page for any users. """ + articles = Article._meta.verbose_name_plural.title() + sections = Section._meta.verbose_name_plural.title() index_url = reverse('admin7:index') self.client.force_login(self.superuser) response = self.client.get(index_url) - self.assertNotContains(response, 'admin_views') - self.assertNotContains(response, 'Articles') + self.assertContains(response, sections) + self.assertNotContains(response, articles) self.client.logout() self.client.force_login(self.adduser) response = self.client.get(index_url) self.assertNotContains(response, 'admin_views') - self.assertNotContains(response, 'Articles') + self.assertNotContains(response, articles) self.client.logout() self.client.force_login(self.changeuser) response = self.client.get(index_url) self.assertNotContains(response, 'admin_views') - self.assertNotContains(response, 'Articles') + self.assertNotContains(response, articles) self.client.logout() self.client.force_login(self.deleteuser) response = self.client.get(index_url) - self.assertNotContains(response, 'admin_views') - self.assertNotContains(response, 'Articles') + self.assertNotContains(response, articles) + + # The app list displays Sections but not Articles as the latter has + # ModelAdmin.has_module_permission() = False. + self.client.force_login(self.superuser) + response = self.client.get(reverse('admin7:app_list', args=('admin_views',))) + self.assertContains(response, sections) + self.assertNotContains(response, articles) def test_post_save_message_no_forbidden_links_visible(self): """