mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #23869 -- Made ModelAdmin.get_deleted_objects() use has_delete_permission() for permissions checking.
This commit is contained in:
		
							
								
								
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -590,6 +590,7 @@ answer newbie questions, and generally made Django that much better: | ||||
|     Mikhail Korobov <kmike84@googlemail.com> | ||||
|     Mikko Hellsing <mikko@sorl.net> | ||||
|     Mikołaj Siedlarek <mikolaj.siedlarek@gmail.com> | ||||
|     milkomeda | ||||
|     Milton Waddams | ||||
|     mitakummaa@gmail.com | ||||
|     mmarshall | ||||
|   | ||||
| @@ -1812,7 +1812,7 @@ class ModelAdmin(BaseModelAdmin): | ||||
|         Hook for customizing the delete process for the delete view and the | ||||
|         "delete selected" action. | ||||
|         """ | ||||
|         return get_deleted_objects(objs, request.user, self.admin_site) | ||||
|         return get_deleted_objects(objs, request, self.admin_site) | ||||
|  | ||||
|     @csrf_protect_m | ||||
|     def delete_view(self, request, object_id, extra_context=None): | ||||
|   | ||||
| @@ -2,7 +2,6 @@ import datetime | ||||
| import decimal | ||||
| from collections import defaultdict | ||||
|  | ||||
| from django.contrib.auth import get_permission_codename | ||||
| from django.core.exceptions import FieldDoesNotExist | ||||
| from django.db import models, router | ||||
| from django.db.models.constants import LOOKUP_SEP | ||||
| @@ -117,7 +116,7 @@ def flatten_fieldsets(fieldsets): | ||||
|     return field_names | ||||
|  | ||||
|  | ||||
| def get_deleted_objects(objs, user, admin_site): | ||||
| def get_deleted_objects(objs, request, admin_site): | ||||
|     """ | ||||
|     Find all objects related to ``objs`` that should also be deleted. ``objs`` | ||||
|     must be a homogeneous iterable of objects (e.g. a QuerySet). | ||||
| @@ -136,12 +135,15 @@ def get_deleted_objects(objs, user, admin_site): | ||||
|     perms_needed = set() | ||||
|  | ||||
|     def format_callback(obj): | ||||
|         has_admin = obj.__class__ in admin_site._registry | ||||
|         model = obj.__class__ | ||||
|         has_admin = model in admin_site._registry | ||||
|         opts = obj._meta | ||||
|  | ||||
|         no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), obj) | ||||
|  | ||||
|         if has_admin: | ||||
|             if not admin_site._registry[model].has_delete_permission(request, obj): | ||||
|                 perms_needed.add(opts.verbose_name) | ||||
|             try: | ||||
|                 admin_url = reverse('%s:%s_%s_change' | ||||
|                                     % (admin_site.name, | ||||
| @@ -152,10 +154,6 @@ def get_deleted_objects(objs, user, admin_site): | ||||
|                 # Change url doesn't exist -- don't display link to edit | ||||
|                 return no_edit_link | ||||
|  | ||||
|             if 'delete' in opts.default_permissions: | ||||
|                 p = '%s.%s' % (opts.app_label, get_permission_codename('delete', opts)) | ||||
|                 if not user.has_perm(p): | ||||
|                     perms_needed.add(opts.verbose_name) | ||||
|             # Display a link to the admin page. | ||||
|             return format_html('{}: <a href="{}">{}</a>', | ||||
|                                capfirst(opts.verbose_name), | ||||
|   | ||||
| @@ -669,13 +669,34 @@ class ModelAdminTests(TestCase): | ||||
|     def test_get_deleted_objects(self): | ||||
|         mock_request = MockRequest() | ||||
|         mock_request.user = User.objects.create_superuser(username='bob', email='bob@test.com', password='test') | ||||
|         ma = ModelAdmin(Band, self.site) | ||||
|         self.site.register(Band, ModelAdmin) | ||||
|         ma = self.site._registry[Band] | ||||
|         deletable_objects, model_count, perms_needed, protected = ma.get_deleted_objects([self.band], request) | ||||
|         self.assertEqual(deletable_objects, ['Band: The Doors']) | ||||
|         self.assertEqual(model_count, {'bands': 1}) | ||||
|         self.assertEqual(perms_needed, set()) | ||||
|         self.assertEqual(protected, []) | ||||
|  | ||||
|     def test_get_deleted_objects_with_custom_has_delete_permission(self): | ||||
|         """ | ||||
|         ModelAdmin.get_deleted_objects() uses ModelAdmin.has_delete_permission() | ||||
|         for permissions checking. | ||||
|         """ | ||||
|         mock_request = MockRequest() | ||||
|         mock_request.user = User.objects.create_superuser(username='bob', email='bob@test.com', password='test') | ||||
|  | ||||
|         class TestModelAdmin(ModelAdmin): | ||||
|             def has_delete_permission(self, request, obj=None): | ||||
|                 return False | ||||
|  | ||||
|         self.site.register(Band, TestModelAdmin) | ||||
|         ma = self.site._registry[Band] | ||||
|         deletable_objects, model_count, perms_needed, protected = ma.get_deleted_objects([self.band], request) | ||||
|         self.assertEqual(deletable_objects, ['Band: The Doors']) | ||||
|         self.assertEqual(model_count, {'bands': 1}) | ||||
|         self.assertEqual(perms_needed, {'band'}) | ||||
|         self.assertEqual(protected, []) | ||||
|  | ||||
|  | ||||
| class ModelAdminPermissionTests(SimpleTestCase): | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user