Просмотр исходного кода

[Doctrine] fixed security user reloading when the user has been changed via a form with validation errors (closes #2033)

Fabien Potencier 13 лет назад
Родитель
Сommit
9d2ab9ca9c

+ 8 - 2
src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php

@@ -30,13 +30,15 @@ class EntityUserProvider implements UserProviderInterface
     private $class;
     private $repository;
     private $property;
+    private $metadata;
 
     public function __construct(EntityManager $em, $class, $property = null)
     {
         $this->class = $class;
+        $this->metadata = $em->getClassMetadata($class);
 
         if (false !== strpos($this->class, ':')) {
-            $this->class = $em->getClassMetadata($class)->name;
+            $this->class = $this->metadata->name;
         }
 
         $this->repository = $em->getRepository($class);
@@ -74,7 +76,11 @@ class EntityUserProvider implements UserProviderInterface
             throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
         }
 
-        return $this->loadUserByUsername($user->getUsername());
+        // The user must be reloaded via the primary key as all other data
+        // might have changed without proper persistence in the database.
+        // That's the case when the user has been changed by a form with
+        // validation errors.
+        return $this->repository->find($this->metadata->getIdentifierValues($user));
     }
 
     /**

+ 27 - 1
tests/Symfony/Tests/Bridge/Doctrine/Fixtures/CompositeIdentEntity.php

@@ -5,9 +5,10 @@ namespace Symfony\Tests\Bridge\Doctrine\Fixtures;
 use Doctrine\ORM\Mapping\Id;
 use Doctrine\ORM\Mapping\Column;
 use Doctrine\ORM\Mapping\Entity;
+use Symfony\Component\Security\Core\User\UserInterface;
 
 /** @Entity */
-class CompositeIdentEntity
+class CompositeIdentEntity implements UserInterface
 {
     /** @Id @Column(type="integer") */
     protected $id1;
@@ -23,4 +24,29 @@ class CompositeIdentEntity
         $this->id2 = $id2;
         $this->name = $name;
     }
+
+    public function getRoles()
+    {
+    }
+
+    public function getPassword()
+    {
+    }
+
+    public function getSalt()
+    {
+    }
+
+    public function getUsername()
+    {
+        return $this->name;
+    }
+
+    public function eraseCredentials()
+    {
+    }
+
+    public function equals(UserInterface $user)
+    {
+    }
 }

+ 51 - 0
tests/Symfony/Tests/Bridge/Doctrine/Security/User/EntityUserProviderTest.php

@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Tests\Bridge\Doctrine\Security\User;
+
+require_once __DIR__.'/../../DoctrineOrmTestCase.php';
+require_once __DIR__.'/../../Fixtures/CompositeIdentEntity.php';
+
+use Symfony\Tests\Bridge\Doctrine\DoctrineOrmTestCase;
+use Symfony\Tests\Bridge\Doctrine\Fixtures\CompositeIdentEntity;
+use Symfony\Bridge\Doctrine\Security\User\EntityUserProvider;
+use Doctrine\ORM\Tools\SchemaTool;
+
+class EntityUserProviderTest extends DoctrineOrmTestCase
+{
+    public function testRefreshUserGetsUserByPrimaryKey()
+    {
+        $em = $this->createTestEntityManager();
+        $this->createSchema($em);
+
+        $user1 = new CompositeIdentEntity(1, 1, 'user1');
+        $user2 = new CompositeIdentEntity(1, 2, 'user2');
+
+        $em->persist($user1);
+        $em->persist($user2);
+        $em->flush();
+
+        $provider = new EntityUserProvider($em, 'Symfony\Tests\Bridge\Doctrine\Fixtures\CompositeIdentEntity', 'name');
+
+        // try to change the user identity
+        $user1->name = 'user2';
+
+        $this->assertSame($user1, $provider->refreshUser($user1));
+    }
+
+    private function createSchema($em)
+    {
+        $schemaTool = new SchemaTool($em);
+        $schemaTool->createSchema(array(
+            $em->getClassMetadata('Symfony\Tests\Bridge\Doctrine\Fixtures\CompositeIdentEntity'),
+        ));
+    }
+}