[Form] Fixed: CSRF token was not displayed on empty complex forms

This commit is contained in:
Bernhard Schussek 2012-04-20 18:58:52 +02:00
parent c623fcf4d4
commit 649752c947
5 changed files with 38 additions and 41 deletions

View File

@ -63,7 +63,7 @@ class CsrfValidationListener implements EventSubscriberInterface
$form = $event->getForm(); $form = $event->getForm();
$data = $event->getData(); $data = $event->getData();
if ($form->isRoot() && $form->hasChildren()) { if ($form->isRoot() && !$form->getAttribute('primitive')) {
if (!isset($data[$this->fieldName]) || !$this->csrfProvider->isCsrfTokenValid($this->intention, $data[$this->fieldName])) { if (!isset($data[$this->fieldName]) || !$this->csrfProvider->isCsrfTokenValid($this->intention, $data[$this->fieldName])) {
$form->addError(new FormError('The CSRF token is invalid. Please try to resubmit the form')); $form->addError(new FormError('The CSRF token is invalid. Please try to resubmit the form'));
} }

View File

@ -64,7 +64,7 @@ class FormTypeCsrfExtension extends AbstractTypeExtension
*/ */
public function buildViewBottomUp(FormView $view, FormInterface $form) public function buildViewBottomUp(FormView $view, FormInterface $form)
{ {
if (!$view->hasParent() && $view->hasChildren() && $form->hasAttribute('csrf_field_name')) { if (!$view->hasParent() && !$form->getAttribute('primitive') && $form->hasAttribute('csrf_field_name')) {
$name = $form->getAttribute('csrf_field_name'); $name = $form->getAttribute('csrf_field_name');
$csrfProvider = $form->getAttribute('csrf_provider'); $csrfProvider = $form->getAttribute('csrf_provider');
$intention = $form->getAttribute('csrf_intention'); $intention = $form->getAttribute('csrf_intention');

View File

@ -285,6 +285,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
$this->assertWidgetMatchesXpath($form->createView(), array(), $this->assertWidgetMatchesXpath($form->createView(), array(),
'/div '/div
[./input[@type="hidden"][@id="name__token"]]
[count(./div)=0] [count(./div)=0]
' '
); );

View File

@ -178,7 +178,8 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
$this->assertWidgetMatchesXpath($form->createView(), array(), $this->assertWidgetMatchesXpath($form->createView(), array(),
'/table '/table
[count(./tr[./td/input])=0] [./tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]]]
[count(./tr[./td/input])=1]
' '
); );
} }

View File

@ -56,43 +56,42 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
)); ));
} }
public function testCsrfProtectionByDefaultIfRootAndChildren() public function testCsrfProtectionByDefaultIfRootAndNotPrimitive()
{ {
$view = $this->factory $view = $this->factory
->createBuilder('form', null, array( ->create('form', null, array(
'csrf_field_name' => 'csrf', 'csrf_field_name' => 'csrf',
'primitive' => false,
)) ))
->add($this->factory->createNamedBuilder('form', 'child'))
->getForm()
->createView(); ->createView();
$this->assertTrue($view->hasChild('csrf')); $this->assertTrue($view->hasChild('csrf'));
} }
public function testNoCsrfProtectionByDefaultIfChildrenButNotRoot() public function testNoCsrfProtectionByDefaultIfNotPrimitiveButNotRoot()
{ {
$view = $this->factory $view = $this->factory
->createNamedBuilder('form', 'root') ->createNamedBuilder('form', 'root')
->add($this->factory ->add($this->factory
->createNamedBuilder('form', 'form', null, array( ->createNamedBuilder('form', 'form', null, array(
'csrf_field_name' => 'csrf', 'csrf_field_name' => 'csrf',
'primitive' => false,
)) ))
->add($this->factory->createNamedBuilder('form', 'child'))
) )
->getForm() ->getForm()
->get('form') ->createView()
->createView(); ->getChild('form');
$this->assertFalse($view->hasChild('csrf')); $this->assertFalse($view->hasChild('csrf'));
} }
public function testNoCsrfProtectionByDefaultIfRootButNoChildren() public function testNoCsrfProtectionByDefaultIfRootButPrimitive()
{ {
$view = $this->factory $view = $this->factory
->createBuilder('form', null, array( ->create('form', null, array(
'csrf_field_name' => 'csrf', 'csrf_field_name' => 'csrf',
'primitive' => true,
)) ))
->getForm()
->createView(); ->createView();
$this->assertFalse($view->hasChild('csrf')); $this->assertFalse($view->hasChild('csrf'));
@ -101,12 +100,11 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
public function testCsrfProtectionCanBeDisabled() public function testCsrfProtectionCanBeDisabled()
{ {
$view = $this->factory $view = $this->factory
->createBuilder('form', null, array( ->create('form', null, array(
'csrf_field_name' => 'csrf', 'csrf_field_name' => 'csrf',
'csrf_protection' => false, 'csrf_protection' => false,
'primitive' => false,
)) ))
->add($this->factory->createNamedBuilder('form', 'child'))
->getForm()
->createView(); ->createView();
$this->assertFalse($view->hasChild('csrf')); $this->assertFalse($view->hasChild('csrf'));
@ -120,13 +118,12 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
->will($this->returnValue('token')); ->will($this->returnValue('token'));
$view = $this->factory $view = $this->factory
->createBuilder('form', null, array( ->create('form', null, array(
'csrf_field_name' => 'csrf', 'csrf_field_name' => 'csrf',
'csrf_provider' => $this->csrfProvider, 'csrf_provider' => $this->csrfProvider,
'intention' => '%INTENTION%' 'intention' => '%INTENTION%',
'primitive' => false,
)) ))
->add($this->factory->createNamedBuilder('form', 'child'))
->getForm()
->createView(); ->createView();
$this->assertEquals('token', $view->getChild('csrf')->get('value')); $this->assertEquals('token', $view->getChild('csrf')->get('value'));
@ -143,7 +140,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
/** /**
* @dataProvider provideBoolean * @dataProvider provideBoolean
*/ */
public function testValidateTokenOnBindIfRootAndChildren($valid) public function testValidateTokenOnBindIfRootAndNotPrimitive($valid)
{ {
$this->csrfProvider->expects($this->once()) $this->csrfProvider->expects($this->once())
->method('isCsrfTokenValid') ->method('isCsrfTokenValid')
@ -151,13 +148,12 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
->will($this->returnValue($valid)); ->will($this->returnValue($valid));
$form = $this->factory $form = $this->factory
->createBuilder('form', null, array( ->create('form', null, array(
'csrf_field_name' => 'csrf', 'csrf_field_name' => 'csrf',
'csrf_provider' => $this->csrfProvider, 'csrf_provider' => $this->csrfProvider,
'intention' => '%INTENTION%' 'intention' => '%INTENTION%',
)) 'primitive' => false,
->add($this->factory->createNamedBuilder('form', 'child')) ));
->getForm();
$form->bind(array( $form->bind(array(
'child' => 'foobar', 'child' => 'foobar',
@ -171,19 +167,18 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
$this->assertSame($valid, $form->isValid()); $this->assertSame($valid, $form->isValid());
} }
public function testFailIfRootAndChildrenAndTokenMissing() public function testFailIfRootAndNotPrimitiveAndTokenMissing()
{ {
$this->csrfProvider->expects($this->never()) $this->csrfProvider->expects($this->never())
->method('isCsrfTokenValid'); ->method('isCsrfTokenValid');
$form = $this->factory $form = $this->factory
->createBuilder('form', null, array( ->create('form', null, array(
'csrf_field_name' => 'csrf', 'csrf_field_name' => 'csrf',
'csrf_provider' => $this->csrfProvider, 'csrf_provider' => $this->csrfProvider,
'intention' => '%INTENTION%' 'intention' => '%INTENTION%',
)) 'primitive' => false,
->add($this->factory->createNamedBuilder('form', 'child')) ));
->getForm();
$form->bind(array( $form->bind(array(
'child' => 'foobar', 'child' => 'foobar',
@ -197,7 +192,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
$this->assertFalse($form->isValid()); $this->assertFalse($form->isValid());
} }
public function testDontValidateTokenIfChildrenButNoRoot() public function testDontValidateTokenIfNotPrimitiveButNoRoot()
{ {
$this->csrfProvider->expects($this->never()) $this->csrfProvider->expects($this->never())
->method('isCsrfTokenValid'); ->method('isCsrfTokenValid');
@ -208,9 +203,9 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
->createNamedBuilder('form', 'form', null, array( ->createNamedBuilder('form', 'form', null, array(
'csrf_field_name' => 'csrf', 'csrf_field_name' => 'csrf',
'csrf_provider' => $this->csrfProvider, 'csrf_provider' => $this->csrfProvider,
'intention' => '%INTENTION%' 'intention' => '%INTENTION%',
'primitive' => false,
)) ))
->add($this->factory->createNamedBuilder('form', 'child'))
) )
->getForm() ->getForm()
->get('form'); ->get('form');
@ -221,18 +216,18 @@ class FormTypeCsrfExtensionTest extends TypeTestCase
)); ));
} }
public function testDontValidateTokenIfRootButNoChildren() public function testDontValidateTokenIfRootButPrimitive()
{ {
$this->csrfProvider->expects($this->never()) $this->csrfProvider->expects($this->never())
->method('isCsrfTokenValid'); ->method('isCsrfTokenValid');
$form = $this->factory $form = $this->factory
->createBuilder('form', null, array( ->create('form', null, array(
'csrf_field_name' => 'csrf', 'csrf_field_name' => 'csrf',
'csrf_provider' => $this->csrfProvider, 'csrf_provider' => $this->csrfProvider,
'intention' => '%INTENTION%' 'intention' => '%INTENTION%',
)) 'primitive' => true,
->getForm(); ));
$form->bind(array( $form->bind(array(
'csrf' => 'token', 'csrf' => 'token',