[1.4.x] Fixed #23431 -- Allowed inline and hidden references to admin fields.

This fixes a regression introduced by the 53ff096982 security fix.

Thanks to @a1tus for the report and Tim for the review.

refs #23329.

Backport of 342ccbd from master
This commit is contained in:
Simon Charette 2014-09-04 17:04:53 -04:00
parent 78085844a7
commit 065caafa70
6 changed files with 55 additions and 4 deletions

View File

@ -270,6 +270,10 @@ class BaseModelAdmin(object):
return clean_lookup in self.list_filter or clean_lookup == self.date_hierarchy return clean_lookup in self.list_filter or clean_lookup == self.date_hierarchy
def to_field_allowed(self, request, to_field): def to_field_allowed(self, request, to_field):
"""
Returns True if the model associated with this admin should be
allowed to be referenced by the specified field.
"""
opts = self.model._meta opts = self.model._meta
try: try:
@ -279,8 +283,13 @@ class BaseModelAdmin(object):
# Make sure at least one of the models registered for this site # Make sure at least one of the models registered for this site
# references this field through a FK or a M2M relationship. # references this field through a FK or a M2M relationship.
registered_models = self.admin_site._registry registered_models = set()
for related_object in (opts.get_all_related_objects() + for model, admin in self.admin_site._registry.items():
registered_models.add(model)
for inline in admin.inlines:
registered_models.add(inline.model)
for related_object in (opts.get_all_related_objects(include_hidden=True) +
opts.get_all_related_many_to_many_objects()): opts.get_all_related_many_to_many_objects()):
related_model = related_object.model related_model = related_object.model
if (any(issubclass(model, related_model) for model in registered_models) and if (any(issubclass(model, related_model) for model in registered_models) and

13
docs/releases/1.4.16.txt Normal file
View File

@ -0,0 +1,13 @@
===========================
Django 1.4.16 release notes
===========================
*Under development*
Django 1.4.16 fixes a regression in the 1.4.14 security release.
Bugfixes
========
* Allowed inline and hidden references to admin fields
(`#23431 <http://code.djangoproject.com/ticket/23431>`_).

View File

@ -19,6 +19,7 @@ Final releases
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
1.4.16
1.4.15 1.4.15
1.4.14 1.4.14
1.4.13 1.4.13

View File

@ -27,7 +27,8 @@ from .models import (Article, Chapter, Account, Media, Child, Parent, Picture,
Album, Question, Answer, ComplexSortedPerson, PrePopulatedPostLargeSlug, Album, Question, Answer, ComplexSortedPerson, PrePopulatedPostLargeSlug,
AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod,
AdminOrderedCallable, Report, Color2, UnorderedObject, MainPrepopulated, AdminOrderedCallable, Report, Color2, UnorderedObject, MainPrepopulated,
RelatedPrepopulated, ReferencedByParent, ChildOfReferer, M2MReference) RelatedPrepopulated, ReferencedByParent, ChildOfReferer, M2MReference,
ReferencedByInline, InlineReference, InlineReferer)
def callable_year(dt_value): def callable_year(dt_value):
@ -570,6 +571,14 @@ class UnorderedObjectAdmin(admin.ModelAdmin):
class InlineReferenceInline(admin.TabularInline):
model = InlineReference
class InlineRefererAdmin(admin.ModelAdmin):
inlines = [InlineReferenceInline]
site = admin.AdminSite(name="admin") site = admin.AdminSite(name="admin")
site.register(Article, ArticleAdmin) site.register(Article, ArticleAdmin)
site.register(CustomArticle, CustomArticleAdmin) site.register(CustomArticle, CustomArticleAdmin)
@ -619,6 +628,8 @@ site.register(UnorderedObject, UnorderedObjectAdmin)
site.register(ReferencedByParent) site.register(ReferencedByParent)
site.register(ChildOfReferer) site.register(ChildOfReferer)
site.register(M2MReference) site.register(M2MReference)
site.register(ReferencedByInline)
site.register(InlineReferer, InlineRefererAdmin)
# We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2. # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
# That way we cover all four cases: # That way we cover all four cases:

View File

@ -625,3 +625,15 @@ class ChildOfReferer(ParentWithFK):
class M2MReference(models.Model): class M2MReference(models.Model):
ref = models.ManyToManyField('self') ref = models.ManyToManyField('self')
# Models for #23431
class ReferencedByInline(models.Model):
pass
class InlineReference(models.Model):
fk = models.ForeignKey(ReferencedByInline, related_name='hidden+')
class InlineReferer(models.Model):
refs = models.ManyToManyField(InlineReference)

View File

@ -590,11 +590,16 @@ class AdminViewBasicTest(TestCase):
response = self.client.get("/test_admin/admin/admin_views/m2mreference/", {TO_FIELD_VAR: 'id'}) response = self.client.get("/test_admin/admin/admin_views/m2mreference/", {TO_FIELD_VAR: 'id'})
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
# Specifying a field that is not refered by any other model directly registered # #23329 - Specifying a field that is not refered by any other model directly registered
# to this admin site but registered through inheritance should be allowed. # to this admin site but registered through inheritance should be allowed.
response = self.client.get("/test_admin/admin/admin_views/referencedbyparent/", {TO_FIELD_VAR: 'id'}) response = self.client.get("/test_admin/admin/admin_views/referencedbyparent/", {TO_FIELD_VAR: 'id'})
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
# #23431 - Specifying a field that is only refered to by a inline of a registered
# model should be allowed.
response = self.client.get("/test_admin/admin/admin_views/referencedbyinline/", {TO_FIELD_VAR: 'id'})
self.assertEqual(response.status_code, 200)
def test_allowed_filtering_15103(self): def test_allowed_filtering_15103(self):
""" """
Regressions test for ticket 15103 - filtering on fields defined in a Regressions test for ticket 15103 - filtering on fields defined in a