Commit 75a1aaa1 authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

Fixed #11513 -- Ensure that the redirect at the end of an object change won't...

Fixed #11513 -- Ensure that the redirect at the end of an object change won't redirect to a page for which the user doesn't have permission. Thanks to rlaager for the report and draft patch, and to Julien Phalip for the final patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15584 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent fe3c9ad5
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -766,7 +766,13 @@ class ModelAdmin(BaseModelAdmin):
            return HttpResponseRedirect("../add/")
        else:
            self.message_user(request, msg)
            return HttpResponseRedirect("../")
            # Figure out where to redirect. If the user has change permission,
            # redirect to the change-list page for this object. Otherwise,
            # redirect to the admin index.
            if self.has_change_permission(request, None):
                return HttpResponseRedirect('../')
            else:
                return HttpResponseRedirect('../../../')

    def response_action(self, request, queryset):
        """
+8 −0
Original line number Diff line number Diff line
@@ -133,6 +133,13 @@ class ArticleAdmin(admin.ModelAdmin):
        ).send()
        return super(ArticleAdmin, self).save_model(request, obj, form, change)

class RowLevelChangePermissionModel(models.Model):
    name = models.CharField(max_length=100, blank=True)

class RowLevelChangePermissionModelAdmin(admin.ModelAdmin):
    def has_change_permission(self, request, obj=None):
        """ Only allow changing objects with even id number """
        return request.user.is_staff and (obj is not None) and (obj.id % 2 == 0)

class CustomArticle(models.Model):
    content = models.TextField()
@@ -735,6 +742,7 @@ admin.site.register(CyclicTwo)
admin.site.register(WorkHour, WorkHourAdmin)
admin.site.register(Reservation)
admin.site.register(FoodDelivery, FoodDeliveryAdmin)
admin.site.register(RowLevelChangePermissionModel, RowLevelChangePermissionModelAdmin)

# We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
# That way we cover all four cases:
+36 −1
Original line number Diff line number Diff line
@@ -35,7 +35,8 @@ from models import (Article, BarAccount, CustomArticle, EmptyModel,
    Person, Persona, Picture, Podcast, Section, Subscriber, Vodcast,
    Language, Collector, Widget, Grommet, DooHickey, FancyDoodad, Whatsit,
    Category, Post, Plot, FunkyTag, Chapter, Book, Promo, WorkHour, Employee,
    Question, Answer, Inquisition, Actor, FoodDelivery)
    Question, Answer, Inquisition, Actor, FoodDelivery,
    RowLevelChangePermissionModel)


class AdminViewBasicTest(TestCase):
@@ -792,6 +793,40 @@ class AdminViewPermissionsTest(TestCase):
                        'Plural error message not found in response to post with multiple errors.')
        self.client.get('/test_admin/admin/logout/')

        # Test redirection when using row-level change permissions. Refs #11513.
        RowLevelChangePermissionModel.objects.create(name="odd id")
        RowLevelChangePermissionModel.objects.create(name="even id")
        for login_dict in [self.super_login, self.changeuser_login, self.adduser_login, self.deleteuser_login]:
            self.client.post('/test_admin/admin/', login_dict)
            request = self.client.get('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/1/')
            self.assertEqual(request.status_code, 403)
            request = self.client.post('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/1/', {'name': 'changed'})
            self.assertEquals(RowLevelChangePermissionModel.objects.get(id=1).name, 'odd id')
            self.assertEqual(request.status_code, 403)
            request = self.client.get('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/2/')
            self.assertEqual(request.status_code, 200)
            request = self.client.post('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/2/', {'name': 'changed'})
            self.assertEquals(RowLevelChangePermissionModel.objects.get(id=2).name, 'changed')
            self.assertRedirects(request, '/test_admin/admin/')
            self.client.get('/test_admin/admin/logout/')
        for login_dict in [self.joepublic_login, self.no_username_login]:
            self.client.post('/test_admin/admin/', login_dict)
            request = self.client.get('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/1/')
            self.assertEqual(request.status_code, 200)
            self.assertContains(request, 'login-form')
            request = self.client.post('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/1/', {'name': 'changed'})
            self.assertEquals(RowLevelChangePermissionModel.objects.get(id=1).name, 'odd id')
            self.assertEqual(request.status_code, 200)
            self.assertContains(request, 'login-form')
            request = self.client.get('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/2/')
            self.assertEqual(request.status_code, 200)
            self.assertContains(request, 'login-form')
            request = self.client.post('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/2/', {'name': 'changed again'})
            self.assertEquals(RowLevelChangePermissionModel.objects.get(id=2).name, 'changed')
            self.assertEqual(request.status_code, 200)
            self.assertContains(request, 'login-form')
            self.client.get('/test_admin/admin/logout/')

    def testConditionallyShowAddSectionLink(self):
        """
        The foreign key widget should only show the "add related" button if the