Преглед изворни кода

[Security] added unit tests to some authenticated providers (code coverage is more than 96% for the Security component now)

Fabien Potencier пре 14 година
родитељ
комит
ec417578ca

+ 3 - 5
src/Symfony/Component/Security/Authentication/Provider/DaoAuthenticationProvider.php

@@ -55,12 +55,10 @@ class DaoAuthenticationProvider extends UserAuthenticationProvider
      */
     protected function checkAuthentication(AccountInterface $account, UsernamePasswordToken $token)
     {
-        if (null === $token->getCredentials()) {
+        if (!$presentedPassword = (string) $token->getCredentials()) {
             throw new BadCredentialsException('Bad credentials');
         }
 
-        $presentedPassword = (string) $token->getCredentials();
-
         if (!$this->passwordEncoder->isPasswordValid($account->getPassword(), $presentedPassword, $account->getSalt())) {
             throw new BadCredentialsException('Bad credentials');
         }
@@ -80,8 +78,8 @@ class DaoAuthenticationProvider extends UserAuthenticationProvider
             throw new AuthenticationServiceException($repositoryProblem->getMessage(), $token, 0, $repositoryProblem);
         }
 
-        if (null === $user) {
-            throw new AuthenticationServiceException('UserProvider returned null.');
+        if (!$user instanceof AccountInterface) {
+            throw new AuthenticationServiceException('The user provider must return an AccountInterface object.');
         }
 
         return $user;

+ 6 - 10
src/Symfony/Component/Security/Authentication/Provider/UserAuthenticationProvider.php

@@ -7,6 +7,7 @@ use Symfony\Component\Security\User\AccountCheckerInterface;
 use Symfony\Component\Security\Exception\UsernameNotFoundException;
 use Symfony\Component\Security\Exception\AuthenticationException;
 use Symfony\Component\Security\Exception\BadCredentialsException;
+use Symfony\Component\Security\Exception\AuthenticationServiceException;
 use Symfony\Component\Security\Authentication\Token\UsernamePasswordToken;
 use Symfony\Component\Security\Authentication\Token\TokenInterface;
 
@@ -62,17 +63,12 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter
             throw $notFound;
         }
 
-        if (null === $user) {
-            throw new \LogicException('The retrieveUser() methods returned null which should not be possible.');
-        }
-
-        try {
-            $this->accountChecker->checkPreAuth($user);
-            $this->checkAuthentication($user, $token);
-        } catch (AuthenticationException $e) {
-            throw $e;
+        if (!$user instanceof AccountInterface) {
+            throw new AuthenticationServiceException('The retrieveUser() methods must return an AccountInterface object.');
         }
 
+        $this->accountChecker->checkPreAuth($user);
+        $this->checkAuthentication($user, $token);
         $this->accountChecker->checkPostAuth($user);
 
         return new UsernamePasswordToken($user, $token->getCredentials(), $user->getRoles());
@@ -92,7 +88,7 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter
      * @param string                $username The username to retrieve
      * @param UsernamePasswordToken $token    The Token
      *
-     * @return mixed The user
+     * @return AccountInterface The user
      *
      * @throws AuthenticationException if the credentials could not be validated
      */

+ 166 - 0
tests/Symfony/Tests/Component/Security/Authentication/Provider/DaoAuthenticationProviderTest.php

@@ -0,0 +1,166 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Tests\Component\Security\Authentication\Provider;
+
+use Symfony\Component\Security\Authentication\Provider\DaoAuthenticationProvider;
+
+class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @expectedException Symfony\Component\Security\Exception\AuthenticationServiceException
+     */
+    public function testRetrieveUserWhenProviderDoesNotReturnAnAccountInterface()
+    {
+        $provider = $this->getProvider('fabien');
+        $method = new \ReflectionMethod($provider, 'retrieveUser');
+        $method->setAccessible(true);
+
+        $method->invoke($provider, 'fabien', $this->getSupportedToken());
+    }
+
+    /**
+     * @expectedException Symfony\Component\Security\Exception\UsernameNotFoundException
+     */
+    public function testRetrieveUserWhenUsernameIsNotFound()
+    {
+        $userProvider = $this->getMock('Symfony\Component\Security\User\UserProviderInterface');
+        $userProvider->expects($this->once())
+                     ->method('loadUserByUsername')
+                     ->will($this->throwException($this->getMock('Symfony\Component\Security\Exception\UsernameNotFoundException', null, array(), '', false)))
+        ;
+
+        $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface'));
+        $method = new \ReflectionMethod($provider, 'retrieveUser');
+        $method->setAccessible(true);
+
+        $method->invoke($provider, 'fabien', $this->getSupportedToken());
+    }
+
+    /**
+     * @expectedException Symfony\Component\Security\Exception\AuthenticationServiceException
+     */
+    public function testRetrieveUserWhenAnExceptionOccurs()
+    {
+        $userProvider = $this->getMock('Symfony\Component\Security\User\UserProviderInterface');
+        $userProvider->expects($this->once())
+                     ->method('loadUserByUsername')
+                     ->will($this->throwException($this->getMock('RuntimeException', null, array(), '', false)))
+        ;
+
+        $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface'));
+        $method = new \ReflectionMethod($provider, 'retrieveUser');
+        $method->setAccessible(true);
+
+        $method->invoke($provider, 'fabien', $this->getSupportedToken());
+    }
+
+    public function testRetrieveUser()
+    {
+        $user = $this->getMock('Symfony\Component\Security\User\AccountInterface');
+
+        $userProvider = $this->getMock('Symfony\Component\Security\User\UserProviderInterface');
+        $userProvider->expects($this->once())
+                     ->method('loadUserByUsername')
+                     ->will($this->returnValue($user))
+        ;
+
+        $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface'));
+        $method = new \ReflectionMethod($provider, 'retrieveUser');
+        $method->setAccessible(true);
+
+        $this->assertSame($user, $method->invoke($provider, 'fabien', $this->getSupportedToken()));
+    }
+
+    /**
+     * @expectedException Symfony\Component\Security\Exception\BadCredentialsException
+     */
+    public function testCheckAuthenticationWhenCredentialsAreEmpty()
+    {
+        $provider = $this->getProvider();
+        $method = new \ReflectionMethod($provider, 'checkAuthentication');
+        $method->setAccessible(true);
+
+        $token = $this->getSupportedToken();
+        $token->expects($this->once())
+              ->method('getCredentials')
+              ->will($this->returnValue(''))
+        ;
+
+        $method->invoke($provider, $this->getMock('Symfony\Component\Security\User\AccountInterface'), $token);
+    }
+
+    /**
+     * @expectedException Symfony\Component\Security\Exception\BadCredentialsException
+     */
+    public function testCheckAuthenticationWhenCredentialsAreNotValid()
+    {
+        $encoder = $this->getMock('Symfony\Component\Security\Encoder\PasswordEncoderInterface');
+        $encoder->expects($this->once())
+                ->method('isPasswordValid')
+                ->will($this->returnValue(false))
+        ;
+
+        $provider = $this->getProvider(false, false, $encoder);
+        $method = new \ReflectionMethod($provider, 'checkAuthentication');
+        $method->setAccessible(true);
+
+        $token = $this->getSupportedToken();
+        $token->expects($this->once())
+              ->method('getCredentials')
+              ->will($this->returnValue('foo'))
+        ;
+
+        $method->invoke($provider, $this->getMock('Symfony\Component\Security\User\AccountInterface'), $token);
+    }
+
+    public function testCheckAuthentication()
+    {
+        $encoder = $this->getMock('Symfony\Component\Security\Encoder\PasswordEncoderInterface');
+        $encoder->expects($this->once())
+                ->method('isPasswordValid')
+                ->will($this->returnValue(true))
+        ;
+
+        $provider = $this->getProvider(false, false, $encoder);
+        $method = new \ReflectionMethod($provider, 'checkAuthentication');
+        $method->setAccessible(true);
+
+        $token = $this->getSupportedToken();
+        $token->expects($this->once())
+              ->method('getCredentials')
+              ->will($this->returnValue('foo'))
+        ;
+
+        $method->invoke($provider, $this->getMock('Symfony\Component\Security\User\AccountInterface'), $token);
+    }
+
+    protected function getSupportedToken()
+    {
+        return $this->getMock('Symfony\Component\Security\Authentication\Token\UsernamePasswordToken', array('getCredentials'), array(), '', false);
+    }
+
+    protected function getProvider($user = false, $userChecker = false, $passwordEncoder = null)
+    {
+        $userProvider = $this->getMock('Symfony\Component\Security\User\UserProviderInterface');
+        if (false !== $user) {
+            $userProvider->expects($this->once())
+                         ->method('loadUserByUsername')
+                         ->will($this->returnValue($user))
+            ;
+        }
+
+        if (false === $userChecker) {
+            $userChecker = $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface');
+        }
+
+        return new DaoAuthenticationProvider($userProvider, $userChecker, $passwordEncoder);
+    }
+}

+ 174 - 0
tests/Symfony/Tests/Component/Security/Authentication/Provider/UserAuthenticationProviderTest.php

@@ -0,0 +1,174 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Tests\Component\Security\Authentication\Provider;
+
+use Symfony\Component\Security\Authentication\Provider\UserAuthenticationProvider;
+use Symfony\Component\Security\Role\Role;
+
+class UserAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
+{
+    public function testSupports()
+    {
+        $provider = $this->getProvider();
+
+        $this->assertTrue($provider->supports($this->getSupportedToken()));
+        $this->assertFalse($provider->supports($this->getMock('Symfony\Component\Security\Authentication\Token\TokenInterface')));
+    }
+
+    public function testAuthenticateWhenTokenIsNotSupported()
+    {
+        $provider = $this->getProvider();
+
+        $this->assertNull($provider->authenticate($this->getMock('Symfony\Component\Security\Authentication\Token\TokenInterface')));
+    }
+
+    /**
+     * @expectedException Symfony\Component\Security\Exception\UsernameNotFoundException
+     */
+    public function testAuthenticateWhenUsernameIsNotFound()
+    {
+        $provider = $this->getProvider(false, false);
+        $provider->expects($this->once())
+                 ->method('retrieveUser')
+                 ->will($this->throwException($this->getMock('Symfony\Component\Security\Exception\UsernameNotFoundException', null, array(), '', false)))
+        ;
+
+        $provider->authenticate($this->getSupportedToken());
+    }
+
+    /**
+     * @expectedException Symfony\Component\Security\Exception\BadCredentialsException
+     */
+    public function testAuthenticateWhenUsernameIsNotFoundAndHideIsTrue()
+    {
+        $provider = $this->getProvider(false, true);
+        $provider->expects($this->once())
+                 ->method('retrieveUser')
+                 ->will($this->throwException($this->getMock('Symfony\Component\Security\Exception\UsernameNotFoundException', null, array(), '', false)))
+        ;
+
+        $provider->authenticate($this->getSupportedToken());
+    }
+
+    /**
+     * @expectedException Symfony\Component\Security\Exception\AuthenticationServiceException
+     */
+    public function testAuthenticateWhenProviderDoesNotReturnAnAccountInterface()
+    {
+        $provider = $this->getProvider(false, true);
+        $provider->expects($this->once())
+                 ->method('retrieveUser')
+                 ->will($this->returnValue(null))
+        ;
+
+        $provider->authenticate($this->getSupportedToken());
+    }
+
+    /**
+     * @expectedException Symfony\Component\Security\Exception\CredentialsExpiredException
+     */
+    public function testAuthenticateWhenPreChecksFails()
+    {
+        $userChecker = $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface');
+        $userChecker->expects($this->once())
+                    ->method('checkPreAuth')
+                    ->will($this->throwException($this->getMock('Symfony\Component\Security\Exception\CredentialsExpiredException', null, array(), '', false)))
+        ;
+
+        $provider = $this->getProvider($userChecker);
+        $provider->expects($this->once())
+                 ->method('retrieveUser')
+                 ->will($this->returnValue($this->getMock('Symfony\Component\Security\User\AccountInterface')))
+        ;
+
+        $provider->authenticate($this->getSupportedToken());
+    }
+
+    /**
+     * @expectedException Symfony\Component\Security\Exception\AccountExpiredException
+     */
+    public function testAuthenticateWhenPostChecksFails()
+    {
+        $userChecker = $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface');
+        $userChecker->expects($this->once())
+                    ->method('checkPostAuth')
+                    ->will($this->throwException($this->getMock('Symfony\Component\Security\Exception\AccountExpiredException', null, array(), '', false)))
+        ;
+
+        $provider = $this->getProvider($userChecker);
+        $provider->expects($this->once())
+                 ->method('retrieveUser')
+                 ->will($this->returnValue($this->getMock('Symfony\Component\Security\User\AccountInterface')))
+        ;
+
+        $provider->authenticate($this->getSupportedToken());
+    }
+
+    /**
+     * @expectedException Symfony\Component\Security\Exception\BadCredentialsException
+     */
+    public function testAuthenticateWhenPostCheckAuthenticationFails()
+    {
+        $provider = $this->getProvider();
+        $provider->expects($this->once())
+                 ->method('retrieveUser')
+                 ->will($this->returnValue($this->getMock('Symfony\Component\Security\User\AccountInterface')))
+        ;
+        $provider->expects($this->once())
+                 ->method('checkAuthentication')
+                 ->will($this->throwException($this->getMock('Symfony\Component\Security\Exception\BadCredentialsException', null, array(), '', false)))
+        ;
+
+        $provider->authenticate($this->getSupportedToken());
+    }
+
+    public function testAuthenticate()
+    {
+        $user = $this->getMock('Symfony\Component\Security\User\AccountInterface');
+        $user->expects($this->once())
+             ->method('getRoles')
+             ->will($this->returnValue(array('ROLE_FOO')))
+        ;
+
+        $provider = $this->getProvider();
+        $provider->expects($this->once())
+                 ->method('retrieveUser')
+                 ->will($this->returnValue($user))
+        ;
+
+        $token = $this->getSupportedToken();
+        $token->expects($this->once())
+              ->method('getCredentials')
+              ->will($this->returnValue('foo'))
+        ;
+
+        $authToken = $provider->authenticate($token);
+
+        $this->assertInstanceOf('Symfony\Component\Security\Authentication\Token\UsernamePasswordToken', $authToken);
+        $this->assertSame($user, $authToken->getUser());
+        $this->assertEquals(array(new Role('ROLE_FOO')), $authToken->getRoles());
+        $this->assertEquals('foo', $authToken->getCredentials());
+    }
+
+    protected function getSupportedToken()
+    {
+        return $this->getMock('Symfony\Component\Security\Authentication\Token\UsernamePasswordToken', array('getCredentials'), array(), '', false);
+    }
+
+    protected function getProvider($userChecker = false, $hide = true)
+    {
+        if (false === $userChecker) {
+            $userChecker = $this->getMock('Symfony\Component\Security\User\AccountCheckerInterface');
+        }
+
+        return $this->getMockForAbstractClass('Symfony\Component\Security\Authentication\Provider\UserAuthenticationProvider', array($userChecker, $hide));
+    }
+}