Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit adbca5e

Browse files
mykwillistimgraham
authored andcommitted
[1.9.x] Fixed incorrect permissions check for admin's "Save as new".
This is a security fix.
1 parent a9fbf07 commit adbca5e

File tree

3 files changed

+46
-6
lines changed

3 files changed

+46
-6
lines changed

django/contrib/admin/options.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,10 @@ def changeform_view(self, request, object_id=None, form_url='', extra_context=No
13431343

13441344
model = self.model
13451345
opts = model._meta
1346+
1347+
if request.method == 'POST' and '_saveasnew' in request.POST:
1348+
object_id = None
1349+
13461350
add = object_id is None
13471351

13481352
if add:
@@ -1360,10 +1364,6 @@ def changeform_view(self, request, object_id=None, form_url='', extra_context=No
13601364
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {
13611365
'name': force_text(opts.verbose_name), 'key': escape(object_id)})
13621366

1363-
if request.method == 'POST' and "_saveasnew" in request.POST:
1364-
object_id = None
1365-
obj = None
1366-
13671367
ModelForm = self.get_form(request, obj)
13681368
if request.method == 'POST':
13691369
form = ModelForm(request.POST, request.FILES, instance=obj)
@@ -1426,6 +1426,8 @@ def changeform_view(self, request, object_id=None, form_url='', extra_context=No
14261426
if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST:
14271427
context['show_save'] = False
14281428
context['show_save_and_continue'] = False
1429+
# Use the change template instead of the add template.
1430+
add = False
14291431

14301432
context.update(extra_context or {})
14311433

docs/releases/1.9.2.txt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,17 @@ Django 1.9.2 release notes
44

55
*Under development*
66

7-
Django 1.9.2 fixes several bugs in 1.9.1 and makes a small backwards
8-
incompatible change that hopefully doesn't affect any users.
7+
Django 1.9.2 fixes a security regression in 1.9 and several bugs in 1.9.1. It
8+
also makes a small backwards incompatible change that hopefully doesn't affect
9+
any users.
10+
11+
Security issue: User with "change" but not "add" permission can create objects for ``ModelAdmin``’s with ``save_as=True``
12+
=========================================================================================================================
13+
14+
If a ``ModelAdmin`` uses ``save_as=True`` (not the default), the admin
15+
provides an option when editing objects to "Save as new". A regression in
16+
Django 1.9 prevented that form submission from raising a "Permission Denied"
17+
error for users without the "add" permission.
918

1019
Backwards incompatible change: ``.py-tpl`` files rewritten in project/app templates
1120
===================================================================================

tests/admin_views/tests.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,35 @@ def test_change_view(self):
17121712
self.assertContains(response, 'login-form')
17131713
self.client.get(reverse('admin:logout'))
17141714

1715+
def test_change_view_save_as_new(self):
1716+
"""
1717+
'Save as new' should raise PermissionDenied for users without the 'add'
1718+
permission.
1719+
"""
1720+
change_dict_save_as_new = {
1721+
'_saveasnew': 'Save as new',
1722+
'title': 'Ikke fordømt',
1723+
'content': '<p>edited article</p>',
1724+
'date_0': '2008-03-18', 'date_1': '10:54:39',
1725+
'section': self.s1.pk,
1726+
}
1727+
article_change_url = reverse('admin:admin_views_article_change', args=(self.a1.pk,))
1728+
1729+
# Add user can perform "Save as new".
1730+
article_count = Article.objects.count()
1731+
self.client.force_login(self.adduser)
1732+
post = self.client.post(article_change_url, change_dict_save_as_new)
1733+
self.assertRedirects(post, self.index_url)
1734+
self.assertEqual(Article.objects.count(), article_count + 1)
1735+
self.client.logout()
1736+
1737+
# Change user cannot perform "Save as new" (no 'add' permission).
1738+
article_count = Article.objects.count()
1739+
self.client.force_login(self.changeuser)
1740+
post = self.client.post(article_change_url, change_dict_save_as_new)
1741+
self.assertEqual(post.status_code, 403)
1742+
self.assertEqual(Article.objects.count(), article_count)
1743+
17151744
def test_delete_view(self):
17161745
"""Delete view should restrict access and actually delete items."""
17171746
delete_dict = {'post': 'yes'}

0 commit comments

Comments
 (0)