Code

Ticket #15261: django-allow-superuser-filters.diff

File django-allow-superuser-filters.diff, 7.0 KB (added by cdestigter, 3 years ago)
Line 
1diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
2index 00ab9fe..924e943 100644
3--- a/django/contrib/admin/views/main.py
4+++ b/django/contrib/admin/views/main.py
5@@ -40,6 +40,7 @@ class ChangeList(object):
6         self.list_select_related = list_select_related
7         self.list_per_page = list_per_page
8         self.model_admin = model_admin
9+        self.allow_all_lookups = request.user.is_superuser
10 
11         # Get search parameters from the query string.
12         try:
13@@ -194,7 +195,7 @@ class ChangeList(object):
14                     value = True
15                 lookup_params[key] = value
16 
17-            if not self.model_admin.lookup_allowed(key, value):
18+            if not (self.allow_all_lookups or self.model_admin.lookup_allowed(key, value)):
19                 raise SuspiciousOperation(
20                     "Filtering by %s not allowed" % key
21                 )
22diff --git a/tests/regressiontests/admin_changelist/tests.py b/tests/regressiontests/admin_changelist/tests.py
23index c3f6186..b03ee9b 100644
24--- a/tests/regressiontests/admin_changelist/tests.py
25+++ b/tests/regressiontests/admin_changelist/tests.py
26@@ -144,6 +144,9 @@ class ChildAdmin(admin.ModelAdmin):
27 
28 class MockRequest(object):
29     GET = {}
30+    def __init__(self):
31+        from django.contrib.auth.models import User
32+        self.user = User(is_staff=True, is_superuser=False)
33 
34 
35 class CustomPaginator(Paginator):
36diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
37index acbbbfc..23fe33e 100644
38--- a/tests/regressiontests/admin_views/tests.py
39+++ b/tests/regressiontests/admin_views/tests.py
40@@ -35,7 +35,7 @@ from models import (Article, BarAccount, CustomArticle, EmptyModel,
41     Person, Persona, Picture, Podcast, Section, Subscriber, Vodcast,
42     Language, Collector, Widget, Grommet, DooHickey, FancyDoodad, Whatsit,
43     Category, Post, Plot, FunkyTag, Chapter, Book, Promo, WorkHour, Employee,
44-    Question, Answer, Inquisition, Actor)
45+    Question, Answer, Inquisition, Actor, Thing)
46 
47 
48 class AdminViewBasicTest(TestCase):
49@@ -393,23 +393,7 @@ class AdminViewBasicTest(TestCase):
50         finally:
51             deactivate()
52 
53-
54-    def test_disallowed_filtering(self):
55-        self.assertRaises(SuspiciousOperation,
56-            self.client.get, "/test_admin/admin/admin_views/album/?owner__email__startswith=fuzzy"
57-        )
58-
59-        try:
60-            self.client.get("/test_admin/admin/admin_views/thing/?color__value__startswith=red")
61-            self.client.get("/test_admin/admin/admin_views/thing/?color__value=red")
62-        except SuspiciousOperation:
63-            self.fail("Filters are allowed if explicitly included in list_filter")
64-
65-        try:
66-            self.client.get("/test_admin/admin/admin_views/person/?age__gt=30")
67-        except SuspiciousOperation:
68-            self.fail("Filters should be allowed if they involve a local field without the need to whitelist them in list_filter or date_hierarchy.")
69-
70+    def test_allowed_filtering(self):
71         e1 = Employee.objects.create(name='Anonymous', gender=1, age=22, alive=True, code='123')
72         e2 = Employee.objects.create(name='Visitor', gender=2, age=19, alive=True, code='124')
73         WorkHour.objects.create(datum=datetime.datetime.now(), employee=e1)
74@@ -420,17 +404,6 @@ class AdminViewBasicTest(TestCase):
75         response = self.client.get("/test_admin/admin/admin_views/workhour/?employee__person_ptr__exact=%d" % e1.pk)
76         self.assertEqual(response.status_code, 200)
77 
78-    def test_allowed_filtering_15103(self):
79-        """
80-        Regressions test for ticket 15103 - filtering on fields defined in a
81-        ForeignKey 'limit_choices_to' should be allowed, otherwise raw_id_fields
82-        can break.
83-        """
84-        try:
85-            self.client.get("/test_admin/admin/admin_views/inquisition/?leader__name=Palin&leader__age=27")
86-        except SuspiciousOperation:
87-            self.fail("Filters should be allowed if they are defined on a ForeignKey pointing to this model")
88-
89 class AdminJavaScriptTest(AdminViewBasicTest):
90     def testSingleWidgetFirsFieldFocus(self):
91         """
92@@ -561,9 +534,17 @@ class AdminViewPermissionsTest(TestCase):
93         delete_user = User.objects.get(username='deleteuser')
94         delete_user.user_permissions.add(get_perm(Article,
95             opts.get_delete_permission()))
96-
97+       
98         delete_user.user_permissions.add(get_perm(Section,
99             Section._meta.get_delete_permission()))
100+       
101+        # Permissions for other models, for tests:
102+        #  - test_disallowed_filtering
103+        #  - test_allowed_filtering_15103
104+        change_user.user_permissions.add(get_perm(Inquisition,
105+            Inquisition._meta.get_change_permission()))
106+        change_user.user_permissions.add(get_perm(Thing,
107+            Thing._meta.get_change_permission()))
108 
109         # login POST dicts
110         self.super_login = {
111@@ -901,6 +882,44 @@ class AdminViewPermissionsTest(TestCase):
112         response = self.client.get('/test_admin/admin/secure-view/')
113         self.assertContains(response, 'id="login-form"')
114 
115+    def test_disallowed_filtering(self):
116+        """
117+        Ensure cross-model querystring lookups are disallowed for non-superusers.
118+        """
119+        self.client.login(username='changeuser', password='secret')
120+        self.assertRaises(SuspiciousOperation,
121+            self.client.get, "/test_admin/admin/admin_views/article/?section__name__startswith=fuzzy"
122+        )
123+
124+        try:
125+            self.client.get("/test_admin/admin/admin_views/article/?title__startswith=fuzzy")
126+        except SuspiciousOperation:
127+            self.fail("Filters should be allowed if they involve a local field without the need to whitelist them in list_filter or date_hierarchy.")
128+       
129+        try:
130+            self.client.get("/test_admin/admin/admin_views/thing/?color__value__startswith=red")
131+            self.client.get("/test_admin/admin/admin_views/thing/?color__value=red")
132+        except SuspiciousOperation:
133+            self.fail("Filters are allowed if explicitly included in list_filter")
134+       
135+        self.client.login(username='super', password='secret')
136+        try:
137+            self.client.get("/test_admin/admin/admin_views/article/?section__name__startswith=fuzzy")
138+        except SuspiciousOperation:
139+            self.fail("Filters should be allowed for superusers.")
140+
141+    def test_allowed_filtering_15103(self):
142+        """
143+        Regressions test for ticket 15103 - filtering on fields defined in a
144+        ForeignKey 'limit_choices_to' should be allowed, otherwise raw_id_fields
145+        can break.
146+        """
147+        self.client.login(username='changeuser', password='secret')
148+        try:
149+            self.client.get("/test_admin/admin/admin_views/inquisition/?leader__name=Palin&leader__age=27")
150+        except SuspiciousOperation:
151+            self.fail("Filters should be allowed if they are defined on a ForeignKey pointing to this model")
152+
153 
154 class AdminViewDeletedObjectsTest(TestCase):
155     fixtures = ['admin-views-users.xml', 'deleted-objects.xml']