mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +00:00
[1.2.X] Fixed #15075 - No longer possible to alter the form_list in FormWizard.process_step
Thanks to niels, stas for the report, and stas for the patch. Backport of [15196] from trunk. git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@15197 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
924bad822a
commit
444bda0be0
@ -146,6 +146,9 @@ class WizardPageOneForm(forms.Form):
|
|||||||
class WizardPageTwoForm(forms.Form):
|
class WizardPageTwoForm(forms.Form):
|
||||||
field = forms.CharField()
|
field = forms.CharField()
|
||||||
|
|
||||||
|
class WizardPageTwoAlternativeForm(forms.Form):
|
||||||
|
field = forms.CharField()
|
||||||
|
|
||||||
class WizardPageThreeForm(forms.Form):
|
class WizardPageThreeForm(forms.Form):
|
||||||
field = forms.CharField()
|
field = forms.CharField()
|
||||||
|
|
||||||
@ -194,7 +197,8 @@ class WizardTests(TestCase):
|
|||||||
|
|
||||||
def test_14498(self):
|
def test_14498(self):
|
||||||
"""
|
"""
|
||||||
Regression test for ticket #14498.
|
Regression test for ticket #14498. All previous steps' forms should be
|
||||||
|
validated.
|
||||||
"""
|
"""
|
||||||
that = self
|
that = self
|
||||||
reached = [False]
|
reached = [False]
|
||||||
@ -237,3 +241,26 @@ class WizardTests(TestCase):
|
|||||||
"wizard_step": "1"}
|
"wizard_step": "1"}
|
||||||
wizard(DummyRequest(POST=data))
|
wizard(DummyRequest(POST=data))
|
||||||
self.assertTrue(reached[0])
|
self.assertTrue(reached[0])
|
||||||
|
|
||||||
|
def test_15075(self):
|
||||||
|
"""
|
||||||
|
Regression test for ticket #15075. Allow modifying wizard's form_list
|
||||||
|
in process_step.
|
||||||
|
"""
|
||||||
|
that = self
|
||||||
|
|
||||||
|
class WizardWithProcessStep(WizardClass):
|
||||||
|
def process_step(self, request, form, step):
|
||||||
|
if step == 0:
|
||||||
|
self.form_list[1] = WizardPageTwoAlternativeForm
|
||||||
|
if step == 1:
|
||||||
|
that.assertTrue(isinstance(form, WizardPageTwoAlternativeForm))
|
||||||
|
|
||||||
|
wizard = WizardWithProcessStep([WizardPageOneForm,
|
||||||
|
WizardPageTwoForm,
|
||||||
|
WizardPageThreeForm])
|
||||||
|
data = {"0-field": "test",
|
||||||
|
"1-field": "test2",
|
||||||
|
"hash_0": "2fdbefd4c0cad51509478fbacddf8b13",
|
||||||
|
"wizard_step": "1"}
|
||||||
|
wizard(DummyRequest(POST=data))
|
||||||
|
@ -68,6 +68,39 @@ class FormWizard(object):
|
|||||||
if current_step >= self.num_steps():
|
if current_step >= self.num_steps():
|
||||||
raise Http404('Step %s does not exist' % current_step)
|
raise Http404('Step %s does not exist' % current_step)
|
||||||
|
|
||||||
|
# Validate and process all the previous forms before instantiating the
|
||||||
|
# current step's form in case self.process_step makes changes to
|
||||||
|
# self.form_list.
|
||||||
|
|
||||||
|
# If any of them fails validation, that must mean the validator relied
|
||||||
|
# on some other input, such as an external Web site.
|
||||||
|
|
||||||
|
# It is also possible that alidation might fail under certain attack
|
||||||
|
# situations: an attacker might be able to bypass previous stages, and
|
||||||
|
# generate correct security hashes for all the skipped stages by virtue
|
||||||
|
# of:
|
||||||
|
# 1) having filled out an identical form which doesn't have the
|
||||||
|
# validation (and does something different at the end),
|
||||||
|
# 2) or having filled out a previous version of the same form which
|
||||||
|
# had some validation missing,
|
||||||
|
# 3) or previously having filled out the form when they had more
|
||||||
|
# privileges than they do now.
|
||||||
|
#
|
||||||
|
# Since the hashes only take into account values, and not other other
|
||||||
|
# validation the form might do, we must re-do validation now for
|
||||||
|
# security reasons.
|
||||||
|
previous_form_list = []
|
||||||
|
for i in range(current_step):
|
||||||
|
f = self.get_form(i, request.POST)
|
||||||
|
if request.POST.get("hash_%d" % i, '') != self.security_hash(request, f):
|
||||||
|
return self.render_hash_failure(request, i)
|
||||||
|
|
||||||
|
if not f.is_valid():
|
||||||
|
return self.render_revalidation_failure(request, i, f)
|
||||||
|
else:
|
||||||
|
self.process_step(request, f, i)
|
||||||
|
previous_form_list.append(f)
|
||||||
|
|
||||||
# Process the current step. If it's valid, go to the next step or call
|
# Process the current step. If it's valid, go to the next step or call
|
||||||
# done(), depending on whether any steps remain.
|
# done(), depending on whether any steps remain.
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
@ -76,36 +109,6 @@ class FormWizard(object):
|
|||||||
form = self.get_form(current_step)
|
form = self.get_form(current_step)
|
||||||
|
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
# Validate all the forms. If any of them fail validation, that
|
|
||||||
# must mean the validator relied on some other input, such as
|
|
||||||
# an external Web site.
|
|
||||||
|
|
||||||
# It is also possible that validation might fail under certain
|
|
||||||
# attack situations: an attacker might be able to bypass previous
|
|
||||||
# stages, and generate correct security hashes for all the
|
|
||||||
# skipped stages by virtue of:
|
|
||||||
# 1) having filled out an identical form which doesn't have the
|
|
||||||
# validation (and does something different at the end),
|
|
||||||
# 2) or having filled out a previous version of the same form
|
|
||||||
# which had some validation missing,
|
|
||||||
# 3) or previously having filled out the form when they had
|
|
||||||
# more privileges than they do now.
|
|
||||||
#
|
|
||||||
# Since the hashes only take into account values, and not other
|
|
||||||
# other validation the form might do, we must re-do validation
|
|
||||||
# now for security reasons.
|
|
||||||
previous_form_list = [self.get_form(i, request.POST) for i in range(current_step)]
|
|
||||||
|
|
||||||
for i, f in enumerate(previous_form_list):
|
|
||||||
if request.POST.get("hash_%d" % i, '') != self.security_hash(request, f):
|
|
||||||
return self.render_hash_failure(request, i)
|
|
||||||
|
|
||||||
if not f.is_valid():
|
|
||||||
return self.render_revalidation_failure(request, i, f)
|
|
||||||
else:
|
|
||||||
self.process_step(request, f, i)
|
|
||||||
|
|
||||||
# Now progress to processing this step:
|
|
||||||
self.process_step(request, form, current_step)
|
self.process_step(request, form, current_step)
|
||||||
next_step = current_step + 1
|
next_step = current_step + 1
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user