summaryrefslogtreecommitdiffstats
path: root/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Core')
-rw-r--r--Core/.gitignore3
-rw-r--r--Core/Authentication/AuthenticationProviderManager.php6
-rw-r--r--Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php34
-rw-r--r--Core/Authentication/Provider/SimpleAuthenticationProvider.php50
-rw-r--r--Core/Authentication/Provider/UserAuthenticationProvider.php4
-rw-r--r--Core/Authentication/SimpleAuthenticatorInterface.php25
-rw-r--r--Core/Authentication/SimpleFormAuthenticatorInterface.php22
-rw-r--r--Core/Authentication/SimplePreAuthenticatorInterface.php22
-rw-r--r--Core/Authentication/Token/AbstractToken.php12
-rw-r--r--Core/Authentication/Token/Storage/TokenStorage.php43
-rw-r--r--Core/Authentication/Token/Storage/TokenStorageInterface.php36
-rw-r--r--Core/Authorization/AccessDecisionManager.php13
-rw-r--r--Core/Authorization/AuthorizationChecker.php70
-rw-r--r--Core/Authorization/AuthorizationCheckerInterface.php30
-rw-r--r--Core/Authorization/ExpressionLanguage.php33
-rw-r--r--Core/Authorization/ExpressionLanguageProvider.php58
-rw-r--r--Core/Authorization/Voter/AbstractVoter.php113
-rw-r--r--Core/Authorization/Voter/ExpressionVoter.php118
-rw-r--r--Core/Encoder/EncoderAwareInterface.php28
-rw-r--r--Core/Encoder/EncoderFactory.php27
-rw-r--r--Core/Encoder/UserPasswordEncoder.php55
-rw-r--r--Core/Encoder/UserPasswordEncoderInterface.php40
-rw-r--r--Core/Exception/AccessDeniedException.php2
-rw-r--r--Core/Exception/ExceptionInterface.php21
-rw-r--r--Core/Exception/InvalidArgumentException.php21
-rw-r--r--Core/Exception/RuntimeException.php21
-rw-r--r--Core/Exception/UsernameNotFoundException.php8
-rw-r--r--Core/LICENSE19
-rw-r--r--Core/README.md23
-rw-r--r--Core/Resources/translations/security.ar.xlf71
-rw-r--r--Core/Resources/translations/security.az.xlf71
-rw-r--r--Core/Resources/translations/security.bg.xlf71
-rw-r--r--Core/Resources/translations/security.ca.xlf71
-rw-r--r--Core/Resources/translations/security.cs.xlf71
-rw-r--r--Core/Resources/translations/security.da.xlf71
-rw-r--r--Core/Resources/translations/security.de.xlf71
-rw-r--r--Core/Resources/translations/security.el.xlf71
-rw-r--r--Core/Resources/translations/security.en.xlf71
-rw-r--r--Core/Resources/translations/security.es.xlf71
-rw-r--r--Core/Resources/translations/security.fa.xlf71
-rw-r--r--Core/Resources/translations/security.fr.xlf71
-rw-r--r--Core/Resources/translations/security.gl.xlf71
-rw-r--r--Core/Resources/translations/security.he.xlf71
-rw-r--r--Core/Resources/translations/security.hr.xlf71
-rw-r--r--Core/Resources/translations/security.hu.xlf71
-rw-r--r--Core/Resources/translations/security.id.xlf71
-rw-r--r--Core/Resources/translations/security.it.xlf71
-rw-r--r--Core/Resources/translations/security.ja.xlf71
-rw-r--r--Core/Resources/translations/security.lb.xlf71
-rw-r--r--Core/Resources/translations/security.lt.xlf71
-rw-r--r--Core/Resources/translations/security.nl.xlf71
-rw-r--r--Core/Resources/translations/security.no.xlf71
-rw-r--r--Core/Resources/translations/security.pl.xlf71
-rw-r--r--Core/Resources/translations/security.pt_BR.xlf71
-rw-r--r--Core/Resources/translations/security.pt_PT.xlf71
-rw-r--r--Core/Resources/translations/security.ro.xlf71
-rw-r--r--Core/Resources/translations/security.ru.xlf71
-rw-r--r--Core/Resources/translations/security.sk.xlf71
-rw-r--r--Core/Resources/translations/security.sl.xlf71
-rw-r--r--Core/Resources/translations/security.sr_Cyrl.xlf71
-rw-r--r--Core/Resources/translations/security.sr_Latn.xlf71
-rw-r--r--Core/Resources/translations/security.sv.xlf71
-rw-r--r--Core/Resources/translations/security.th.xlf71
-rw-r--r--Core/Resources/translations/security.tr.xlf71
-rw-r--r--Core/Resources/translations/security.ua.xlf71
-rw-r--r--Core/Resources/translations/security.vi.xlf71
-rw-r--r--Core/Resources/translations/security.zh_CN.xlf71
-rw-r--r--Core/Role/RoleHierarchy.php4
-rw-r--r--Core/Security.php24
-rw-r--r--Core/SecurityContext.php79
-rw-r--r--Core/SecurityContextInterface.php37
-rw-r--r--Core/Tests/Authentication/AuthenticationProviderManagerTest.php148
-rw-r--r--Core/Tests/Authentication/AuthenticationTrustResolverTest.php70
-rw-r--r--Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php66
-rw-r--r--Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php300
-rw-r--r--Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php134
-rw-r--r--Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php107
-rw-r--r--Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php250
-rw-r--r--Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php63
-rw-r--r--Core/Tests/Authentication/RememberMe/PersistentTokenTest.php29
-rw-r--r--Core/Tests/Authentication/Token/AbstractTokenTest.php269
-rw-r--r--Core/Tests/Authentication/Token/AnonymousTokenTest.php45
-rw-r--r--Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.php48
-rw-r--r--Core/Tests/Authentication/Token/RememberMeTokenTest.php66
-rw-r--r--Core/Tests/Authentication/Token/Storage/TokenStorageTest.php26
-rw-r--r--Core/Tests/Authentication/Token/UsernamePasswordTokenTest.php58
-rw-r--r--Core/Tests/Authorization/AccessDecisionManagerTest.php198
-rw-r--r--Core/Tests/Authorization/AuthorizationCheckerTest.php99
-rw-r--r--Core/Tests/Authorization/ExpressionLanguageTest.php79
-rw-r--r--Core/Tests/Authorization/Voter/AbstractVoterTest.php74
-rw-r--r--Core/Tests/Authorization/Voter/AuthenticatedVoterTest.php78
-rw-r--r--Core/Tests/Authorization/Voter/ExpressionVoterTest.php97
-rw-r--r--Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.php36
-rw-r--r--Core/Tests/Authorization/Voter/RoleVoterTest.php61
-rw-r--r--Core/Tests/Encoder/BCryptPasswordEncoderTest.php81
-rw-r--r--Core/Tests/Encoder/BasePasswordEncoderTest.php101
-rw-r--r--Core/Tests/Encoder/EncoderFactoryTest.php172
-rw-r--r--Core/Tests/Encoder/MessageDigestPasswordEncoderTest.php62
-rw-r--r--Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.php62
-rw-r--r--Core/Tests/Encoder/PlaintextPasswordEncoderTest.php56
-rw-r--r--Core/Tests/Encoder/UserPasswordEncoderTest.php70
-rw-r--r--Core/Tests/Exception/UsernameNotFoundExceptionTest.php25
-rw-r--r--Core/Tests/LegacySecurityContextInterfaceTest.php31
-rw-r--r--Core/Tests/LegacySecurityContextTest.php122
-rw-r--r--Core/Tests/Role/RoleHierarchyTest.php32
-rw-r--r--Core/Tests/Role/RoleTest.php24
-rw-r--r--Core/Tests/Role/SwitchUserRoleTest.php31
-rw-r--r--Core/Tests/User/ChainUserProviderTest.php183
-rw-r--r--Core/Tests/User/InMemoryUserProviderTest.php83
-rw-r--r--Core/Tests/User/UserCheckerTest.php108
-rw-r--r--Core/Tests/User/UserTest.php101
-rw-r--r--Core/Tests/Util/ClassUtilsTest.php50
-rw-r--r--Core/Tests/Util/StringUtilsTest.php61
-rw-r--r--Core/Tests/Validator/Constraints/LegacyUserPasswordValidatorTest.php28
-rw-r--r--Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php169
-rw-r--r--Core/User/User.php5
-rw-r--r--Core/Validator/Constraints/UserPassword.php2
-rw-r--r--Core/Validator/Constraints/UserPasswordValidator.php15
-rw-r--r--Core/composer.json49
-rw-r--r--Core/phpunit.xml.dist34
120 files changed, 7853 insertions, 104 deletions
diff --git a/Core/.gitignore b/Core/.gitignore
new file mode 100644
index 0000000..c49a5d8
--- /dev/null
+++ b/Core/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/Core/Authentication/AuthenticationProviderManager.php b/Core/Authentication/AuthenticationProviderManager.php
index f713e8f..16de8da 100644
--- a/Core/Authentication/AuthenticationProviderManager.php
+++ b/Core/Authentication/AuthenticationProviderManager.php
@@ -48,6 +48,12 @@ class AuthenticationProviderManager implements AuthenticationManagerInterface
throw new \InvalidArgumentException('You must at least add one authentication provider.');
}
+ foreach ($providers as $provider) {
+ if (!$provider instanceof AuthenticationProviderInterface) {
+ throw new \InvalidArgumentException(sprintf('Provider "%s" must implement the AuthenticationProviderInterface.', get_class($provider)));
+ }
+ }
+
$this->providers = $providers;
$this->eraseCredentials = (bool) $eraseCredentials;
}
diff --git a/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php b/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php
index 87b7114..4f73254 100644
--- a/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php
+++ b/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php
@@ -47,28 +47,28 @@ class PreAuthenticatedAuthenticationProvider implements AuthenticationProviderIn
$this->providerKey = $providerKey;
}
- /**
- * {@inheritdoc}
- */
- public function authenticate(TokenInterface $token)
- {
- if (!$this->supports($token)) {
- return;
- }
+ /**
+ * {@inheritdoc}
+ */
+ public function authenticate(TokenInterface $token)
+ {
+ if (!$this->supports($token)) {
+ return;
+ }
- if (!$user = $token->getUser()) {
- throw new BadCredentialsException('No pre-authenticated principal found in request.');
- }
+ if (!$user = $token->getUser()) {
+ throw new BadCredentialsException('No pre-authenticated principal found in request.');
+ }
- $user = $this->userProvider->loadUserByUsername($user);
+ $user = $this->userProvider->loadUserByUsername($user);
- $this->userChecker->checkPostAuth($user);
+ $this->userChecker->checkPostAuth($user);
- $authenticatedToken = new PreAuthenticatedToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles());
- $authenticatedToken->setAttributes($token->getAttributes());
+ $authenticatedToken = new PreAuthenticatedToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles());
+ $authenticatedToken->setAttributes($token->getAttributes());
- return $authenticatedToken;
- }
+ return $authenticatedToken;
+ }
/**
* {@inheritdoc}
diff --git a/Core/Authentication/Provider/SimpleAuthenticationProvider.php b/Core/Authentication/Provider/SimpleAuthenticationProvider.php
new file mode 100644
index 0000000..ffbc72c
--- /dev/null
+++ b/Core/Authentication/Provider/SimpleAuthenticationProvider.php
@@ -0,0 +1,50 @@
+<?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\Component\Security\Core\Authentication\Provider;
+
+use Symfony\Component\Security\Core\User\UserProviderInterface;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface;
+use Symfony\Component\Security\Core\Exception\AuthenticationException;
+
+/**
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+class SimpleAuthenticationProvider implements AuthenticationProviderInterface
+{
+ private $simpleAuthenticator;
+ private $userProvider;
+ private $providerKey;
+
+ public function __construct(SimpleAuthenticatorInterface $simpleAuthenticator, UserProviderInterface $userProvider, $providerKey)
+ {
+ $this->simpleAuthenticator = $simpleAuthenticator;
+ $this->userProvider = $userProvider;
+ $this->providerKey = $providerKey;
+ }
+
+ public function authenticate(TokenInterface $token)
+ {
+ $authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey);
+
+ if ($authToken instanceof TokenInterface) {
+ return $authToken;
+ }
+
+ throw new AuthenticationException('Simple authenticator failed to return an authenticated token.');
+ }
+
+ public function supports(TokenInterface $token)
+ {
+ return $this->simpleAuthenticator->supportsToken($token, $this->providerKey);
+ }
+}
diff --git a/Core/Authentication/Provider/UserAuthenticationProvider.php b/Core/Authentication/Provider/UserAuthenticationProvider.php
index a624ccf..2674088 100644
--- a/Core/Authentication/Provider/UserAuthenticationProvider.php
+++ b/Core/Authentication/Provider/UserAuthenticationProvider.php
@@ -70,7 +70,7 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter
$user = $this->retrieveUser($username, $token);
} catch (UsernameNotFoundException $e) {
if ($this->hideUserNotFoundExceptions) {
- throw new BadCredentialsException('Bad credentials', 0, $e);
+ throw new BadCredentialsException('Bad credentials.', 0, $e);
}
$e->setUsername($username);
@@ -87,7 +87,7 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter
$this->userChecker->checkPostAuth($user);
} catch (BadCredentialsException $e) {
if ($this->hideUserNotFoundExceptions) {
- throw new BadCredentialsException('Bad credentials', 0, $e);
+ throw new BadCredentialsException('Bad credentials.', 0, $e);
}
throw $e;
diff --git a/Core/Authentication/SimpleAuthenticatorInterface.php b/Core/Authentication/SimpleAuthenticatorInterface.php
new file mode 100644
index 0000000..868d072
--- /dev/null
+++ b/Core/Authentication/SimpleAuthenticatorInterface.php
@@ -0,0 +1,25 @@
+<?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\Component\Security\Core\Authentication;
+
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Core\User\UserProviderInterface;
+
+/**
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+interface SimpleAuthenticatorInterface
+{
+ public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey);
+
+ public function supportsToken(TokenInterface $token, $providerKey);
+}
diff --git a/Core/Authentication/SimpleFormAuthenticatorInterface.php b/Core/Authentication/SimpleFormAuthenticatorInterface.php
new file mode 100644
index 0000000..95ee881
--- /dev/null
+++ b/Core/Authentication/SimpleFormAuthenticatorInterface.php
@@ -0,0 +1,22 @@
+<?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\Component\Security\Core\Authentication;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+interface SimpleFormAuthenticatorInterface extends SimpleAuthenticatorInterface
+{
+ public function createToken(Request $request, $username, $password, $providerKey);
+}
diff --git a/Core/Authentication/SimplePreAuthenticatorInterface.php b/Core/Authentication/SimplePreAuthenticatorInterface.php
new file mode 100644
index 0000000..6164e7d
--- /dev/null
+++ b/Core/Authentication/SimplePreAuthenticatorInterface.php
@@ -0,0 +1,22 @@
+<?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\Component\Security\Core\Authentication;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+interface SimplePreAuthenticatorInterface extends SimpleAuthenticatorInterface
+{
+ public function createToken(Request $request, $providerKey);
+}
diff --git a/Core/Authentication/Token/AbstractToken.php b/Core/Authentication/Token/AbstractToken.php
index b07312f..7538648 100644
--- a/Core/Authentication/Token/AbstractToken.php
+++ b/Core/Authentication/Token/AbstractToken.php
@@ -26,9 +26,9 @@ use Symfony\Component\Security\Core\User\EquatableInterface;
abstract class AbstractToken implements TokenInterface
{
private $user;
- private $roles;
- private $authenticated;
- private $attributes;
+ private $roles = array();
+ private $authenticated = false;
+ private $attributes = array();
/**
* Constructor.
@@ -39,10 +39,6 @@ abstract class AbstractToken implements TokenInterface
*/
public function __construct(array $roles = array())
{
- $this->authenticated = false;
- $this->attributes = array();
-
- $this->roles = array();
foreach ($roles as $role) {
if (is_string($role)) {
$role = new Role($role);
@@ -219,7 +215,7 @@ abstract class AbstractToken implements TokenInterface
}
/**
- * Sets a attribute.
+ * Sets an attribute.
*
* @param string $name The attribute name
* @param mixed $value The attribute value
diff --git a/Core/Authentication/Token/Storage/TokenStorage.php b/Core/Authentication/Token/Storage/TokenStorage.php
new file mode 100644
index 0000000..b493081
--- /dev/null
+++ b/Core/Authentication/Token/Storage/TokenStorage.php
@@ -0,0 +1,43 @@
+<?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\Component\Security\Core\Authentication\Token\Storage;
+
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+
+/**
+ * TokenStorage contains a TokenInterface.
+ *
+ * It gives access to the token representing the current user authentication.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class TokenStorage implements TokenStorageInterface
+{
+ private $token;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getToken()
+ {
+ return $this->token;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setToken(TokenInterface $token = null)
+ {
+ $this->token = $token;
+ }
+}
diff --git a/Core/Authentication/Token/Storage/TokenStorageInterface.php b/Core/Authentication/Token/Storage/TokenStorageInterface.php
new file mode 100644
index 0000000..218d750
--- /dev/null
+++ b/Core/Authentication/Token/Storage/TokenStorageInterface.php
@@ -0,0 +1,36 @@
+<?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\Component\Security\Core\Authentication\Token\Storage;
+
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+
+/**
+ * The TokenStorageInterface.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+interface TokenStorageInterface
+{
+ /**
+ * Returns the current security token.
+ *
+ * @return TokenInterface|null A TokenInterface instance or null if no authentication information is available
+ */
+ public function getToken();
+
+ /**
+ * Sets the authentication token.
+ *
+ * @param TokenInterface $token A TokenInterface token, or null if no further authentication information should be stored
+ */
+ public function setToken(TokenInterface $token = null);
+}
diff --git a/Core/Authorization/AccessDecisionManager.php b/Core/Authorization/AccessDecisionManager.php
index 6e5effb..b8b6a77 100644
--- a/Core/Authorization/AccessDecisionManager.php
+++ b/Core/Authorization/AccessDecisionManager.php
@@ -22,6 +22,10 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
*/
class AccessDecisionManager implements AccessDecisionManagerInterface
{
+ const STRATEGY_AFFIRMATIVE = 'affirmative';
+ const STRATEGY_CONSENSUS = 'consensus';
+ const STRATEGY_UNANIMOUS = 'unanimous';
+
private $voters;
private $strategy;
private $allowIfAllAbstainDecisions;
@@ -37,14 +41,19 @@ class AccessDecisionManager implements AccessDecisionManagerInterface
*
* @throws \InvalidArgumentException
*/
- public function __construct(array $voters, $strategy = 'affirmative', $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true)
+ public function __construct(array $voters, $strategy = self::STRATEGY_AFFIRMATIVE, $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true)
{
if (!$voters) {
throw new \InvalidArgumentException('You must at least add one voter.');
}
+ $strategyMethod = 'decide'.ucfirst($strategy);
+ if (!is_callable(array($this, $strategyMethod))) {
+ throw new \InvalidArgumentException(sprintf('The strategy "%s" is not supported.', $strategy));
+ }
+
$this->voters = $voters;
- $this->strategy = 'decide'.ucfirst($strategy);
+ $this->strategy = $strategyMethod;
$this->allowIfAllAbstainDecisions = (bool) $allowIfAllAbstainDecisions;
$this->allowIfEqualGrantedDeniedDecisions = (bool) $allowIfEqualGrantedDeniedDecisions;
}
diff --git a/Core/Authorization/AuthorizationChecker.php b/Core/Authorization/AuthorizationChecker.php
new file mode 100644
index 0000000..23c190c
--- /dev/null
+++ b/Core/Authorization/AuthorizationChecker.php
@@ -0,0 +1,70 @@
+<?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\Component\Security\Core\Authorization;
+
+use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
+use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
+
+/**
+ * AuthorizationChecker is the main authorization point of the Security component.
+ *
+ * It gives access to the token representing the current user authentication.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class AuthorizationChecker implements AuthorizationCheckerInterface
+{
+ private $tokenStorage;
+ private $accessDecisionManager;
+ private $authenticationManager;
+ private $alwaysAuthenticate;
+
+ /**
+ * Constructor.
+ *
+ * @param TokenStorageInterface $tokenStorage
+ * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManager instance
+ * @param AccessDecisionManagerInterface $accessDecisionManager An AccessDecisionManager instance
+ * @param bool $alwaysAuthenticate
+ */
+ public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, AccessDecisionManagerInterface $accessDecisionManager, $alwaysAuthenticate = false)
+ {
+ $this->tokenStorage = $tokenStorage;
+ $this->authenticationManager = $authenticationManager;
+ $this->accessDecisionManager = $accessDecisionManager;
+ $this->alwaysAuthenticate = $alwaysAuthenticate;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @throws AuthenticationCredentialsNotFoundException when the token storage has no authentication token.
+ */
+ final public function isGranted($attributes, $object = null)
+ {
+ if (null === ($token = $this->tokenStorage->getToken())) {
+ throw new AuthenticationCredentialsNotFoundException('The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL.');
+ }
+
+ if ($this->alwaysAuthenticate || !$token->isAuthenticated()) {
+ $this->tokenStorage->setToken($token = $this->authenticationManager->authenticate($token));
+ }
+
+ if (!is_array($attributes)) {
+ $attributes = array($attributes);
+ }
+
+ return $this->accessDecisionManager->decide($token, $attributes, $object);
+ }
+}
diff --git a/Core/Authorization/AuthorizationCheckerInterface.php b/Core/Authorization/AuthorizationCheckerInterface.php
new file mode 100644
index 0000000..bd24d6f
--- /dev/null
+++ b/Core/Authorization/AuthorizationCheckerInterface.php
@@ -0,0 +1,30 @@
+<?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\Component\Security\Core\Authorization;
+
+/**
+ * The AuthorizationCheckerInterface.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+interface AuthorizationCheckerInterface
+{
+ /**
+ * Checks if the attributes are granted against the current authentication token and optionally supplied object.
+ *
+ * @param mixed $attributes
+ * @param mixed $object
+ *
+ * @return bool
+ */
+ public function isGranted($attributes, $object = null);
+}
diff --git a/Core/Authorization/ExpressionLanguage.php b/Core/Authorization/ExpressionLanguage.php
new file mode 100644
index 0000000..c2925af
--- /dev/null
+++ b/Core/Authorization/ExpressionLanguage.php
@@ -0,0 +1,33 @@
+<?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\Component\Security\Core\Authorization;
+
+use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
+use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;
+
+/**
+ * Adds some function to the default ExpressionLanguage.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @see ExpressionLanguageProvider
+ */
+class ExpressionLanguage extends BaseExpressionLanguage
+{
+ public function __construct(ParserCacheInterface $cache = null, array $providers = array())
+ {
+ // prepend the default provider to let users override it easily
+ array_unshift($providers, new ExpressionLanguageProvider());
+
+ parent::__construct($cache, $providers);
+ }
+}
diff --git a/Core/Authorization/ExpressionLanguageProvider.php b/Core/Authorization/ExpressionLanguageProvider.php
new file mode 100644
index 0000000..9293ba7
--- /dev/null
+++ b/Core/Authorization/ExpressionLanguageProvider.php
@@ -0,0 +1,58 @@
+<?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\Component\Security\Core\Authorization;
+
+use Symfony\Component\ExpressionLanguage\ExpressionFunction;
+use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
+
+/**
+ * Define some ExpressionLanguage functions.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
+{
+ public function getFunctions()
+ {
+ return array(
+ new ExpressionFunction('is_anonymous', function () {
+ return '$trust_resolver->isAnonymous($token)';
+ }, function (array $variables) {
+ return $variables['trust_resolver']->isAnonymous($variables['token']);
+ }),
+
+ new ExpressionFunction('is_authenticated', function () {
+ return '$token && !$trust_resolver->isAnonymous($token)';
+ }, function (array $variables) {
+ return $variables['token'] && !$variables['trust_resolver']->isAnonymous($variables['token']);
+ }),
+
+ new ExpressionFunction('is_fully_authenticated', function () {
+ return '$trust_resolver->isFullFledged($token)';
+ }, function (array $variables) {
+ return $variables['trust_resolver']->isFullFledged($variables['token']);
+ }),
+
+ new ExpressionFunction('is_remember_me', function () {
+ return '$trust_resolver->isRememberMe($token)';
+ }, function (array $variables) {
+ return $variables['trust_resolver']->isRememberMe($variables['token']);
+ }),
+
+ new ExpressionFunction('has_role', function ($role) {
+ return sprintf('in_array(%s, $roles)', $role);
+ }, function (array $variables, $role) {
+ return in_array($role, $variables['roles']);
+ }),
+ );
+ }
+}
diff --git a/Core/Authorization/Voter/AbstractVoter.php b/Core/Authorization/Voter/AbstractVoter.php
new file mode 100644
index 0000000..efa1562
--- /dev/null
+++ b/Core/Authorization/Voter/AbstractVoter.php
@@ -0,0 +1,113 @@
+<?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\Component\Security\Core\Authorization\Voter;
+
+use Symfony\Component\Security\Core\User\UserInterface;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+
+/**
+ * Abstract Voter implementation that reduces boilerplate code required to create a custom Voter.
+ *
+ * @author Roman Marintšenko <inoryy@gmail.com>
+ */
+abstract class AbstractVoter implements VoterInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function supportsAttribute($attribute)
+ {
+ return in_array($attribute, $this->getSupportedAttributes());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function supportsClass($class)
+ {
+ foreach ($this->getSupportedClasses() as $supportedClass) {
+ if ($supportedClass === $class || is_subclass_of($class, $supportedClass)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Iteratively check all given attributes by calling isGranted.
+ *
+ * This method terminates as soon as it is able to return ACCESS_GRANTED
+ * If at least one attribute is supported, but access not granted, then ACCESS_DENIED is returned
+ * Otherwise it will return ACCESS_ABSTAIN
+ *
+ * @param TokenInterface $token A TokenInterface instance
+ * @param object $object The object to secure
+ * @param array $attributes An array of attributes associated with the method being invoked
+ *
+ * @return int either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED
+ */
+ public function vote(TokenInterface $token, $object, array $attributes)
+ {
+ if (!$object || !$this->supportsClass(get_class($object))) {
+ return self::ACCESS_ABSTAIN;
+ }
+
+ // abstain vote by default in case none of the attributes are supported
+ $vote = self::ACCESS_ABSTAIN;
+
+ foreach ($attributes as $attribute) {
+ if (!$this->supportsAttribute($attribute)) {
+ continue;
+ }
+
+ // as soon as at least one attribute is supported, default is to deny access
+ $vote = self::ACCESS_DENIED;
+
+ if ($this->isGranted($attribute, $object, $token->getUser())) {
+ // grant access as soon as at least one voter returns a positive response
+ return self::ACCESS_GRANTED;
+ }
+ }
+
+ return $vote;
+ }
+
+ /**
+ * Return an array of supported classes. This will be called by supportsClass.
+ *
+ * @return array an array of supported classes, i.e. array('Acme\DemoBundle\Model\Product')
+ */
+ abstract protected function getSupportedClasses();
+
+ /**
+ * Return an array of supported attributes. This will be called by supportsAttribute.
+ *
+ * @return array an array of supported attributes, i.e. array('CREATE', 'READ')
+ */
+ abstract protected function getSupportedAttributes();
+
+ /**
+ * Perform a single access check operation on a given attribute, object and (optionally) user
+ * It is safe to assume that $attribute and $object's class pass supportsAttribute/supportsClass
+ * $user can be one of the following:
+ * a UserInterface object (fully authenticated user)
+ * a string (anonymously authenticated user).
+ *
+ * @param string $attribute
+ * @param object $object
+ * @param UserInterface|string $user
+ *
+ * @return bool
+ */
+ abstract protected function isGranted($attribute, $object, $user = null);
+}
diff --git a/Core/Authorization/Voter/ExpressionVoter.php b/Core/Authorization/Voter/ExpressionVoter.php
new file mode 100644
index 0000000..98b8f50
--- /dev/null
+++ b/Core/Authorization/Voter/ExpressionVoter.php
@@ -0,0 +1,118 @@
+<?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\Component\Security\Core\Authorization\Voter;
+
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
+use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
+use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
+use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
+use Symfony\Component\ExpressionLanguage\Expression;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * ExpressionVoter votes based on the evaluation of an expression.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ExpressionVoter implements VoterInterface
+{
+ private $expressionLanguage;
+ private $trustResolver;
+ private $roleHierarchy;
+
+ /**
+ * Constructor.
+ *
+ * @param ExpressionLanguage $expressionLanguage
+ * @param AuthenticationTrustResolverInterface $trustResolver
+ * @param RoleHierarchyInterface|null $roleHierarchy
+ */
+ public function __construct(ExpressionLanguage $expressionLanguage, AuthenticationTrustResolverInterface $trustResolver, RoleHierarchyInterface $roleHierarchy = null)
+ {
+ $this->expressionLanguage = $expressionLanguage;
+ $this->trustResolver = $trustResolver;
+ $this->roleHierarchy = $roleHierarchy;
+ }
+
+ public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
+ {
+ $this->expressionLanguage->registerProvider($provider);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function supportsAttribute($attribute)
+ {
+ return $attribute instanceof Expression;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function supportsClass($class)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function vote(TokenInterface $token, $object, array $attributes)
+ {
+ $result = VoterInterface::ACCESS_ABSTAIN;
+ $variables = null;
+ foreach ($attributes as $attribute) {
+ if (!$this->supportsAttribute($attribute)) {
+ continue;
+ }
+
+ if (null === $variables) {
+ $variables = $this->getVariables($token, $object);
+ }
+
+ $result = VoterInterface::ACCESS_DENIED;
+ if ($this->expressionLanguage->evaluate($attribute, $variables)) {
+ return VoterInterface::ACCESS_GRANTED;
+ }
+ }
+
+ return $result;
+ }
+
+ private function getVariables(TokenInterface $token, $object)
+ {
+ if (null !== $this->roleHierarchy) {
+ $roles = $this->roleHierarchy->getReachableRoles($token->getRoles());
+ } else {
+ $roles = $token->getRoles();
+ }
+
+ $variables = array(
+ 'token' => $token,
+ 'user' => $token->getUser(),
+ 'object' => $object,
+ 'roles' => array_map(function ($role) { return $role->getRole(); }, $roles),
+ 'trust_resolver' => $this->trustResolver,
+ );
+
+ // this is mainly to propose a better experience when the expression is used
+ // in an access control rule, as the developer does not know that it's going
+ // to be handled by this voter
+ if ($object instanceof Request) {
+ $variables['request'] = $object;
+ }
+
+ return $variables;
+ }
+}
diff --git a/Core/Encoder/EncoderAwareInterface.php b/Core/Encoder/EncoderAwareInterface.php
new file mode 100644
index 0000000..22ae820
--- /dev/null
+++ b/Core/Encoder/EncoderAwareInterface.php
@@ -0,0 +1,28 @@
+<?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\Component\Security\Core\Encoder;
+
+/**
+ * @author Christophe Coevoet <stof@notk.org>
+ */
+interface EncoderAwareInterface
+{
+ /**
+ * Gets the name of the encoder used to encode the password.
+ *
+ * If the method returns null, the standard way to retrieve the encoder
+ * will be used instead.
+ *
+ * @return string
+ */
+ public function getEncoderName();
+}
diff --git a/Core/Encoder/EncoderFactory.php b/Core/Encoder/EncoderFactory.php
index 5f6c20c..0568d41 100644
--- a/Core/Encoder/EncoderFactory.php
+++ b/Core/Encoder/EncoderFactory.php
@@ -30,19 +30,32 @@ class EncoderFactory implements EncoderFactoryInterface
*/
public function getEncoder($user)
{
- foreach ($this->encoders as $class => $encoder) {
- if ((is_object($user) && !$user instanceof $class) || (!is_object($user) && !is_subclass_of($user, $class) && $user != $class)) {
- continue;
+ $encoderKey = null;
+
+ if ($user instanceof EncoderAwareInterface && (null !== $encoderName = $user->getEncoderName())) {
+ if (!array_key_exists($encoderName, $this->encoders)) {
+ throw new \RuntimeException(sprintf('The encoder "%s" was not configured.', $encoderName));
}
- if (!$encoder instanceof PasswordEncoderInterface) {
- return $this->encoders[$class] = $this->createEncoder($encoder);
+ $encoderKey = $encoderName;
+ } else {
+ foreach ($this->encoders as $class => $encoder) {
+ if ((is_object($user) && $user instanceof $class) || (!is_object($user) && (is_subclass_of($user, $class) || $user == $class))) {
+ $encoderKey = $class;
+ break;
+ }
}
+ }
+
+ if (null === $encoderKey) {
+ throw new \RuntimeException(sprintf('No encoder has been configured for account "%s".', is_object($user) ? get_class($user) : $user));
+ }
- return $this->encoders[$class];
+ if (!$this->encoders[$encoderKey] instanceof PasswordEncoderInterface) {
+ $this->encoders[$encoderKey] = $this->createEncoder($this->encoders[$encoderKey]);
}
- throw new \RuntimeException(sprintf('No encoder has been configured for account "%s".', is_object($user) ? get_class($user) : $user));
+ return $this->encoders[$encoderKey];
}
/**
diff --git a/Core/Encoder/UserPasswordEncoder.php b/Core/Encoder/UserPasswordEncoder.php
new file mode 100644
index 0000000..b096049
--- /dev/null
+++ b/Core/Encoder/UserPasswordEncoder.php
@@ -0,0 +1,55 @@
+<?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\Component\Security\Core\Encoder;
+
+use Symfony\Component\Security\Core\User\UserInterface;
+
+/**
+ * A generic password encoder.
+ *
+ * @author Ariel Ferrandini <arielferrandini@gmail.com>
+ */
+class UserPasswordEncoder implements UserPasswordEncoderInterface
+{
+ /**
+ * @var EncoderFactoryInterface
+ */
+ private $encoderFactory;
+
+ /**
+ * @param EncoderFactoryInterface $encoderFactory The encoder factory
+ */
+ public function __construct(EncoderFactoryInterface $encoderFactory)
+ {
+ $this->encoderFactory = $encoderFactory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function encodePassword(UserInterface $user, $plainPassword)
+ {
+ $encoder = $this->encoderFactory->getEncoder($user);
+
+ return $encoder->encodePassword($plainPassword, $user->getSalt());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isPasswordValid(UserInterface $user, $raw)
+ {
+ $encoder = $this->encoderFactory->getEncoder($user);
+
+ return $encoder->isPasswordValid($user->getPassword(), $raw, $user->getSalt());
+ }
+}
diff --git a/Core/Encoder/UserPasswordEncoderInterface.php b/Core/Encoder/UserPasswordEncoderInterface.php
new file mode 100644
index 0000000..7861caa
--- /dev/null
+++ b/Core/Encoder/UserPasswordEncoderInterface.php
@@ -0,0 +1,40 @@
+<?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\Component\Security\Core\Encoder;
+
+use Symfony\Component\Security\Core\User\UserInterface;
+
+/**
+ * UserPasswordEncoderInterface is the interface for the password encoder service.
+ *
+ * @author Ariel Ferrandini <arielferrandini@gmail.com>
+ */
+interface UserPasswordEncoderInterface
+{
+ /**
+ * Encodes the plain password.
+ *
+ * @param UserInterface $user The user
+ * @param string $plainPassword The password to encode
+ *
+ * @return string The encoded password
+ */
+ public function encodePassword(UserInterface $user, $plainPassword);
+
+ /**
+ * @param UserInterface $user The user
+ * @param string $raw A raw password
+ *
+ * @return bool true if the password is valid, false otherwise
+ */
+ public function isPasswordValid(UserInterface $user, $raw);
+}
diff --git a/Core/Exception/AccessDeniedException.php b/Core/Exception/AccessDeniedException.php
index 7c16afb..736a36b 100644
--- a/Core/Exception/AccessDeniedException.php
+++ b/Core/Exception/AccessDeniedException.php
@@ -18,7 +18,7 @@ namespace Symfony\Component\Security\Core\Exception;
*/
class AccessDeniedException extends \RuntimeException
{
- public function __construct($message = 'Access Denied', \Exception $previous = null)
+ public function __construct($message = 'Access Denied.', \Exception $previous = null)
{
parent::__construct($message, 403, $previous);
}
diff --git a/Core/Exception/ExceptionInterface.php b/Core/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..5000d02
--- /dev/null
+++ b/Core/Exception/ExceptionInterface.php
@@ -0,0 +1,21 @@
+<?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\Component\Security\Core\Exception;
+
+/**
+ * Base ExceptionInterface for the Security component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface ExceptionInterface
+{
+}
diff --git a/Core/Exception/InvalidArgumentException.php b/Core/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000..6f85e95
--- /dev/null
+++ b/Core/Exception/InvalidArgumentException.php
@@ -0,0 +1,21 @@
+<?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\Component\Security\Core\Exception;
+
+/**
+ * Base InvalidArgumentException for the Security component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/Core/Exception/RuntimeException.php b/Core/Exception/RuntimeException.php
new file mode 100644
index 0000000..95edec8
--- /dev/null
+++ b/Core/Exception/RuntimeException.php
@@ -0,0 +1,21 @@
+<?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\Component\Security\Core\Exception;
+
+/**
+ * Base RuntimeException for the Security component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+}
diff --git a/Core/Exception/UsernameNotFoundException.php b/Core/Exception/UsernameNotFoundException.php
index 11607d3..6979389 100644
--- a/Core/Exception/UsernameNotFoundException.php
+++ b/Core/Exception/UsernameNotFoundException.php
@@ -69,4 +69,12 @@ class UsernameNotFoundException extends AuthenticationException
parent::unserialize($parentData);
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMessageData()
+ {
+ return array('{{ username }}' => $this->username);
+ }
}
diff --git a/Core/LICENSE b/Core/LICENSE
new file mode 100644
index 0000000..12a7453
--- /dev/null
+++ b/Core/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2016 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Core/README.md b/Core/README.md
new file mode 100644
index 0000000..b0d1749
--- /dev/null
+++ b/Core/README.md
@@ -0,0 +1,23 @@
+Security Component - Core
+=========================
+
+Security provides an infrastructure for sophisticated authorization systems,
+which makes it possible to easily separate the actual authorization logic from
+so called user providers that hold the users credentials. It is inspired by
+the Java Spring framework.
+
+Resources
+---------
+
+Documentation:
+
+https://symfony.com/doc/2.7/book/security.html
+
+Tests
+-----
+
+You can run the unit tests with the following command:
+
+ $ cd path/to/Symfony/Component/Security/Core/
+ $ composer.phar install --dev
+ $ phpunit
diff --git a/Core/Resources/translations/security.ar.xlf b/Core/Resources/translations/security.ar.xlf
new file mode 100644
index 0000000..fd18ee6
--- /dev/null
+++ b/Core/Resources/translations/security.ar.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>حدث خطأ اثناء الدخول.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>لم استطع العثور على معلومات الدخول.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>لم يكتمل طلب الدخول نتيجه عطل فى النظام.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>معلومات الدخول خاطئة.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>ملفات تعريف الارتباط(cookies) تم استخدامها من قبل شخص اخر.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>ليست لديك الصلاحيات الكافية لهذا الطلب.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>رمز الموقع غير صحيح.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>انتهت صلاحية(digest nonce).</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>لا يوجد معرف للدخول يدعم الرمز المستخدم للدخول.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>لا يوجد صلة بينك و بين الموقع اما انها انتهت او ان متصفحك لا يدعم خاصية ملفات تعريف الارتباط (cookies).</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>لم استطع العثور على الرمز.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>لم استطع العثور على اسم الدخول.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>انتهت صلاحية الحساب.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>انتهت صلاحية معلومات الدخول.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>الحساب موقوف.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>الحساب مغلق.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.az.xlf b/Core/Resources/translations/security.az.xlf
new file mode 100644
index 0000000..a974ed0
--- /dev/null
+++ b/Core/Resources/translations/security.az.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Doğrulama istisnası baş verdi.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Doğrulama məlumatları tapılmadı.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Sistem xətası səbəbilə doğrulama istəyi emal edilə bilmədi.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Yanlış məlumat.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Kuki başqası tərəfindən istifadə edilib.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Resurs istəyi üçün imtiyaz yoxdur.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Yanlış CSRF nişanı.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Dərləmə istifadə müddəti bitib.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Doğrulama nişanını dəstəkləyəcək provayder tapılmadı.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Uyğun seans yoxdur, vaxtı keçib və ya kuki aktiv deyil.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Nişan tapılmadı.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>İstifadəçi adı tapılmadı.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Hesabın istifadə müddəti bitib.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Məlumatların istifadə müddəti bitib.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Hesab qeyri-aktiv edilib.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Hesab kilitlənib.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.bg.xlf b/Core/Resources/translations/security.bg.xlf
new file mode 100644
index 0000000..06692ea
--- /dev/null
+++ b/Core/Resources/translations/security.bg.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Грешка при автентикация.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Удостоверението за автентикация не е открито.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Заявката за автентикация не може да бъде обработената поради системна грешка.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Невалидно удостоверение за автентикация.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Това cookie вече се ползва от някой друг.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Нямате права за достъп до този ресурс.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Невалиден CSRF токен.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce е изтекъл.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Не е открит провайдър, който да поддържа този токен за автентикация.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Сесията не е достъпна, или времето за достъп е изтекло, или кукитата не са разрешени.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Токена не е открит.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Потребителското име не е открито.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Акаунта е изтекъл.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Удостоверението за автентикация е изтекло.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Акаунта е деактивиран.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Акаунта е заключен.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.ca.xlf b/Core/Resources/translations/security.ca.xlf
new file mode 100644
index 0000000..7ece260
--- /dev/null
+++ b/Core/Resources/translations/security.ca.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Ha succeït un error d'autenticació.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>No s'han trobat les credencials d'autenticació.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>La solicitud d'autenticació no s'ha pogut processar per un problema del sistema.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Credencials no vàlides.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>La cookie ja ha estat utilitzada per una altra persona.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>No té privilegis per solicitar el recurs.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Token CSRF no vàlid.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>El vector d'inicialització (digest nonce) ha expirat.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>No s'ha trobat un proveïdor d'autenticació que suporti el token d'autenticació.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>No hi ha sessió disponible, ha expirat o les cookies no estan habilitades.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>No s'ha trobat cap token.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>No s'ha trobat el nom d'usuari.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>El compte ha expirat.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Les credencials han expirat.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>El compte està deshabilitat.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>El compte està bloquejat.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.cs.xlf b/Core/Resources/translations/security.cs.xlf
new file mode 100644
index 0000000..bd146c6
--- /dev/null
+++ b/Core/Resources/translations/security.cs.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Při ověřování došlo k chybě.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Ověřovací údaje nebyly nalezeny.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Požadavek na ověření nemohl být zpracován kvůli systémové chybě.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Neplatné přihlašovací údaje.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie již bylo použité někým jiným.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Nemáte oprávnění přistupovat k prostředku.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Neplatný CSRF token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Platnost inicializačního vektoru (digest nonce) vypršela.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Poskytovatel pro ověřovací token nebyl nalezen.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Session není k dispozici, vypršela její platnost, nebo jsou zakázané cookies.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Token nebyl nalezen.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Přihlašovací jméno nebylo nalezeno.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Platnost účtu vypršela.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Platnost přihlašovacích údajů vypršela.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Účet je zakázaný.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Účet je zablokovaný.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.da.xlf b/Core/Resources/translations/security.da.xlf
new file mode 100644
index 0000000..2ac4150
--- /dev/null
+++ b/Core/Resources/translations/security.da.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>En fejl indtraf ved godkendelse.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Loginoplysninger kan findes.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Godkendelsesanmodning kan ikke behandles på grund af et systemfejl.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Ugyldige loginoplysninger.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie er allerede brugt af en anden.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Ingen tilladselese at anvende kilden.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Ugyldigt CSRF token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce er udløbet.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Ingen godkendelsesudbyder er fundet til understøttelsen af godkendelsestoken.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Ingen session tilgængelig, sessionen er enten udløbet eller cookies er ikke aktiveret.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Ingen token kan findes.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Brugernavn kan ikke findes.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Brugerkonto er udløbet.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Loginoplysninger er udløbet.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Brugerkonto er deaktiveret.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Brugerkonto er låst.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.de.xlf b/Core/Resources/translations/security.de.xlf
new file mode 100644
index 0000000..e5946ed
--- /dev/null
+++ b/Core/Resources/translations/security.de.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Es ist ein Fehler bei der Authentifikation aufgetreten.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Es konnten keine Zugangsdaten gefunden werden.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Die Authentifikation konnte wegen eines Systemproblems nicht bearbeitet werden.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Fehlerhafte Zugangsdaten.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie wurde bereits von jemand anderem verwendet.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Keine Rechte, um die Ressource anzufragen.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Ungültiges CSRF-Token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce ist abgelaufen.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Es wurde kein Authentifizierungs-Provider gefunden, der das Authentifizierungs-Token unterstützt.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Keine Session verfügbar, entweder ist diese abgelaufen oder Cookies sind nicht aktiviert.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Es wurde kein Token gefunden.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Der Benutzername wurde nicht gefunden.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Der Account ist abgelaufen.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Die Zugangsdaten sind abgelaufen.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Der Account ist deaktiviert.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Der Account ist gesperrt.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.el.xlf b/Core/Resources/translations/security.el.xlf
new file mode 100644
index 0000000..07eabe7
--- /dev/null
+++ b/Core/Resources/translations/security.el.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Συνέβη ένα σφάλμα πιστοποίησης.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Τα στοιχεία πιστοποίησης δε βρέθηκαν.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Το αίτημα πιστοποίησης δε μπορεί να επεξεργαστεί λόγω σφάλματος του συστήματος.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Λανθασμένα στοιχεία σύνδεσης.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Το Cookie έχει ήδη χρησιμοποιηθεί από κάποιον άλλο.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Δεν είστε εξουσιοδοτημένος για πρόσβαση στο συγκεκριμένο περιεχόμενο.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Μη έγκυρο CSRF token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Το digest nonce έχει λήξει.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Δε βρέθηκε κάποιος πάροχος πιστοποίησης που να υποστηρίζει το token πιστοποίησης.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Δεν υπάρχει ενεργή σύνοδος (session), είτε έχει λήξει ή τα cookies δεν είναι ενεργοποιημένα.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Δεν ήταν δυνατόν να βρεθεί κάποιο token.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Το Username δε βρέθηκε.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Ο λογαριασμός έχει λήξει.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Τα στοιχεία σύνδεσης έχουν λήξει.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Ο λογαριασμός είναι απενεργοποιημένος.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Ο λογαριασμός είναι κλειδωμένος.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.en.xlf b/Core/Resources/translations/security.en.xlf
new file mode 100644
index 0000000..3640698
--- /dev/null
+++ b/Core/Resources/translations/security.en.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>An authentication exception occurred.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Authentication credentials could not be found.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Authentication request could not be processed due to a system problem.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Invalid credentials.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie has already been used by someone else.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Not privileged to request the resource.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Invalid CSRF token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce has expired.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>No authentication provider found to support the authentication token.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>No session available, it either timed out or cookies are not enabled.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>No token could be found.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Username could not be found.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Account has expired.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Credentials have expired.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Account is disabled.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Account is locked.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.es.xlf b/Core/Resources/translations/security.es.xlf
new file mode 100644
index 0000000..00cefbb
--- /dev/null
+++ b/Core/Resources/translations/security.es.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Ocurrió un error de autenticación.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>No se encontraron las credenciales de autenticación.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>La solicitud de autenticación no se pudo procesar debido a un problema del sistema.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Credenciales no válidas.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>La cookie ya ha sido usada por otra persona.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>No tiene privilegios para solicitar el recurso.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Token CSRF no válido.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>El vector de inicialización (digest nonce) ha expirado.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>No se encontró un proveedor de autenticación que soporte el token de autenticación.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>No hay ninguna sesión disponible, ha expirado o las cookies no están habilitados.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>No se encontró ningún token.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>No se encontró el nombre de usuario.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>La cuenta ha expirado.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Las credenciales han expirado.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>La cuenta está deshabilitada.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>La cuenta está bloqueada.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.fa.xlf b/Core/Resources/translations/security.fa.xlf
new file mode 100644
index 0000000..0b76290
--- /dev/null
+++ b/Core/Resources/translations/security.fa.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>خطایی هنگام تعیین اعتبار اتفاق افتاد.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>شرایط تعیین اعتبار پیدا نشد.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>درخواست تعیین اعتبار به دلیل مشکل سیستم قابل بررسی نیست.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>شرایط نامعتبر.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>کوکی قبلا برای شخص دیگری استفاده شده است.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>دسترسی لازم برای درخواست این منبع را ندارید.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>توکن CSRF معتبر نیست.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce منقضی شده است.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>هیچ ارایه کننده تعیین اعتباری برای ساپورت توکن تعیین اعتبار پیدا نشد.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>جلسه‌ای در دسترس نیست. این میتواند یا به دلیل پایان یافتن زمان باشد یا اینکه کوکی ها فعال نیستند.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>هیچ توکنی پیدا نشد.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>نام ‌کاربری پیدا نشد.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>حساب کاربری منقضی شده است.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>پارامترهای تعیین اعتبار منقضی شده‌اند.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>حساب کاربری غیرفعال است.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>حساب کاربری قفل شده است.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.fr.xlf b/Core/Resources/translations/security.fr.xlf
new file mode 100644
index 0000000..5a77c6e
--- /dev/null
+++ b/Core/Resources/translations/security.fr.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Une exception d'authentification s'est produite.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Les identifiants d'authentification n'ont pas pu être trouvés.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>La requête d'authentification n'a pas pu être executée à cause d'un problème système.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Identifiants invalides.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Le cookie a déjà été utilisé par quelqu'un d'autre.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Privilèges insuffisants pour accéder à la ressource.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Jeton CSRF invalide.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Le digest nonce a expiré.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Aucun fournisseur d'authentification n'a été trouvé pour supporter le jeton d'authentification.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Aucune session disponible, celle-ci a expiré ou les cookies ne sont pas activés.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Aucun jeton n'a pu être trouvé.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Le nom d'utilisateur n'a pas pu être trouvé.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Le compte a expiré.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Les identifiants ont expiré.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Le compte est désactivé.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Le compte est bloqué.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.gl.xlf b/Core/Resources/translations/security.gl.xlf
new file mode 100644
index 0000000..ed6491f
--- /dev/null
+++ b/Core/Resources/translations/security.gl.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Ocorreu un erro de autenticación.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Non se atoparon as credenciais de autenticación.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>A solicitude de autenticación no puido ser procesada debido a un problema do sistema.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Credenciais non válidas.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>A cookie xa foi empregado por outro usuario.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Non ten privilexios para solicitar o recurso.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Token CSRF non válido.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>O vector de inicialización (digest nonce) expirou.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Non se atopou un provedor de autenticación que soporte o token de autenticación.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Non hai ningunha sesión dispoñible, expirou ou as cookies non están habilitadas.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Non se atopou ningún token.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Non se atopou o nome de usuario.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>A conta expirou.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>As credenciais expiraron.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>A conta está deshabilitada.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>A conta está bloqueada.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.he.xlf b/Core/Resources/translations/security.he.xlf
new file mode 100644
index 0000000..3640698
--- /dev/null
+++ b/Core/Resources/translations/security.he.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>An authentication exception occurred.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Authentication credentials could not be found.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Authentication request could not be processed due to a system problem.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Invalid credentials.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie has already been used by someone else.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Not privileged to request the resource.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Invalid CSRF token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce has expired.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>No authentication provider found to support the authentication token.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>No session available, it either timed out or cookies are not enabled.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>No token could be found.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Username could not be found.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Account has expired.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Credentials have expired.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Account is disabled.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Account is locked.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.hr.xlf b/Core/Resources/translations/security.hr.xlf
new file mode 100644
index 0000000..147b6e3
--- /dev/null
+++ b/Core/Resources/translations/security.hr.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Dogodila se autentifikacijske iznimka.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Autentifikacijski podaci nisu pronađeni.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Autentifikacijski zahtjev nije moguće provesti uslijed sistemskog problema.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Neispravni akreditacijski podaci.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie je već netko drugi iskoristio.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Nemate privilegije zahtijevati resurs.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Neispravan CSRF token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce je isteko.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Nije pronađen autentifikacijski provider koji bi podržao autentifikacijski token.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Sesija nije dostupna, ili je istekla ili cookies nisu omogućeni.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Token nije pronađen.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Korisničko ime nije pronađeno.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Račun je isteko.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Akreditacijski podaci su istekli.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Račun je onemogućen.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Račun je zaključan.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.hu.xlf b/Core/Resources/translations/security.hu.xlf
new file mode 100644
index 0000000..7243970
--- /dev/null
+++ b/Core/Resources/translations/security.hu.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Hitelesítési hiba lépett fel.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Nem találhatók hitelesítési információk.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>A hitelesítési kérést rendszerhiba miatt nem lehet feldolgozni.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Érvénytelen hitelesítési információk.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Ezt a sütit valaki más már felhasználta.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Nem rendelkezik az erőforrás eléréséhez szükséges jogosultsággal.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Érvénytelen CSRF token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>A kivonat bélyege (nonce) lejárt.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Nem található a hitelesítési tokent támogató hitelesítési szolgáltatás.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Munkamenet nem áll rendelkezésre, túllépte az időkeretet vagy a sütik le vannak tiltva.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Nem található token.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>A felhasználónév nem található.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>A fiók lejárt.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>A hitelesítési információk lejártak.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Felfüggesztett fiók.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Zárolt fiók.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.id.xlf b/Core/Resources/translations/security.id.xlf
new file mode 100644
index 0000000..ab1153b
--- /dev/null
+++ b/Core/Resources/translations/security.id.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Terjadi sebuah pengecualian otentikasi.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Kredensial otentikasi tidak bisa ditemukan.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Permintaan otentikasi tidak bisa diproses karena masalah sistem.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Kredensial salah.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie sudah digunakan oleh orang lain.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Tidak berhak untuk meminta sumber daya.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Token CSRF salah.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce telah berakhir.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Tidak ditemukan penyedia otentikasi untuk mendukung token otentikasi.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Tidak ada sesi yang tersedia, mungkin waktu sudah habis atau cookie tidak diaktifkan</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Tidak ada token yang bisa ditemukan.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Username tidak bisa ditemukan.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Akun telah berakhir.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Kredensial telah berakhir.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Akun dinonaktifkan.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Akun terkunci.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.it.xlf b/Core/Resources/translations/security.it.xlf
new file mode 100644
index 0000000..75d81cc
--- /dev/null
+++ b/Core/Resources/translations/security.it.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Si è verificato un errore di autenticazione.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Impossibile trovare le credenziali di autenticazione.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>La richiesta di autenticazione non può essere processata a causa di un errore di sistema.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Credenziali non valide.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Il cookie è già stato usato da qualcun altro.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Non hai i privilegi per richiedere questa risorsa.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>CSRF token non valido.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Il numero di autenticazione è scaduto.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Non è stato trovato un valido fornitore di autenticazione per supportare il token.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Nessuna sessione disponibile, può essere scaduta o i cookie non sono abilitati.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Nessun token trovato.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Username non trovato.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Account scaduto.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Credenziali scadute.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>L'account è disabilitato.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>L'account è bloccato.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.ja.xlf b/Core/Resources/translations/security.ja.xlf
new file mode 100644
index 0000000..6a6b062
--- /dev/null
+++ b/Core/Resources/translations/security.ja.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>認証エラーが発生しました。</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>認証資格がありません。</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>システムの問題により認証要求を処理できませんでした。</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>資格が無効です。</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie が別のユーザーで使用されています。</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>リソースをリクエストする権限がありません。</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>CSRF トークンが無効です。</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest の nonce 値が期限切れです。</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>認証トークンをサポートする認証プロバイダーが見つかりません。</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>利用可能なセッションがありません。タイムアウトしたか、Cookie が無効になっています。</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>トークンが見つかりません。</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>ユーザー名が見つかりません。</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>アカウントが有効期限切れです。</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>資格が有効期限切れです。</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>アカウントが無効です。</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>アカウントはロックされています。</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.lb.xlf b/Core/Resources/translations/security.lb.xlf
new file mode 100644
index 0000000..3dc76d5
--- /dev/null
+++ b/Core/Resources/translations/security.lb.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" target-language="lb" datatype="plaintext" original="security.en.xlf">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Bei der Authentifikatioun ass e Feeler opgetrueden.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Et konnte keng Zouganksdate fonnt ginn.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>D'Ufro fir eng Authentifikatioun konnt wéinst engem Problem vum System net beaarbecht ginn.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Ongëlteg Zouganksdaten.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>De Cookie gouf scho vun engem anere benotzt.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Keng Rechter fir d'Ressource unzefroen.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Ongëltegen CSRF-Token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Den eemolege Schlëssel ass ofgelaf.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Et gouf keen Authentifizéierungs-Provider fonnt deen den Authentifizéierungs-Token ënnerstëtzt.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Keng Sëtzung disponibel. Entweder ass se ofgelaf oder Cookies sinn net aktivéiert.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Et konnt keen Token fonnt ginn.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>De Benotzernumm konnt net fonnt ginn.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Den Account ass ofgelaf.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>D'Zouganksdate sinn ofgelaf.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>De Konto ass deaktivéiert.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>De Konto ass gespaart.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.lt.xlf b/Core/Resources/translations/security.lt.xlf
new file mode 100644
index 0000000..da6c332
--- /dev/null
+++ b/Core/Resources/translations/security.lt.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Įvyko autentifikacijos klaida.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Nepavyko rasti autentifikacijos duomneų.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Autentifikacijos užklausos nepavyko įvykdyti dėl sistemos klaidų.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Klaidingi duomenys.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Slapukas buvo panaudotas kažkam kitam.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Neturite teisių pasiektį resursą.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Neteisingas CSRF raktas.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Prieigos kodas yra pasibaigęs.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Nerastas autentifikacijos tiekėjas, kuris palaikytų autentifikacijos raktą.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Sesija yra nepasiekiama, pasibaigė galiojimo laikas arba slapukai yra išjungti.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Nepavyko rasti rakto.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Tokio naudotojo vardo nepavyko rasti.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Paskyros galiojimo laikas baigėsi.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Autentifikacijos duomenų galiojimo laikas baigėsi.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Paskyra yra išjungta.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Paskyra yra užblokuota.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.nl.xlf b/Core/Resources/translations/security.nl.xlf
new file mode 100644
index 0000000..8969e9e
--- /dev/null
+++ b/Core/Resources/translations/security.nl.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Er heeft zich een authenticatieprobleem voorgedaan.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Authenticatiegegevens konden niet worden gevonden.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Authenticatieaanvraag kon niet worden verwerkt door een technisch probleem.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Ongeldige inloggegevens.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie is al door een ander persoon gebruikt.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Onvoldoende rechten om de aanvraag te verwerken.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>CSRF-code is ongeldig.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Serverauthenticatiesleutel (digest nonce) is verlopen.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Geen authenticatieprovider gevonden die de authenticatietoken ondersteunt.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Geen sessie beschikbaar, mogelijk is deze verlopen of cookies zijn uitgeschakeld.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Er kon geen authenticatietoken worden gevonden.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Gebruikersnaam kon niet worden gevonden.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Account is verlopen.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Authenticatiegegevens zijn verlopen.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Account is gedeactiveerd.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Account is geblokkeerd.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.no.xlf b/Core/Resources/translations/security.no.xlf
new file mode 100644
index 0000000..3369d43
--- /dev/null
+++ b/Core/Resources/translations/security.no.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>En autentiserings feil har skjedd.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Påloggingsinformasjonen kunne ikke bli funnet.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Autentiserings forespørselen kunne ikke bli prosessert grunnet en system feil.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Ugyldig påloggingsinformasjonen.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie har allerede blitt brukt av noen andre.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Ingen tilgang til å be om gitt kilde.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Ugyldig CSRF token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce er utløpt.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Ingen autentiserings tilbyder funnet som støtter gitt autentiserings token.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Ingen sesjon tilgjengelig, sesjonen er enten utløpt eller cookies ikke skrudd på.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Ingen token kunne bli funnet.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Brukernavn kunne ikke bli funnet.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Brukerkonto har utgått.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Påloggingsinformasjon har utløpt.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Brukerkonto er deaktivert.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Brukerkonto er sperret.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.pl.xlf b/Core/Resources/translations/security.pl.xlf
new file mode 100644
index 0000000..8d563d2
--- /dev/null
+++ b/Core/Resources/translations/security.pl.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Wystąpił błąd uwierzytelniania.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Dane uwierzytelniania nie zostały znalezione.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Żądanie uwierzytelniania nie mogło zostać pomyślnie zakończone z powodu problemu z systemem.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Nieprawidłowe dane.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>To ciasteczko jest używane przez kogoś innego.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Brak uprawnień dla żądania wskazanego zasobu.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Nieprawidłowy token CSRF.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Kod dostępu wygasł.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Nie znaleziono mechanizmu uwierzytelniania zdolnego do obsługi przesłanego tokenu.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Brak danych sesji, sesja wygasła lub ciasteczka nie są włączone.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Nie znaleziono tokenu.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Użytkownik o podanej nazwie nie istnieje.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Konto wygasło.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Dane uwierzytelniania wygasły.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Konto jest wyłączone.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Konto jest zablokowane.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.pt_BR.xlf b/Core/Resources/translations/security.pt_BR.xlf
new file mode 100644
index 0000000..61685d9
--- /dev/null
+++ b/Core/Resources/translations/security.pt_BR.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Uma exceção ocorreu durante a autenticação.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>As credenciais de autenticação não foram encontradas.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>A autenticação não pôde ser concluída devido a um problema no sistema.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Credenciais inválidas.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Este cookie já está em uso.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Não possui privilégios o bastante para requisitar este recurso.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Token CSRF inválido.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce expirado.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Nenhum provedor de autenticação encontrado para suportar o token de autenticação.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Nenhuma sessão disponível, ela expirou ou os cookies estão desativados.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Nenhum token foi encontrado.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Nome de usuário não encontrado.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>A conta está expirada.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>As credenciais estão expiradas.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Conta desativada.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>A conta está travada.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.pt_PT.xlf b/Core/Resources/translations/security.pt_PT.xlf
new file mode 100644
index 0000000..f2af13e
--- /dev/null
+++ b/Core/Resources/translations/security.pt_PT.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Ocorreu uma excepção durante a autenticação.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>As credenciais de autenticação não foram encontradas.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>O pedido de autenticação não foi concluído devido a um problema no sistema.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Credenciais inválidas.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Este cookie já está em uso.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Não possui privilégios para aceder a este recurso.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Token CSRF inválido.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce expirado.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Nenhum fornecedor de autenticação encontrado para suportar o token de autenticação.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Não existe sessão disponível, esta expirou ou os cookies estão desativados.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>O token não foi encontrado.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Nome de utilizador não encontrado.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>A conta expirou.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>As credenciais expiraram.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Conta desativada.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>A conta está trancada.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.ro.xlf b/Core/Resources/translations/security.ro.xlf
new file mode 100644
index 0000000..440f110
--- /dev/null
+++ b/Core/Resources/translations/security.ro.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>A apărut o eroare de autentificare.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Informațiile de autentificare nu au fost găsite.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Sistemul nu a putut procesa cererea de autentificare din cauza unei erori.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Date de autentificare invalide.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookieul este folosit deja de altcineva.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Permisiuni insuficiente pentru resursa cerută.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Tokenul CSRF este invalid.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Tokenul temporar a expirat.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Nu a fost găsit nici un agent de autentificare pentru tokenul specificat.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Sesiunea nu mai este disponibilă, a expirat sau suportul pentru cookieuri nu este activat.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Tokenul nu a putut fi găsit.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Numele de utilizator nu a fost găsit.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Contul a expirat.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Datele de autentificare au expirat.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Contul este dezactivat.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Contul este blocat.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.ru.xlf b/Core/Resources/translations/security.ru.xlf
new file mode 100644
index 0000000..1964f95
--- /dev/null
+++ b/Core/Resources/translations/security.ru.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Ошибка аутентификации.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Аутентификационные данные не найдены.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Запрос аутентификации не может быть обработан в связи с проблемой в системе.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Недействительные аутентификационные данные.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie уже был использован кем-то другим.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Отсутствуют права на запрос этого ресурса.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Недействительный токен CSRF.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Время действия одноразового ключа дайджеста истекло.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Не найден провайдер аутентификации, поддерживающий токен аутентификации.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Сессия не найдена, ее время истекло, либо cookies не включены.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Токен не найден.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Имя пользователя не найдено.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Время действия учетной записи истекло.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Время действия аутентификационных данных истекло.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Учетная запись отключена.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Учетная запись заблокирована.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.sk.xlf b/Core/Resources/translations/security.sk.xlf
new file mode 100644
index 0000000..e6552a6
--- /dev/null
+++ b/Core/Resources/translations/security.sk.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Pri overovaní došlo k chybe.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Overovacie údaje neboli nájdené.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Požiadavok na overenie nemohol byť spracovaný kvôli systémovej chybe.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Neplatné prihlasovacie údaje.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie už bolo použité niekým iným.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Nemáte oprávnenie pristupovať k prostriedku.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Neplatný CSRF token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Platnosť inicializačného vektoru (digest nonce) skončila.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Poskytovateľ pre overovací token nebol nájdený.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Session nie je k dispozíci, vypršala jej platnosť, alebo sú zakázané cookies.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Token nebol nájdený.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Prihlasovacie meno nebolo nájdené.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Platnosť účtu skončila.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Platnosť prihlasovacích údajov skončila.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Účet je zakázaný.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Účet je zablokovaný.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.sl.xlf b/Core/Resources/translations/security.sl.xlf
new file mode 100644
index 0000000..ee70c9a
--- /dev/null
+++ b/Core/Resources/translations/security.sl.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Prišlo je do izjeme pri preverjanju avtentikacije.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Poverilnic za avtentikacijo ni bilo mogoče najti.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Zahteve za avtentikacijo ni bilo mogoče izvesti zaradi sistemske težave.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Neveljavne pravice.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Piškotek je uporabil že nekdo drug.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Nimate privilegijev za zahtevani vir.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Neveljaven CSRF žeton.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Začasni žeton je potekel.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Ponudnika avtentikacije za podporo prijavnega žetona ni bilo mogoče najti.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Seja ni na voljo, ali je potekla ali pa piškotki niso omogočeni.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Žetona ni bilo mogoče najti.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Uporabniškega imena ni bilo mogoče najti.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Račun je potekel.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Poverilnice so potekle.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Račun je onemogočen.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Račun je zaklenjen.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.sr_Cyrl.xlf b/Core/Resources/translations/security.sr_Cyrl.xlf
new file mode 100644
index 0000000..35e4ddf
--- /dev/null
+++ b/Core/Resources/translations/security.sr_Cyrl.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Изузетак при аутентификацији.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Аутентификациони подаци нису пронађени.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Захтев за аутентификацију не може бити обрађен због системских проблема.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Невалидни подаци за аутентификацију.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Колачић је већ искоришћен од стране неког другог.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Немате права приступа овом ресурсу.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Невалидан CSRF токен.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Време криптографског кључа је истекло.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Аутентификациони провајдер за подршку токена није пронађен.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Сесија није доступна, истекла је или су колачићи искључени.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Токен не може бити пронађен.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Корисничко име не може бити пронађено.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Налог је истекао.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Подаци за аутентификацију су истекли.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Налог је онемогућен.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Налог је закључан.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.sr_Latn.xlf b/Core/Resources/translations/security.sr_Latn.xlf
new file mode 100644
index 0000000..ddc4807
--- /dev/null
+++ b/Core/Resources/translations/security.sr_Latn.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Izuzetak pri autentifikaciji.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Autentifikacioni podaci nisu pronađeni.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Zahtev za autentifikaciju ne može biti obrađen zbog sistemskih problema.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Nevalidni podaci za autentifikaciju.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Kolačić je već iskorišćen od strane nekog drugog.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Nemate prava pristupa ovom resursu.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Nevalidan CSRF token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Vreme kriptografskog ključa je isteklo.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Autentifikacioni provajder za podršku tokena nije pronađen.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Sesija nije dostupna, istekla je ili su kolačići isključeni.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Token ne može biti pronađen.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Korisničko ime ne može biti pronađeno.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Nalog je istekao.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Podaci za autentifikaciju su istekli.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Nalog je onemogućen.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Nalog je zaključan.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.sv.xlf b/Core/Resources/translations/security.sv.xlf
new file mode 100644
index 0000000..b5f6209
--- /dev/null
+++ b/Core/Resources/translations/security.sv.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Ett autentiseringsfel har inträffat.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Uppgifterna för autentisering kunde inte hittas.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Autentiseringen kunde inte genomföras på grund av systemfel.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Felaktiga uppgifter.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookien har redan använts av någon annan.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Saknar rättigheter för resursen.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Ogiltig CSRF-token.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Förfallen digest nonce.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Ingen leverantör för autentisering hittades för angiven autentiseringstoken.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Ingen session finns tillgänglig, antingen har den förfallit eller är cookies inte aktiverat.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Ingen token kunde hittas.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Användarnamnet kunde inte hittas.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Kontot har förfallit.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Uppgifterna har förfallit.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Kontot är inaktiverat.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Kontot är låst.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.th.xlf b/Core/Resources/translations/security.th.xlf
new file mode 100644
index 0000000..a8cb8d5
--- /dev/null
+++ b/Core/Resources/translations/security.th.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>พบความผิดพลาดในการรับรองตัวตน</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>ไม่พบข้อมูลในการรับรองตัวตน (credentials) </target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>คำร้องในการรับรองตัวตนไม่สามารถดำเนินการได้ เนื่องมาจากปัญหาของระบบ</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>ข้อมูลการรับรองตัวตนไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie ถูกใช้งานไปแล้วด้วยผู้อื่น</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>ไม่ได้รับสิทธิ์ให้ใช้งานส่วนนี้ได้</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>CSRF token ไม่ถูกต้อง</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Digest nonce หมดอายุ</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>ไม่พบ authentication provider ที่รองรับสำหรับ authentication token</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>ไม่มี session ที่พร้อมใช้งาน, Session หมดอายุไปแล้วหรือ cookies ไม่ถูกเปิดใช้งาน</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>ไม่พบ token</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>ไม่พบ Username</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>บัญชีหมดอายุไปแล้ว</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>ข้อมูลการระบุตัวตนหมดอายุแล้ว</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>บัญชีถูกระงับแล้ว</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>บัญชีถูกล็อกแล้ว</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.tr.xlf b/Core/Resources/translations/security.tr.xlf
new file mode 100644
index 0000000..68c4421
--- /dev/null
+++ b/Core/Resources/translations/security.tr.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Bir yetkilendirme istisnası oluştu.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Kimlik bilgileri bulunamadı.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Bir sistem hatası nedeniyle yetkilendirme isteği işleme alınamıyor.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Geçersiz kimlik bilgileri.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Çerez bir başkası tarafından zaten kullanılmıştı.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Kaynak talebi için imtiyaz bulunamadı.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Geçersiz CSRF fişi.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Derleme zaman aşımına uğradı.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Yetkilendirme fişini destekleyecek yetkilendirme sağlayıcısı bulunamadı.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Oturum bulunamadı, zaman aşımına uğradı veya çerezler etkin değil.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Fiş bulunamadı.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Kullanıcı adı bulunamadı.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Hesap zaman aşımına uğradı.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Kimlik bilgileri zaman aşımına uğradı.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Hesap engellenmiş.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Hesap kilitlenmiş.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.ua.xlf b/Core/Resources/translations/security.ua.xlf
new file mode 100644
index 0000000..7972121
--- /dev/null
+++ b/Core/Resources/translations/security.ua.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Помилка автентифікації.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Автентифікаційні дані не знайдено.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Запит на автентифікацію не може бути опрацьовано у зв’язку з проблемою в системі.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Невірні автентифікаційні дані.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Хтось інший вже використав цей сookie.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Відсутні права на запит цього ресурсу.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Невірний токен CSRF.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Закінчився термін дії одноразового ключа дайджесту.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Не знайдено провайдера автентифікації, що підтримує токен автентифікаціії.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Сесія недоступна, її час вийшов, або cookies вимкнено.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Токен не знайдено.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Ім’я користувача не знайдено.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Термін дії облікового запису вичерпано.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Термін дії автентифікаційних даних вичерпано.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Обліковий запис відключено.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Обліковий запис заблоковано.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.vi.xlf b/Core/Resources/translations/security.vi.xlf
new file mode 100644
index 0000000..b85a439
--- /dev/null
+++ b/Core/Resources/translations/security.vi.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>Có lỗi trong quá trình xác thực.</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>Thông tin dùng để xác thực không tìm thấy.</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>Yêu cầu xác thực không thể thực hiện do lỗi của hệ thống.</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>Thông tin dùng để xác thực không hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie đã được dùng bởi người dùng khác.</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>Không được phép yêu cầu tài nguyên.</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>Mã CSRF không hợp lệ.</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>Mã dùng một lần đã hết hạn.</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>Không tìm thấy nhà cung cấp dịch vụ xác thực nào cho mã xác thực mà bạn sử dụng.</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Không tìm thấy phiên làm việc. Phiên làm việc hoặc cookie có thể bị tắt.</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>Không tìm thấy mã token.</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>Không tìm thấy tên người dùng username.</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>Tài khoản đã hết hạn.</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>Thông tin xác thực đã hết hạn.</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>Tài khoản bị tạm ngừng.</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>Tài khoản bị khóa.</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Resources/translations/security.zh_CN.xlf b/Core/Resources/translations/security.zh_CN.xlf
new file mode 100644
index 0000000..2d6affe
--- /dev/null
+++ b/Core/Resources/translations/security.zh_CN.xlf
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
+ <file source-language="en" datatype="plaintext" original="file.ext">
+ <body>
+ <trans-unit id="1">
+ <source>An authentication exception occurred.</source>
+ <target>身份验证发生异常。</target>
+ </trans-unit>
+ <trans-unit id="2">
+ <source>Authentication credentials could not be found.</source>
+ <target>没有找到身份验证的凭证。</target>
+ </trans-unit>
+ <trans-unit id="3">
+ <source>Authentication request could not be processed due to a system problem.</source>
+ <target>由于系统故障,身份验证的请求无法被处理。</target>
+ </trans-unit>
+ <trans-unit id="4">
+ <source>Invalid credentials.</source>
+ <target>无效的凭证。</target>
+ </trans-unit>
+ <trans-unit id="5">
+ <source>Cookie has already been used by someone else.</source>
+ <target>Cookie 已经被其他人使用。</target>
+ </trans-unit>
+ <trans-unit id="6">
+ <source>Not privileged to request the resource.</source>
+ <target>没有权限请求此资源。</target>
+ </trans-unit>
+ <trans-unit id="7">
+ <source>Invalid CSRF token.</source>
+ <target>无效的 CSRF token 。</target>
+ </trans-unit>
+ <trans-unit id="8">
+ <source>Digest nonce has expired.</source>
+ <target>摘要随机串(digest nonce)已过期。</target>
+ </trans-unit>
+ <trans-unit id="9">
+ <source>No authentication provider found to support the authentication token.</source>
+ <target>没有找到支持此 token 的身份验证服务提供方。</target>
+ </trans-unit>
+ <trans-unit id="10">
+ <source>No session available, it either timed out or cookies are not enabled.</source>
+ <target>Session 不可用。会话超时或没有启用 cookies 。</target>
+ </trans-unit>
+ <trans-unit id="11">
+ <source>No token could be found.</source>
+ <target>找不到 token 。</target>
+ </trans-unit>
+ <trans-unit id="12">
+ <source>Username could not be found.</source>
+ <target>找不到用户名。</target>
+ </trans-unit>
+ <trans-unit id="13">
+ <source>Account has expired.</source>
+ <target>帐号已过期。</target>
+ </trans-unit>
+ <trans-unit id="14">
+ <source>Credentials have expired.</source>
+ <target>凭证已过期。</target>
+ </trans-unit>
+ <trans-unit id="15">
+ <source>Account is disabled.</source>
+ <target>帐号已被禁用。</target>
+ </trans-unit>
+ <trans-unit id="16">
+ <source>Account is locked.</source>
+ <target>帐号已被锁定。</target>
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
diff --git a/Core/Role/RoleHierarchy.php b/Core/Role/RoleHierarchy.php
index 2e7df0e..793007e 100644
--- a/Core/Role/RoleHierarchy.php
+++ b/Core/Role/RoleHierarchy.php
@@ -19,7 +19,7 @@ namespace Symfony\Component\Security\Core\Role;
class RoleHierarchy implements RoleHierarchyInterface
{
private $hierarchy;
- private $map;
+ protected $map;
/**
* Constructor.
@@ -52,7 +52,7 @@ class RoleHierarchy implements RoleHierarchyInterface
return $reachableRoles;
}
- private function buildRoleMap()
+ protected function buildRoleMap()
{
$this->map = array();
foreach ($this->hierarchy as $main => $roles) {
diff --git a/Core/Security.php b/Core/Security.php
new file mode 100644
index 0000000..14d32f8
--- /dev/null
+++ b/Core/Security.php
@@ -0,0 +1,24 @@
+<?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\Component\Security\Core;
+
+/**
+ * This class holds security information.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+final class Security
+{
+ const ACCESS_DENIED_ERROR = '_security.403_error';
+ const AUTHENTICATION_ERROR = '_security.last_error';
+ const LAST_USERNAME = '_security.last_username';
+}
diff --git a/Core/SecurityContext.php b/Core/SecurityContext.php
index 0326f1d..027ff49 100644
--- a/Core/SecurityContext.php
+++ b/Core/SecurityContext.php
@@ -11,10 +11,15 @@
namespace Symfony\Component\Security\Core;
-use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
-use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
+@trigger_error('The '.__NAMESPACE__.'\SecurityContext class is deprecated since version 2.6 and will be removed in 3.0. Use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage or Symfony\Component\Security\Core\Authorization\AuthorizationChecker instead.', E_USER_DEPRECATED);
+
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
+use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
+use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
/**
* SecurityContext is the main entry point of the Security component.
@@ -23,63 +28,77 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ *
+ * @deprecated since version 2.6, to be removed in 3.0.
*/
class SecurityContext implements SecurityContextInterface
{
- private $token;
- private $accessDecisionManager;
- private $authenticationManager;
- private $alwaysAuthenticate;
+ /**
+ * @var TokenStorageInterface
+ */
+ private $tokenStorage;
/**
- * Constructor.
- *
- * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManager instance
- * @param AccessDecisionManagerInterface|null $accessDecisionManager An AccessDecisionManager instance
- * @param bool $alwaysAuthenticate
+ * @var AuthorizationCheckerInterface
*/
- public function __construct(AuthenticationManagerInterface $authenticationManager, AccessDecisionManagerInterface $accessDecisionManager, $alwaysAuthenticate = false)
- {
- $this->authenticationManager = $authenticationManager;
- $this->accessDecisionManager = $accessDecisionManager;
- $this->alwaysAuthenticate = $alwaysAuthenticate;
- }
+ private $authorizationChecker;
/**
- * {@inheritdoc}
+ * For backwards compatibility, the signature of sf <2.6 still works.
*
- * @throws AuthenticationCredentialsNotFoundException when the security context has no authentication token.
+ * @param TokenStorageInterface|AuthenticationManagerInterface $tokenStorage
+ * @param AuthorizationCheckerInterface|AccessDecisionManagerInterface $authorizationChecker
+ * @param bool $alwaysAuthenticate only applicable with old signature
*/
- final public function isGranted($attributes, $object = null)
+ public function __construct($tokenStorage, $authorizationChecker, $alwaysAuthenticate = false)
{
- if (null === $this->token) {
- throw new AuthenticationCredentialsNotFoundException('The security context contains no authentication token. One possible reason may be that there is no firewall configured for this URL.');
- }
+ $oldSignature = $tokenStorage instanceof AuthenticationManagerInterface && $authorizationChecker instanceof AccessDecisionManagerInterface;
+ $newSignature = $tokenStorage instanceof TokenStorageInterface && $authorizationChecker instanceof AuthorizationCheckerInterface;
- if ($this->alwaysAuthenticate || !$this->token->isAuthenticated()) {
- $this->token = $this->authenticationManager->authenticate($this->token);
+ // confirm possible signatures
+ if (!$oldSignature && !$newSignature) {
+ throw new \BadMethodCallException('Unable to construct SecurityContext, please provide the correct arguments');
}
- if (!is_array($attributes)) {
- $attributes = array($attributes);
+ if ($oldSignature) {
+ // renamed for clarity
+ $authenticationManager = $tokenStorage;
+ $accessDecisionManager = $authorizationChecker;
+ $tokenStorage = new TokenStorage();
+ $authorizationChecker = new AuthorizationChecker($tokenStorage, $authenticationManager, $accessDecisionManager, $alwaysAuthenticate);
}
- return $this->accessDecisionManager->decide($this->token, $attributes, $object);
+ $this->tokenStorage = $tokenStorage;
+ $this->authorizationChecker = $authorizationChecker;
}
/**
+ * @deprecated since version 2.6, to be removed in 3.0. Use TokenStorageInterface::getToken() instead.
+ *
* {@inheritdoc}
*/
public function getToken()
{
- return $this->token;
+ return $this->tokenStorage->getToken();
}
/**
+ * @deprecated since version 2.6, to be removed in 3.0. Use TokenStorageInterface::setToken() instead.
+ *
* {@inheritdoc}
*/
public function setToken(TokenInterface $token = null)
{
- $this->token = $token;
+ return $this->tokenStorage->setToken($token);
+ }
+
+ /**
+ * @deprecated since version 2.6, to be removed in 3.0. Use AuthorizationCheckerInterface::isGranted() instead.
+ *
+ * {@inheritdoc}
+ */
+ public function isGranted($attributes, $object = null)
+ {
+ return $this->authorizationChecker->isGranted($attributes, $object);
}
}
diff --git a/Core/SecurityContextInterface.php b/Core/SecurityContextInterface.php
index 50c30bb..2a06ca4 100644
--- a/Core/SecurityContextInterface.php
+++ b/Core/SecurityContextInterface.php
@@ -11,40 +11,19 @@
namespace Symfony\Component\Security\Core;
-use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
+use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
/**
* The SecurityContextInterface.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ *
+ * @deprecated since version 2.6, to be removed in 3.0.
*/
-interface SecurityContextInterface
+interface SecurityContextInterface extends TokenStorageInterface, AuthorizationCheckerInterface
{
- const ACCESS_DENIED_ERROR = '_security.403_error';
- const AUTHENTICATION_ERROR = '_security.last_error';
- const LAST_USERNAME = '_security.last_username';
-
- /**
- * Returns the current security token.
- *
- * @return TokenInterface|null A TokenInterface instance or null if no authentication information is available
- */
- public function getToken();
-
- /**
- * Sets the authentication token.
- *
- * @param TokenInterface $token A TokenInterface token, or null if no further authentication information should be stored
- */
- public function setToken(TokenInterface $token = null);
-
- /**
- * Checks if the attributes are granted against the current authentication token and optionally supplied object.
- *
- * @param mixed $attributes
- * @param mixed $object
- *
- * @return bool
- */
- public function isGranted($attributes, $object = null);
+ const ACCESS_DENIED_ERROR = Security::ACCESS_DENIED_ERROR;
+ const AUTHENTICATION_ERROR = Security::AUTHENTICATION_ERROR;
+ const LAST_USERNAME = Security::LAST_USERNAME;
}
diff --git a/Core/Tests/Authentication/AuthenticationProviderManagerTest.php b/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
new file mode 100644
index 0000000..cc8b7c0
--- /dev/null
+++ b/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
@@ -0,0 +1,148 @@
+<?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\Component\Security\Core\Tests\Authentication;
+
+use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager;
+use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
+use Symfony\Component\Security\Core\Exception\AuthenticationException;
+use Symfony\Component\Security\Core\Exception\AccountStatusException;
+use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
+
+class AuthenticationProviderManagerTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testAuthenticateWithoutProviders()
+ {
+ new AuthenticationProviderManager(array());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testAuthenticateWithProvidersWithIncorrectInterface()
+ {
+ new AuthenticationProviderManager(array(
+ new \stdClass(),
+ ));
+ }
+
+ public function testAuthenticateWhenNoProviderSupportsToken()
+ {
+ $manager = new AuthenticationProviderManager(array(
+ $this->getAuthenticationProvider(false),
+ ));
+
+ try {
+ $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
+ $this->fail();
+ } catch (ProviderNotFoundException $e) {
+ $this->assertSame($token, $e->getToken());
+ }
+ }
+
+ public function testAuthenticateWhenProviderReturnsAccountStatusException()
+ {
+ $manager = new AuthenticationProviderManager(array(
+ $this->getAuthenticationProvider(true, null, 'Symfony\Component\Security\Core\Exception\AccountStatusException'),
+ ));
+
+ try {
+ $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
+ $this->fail();
+ } catch (AccountStatusException $e) {
+ $this->assertSame($token, $e->getToken());
+ }
+ }
+
+ public function testAuthenticateWhenProviderReturnsAuthenticationException()
+ {
+ $manager = new AuthenticationProviderManager(array(
+ $this->getAuthenticationProvider(true, null, 'Symfony\Component\Security\Core\Exception\AuthenticationException'),
+ ));
+
+ try {
+ $manager->authenticate($token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
+ $this->fail();
+ } catch (AuthenticationException $e) {
+ $this->assertSame($token, $e->getToken());
+ }
+ }
+
+ public function testAuthenticateWhenOneReturnsAuthenticationExceptionButNotAll()
+ {
+ $manager = new AuthenticationProviderManager(array(
+ $this->getAuthenticationProvider(true, null, 'Symfony\Component\Security\Core\Exception\AuthenticationException'),
+ $this->getAuthenticationProvider(true, $expected = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')),
+ ));
+
+ $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
+ $this->assertSame($expected, $token);
+ }
+
+ public function testAuthenticateReturnsTokenOfTheFirstMatchingProvider()
+ {
+ $second = $this->getMock('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface');
+ $second
+ ->expects($this->never())
+ ->method('supports')
+ ;
+ $manager = new AuthenticationProviderManager(array(
+ $this->getAuthenticationProvider(true, $expected = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')),
+ $second,
+ ));
+
+ $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
+ $this->assertSame($expected, $token);
+ }
+
+ public function testEraseCredentialFlag()
+ {
+ $manager = new AuthenticationProviderManager(array(
+ $this->getAuthenticationProvider(true, $token = new UsernamePasswordToken('foo', 'bar', 'key')),
+ ));
+
+ $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
+ $this->assertEquals('', $token->getCredentials());
+
+ $manager = new AuthenticationProviderManager(array(
+ $this->getAuthenticationProvider(true, $token = new UsernamePasswordToken('foo', 'bar', 'key')),
+ ), false);
+
+ $token = $manager->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
+ $this->assertEquals('bar', $token->getCredentials());
+ }
+
+ protected function getAuthenticationProvider($supports, $token = null, $exception = null)
+ {
+ $provider = $this->getMock('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface');
+ $provider->expects($this->once())
+ ->method('supports')
+ ->will($this->returnValue($supports))
+ ;
+
+ if (null !== $token) {
+ $provider->expects($this->once())
+ ->method('authenticate')
+ ->will($this->returnValue($token))
+ ;
+ } elseif (null !== $exception) {
+ $provider->expects($this->once())
+ ->method('authenticate')
+ ->will($this->throwException($this->getMock($exception, null, array(), '')))
+ ;
+ }
+
+ return $provider;
+ }
+}
diff --git a/Core/Tests/Authentication/AuthenticationTrustResolverTest.php b/Core/Tests/Authentication/AuthenticationTrustResolverTest.php
new file mode 100644
index 0000000..3640981
--- /dev/null
+++ b/Core/Tests/Authentication/AuthenticationTrustResolverTest.php
@@ -0,0 +1,70 @@
+<?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\Component\Security\Core\Tests\Authentication;
+
+use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
+
+class AuthenticationTrustResolverTest extends \PHPUnit_Framework_TestCase
+{
+ public function testIsAnonymous()
+ {
+ $resolver = $this->getResolver();
+
+ $this->assertFalse($resolver->isAnonymous(null));
+ $this->assertFalse($resolver->isAnonymous($this->getToken()));
+ $this->assertFalse($resolver->isAnonymous($this->getRememberMeToken()));
+ $this->assertTrue($resolver->isAnonymous($this->getAnonymousToken()));
+ }
+
+ public function testIsRememberMe()
+ {
+ $resolver = $this->getResolver();
+
+ $this->assertFalse($resolver->isRememberMe(null));
+ $this->assertFalse($resolver->isRememberMe($this->getToken()));
+ $this->assertFalse($resolver->isRememberMe($this->getAnonymousToken()));
+ $this->assertTrue($resolver->isRememberMe($this->getRememberMeToken()));
+ }
+
+ public function testisFullFledged()
+ {
+ $resolver = $this->getResolver();
+
+ $this->assertFalse($resolver->isFullFledged(null));
+ $this->assertFalse($resolver->isFullFledged($this->getAnonymousToken()));
+ $this->assertFalse($resolver->isFullFledged($this->getRememberMeToken()));
+ $this->assertTrue($resolver->isFullFledged($this->getToken()));
+ }
+
+ protected function getToken()
+ {
+ return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ }
+
+ protected function getAnonymousToken()
+ {
+ return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken', null, array('', ''));
+ }
+
+ protected function getRememberMeToken()
+ {
+ return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', array('setPersistent'), array(), '', false);
+ }
+
+ protected function getResolver()
+ {
+ return new AuthenticationTrustResolver(
+ 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\AnonymousToken',
+ 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken'
+ );
+ }
+}
diff --git a/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php b/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php
new file mode 100644
index 0000000..5a189b0
--- /dev/null
+++ b/Core/Tests/Authentication/Provider/AnonymousAuthenticationProviderTest.php
@@ -0,0 +1,66 @@
+<?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\Component\Security\Core\Tests\Authentication\Provider;
+
+use Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider;
+
+class AnonymousAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testSupports()
+ {
+ $provider = $this->getProvider('foo');
+
+ $this->assertTrue($provider->supports($this->getSupportedToken('foo')));
+ $this->assertFalse($provider->supports($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));
+ }
+
+ public function testAuthenticateWhenTokenIsNotSupported()
+ {
+ $provider = $this->getProvider('foo');
+
+ $this->assertNull($provider->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testAuthenticateWhenKeyIsNotValid()
+ {
+ $provider = $this->getProvider('foo');
+
+ $this->assertNull($provider->authenticate($this->getSupportedToken('bar')));
+ }
+
+ public function testAuthenticate()
+ {
+ $provider = $this->getProvider('foo');
+ $token = $this->getSupportedToken('foo');
+
+ $this->assertSame($token, $provider->authenticate($token));
+ }
+
+ protected function getSupportedToken($key)
+ {
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken', array('getKey'), array(), '', false);
+ $token->expects($this->any())
+ ->method('getKey')
+ ->will($this->returnValue($key))
+ ;
+
+ return $token;
+ }
+
+ protected function getProvider($key)
+ {
+ return new AnonymousAuthenticationProvider($key);
+ }
+}
diff --git a/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php b/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php
new file mode 100644
index 0000000..3eedb8e
--- /dev/null
+++ b/Core/Tests/Authentication/Provider/DaoAuthenticationProviderTest.php
@@ -0,0 +1,300 @@
+<?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\Component\Security\Core\Tests\Authentication\Provider;
+
+use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;
+use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider;
+use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
+
+class DaoAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException
+ */
+ public function testRetrieveUserWhenProviderDoesNotReturnAnUserInterface()
+ {
+ $provider = $this->getProvider('fabien');
+ $method = new \ReflectionMethod($provider, 'retrieveUser');
+ $method->setAccessible(true);
+
+ $method->invoke($provider, 'fabien', $this->getSupportedToken());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
+ */
+ public function testRetrieveUserWhenUsernameIsNotFound()
+ {
+ $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface');
+ $userProvider->expects($this->once())
+ ->method('loadUserByUsername')
+ ->will($this->throwException(new UsernameNotFoundException()))
+ ;
+
+ $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface'));
+ $method = new \ReflectionMethod($provider, 'retrieveUser');
+ $method->setAccessible(true);
+
+ $method->invoke($provider, 'fabien', $this->getSupportedToken());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException
+ */
+ public function testRetrieveUserWhenAnExceptionOccurs()
+ {
+ $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface');
+ $userProvider->expects($this->once())
+ ->method('loadUserByUsername')
+ ->will($this->throwException(new \RuntimeException()))
+ ;
+
+ $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface'));
+ $method = new \ReflectionMethod($provider, 'retrieveUser');
+ $method->setAccessible(true);
+
+ $method->invoke($provider, 'fabien', $this->getSupportedToken());
+ }
+
+ public function testRetrieveUserReturnsUserFromTokenOnReauthentication()
+ {
+ $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface');
+ $userProvider->expects($this->never())
+ ->method('loadUserByUsername')
+ ;
+
+ $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');
+ $token = $this->getSupportedToken();
+ $token->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($user))
+ ;
+
+ $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface'));
+ $reflection = new \ReflectionMethod($provider, 'retrieveUser');
+ $reflection->setAccessible(true);
+ $result = $reflection->invoke($provider, null, $token);
+
+ $this->assertSame($user, $result);
+ }
+
+ public function testRetrieveUser()
+ {
+ $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');
+
+ $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface');
+ $userProvider->expects($this->once())
+ ->method('loadUserByUsername')
+ ->will($this->returnValue($user))
+ ;
+
+ $provider = new DaoAuthenticationProvider($userProvider, $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface'), 'key', $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface'));
+ $method = new \ReflectionMethod($provider, 'retrieveUser');
+ $method->setAccessible(true);
+
+ $this->assertSame($user, $method->invoke($provider, 'fabien', $this->getSupportedToken()));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testCheckAuthenticationWhenCredentialsAreEmpty()
+ {
+ $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface');
+ $encoder
+ ->expects($this->never())
+ ->method('isPasswordValid')
+ ;
+
+ $provider = $this->getProvider(null, null, $encoder);
+ $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\\Core\\User\\UserInterface'),
+ $token
+ );
+ }
+
+ public function testCheckAuthenticationWhenCredentialsAre0()
+ {
+ $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface');
+ $encoder
+ ->expects($this->once())
+ ->method('isPasswordValid')
+ ->will($this->returnValue(true))
+ ;
+
+ $provider = $this->getProvider(null, null, $encoder);
+ $method = new \ReflectionMethod($provider, 'checkAuthentication');
+ $method->setAccessible(true);
+
+ $token = $this->getSupportedToken();
+ $token
+ ->expects($this->once())
+ ->method('getCredentials')
+ ->will($this->returnValue('0'))
+ ;
+
+ $method->invoke(
+ $provider,
+ $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface'),
+ $token
+ );
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testCheckAuthenticationWhenCredentialsAreNotValid()
+ {
+ $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface');
+ $encoder->expects($this->once())
+ ->method('isPasswordValid')
+ ->will($this->returnValue(false))
+ ;
+
+ $provider = $this->getProvider(null, null, $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\\Core\\User\\UserInterface'), $token);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testCheckAuthenticationDoesNotReauthenticateWhenPasswordHasChanged()
+ {
+ $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');
+ $user->expects($this->once())
+ ->method('getPassword')
+ ->will($this->returnValue('foo'))
+ ;
+
+ $token = $this->getSupportedToken();
+ $token->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($user));
+
+ $dbUser = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');
+ $dbUser->expects($this->once())
+ ->method('getPassword')
+ ->will($this->returnValue('newFoo'))
+ ;
+
+ $provider = $this->getProvider();
+ $reflection = new \ReflectionMethod($provider, 'checkAuthentication');
+ $reflection->setAccessible(true);
+ $reflection->invoke($provider, $dbUser, $token);
+ }
+
+ public function testCheckAuthenticationWhenTokenNeedsReauthenticationWorksWithoutOriginalCredentials()
+ {
+ $user = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');
+ $user->expects($this->once())
+ ->method('getPassword')
+ ->will($this->returnValue('foo'))
+ ;
+
+ $token = $this->getSupportedToken();
+ $token->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($user));
+
+ $dbUser = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserInterface');
+ $dbUser->expects($this->once())
+ ->method('getPassword')
+ ->will($this->returnValue('foo'))
+ ;
+
+ $provider = $this->getProvider();
+ $reflection = new \ReflectionMethod($provider, 'checkAuthentication');
+ $reflection->setAccessible(true);
+ $reflection->invoke($provider, $dbUser, $token);
+ }
+
+ public function testCheckAuthentication()
+ {
+ $encoder = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface');
+ $encoder->expects($this->once())
+ ->method('isPasswordValid')
+ ->will($this->returnValue(true))
+ ;
+
+ $provider = $this->getProvider(null, null, $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\\Core\\User\\UserInterface'), $token);
+ }
+
+ protected function getSupportedToken()
+ {
+ $mock = $this->getMock('Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken', array('getCredentials', 'getUser', 'getProviderKey'), array(), '', false);
+ $mock
+ ->expects($this->any())
+ ->method('getProviderKey')
+ ->will($this->returnValue('key'))
+ ;
+
+ return $mock;
+ }
+
+ protected function getProvider($user = null, $userChecker = null, $passwordEncoder = null)
+ {
+ $userProvider = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserProviderInterface');
+ if (null !== $user) {
+ $userProvider->expects($this->once())
+ ->method('loadUserByUsername')
+ ->will($this->returnValue($user))
+ ;
+ }
+
+ if (null === $userChecker) {
+ $userChecker = $this->getMock('Symfony\\Component\\Security\\Core\\User\\UserCheckerInterface');
+ }
+
+ if (null === $passwordEncoder) {
+ $passwordEncoder = new PlaintextPasswordEncoder();
+ }
+
+ $encoderFactory = $this->getMock('Symfony\\Component\\Security\\Core\\Encoder\\EncoderFactoryInterface');
+ $encoderFactory
+ ->expects($this->any())
+ ->method('getEncoder')
+ ->will($this->returnValue($passwordEncoder))
+ ;
+
+ return new DaoAuthenticationProvider($userProvider, $userChecker, 'key', $encoderFactory);
+ }
+}
diff --git a/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php b/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php
new file mode 100644
index 0000000..5fd7b05
--- /dev/null
+++ b/Core/Tests/Authentication/Provider/PreAuthenticatedAuthenticationProviderTest.php
@@ -0,0 +1,134 @@
+<?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\Component\Security\Core\Tests\Authentication\Provider;
+
+use Symfony\Component\Security\Core\Authentication\Provider\PreAuthenticatedAuthenticationProvider;
+use Symfony\Component\Security\Core\Exception\LockedException;
+
+class PreAuthenticatedAuthenticationProviderTest 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\Core\Authentication\Token\TokenInterface')));
+
+ $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken')
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+ $token
+ ->expects($this->once())
+ ->method('getProviderKey')
+ ->will($this->returnValue('foo'))
+ ;
+ $this->assertFalse($provider->supports($token));
+ }
+
+ public function testAuthenticateWhenTokenIsNotSupported()
+ {
+ $provider = $this->getProvider();
+
+ $this->assertNull($provider->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testAuthenticateWhenNoUserIsSet()
+ {
+ $provider = $this->getProvider();
+ $provider->authenticate($this->getSupportedToken(''));
+ }
+
+ public function testAuthenticate()
+ {
+ $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $user
+ ->expects($this->once())
+ ->method('getRoles')
+ ->will($this->returnValue(array()))
+ ;
+ $provider = $this->getProvider($user);
+
+ $token = $provider->authenticate($this->getSupportedToken('fabien', 'pass'));
+ $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken', $token);
+ $this->assertEquals('pass', $token->getCredentials());
+ $this->assertEquals('key', $token->getProviderKey());
+ $this->assertEquals(array(), $token->getRoles());
+ $this->assertEquals(array('foo' => 'bar'), $token->getAttributes(), '->authenticate() copies token attributes');
+ $this->assertSame($user, $token->getUser());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\LockedException
+ */
+ public function testAuthenticateWhenUserCheckerThrowsException()
+ {
+ $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+
+ $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
+ $userChecker->expects($this->once())
+ ->method('checkPostAuth')
+ ->will($this->throwException(new LockedException()))
+ ;
+
+ $provider = $this->getProvider($user, $userChecker);
+
+ $provider->authenticate($this->getSupportedToken('fabien'));
+ }
+
+ protected function getSupportedToken($user = false, $credentials = false)
+ {
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken', array('getUser', 'getCredentials', 'getProviderKey'), array(), '', false);
+ if (false !== $user) {
+ $token->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($user))
+ ;
+ }
+ if (false !== $credentials) {
+ $token->expects($this->once())
+ ->method('getCredentials')
+ ->will($this->returnValue($credentials))
+ ;
+ }
+
+ $token
+ ->expects($this->any())
+ ->method('getProviderKey')
+ ->will($this->returnValue('key'))
+ ;
+
+ $token->setAttributes(array('foo' => 'bar'));
+
+ return $token;
+ }
+
+ protected function getProvider($user = null, $userChecker = null)
+ {
+ $userProvider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');
+ if (null !== $user) {
+ $userProvider->expects($this->once())
+ ->method('loadUserByUsername')
+ ->will($this->returnValue($user))
+ ;
+ }
+
+ if (null === $userChecker) {
+ $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
+ }
+
+ return new PreAuthenticatedAuthenticationProvider($userProvider, $userChecker, 'key');
+ }
+}
diff --git a/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php b/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php
new file mode 100644
index 0000000..a6fff4b
--- /dev/null
+++ b/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php
@@ -0,0 +1,107 @@
+<?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\Component\Security\Core\Tests\Authentication\Provider;
+
+use Symfony\Component\Security\Core\Authentication\Provider\RememberMeAuthenticationProvider;
+use Symfony\Component\Security\Core\Exception\DisabledException;
+use Symfony\Component\Security\Core\Role\Role;
+
+class RememberMeAuthenticationProviderTest 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\Core\Authentication\Token\TokenInterface')));
+ }
+
+ public function testAuthenticateWhenTokenIsNotSupported()
+ {
+ $provider = $this->getProvider();
+
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $this->assertNull($provider->authenticate($token));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testAuthenticateWhenKeysDoNotMatch()
+ {
+ $provider = $this->getProvider(null, 'key1');
+ $token = $this->getSupportedToken(null, 'key2');
+
+ $provider->authenticate($token);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\DisabledException
+ */
+ public function testAuthenticateWhenPreChecksFails()
+ {
+ $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
+ $userChecker->expects($this->once())
+ ->method('checkPreAuth')
+ ->will($this->throwException(new DisabledException()));
+
+ $provider = $this->getProvider($userChecker);
+
+ $provider->authenticate($this->getSupportedToken());
+ }
+
+ public function testAuthenticate()
+ {
+ $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $user->expects($this->exactly(2))
+ ->method('getRoles')
+ ->will($this->returnValue(array('ROLE_FOO')));
+
+ $provider = $this->getProvider();
+
+ $token = $this->getSupportedToken($user);
+ $authToken = $provider->authenticate($token);
+
+ $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', $authToken);
+ $this->assertSame($user, $authToken->getUser());
+ $this->assertEquals(array(new Role('ROLE_FOO')), $authToken->getRoles());
+ $this->assertEquals('', $authToken->getCredentials());
+ }
+
+ protected function getSupportedToken($user = null, $key = 'test')
+ {
+ if (null === $user) {
+ $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $user
+ ->expects($this->any())
+ ->method('getRoles')
+ ->will($this->returnValue(array()));
+ }
+
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', array('getProviderKey'), array($user, 'foo', $key));
+ $token
+ ->expects($this->once())
+ ->method('getProviderKey')
+ ->will($this->returnValue('foo'));
+
+ return $token;
+ }
+
+ protected function getProvider($userChecker = null, $key = 'test')
+ {
+ if (null === $userChecker) {
+ $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
+ }
+
+ return new RememberMeAuthenticationProvider($userChecker, $key, 'foo');
+ }
+}
diff --git a/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php b/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php
new file mode 100644
index 0000000..0503054
--- /dev/null
+++ b/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php
@@ -0,0 +1,250 @@
+<?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\Component\Security\Core\Tests\Authentication\Provider;
+
+use Symfony\Component\Security\Core\Exception\AccountExpiredException;
+use Symfony\Component\Security\Core\Exception\BadCredentialsException;
+use Symfony\Component\Security\Core\Exception\CredentialsExpiredException;
+use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
+use Symfony\Component\Security\Core\Role\Role;
+use Symfony\Component\Security\Core\Role\SwitchUserRole;
+
+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\Core\Authentication\Token\TokenInterface')));
+ }
+
+ public function testAuthenticateWhenTokenIsNotSupported()
+ {
+ $provider = $this->getProvider();
+
+ $this->assertNull($provider->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
+ */
+ public function testAuthenticateWhenUsernameIsNotFound()
+ {
+ $provider = $this->getProvider(false, false);
+ $provider->expects($this->once())
+ ->method('retrieveUser')
+ ->will($this->throwException(new UsernameNotFoundException()))
+ ;
+
+ $provider->authenticate($this->getSupportedToken());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testAuthenticateWhenUsernameIsNotFoundAndHideIsTrue()
+ {
+ $provider = $this->getProvider(false, true);
+ $provider->expects($this->once())
+ ->method('retrieveUser')
+ ->will($this->throwException(new UsernameNotFoundException()))
+ ;
+
+ $provider->authenticate($this->getSupportedToken());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationServiceException
+ */
+ public function testAuthenticateWhenProviderDoesNotReturnAnUserInterface()
+ {
+ $provider = $this->getProvider(false, true);
+ $provider->expects($this->once())
+ ->method('retrieveUser')
+ ->will($this->returnValue(null))
+ ;
+
+ $provider->authenticate($this->getSupportedToken());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\CredentialsExpiredException
+ */
+ public function testAuthenticateWhenPreChecksFails()
+ {
+ $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
+ $userChecker->expects($this->once())
+ ->method('checkPreAuth')
+ ->will($this->throwException(new CredentialsExpiredException()))
+ ;
+
+ $provider = $this->getProvider($userChecker);
+ $provider->expects($this->once())
+ ->method('retrieveUser')
+ ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface')))
+ ;
+
+ $provider->authenticate($this->getSupportedToken());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException
+ */
+ public function testAuthenticateWhenPostChecksFails()
+ {
+ $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
+ $userChecker->expects($this->once())
+ ->method('checkPostAuth')
+ ->will($this->throwException(new AccountExpiredException()))
+ ;
+
+ $provider = $this->getProvider($userChecker);
+ $provider->expects($this->once())
+ ->method('retrieveUser')
+ ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface')))
+ ;
+
+ $provider->authenticate($this->getSupportedToken());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ * @expectedExceptionMessage Bad credentials
+ */
+ public function testAuthenticateWhenPostCheckAuthenticationFails()
+ {
+ $provider = $this->getProvider();
+ $provider->expects($this->once())
+ ->method('retrieveUser')
+ ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface')))
+ ;
+ $provider->expects($this->once())
+ ->method('checkAuthentication')
+ ->will($this->throwException(new BadCredentialsException()))
+ ;
+
+ $provider->authenticate($this->getSupportedToken());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ * @expectedExceptionMessage Foo
+ */
+ public function testAuthenticateWhenPostCheckAuthenticationFailsWithHideFalse()
+ {
+ $provider = $this->getProvider(false, false);
+ $provider->expects($this->once())
+ ->method('retrieveUser')
+ ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\User\UserInterface')))
+ ;
+ $provider->expects($this->once())
+ ->method('checkAuthentication')
+ ->will($this->throwException(new BadCredentialsException('Foo')))
+ ;
+
+ $provider->authenticate($this->getSupportedToken());
+ }
+
+ public function testAuthenticate()
+ {
+ $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $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'))
+ ;
+
+ $token->expects($this->once())
+ ->method('getRoles')
+ ->will($this->returnValue(array()))
+ ;
+
+ $authToken = $provider->authenticate($token);
+
+ $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken);
+ $this->assertSame($user, $authToken->getUser());
+ $this->assertEquals(array(new Role('ROLE_FOO')), $authToken->getRoles());
+ $this->assertEquals('foo', $authToken->getCredentials());
+ $this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes');
+ }
+
+ public function testAuthenticateWithPreservingRoleSwitchUserRole()
+ {
+ $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $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'))
+ ;
+
+ $switchUserRole = new SwitchUserRole('foo', $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
+ $token->expects($this->once())
+ ->method('getRoles')
+ ->will($this->returnValue(array($switchUserRole)))
+ ;
+
+ $authToken = $provider->authenticate($token);
+
+ $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken);
+ $this->assertSame($user, $authToken->getUser());
+ $this->assertContains(new Role('ROLE_FOO'), $authToken->getRoles(), '', false, false);
+ $this->assertContains($switchUserRole, $authToken->getRoles());
+ $this->assertEquals('foo', $authToken->getCredentials());
+ $this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes');
+ }
+
+ protected function getSupportedToken()
+ {
+ $mock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', array('getCredentials', 'getProviderKey', 'getRoles'), array(), '', false);
+ $mock
+ ->expects($this->any())
+ ->method('getProviderKey')
+ ->will($this->returnValue('key'))
+ ;
+
+ $mock->setAttributes(array('foo' => 'bar'));
+
+ return $mock;
+ }
+
+ protected function getProvider($userChecker = false, $hide = true)
+ {
+ if (false === $userChecker) {
+ $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface');
+ }
+
+ return $this->getMockForAbstractClass('Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider', array($userChecker, 'key', $hide));
+ }
+}
diff --git a/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php b/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php
new file mode 100644
index 0000000..3bdf38c
--- /dev/null
+++ b/Core/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php
@@ -0,0 +1,63 @@
+<?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\Component\Security\Core\Tests\Authentication\RememberMe;
+
+use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
+use Symfony\Component\Security\Core\Authentication\RememberMe\InMemoryTokenProvider;
+
+class InMemoryTokenProviderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCreateNewToken()
+ {
+ $provider = new InMemoryTokenProvider();
+
+ $token = new PersistentToken('foo', 'foo', 'foo', 'foo', new \DateTime());
+ $provider->createNewToken($token);
+
+ $this->assertSame($provider->loadTokenBySeries('foo'), $token);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\TokenNotFoundException
+ */
+ public function testLoadTokenBySeriesThrowsNotFoundException()
+ {
+ $provider = new InMemoryTokenProvider();
+ $provider->loadTokenBySeries('foo');
+ }
+
+ public function testUpdateToken()
+ {
+ $provider = new InMemoryTokenProvider();
+
+ $token = new PersistentToken('foo', 'foo', 'foo', 'foo', new \DateTime());
+ $provider->createNewToken($token);
+ $provider->updateToken('foo', 'newFoo', $lastUsed = new \DateTime());
+ $token = $provider->loadTokenBySeries('foo');
+
+ $this->assertEquals('newFoo', $token->getTokenValue());
+ $this->assertSame($token->getLastUsed(), $lastUsed);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\TokenNotFoundException
+ */
+ public function testDeleteToken()
+ {
+ $provider = new InMemoryTokenProvider();
+
+ $token = new PersistentToken('foo', 'foo', 'foo', 'foo', new \DateTime());
+ $provider->createNewToken($token);
+ $provider->deleteTokenBySeries('foo');
+ $provider->loadTokenBySeries('foo');
+ }
+}
diff --git a/Core/Tests/Authentication/RememberMe/PersistentTokenTest.php b/Core/Tests/Authentication/RememberMe/PersistentTokenTest.php
new file mode 100644
index 0000000..903c030
--- /dev/null
+++ b/Core/Tests/Authentication/RememberMe/PersistentTokenTest.php
@@ -0,0 +1,29 @@
+<?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\Component\Security\Core\Tests\Authentication\RememberMe;
+
+use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
+
+class PersistentTokenTest extends \PHPUnit_Framework_TestCase
+{
+ public function testConstructor()
+ {
+ $lastUsed = new \DateTime();
+ $token = new PersistentToken('fooclass', 'fooname', 'fooseries', 'footokenvalue', $lastUsed);
+
+ $this->assertEquals('fooclass', $token->getClass());
+ $this->assertEquals('fooname', $token->getUsername());
+ $this->assertEquals('fooseries', $token->getSeries());
+ $this->assertEquals('footokenvalue', $token->getTokenValue());
+ $this->assertSame($lastUsed, $token->getLastUsed());
+ }
+}
diff --git a/Core/Tests/Authentication/Token/AbstractTokenTest.php b/Core/Tests/Authentication/Token/AbstractTokenTest.php
new file mode 100644
index 0000000..1a786d7
--- /dev/null
+++ b/Core/Tests/Authentication/Token/AbstractTokenTest.php
@@ -0,0 +1,269 @@
+<?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\Component\Security\Core\Tests\Authentication\Token;
+
+use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
+use Symfony\Component\Security\Core\Role\Role;
+use Symfony\Component\Security\Core\Role\SwitchUserRole;
+
+class TestUser
+{
+ protected $name;
+
+ public function __construct($name)
+ {
+ $this->name = $name;
+ }
+
+ public function __toString()
+ {
+ return $this->name;
+ }
+}
+
+class ConcreteToken extends AbstractToken
+{
+ private $credentials = 'credentials_value';
+
+ public function __construct($user, array $roles = array())
+ {
+ parent::__construct($roles);
+
+ $this->setUser($user);
+ }
+
+ public function serialize()
+ {
+ return serialize(array($this->credentials, parent::serialize()));
+ }
+
+ public function unserialize($serialized)
+ {
+ list($this->credentials, $parentStr) = unserialize($serialized);
+ parent::unserialize($parentStr);
+ }
+
+ public function getCredentials()
+ {
+ }
+}
+
+class AbstractTokenTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetUsername()
+ {
+ $token = $this->getToken(array('ROLE_FOO'));
+ $token->setUser('fabien');
+ $this->assertEquals('fabien', $token->getUsername());
+
+ $token->setUser(new TestUser('fabien'));
+ $this->assertEquals('fabien', $token->getUsername());
+
+ $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $user->expects($this->once())->method('getUsername')->will($this->returnValue('fabien'));
+ $token->setUser($user);
+ $this->assertEquals('fabien', $token->getUsername());
+ }
+
+ public function testEraseCredentials()
+ {
+ $token = $this->getToken(array('ROLE_FOO'));
+
+ $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $user->expects($this->once())->method('eraseCredentials');
+ $token->setUser($user);
+
+ $token->eraseCredentials();
+ }
+
+ public function testSerialize()
+ {
+ $token = $this->getToken(array('ROLE_FOO'));
+ $token->setAttributes(array('foo' => 'bar'));
+
+ $uToken = unserialize(serialize($token));
+
+ $this->assertEquals($token->getRoles(), $uToken->getRoles());
+ $this->assertEquals($token->getAttributes(), $uToken->getAttributes());
+ }
+
+ public function testSerializeParent()
+ {
+ $user = new TestUser('fabien');
+ $token = new ConcreteToken($user, array('ROLE_FOO'));
+
+ $parentToken = new ConcreteToken($user, array(new SwitchUserRole('ROLE_PREVIOUS', $token)));
+ $uToken = unserialize(serialize($parentToken));
+
+ $this->assertEquals(
+ current($parentToken->getRoles())->getSource()->getUser(),
+ current($uToken->getRoles())->getSource()->getUser()
+ );
+ }
+
+ public function testConstructor()
+ {
+ $token = $this->getToken(array('ROLE_FOO'));
+ $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());
+
+ $token = $this->getToken(array(new Role('ROLE_FOO')));
+ $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());
+
+ $token = $this->getToken(array(new Role('ROLE_FOO'), 'ROLE_BAR'));
+ $this->assertEquals(array(new Role('ROLE_FOO'), new Role('ROLE_BAR')), $token->getRoles());
+ }
+
+ public function testAuthenticatedFlag()
+ {
+ $token = $this->getToken();
+ $this->assertFalse($token->isAuthenticated());
+
+ $token->setAuthenticated(true);
+ $this->assertTrue($token->isAuthenticated());
+
+ $token->setAuthenticated(false);
+ $this->assertFalse($token->isAuthenticated());
+ }
+
+ public function testAttributes()
+ {
+ $attributes = array('foo' => 'bar');
+ $token = $this->getToken();
+ $token->setAttributes($attributes);
+
+ $this->assertEquals($attributes, $token->getAttributes(), '->getAttributes() returns the token attributes');
+ $this->assertEquals('bar', $token->getAttribute('foo'), '->getAttribute() returns the value of an attribute');
+ $token->setAttribute('foo', 'foo');
+ $this->assertEquals('foo', $token->getAttribute('foo'), '->setAttribute() changes the value of an attribute');
+ $this->assertTrue($token->hasAttribute('foo'), '->hasAttribute() returns true if the attribute is defined');
+ $this->assertFalse($token->hasAttribute('oof'), '->hasAttribute() returns false if the attribute is not defined');
+
+ try {
+ $token->getAttribute('foobar');
+ $this->fail('->getAttribute() throws an \InvalidArgumentException exception when the attribute does not exist');
+ } catch (\Exception $e) {
+ $this->assertInstanceOf('\InvalidArgumentException', $e, '->getAttribute() throws an \InvalidArgumentException exception when the attribute does not exist');
+ $this->assertEquals('This token has no "foobar" attribute.', $e->getMessage(), '->getAttribute() throws an \InvalidArgumentException exception when the attribute does not exist');
+ }
+ }
+
+ /**
+ * @dataProvider getUsers
+ */
+ public function testSetUser($user)
+ {
+ $token = $this->getToken();
+ $token->setUser($user);
+ $this->assertSame($user, $token->getUser());
+ }
+
+ public function getUsers()
+ {
+ $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $advancedUser = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
+
+ return array(
+ array($advancedUser),
+ array($user),
+ array(new TestUser('foo')),
+ array('foo'),
+ );
+ }
+
+ /**
+ * @dataProvider getUserChanges
+ */
+ public function testSetUserSetsAuthenticatedToFalseWhenUserChanges($firstUser, $secondUser)
+ {
+ $token = $this->getToken();
+ $token->setAuthenticated(true);
+ $this->assertTrue($token->isAuthenticated());
+
+ $token->setUser($firstUser);
+ $this->assertTrue($token->isAuthenticated());
+
+ $token->setUser($secondUser);
+ $this->assertFalse($token->isAuthenticated());
+ }
+
+ public function getUserChanges()
+ {
+ $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $advancedUser = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
+
+ return array(
+ array(
+ 'foo', 'bar',
+ ),
+ array(
+ 'foo', new TestUser('bar'),
+ ),
+ array(
+ 'foo', $user,
+ ),
+ array(
+ 'foo', $advancedUser,
+ ),
+ array(
+ $user, 'foo',
+ ),
+ array(
+ $advancedUser, 'foo',
+ ),
+ array(
+ $user, new TestUser('foo'),
+ ),
+ array(
+ $advancedUser, new TestUser('foo'),
+ ),
+ array(
+ new TestUser('foo'), new TestUser('bar'),
+ ),
+ array(
+ new TestUser('foo'), 'bar',
+ ),
+ array(
+ new TestUser('foo'), $user,
+ ),
+ array(
+ new TestUser('foo'), $advancedUser,
+ ),
+ array(
+ $user, $advancedUser,
+ ),
+ array(
+ $advancedUser, $user,
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider getUsers
+ */
+ public function testSetUserDoesNotSetAuthenticatedToFalseWhenUserDoesNotChange($user)
+ {
+ $token = $this->getToken();
+ $token->setAuthenticated(true);
+ $this->assertTrue($token->isAuthenticated());
+
+ $token->setUser($user);
+ $this->assertTrue($token->isAuthenticated());
+
+ $token->setUser($user);
+ $this->assertTrue($token->isAuthenticated());
+ }
+
+ protected function getToken(array $roles = array())
+ {
+ return $this->getMockForAbstractClass('Symfony\Component\Security\Core\Authentication\Token\AbstractToken', array($roles));
+ }
+}
diff --git a/Core/Tests/Authentication/Token/AnonymousTokenTest.php b/Core/Tests/Authentication/Token/AnonymousTokenTest.php
new file mode 100644
index 0000000..b5cf006
--- /dev/null
+++ b/Core/Tests/Authentication/Token/AnonymousTokenTest.php
@@ -0,0 +1,45 @@
+<?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\Component\Security\Core\Tests\Authentication\Token;
+
+use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
+use Symfony\Component\Security\Core\Role\Role;
+
+class AnonymousTokenTest extends \PHPUnit_Framework_TestCase
+{
+ public function testConstructor()
+ {
+ $token = new AnonymousToken('foo', 'bar');
+ $this->assertTrue($token->isAuthenticated());
+
+ $token = new AnonymousToken('foo', 'bar', array('ROLE_FOO'));
+ $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());
+ }
+
+ public function testGetKey()
+ {
+ $token = new AnonymousToken('foo', 'bar');
+ $this->assertEquals('foo', $token->getKey());
+ }
+
+ public function testGetCredentials()
+ {
+ $token = new AnonymousToken('foo', 'bar');
+ $this->assertEquals('', $token->getCredentials());
+ }
+
+ public function testGetUser()
+ {
+ $token = new AnonymousToken('foo', 'bar');
+ $this->assertEquals('bar', $token->getUser());
+ }
+}
diff --git a/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.php b/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.php
new file mode 100644
index 0000000..77d2608
--- /dev/null
+++ b/Core/Tests/Authentication/Token/PreAuthenticatedTokenTest.php
@@ -0,0 +1,48 @@
+<?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\Component\Security\Core\Tests\Authentication\Token;
+
+use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
+use Symfony\Component\Security\Core\Role\Role;
+
+class PreAuthenticatedTokenTest extends \PHPUnit_Framework_TestCase
+{
+ public function testConstructor()
+ {
+ $token = new PreAuthenticatedToken('foo', 'bar', 'key');
+ $this->assertFalse($token->isAuthenticated());
+
+ $token = new PreAuthenticatedToken('foo', 'bar', 'key', array('ROLE_FOO'));
+ $this->assertTrue($token->isAuthenticated());
+ $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());
+ $this->assertEquals('key', $token->getProviderKey());
+ }
+
+ public function testGetCredentials()
+ {
+ $token = new PreAuthenticatedToken('foo', 'bar', 'key');
+ $this->assertEquals('bar', $token->getCredentials());
+ }
+
+ public function testGetUser()
+ {
+ $token = new PreAuthenticatedToken('foo', 'bar', 'key');
+ $this->assertEquals('foo', $token->getUser());
+ }
+
+ public function testEraseCredentials()
+ {
+ $token = new PreAuthenticatedToken('foo', 'bar', 'key');
+ $token->eraseCredentials();
+ $this->assertEquals('', $token->getCredentials());
+ }
+}
diff --git a/Core/Tests/Authentication/Token/RememberMeTokenTest.php b/Core/Tests/Authentication/Token/RememberMeTokenTest.php
new file mode 100644
index 0000000..7449204
--- /dev/null
+++ b/Core/Tests/Authentication/Token/RememberMeTokenTest.php
@@ -0,0 +1,66 @@
+<?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\Component\Security\Core\Tests\Authentication\Token;
+
+use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
+use Symfony\Component\Security\Core\Role\Role;
+
+class RememberMeTokenTest extends \PHPUnit_Framework_TestCase
+{
+ public function testConstructor()
+ {
+ $user = $this->getUser();
+ $token = new RememberMeToken($user, 'fookey', 'foo');
+
+ $this->assertEquals('fookey', $token->getProviderKey());
+ $this->assertEquals('foo', $token->getKey());
+ $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());
+ $this->assertSame($user, $token->getUser());
+ $this->assertTrue($token->isAuthenticated());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testConstructorKeyCannotBeNull()
+ {
+ new RememberMeToken(
+ $this->getUser(),
+ null,
+ null
+ );
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testConstructorKeyCannotBeEmptyString()
+ {
+ new RememberMeToken(
+ $this->getUser(),
+ '',
+ ''
+ );
+ }
+
+ protected function getUser($roles = array('ROLE_FOO'))
+ {
+ $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $user
+ ->expects($this->once())
+ ->method('getRoles')
+ ->will($this->returnValue($roles))
+ ;
+
+ return $user;
+ }
+}
diff --git a/Core/Tests/Authentication/Token/Storage/TokenStorageTest.php b/Core/Tests/Authentication/Token/Storage/TokenStorageTest.php
new file mode 100644
index 0000000..d06e3f0
--- /dev/null
+++ b/Core/Tests/Authentication/Token/Storage/TokenStorageTest.php
@@ -0,0 +1,26 @@
+<?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\Component\Security\Core\Tests\Authentication\Token\Storage;
+
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
+
+class TokenStorageTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetSetToken()
+ {
+ $tokenStorage = new TokenStorage();
+ $this->assertNull($tokenStorage->getToken());
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $tokenStorage->setToken($token);
+ $this->assertSame($token, $tokenStorage->getToken());
+ }
+}
diff --git a/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.php b/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.php
new file mode 100644
index 0000000..0297eff
--- /dev/null
+++ b/Core/Tests/Authentication/Token/UsernamePasswordTokenTest.php
@@ -0,0 +1,58 @@
+<?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\Component\Security\Core\Tests\Authentication\Token;
+
+use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
+use Symfony\Component\Security\Core\Role\Role;
+
+class UsernamePasswordTokenTest extends \PHPUnit_Framework_TestCase
+{
+ public function testConstructor()
+ {
+ $token = new UsernamePasswordToken('foo', 'bar', 'key');
+ $this->assertFalse($token->isAuthenticated());
+
+ $token = new UsernamePasswordToken('foo', 'bar', 'key', array('ROLE_FOO'));
+ $this->assertEquals(array(new Role('ROLE_FOO')), $token->getRoles());
+ $this->assertTrue($token->isAuthenticated());
+ $this->assertEquals('key', $token->getProviderKey());
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testSetAuthenticatedToTrue()
+ {
+ $token = new UsernamePasswordToken('foo', 'bar', 'key');
+ $token->setAuthenticated(true);
+ }
+
+ public function testSetAuthenticatedToFalse()
+ {
+ $token = new UsernamePasswordToken('foo', 'bar', 'key');
+ $token->setAuthenticated(false);
+ $this->assertFalse($token->isAuthenticated());
+ }
+
+ public function testEraseCredentials()
+ {
+ $token = new UsernamePasswordToken('foo', 'bar', 'key');
+ $token->eraseCredentials();
+ $this->assertEquals('', $token->getCredentials());
+ }
+
+ public function testToString()
+ {
+ $token = new UsernamePasswordToken('foo', '', 'foo', array('A', 'B'));
+ $this->assertEquals('UsernamePasswordToken(user="foo", authenticated=true, roles="A, B")', (string) $token);
+ }
+}
diff --git a/Core/Tests/Authorization/AccessDecisionManagerTest.php b/Core/Tests/Authorization/AccessDecisionManagerTest.php
new file mode 100644
index 0000000..7a9ab08
--- /dev/null
+++ b/Core/Tests/Authorization/AccessDecisionManagerTest.php
@@ -0,0 +1,198 @@
+<?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\Component\Security\Core\Tests\Authorization;
+
+use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+
+class AccessDecisionManagerTest extends \PHPUnit_Framework_TestCase
+{
+ public function testSupportsClass()
+ {
+ $manager = new AccessDecisionManager(array(
+ $this->getVoterSupportsClass(true),
+ $this->getVoterSupportsClass(false),
+ ));
+ $this->assertTrue($manager->supportsClass('FooClass'));
+
+ $manager = new AccessDecisionManager(array(
+ $this->getVoterSupportsClass(false),
+ $this->getVoterSupportsClass(false),
+ ));
+ $this->assertFalse($manager->supportsClass('FooClass'));
+ }
+
+ public function testSupportsAttribute()
+ {
+ $manager = new AccessDecisionManager(array(
+ $this->getVoterSupportsAttribute(true),
+ $this->getVoterSupportsAttribute(false),
+ ));
+ $this->assertTrue($manager->supportsAttribute('foo'));
+
+ $manager = new AccessDecisionManager(array(
+ $this->getVoterSupportsAttribute(false),
+ $this->getVoterSupportsAttribute(false),
+ ));
+ $this->assertFalse($manager->supportsAttribute('foo'));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testSetVotersEmpty()
+ {
+ $manager = new AccessDecisionManager(array());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testSetUnsupportedStrategy()
+ {
+ new AccessDecisionManager(array($this->getVoter(VoterInterface::ACCESS_GRANTED)), 'fooBar');
+ }
+
+ /**
+ * @dataProvider getStrategyTests
+ */
+ public function testStrategies($strategy, $voters, $allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions, $expected)
+ {
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $manager = new AccessDecisionManager($voters, $strategy, $allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions);
+
+ $this->assertSame($expected, $manager->decide($token, array('ROLE_FOO')));
+ }
+
+ /**
+ * @dataProvider getStrategiesWith2RolesTests
+ */
+ public function testStrategiesWith2Roles($token, $strategy, $voter, $expected)
+ {
+ $manager = new AccessDecisionManager(array($voter), $strategy);
+
+ $this->assertSame($expected, $manager->decide($token, array('ROLE_FOO', 'ROLE_BAR')));
+ }
+
+ public function getStrategiesWith2RolesTests()
+ {
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+
+ return array(
+ array($token, 'affirmative', $this->getVoter(VoterInterface::ACCESS_DENIED), false),
+ array($token, 'affirmative', $this->getVoter(VoterInterface::ACCESS_GRANTED), true),
+
+ array($token, 'consensus', $this->getVoter(VoterInterface::ACCESS_DENIED), false),
+ array($token, 'consensus', $this->getVoter(VoterInterface::ACCESS_GRANTED), true),
+
+ array($token, 'unanimous', $this->getVoterFor2Roles($token, VoterInterface::ACCESS_DENIED, VoterInterface::ACCESS_DENIED), false),
+ array($token, 'unanimous', $this->getVoterFor2Roles($token, VoterInterface::ACCESS_DENIED, VoterInterface::ACCESS_GRANTED), false),
+ array($token, 'unanimous', $this->getVoterFor2Roles($token, VoterInterface::ACCESS_GRANTED, VoterInterface::ACCESS_DENIED), false),
+ array($token, 'unanimous', $this->getVoterFor2Roles($token, VoterInterface::ACCESS_GRANTED, VoterInterface::ACCESS_GRANTED), true),
+ );
+ }
+
+ protected function getVoterFor2Roles($token, $vote1, $vote2)
+ {
+ $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface');
+ $voter->expects($this->any())
+ ->method('vote')
+ ->will($this->returnValueMap(array(
+ array($token, null, array('ROLE_FOO'), $vote1),
+ array($token, null, array('ROLE_BAR'), $vote2),
+ )))
+ ;
+
+ return $voter;
+ }
+
+ public function getStrategyTests()
+ {
+ return array(
+ // affirmative
+ array(AccessDecisionManager::STRATEGY_AFFIRMATIVE, $this->getVoters(1, 0, 0), false, true, true),
+ array(AccessDecisionManager::STRATEGY_AFFIRMATIVE, $this->getVoters(1, 2, 0), false, true, true),
+ array(AccessDecisionManager::STRATEGY_AFFIRMATIVE, $this->getVoters(0, 1, 0), false, true, false),
+ array(AccessDecisionManager::STRATEGY_AFFIRMATIVE, $this->getVoters(0, 0, 1), false, true, false),
+ array(AccessDecisionManager::STRATEGY_AFFIRMATIVE, $this->getVoters(0, 0, 1), true, true, true),
+
+ // consensus
+ array(AccessDecisionManager::STRATEGY_CONSENSUS, $this->getVoters(1, 0, 0), false, true, true),
+ array(AccessDecisionManager::STRATEGY_CONSENSUS, $this->getVoters(1, 2, 0), false, true, false),
+ array(AccessDecisionManager::STRATEGY_CONSENSUS, $this->getVoters(2, 1, 0), false, true, true),
+
+ array(AccessDecisionManager::STRATEGY_CONSENSUS, $this->getVoters(0, 0, 1), false, true, false),
+
+ array(AccessDecisionManager::STRATEGY_CONSENSUS, $this->getVoters(0, 0, 1), true, true, true),
+
+ array(AccessDecisionManager::STRATEGY_CONSENSUS, $this->getVoters(2, 2, 0), false, true, true),
+ array(AccessDecisionManager::STRATEGY_CONSENSUS, $this->getVoters(2, 2, 1), false, true, true),
+
+ array(AccessDecisionManager::STRATEGY_CONSENSUS, $this->getVoters(2, 2, 0), false, false, false),
+ array(AccessDecisionManager::STRATEGY_CONSENSUS, $this->getVoters(2, 2, 1), false, false, false),
+
+ // unanimous
+ array(AccessDecisionManager::STRATEGY_UNANIMOUS, $this->getVoters(1, 0, 0), false, true, true),
+ array(AccessDecisionManager::STRATEGY_UNANIMOUS, $this->getVoters(1, 0, 1), false, true, true),
+ array(AccessDecisionManager::STRATEGY_UNANIMOUS, $this->getVoters(1, 1, 0), false, true, false),
+
+ array(AccessDecisionManager::STRATEGY_UNANIMOUS, $this->getVoters(0, 0, 2), false, true, false),
+ array(AccessDecisionManager::STRATEGY_UNANIMOUS, $this->getVoters(0, 0, 2), true, true, true),
+ );
+ }
+
+ protected function getVoters($grants, $denies, $abstains)
+ {
+ $voters = array();
+ for ($i = 0; $i < $grants; ++$i) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_GRANTED);
+ }
+ for ($i = 0; $i < $denies; ++$i) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_DENIED);
+ }
+ for ($i = 0; $i < $abstains; ++$i) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_ABSTAIN);
+ }
+
+ return $voters;
+ }
+
+ protected function getVoter($vote)
+ {
+ $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface');
+ $voter->expects($this->any())
+ ->method('vote')
+ ->will($this->returnValue($vote));
+
+ return $voter;
+ }
+
+ protected function getVoterSupportsClass($ret)
+ {
+ $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface');
+ $voter->expects($this->any())
+ ->method('supportsClass')
+ ->will($this->returnValue($ret));
+
+ return $voter;
+ }
+
+ protected function getVoterSupportsAttribute($ret)
+ {
+ $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface');
+ $voter->expects($this->any())
+ ->method('supportsAttribute')
+ ->will($this->returnValue($ret));
+
+ return $voter;
+ }
+}
diff --git a/Core/Tests/Authorization/AuthorizationCheckerTest.php b/Core/Tests/Authorization/AuthorizationCheckerTest.php
new file mode 100644
index 0000000..aafc12f
--- /dev/null
+++ b/Core/Tests/Authorization/AuthorizationCheckerTest.php
@@ -0,0 +1,99 @@
+<?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\Component\Security\Core\Tests\Authorization;
+
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
+use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
+
+class AuthorizationCheckerTest extends \PHPUnit_Framework_TestCase
+{
+ private $authenticationManager;
+ private $accessDecisionManager;
+ private $authorizationChecker;
+ private $tokenStorage;
+
+ protected function setUp()
+ {
+ $this->authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
+ $this->accessDecisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface');
+ $this->tokenStorage = new TokenStorage();
+
+ $this->authorizationChecker = new AuthorizationChecker(
+ $this->tokenStorage,
+ $this->authenticationManager,
+ $this->accessDecisionManager
+ );
+ }
+
+ public function testVoteAuthenticatesTokenIfNecessary()
+ {
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $this->tokenStorage->setToken($token);
+
+ $newToken = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+
+ $this->authenticationManager
+ ->expects($this->once())
+ ->method('authenticate')
+ ->with($this->equalTo($token))
+ ->will($this->returnValue($newToken));
+
+ // default with() isn't a strict check
+ $tokenComparison = function ($value) use ($newToken) {
+ // make sure that the new token is used in "decide()" and not the old one
+ return $value === $newToken;
+ };
+
+ $this->accessDecisionManager
+ ->expects($this->once())
+ ->method('decide')
+ ->with($this->callback($tokenComparison))
+ ->will($this->returnValue(true));
+
+ // first run the token has not been re-authenticated yet, after isGranted is called, it should be equal
+ $this->assertFalse($newToken === $this->tokenStorage->getToken());
+ $this->assertTrue($this->authorizationChecker->isGranted('foo'));
+ $this->assertTrue($newToken === $this->tokenStorage->getToken());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException
+ */
+ public function testVoteWithoutAuthenticationToken()
+ {
+ $this->authorizationChecker->isGranted('ROLE_FOO');
+ }
+
+ /**
+ * @dataProvider isGrantedProvider
+ */
+ public function testIsGranted($decide)
+ {
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $token
+ ->expects($this->once())
+ ->method('isAuthenticated')
+ ->will($this->returnValue(true));
+
+ $this->accessDecisionManager
+ ->expects($this->once())
+ ->method('decide')
+ ->will($this->returnValue($decide));
+ $this->tokenStorage->setToken($token);
+ $this->assertTrue($decide === $this->authorizationChecker->isGranted('ROLE_FOO'));
+ }
+
+ public function isGrantedProvider()
+ {
+ return array(array(true), array(false));
+ }
+}
diff --git a/Core/Tests/Authorization/ExpressionLanguageTest.php b/Core/Tests/Authorization/ExpressionLanguageTest.php
new file mode 100644
index 0000000..5b4aca6
--- /dev/null
+++ b/Core/Tests/Authorization/ExpressionLanguageTest.php
@@ -0,0 +1,79 @@
+<?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\Component\Security\Core\Tests\Authorization;
+
+use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
+use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
+use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
+use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
+use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
+use Symfony\Component\Security\Core\User\User;
+
+class ExpressionLanguageTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider provider
+ */
+ public function testIsAuthenticated($token, $expression, $result, array $roles = array())
+ {
+ $anonymousTokenClass = 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\AnonymousToken';
+ $rememberMeTokenClass = 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken';
+ $expressionLanguage = new ExpressionLanguage();
+ $trustResolver = new AuthenticationTrustResolver($anonymousTokenClass, $rememberMeTokenClass);
+
+ $context = array();
+ $context['trust_resolver'] = $trustResolver;
+ $context['token'] = $token;
+ $context['roles'] = $roles;
+
+ $this->assertEquals($result, $expressionLanguage->evaluate($expression, $context));
+ }
+
+ public function provider()
+ {
+ $roles = array('ROLE_USER', 'ROLE_ADMIN');
+ $user = new User('username', 'password', $roles);
+
+ $noToken = null;
+ $anonymousToken = new AnonymousToken('firewall', 'anon.');
+ $rememberMeToken = new RememberMeToken($user, 'providerkey', 'firewall');
+ $usernamePasswordToken = new UsernamePasswordToken('username', 'password', 'providerkey', $roles);
+
+ return array(
+ array($noToken, 'is_anonymous()', false),
+ array($noToken, 'is_authenticated()', false),
+ array($noToken, 'is_fully_authenticated()', false),
+ array($noToken, 'is_remember_me()', false),
+ array($noToken, "has_role('ROLE_USER')", false),
+
+ array($anonymousToken, 'is_anonymous()', true),
+ array($anonymousToken, 'is_authenticated()', false),
+ array($anonymousToken, 'is_fully_authenticated()', false),
+ array($anonymousToken, 'is_remember_me()', false),
+ array($anonymousToken, "has_role('ROLE_USER')", false),
+
+ array($rememberMeToken, 'is_anonymous()', false),
+ array($rememberMeToken, 'is_authenticated()', true),
+ array($rememberMeToken, 'is_fully_authenticated()', false),
+ array($rememberMeToken, 'is_remember_me()', true),
+ array($rememberMeToken, "has_role('ROLE_FOO')", false, $roles),
+ array($rememberMeToken, "has_role('ROLE_USER')", true, $roles),
+
+ array($usernamePasswordToken, 'is_anonymous()', false),
+ array($usernamePasswordToken, 'is_authenticated()', true),
+ array($usernamePasswordToken, 'is_fully_authenticated()', true),
+ array($usernamePasswordToken, 'is_remember_me()', false),
+ array($usernamePasswordToken, "has_role('ROLE_FOO')", false, $roles),
+ array($usernamePasswordToken, "has_role('ROLE_USER')", true, $roles),
+ );
+ }
+}
diff --git a/Core/Tests/Authorization/Voter/AbstractVoterTest.php b/Core/Tests/Authorization/Voter/AbstractVoterTest.php
new file mode 100644
index 0000000..2ab943b
--- /dev/null
+++ b/Core/Tests/Authorization/Voter/AbstractVoterTest.php
@@ -0,0 +1,74 @@
+<?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\Component\Security\Core\Tests\Authorization\Voter;
+
+use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter;
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+
+class AbstractVoterTest extends \PHPUnit_Framework_TestCase
+{
+ protected $token;
+
+ protected function setUp()
+ {
+ $this->token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ }
+
+ public function getTests()
+ {
+ return array(
+ array(array('EDIT'), VoterInterface::ACCESS_GRANTED, new \stdClass(), 'ACCESS_GRANTED if attribute and class are supported and attribute grants access'),
+ array(array('CREATE'), VoterInterface::ACCESS_DENIED, new \stdClass(), 'ACCESS_DENIED if attribute and class are supported and attribute does not grant access'),
+
+ array(array('DELETE', 'EDIT'), VoterInterface::ACCESS_GRANTED, new \stdClass(), 'ACCESS_GRANTED if one attribute is supported and grants access'),
+ array(array('DELETE', 'CREATE'), VoterInterface::ACCESS_DENIED, new \stdClass(), 'ACCESS_DENIED if one attribute is supported and denies access'),
+
+ array(array('CREATE', 'EDIT'), VoterInterface::ACCESS_GRANTED, new \stdClass(), 'ACCESS_GRANTED if one attribute grants access'),
+
+ array(array('DELETE'), VoterInterface::ACCESS_ABSTAIN, new \stdClass(), 'ACCESS_ABSTAIN if no attribute is supported'),
+
+ array(array('EDIT'), VoterInterface::ACCESS_ABSTAIN, $this, 'ACCESS_ABSTAIN if class is not supported'),
+
+ array(array('EDIT'), VoterInterface::ACCESS_ABSTAIN, null, 'ACCESS_ABSTAIN if object is null'),
+
+ array(array(), VoterInterface::ACCESS_ABSTAIN, new \stdClass(), 'ACCESS_ABSTAIN if no attributes were provided'),
+ );
+ }
+
+ /**
+ * @dataProvider getTests
+ */
+ public function testVote(array $attributes, $expectedVote, $object, $message)
+ {
+ $voter = new AbstractVoterTest_Voter();
+
+ $this->assertEquals($expectedVote, $voter->vote($this->token, $object, $attributes), $message);
+ }
+}
+
+class AbstractVoterTest_Voter extends AbstractVoter
+{
+ protected function getSupportedClasses()
+ {
+ return array('stdClass');
+ }
+
+ protected function getSupportedAttributes()
+ {
+ return array('EDIT', 'CREATE');
+ }
+
+ protected function isGranted($attribute, $object, $user = null)
+ {
+ return 'EDIT' === $attribute;
+ }
+}
diff --git a/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.php b/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.php
new file mode 100644
index 0000000..4679c0f
--- /dev/null
+++ b/Core/Tests/Authorization/Voter/AuthenticatedVoterTest.php
@@ -0,0 +1,78 @@
+<?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\Component\Security\Core\Tests\Authorization\Voter;
+
+use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
+use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+
+class AuthenticatedVoterTest extends \PHPUnit_Framework_TestCase
+{
+ public function testSupportsClass()
+ {
+ $voter = new AuthenticatedVoter($this->getResolver());
+ $this->assertTrue($voter->supportsClass('stdClass'));
+ }
+
+ /**
+ * @dataProvider getVoteTests
+ */
+ public function testVote($authenticated, $attributes, $expected)
+ {
+ $voter = new AuthenticatedVoter($this->getResolver());
+
+ $this->assertSame($expected, $voter->vote($this->getToken($authenticated), null, $attributes));
+ }
+
+ public function getVoteTests()
+ {
+ return array(
+ array('fully', array(), VoterInterface::ACCESS_ABSTAIN),
+ array('fully', array('FOO'), VoterInterface::ACCESS_ABSTAIN),
+ array('remembered', array(), VoterInterface::ACCESS_ABSTAIN),
+ array('remembered', array('FOO'), VoterInterface::ACCESS_ABSTAIN),
+ array('anonymously', array(), VoterInterface::ACCESS_ABSTAIN),
+ array('anonymously', array('FOO'), VoterInterface::ACCESS_ABSTAIN),
+
+ array('fully', array('IS_AUTHENTICATED_ANONYMOUSLY'), VoterInterface::ACCESS_GRANTED),
+ array('remembered', array('IS_AUTHENTICATED_ANONYMOUSLY'), VoterInterface::ACCESS_GRANTED),
+ array('anonymously', array('IS_AUTHENTICATED_ANONYMOUSLY'), VoterInterface::ACCESS_GRANTED),
+
+ array('fully', array('IS_AUTHENTICATED_REMEMBERED'), VoterInterface::ACCESS_GRANTED),
+ array('remembered', array('IS_AUTHENTICATED_REMEMBERED'), VoterInterface::ACCESS_GRANTED),
+ array('anonymously', array('IS_AUTHENTICATED_REMEMBERED'), VoterInterface::ACCESS_DENIED),
+
+ array('fully', array('IS_AUTHENTICATED_FULLY'), VoterInterface::ACCESS_GRANTED),
+ array('remembered', array('IS_AUTHENTICATED_FULLY'), VoterInterface::ACCESS_DENIED),
+ array('anonymously', array('IS_AUTHENTICATED_FULLY'), VoterInterface::ACCESS_DENIED),
+ );
+ }
+
+ protected function getResolver()
+ {
+ return new AuthenticationTrustResolver(
+ 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\AnonymousToken',
+ 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken'
+ );
+ }
+
+ protected function getToken($authenticated)
+ {
+ if ('fully' === $authenticated) {
+ return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ } elseif ('remembered' === $authenticated) {
+ return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', array('setPersistent'), array(), '', false);
+ } else {
+ return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken', null, array('', ''));
+ }
+ }
+}
diff --git a/Core/Tests/Authorization/Voter/ExpressionVoterTest.php b/Core/Tests/Authorization/Voter/ExpressionVoterTest.php
new file mode 100644
index 0000000..dc8ea79
--- /dev/null
+++ b/Core/Tests/Authorization/Voter/ExpressionVoterTest.php
@@ -0,0 +1,97 @@
+<?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\Component\Security\Core\Tests\Authorization\Voter;
+
+use Symfony\Component\Security\Core\Authorization\Voter\ExpressionVoter;
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+use Symfony\Component\Security\Core\Role\Role;
+
+class ExpressionVoterTest extends \PHPUnit_Framework_TestCase
+{
+ public function testSupportsAttribute()
+ {
+ $expression = $this->createExpression();
+ $expressionLanguage = $this->getMock('Symfony\Component\Security\Core\Authorization\ExpressionLanguage');
+ $voter = new ExpressionVoter($expressionLanguage, $this->createTrustResolver(), $this->createRoleHierarchy());
+
+ $this->assertTrue($voter->supportsAttribute($expression));
+ }
+
+ /**
+ * @dataProvider getVoteTests
+ */
+ public function testVote($roles, $attributes, $expected, $tokenExpectsGetRoles = true, $expressionLanguageExpectsEvaluate = true)
+ {
+ $voter = new ExpressionVoter($this->createExpressionLanguage($expressionLanguageExpectsEvaluate), $this->createTrustResolver());
+
+ $this->assertSame($expected, $voter->vote($this->getToken($roles, $tokenExpectsGetRoles), null, $attributes));
+ }
+
+ public function getVoteTests()
+ {
+ return array(
+ array(array(), array(), VoterInterface::ACCESS_ABSTAIN, false, false),
+ array(array(), array('FOO'), VoterInterface::ACCESS_ABSTAIN, false, false),
+
+ array(array(), array($this->createExpression()), VoterInterface::ACCESS_DENIED, true, false),
+
+ array(array('ROLE_FOO'), array($this->createExpression(), $this->createExpression()), VoterInterface::ACCESS_GRANTED),
+ array(array('ROLE_BAR', 'ROLE_FOO'), array($this->createExpression()), VoterInterface::ACCESS_GRANTED),
+ );
+ }
+
+ protected function getToken(array $roles, $tokenExpectsGetRoles = true)
+ {
+ foreach ($roles as $i => $role) {
+ $roles[$i] = new Role($role);
+ }
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+
+ if ($tokenExpectsGetRoles) {
+ $token->expects($this->once())
+ ->method('getRoles')
+ ->will($this->returnValue($roles));
+ }
+
+ return $token;
+ }
+
+ protected function createExpressionLanguage($expressionLanguageExpectsEvaluate = true)
+ {
+ $mock = $this->getMock('Symfony\Component\Security\Core\Authorization\ExpressionLanguage');
+
+ if ($expressionLanguageExpectsEvaluate) {
+ $mock->expects($this->once())
+ ->method('evaluate')
+ ->will($this->returnValue(true));
+ }
+
+ return $mock;
+ }
+
+ protected function createTrustResolver()
+ {
+ return $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface');
+ }
+
+ protected function createRoleHierarchy()
+ {
+ return $this->getMock('Symfony\Component\Security\Core\Role\RoleHierarchyInterface');
+ }
+
+ protected function createExpression()
+ {
+ return $this->getMockBuilder('Symfony\Component\ExpressionLanguage\Expression')
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+}
diff --git a/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.php b/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.php
new file mode 100644
index 0000000..c50ecf3
--- /dev/null
+++ b/Core/Tests/Authorization/Voter/RoleHierarchyVoterTest.php
@@ -0,0 +1,36 @@
+<?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\Component\Security\Core\Tests\Authorization\Voter;
+
+use Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter;
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+use Symfony\Component\Security\Core\Role\RoleHierarchy;
+
+class RoleHierarchyVoterTest extends RoleVoterTest
+{
+ /**
+ * @dataProvider getVoteTests
+ */
+ public function testVote($roles, $attributes, $expected)
+ {
+ $voter = new RoleHierarchyVoter(new RoleHierarchy(array('ROLE_FOO' => array('ROLE_FOOBAR'))));
+
+ $this->assertSame($expected, $voter->vote($this->getToken($roles), null, $attributes));
+ }
+
+ public function getVoteTests()
+ {
+ return array_merge(parent::getVoteTests(), array(
+ array(array('ROLE_FOO'), array('ROLE_FOOBAR'), VoterInterface::ACCESS_GRANTED),
+ ));
+ }
+}
diff --git a/Core/Tests/Authorization/Voter/RoleVoterTest.php b/Core/Tests/Authorization/Voter/RoleVoterTest.php
new file mode 100644
index 0000000..03ab2da
--- /dev/null
+++ b/Core/Tests/Authorization/Voter/RoleVoterTest.php
@@ -0,0 +1,61 @@
+<?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\Component\Security\Core\Tests\Authorization\Voter;
+
+use Symfony\Component\Security\Core\Authorization\Voter\RoleVoter;
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+use Symfony\Component\Security\Core\Role\Role;
+
+class RoleVoterTest extends \PHPUnit_Framework_TestCase
+{
+ public function testSupportsClass()
+ {
+ $voter = new RoleVoter();
+
+ $this->assertTrue($voter->supportsClass('Foo'));
+ }
+
+ /**
+ * @dataProvider getVoteTests
+ */
+ public function testVote($roles, $attributes, $expected)
+ {
+ $voter = new RoleVoter();
+
+ $this->assertSame($expected, $voter->vote($this->getToken($roles), null, $attributes));
+ }
+
+ public function getVoteTests()
+ {
+ return array(
+ array(array(), array(), VoterInterface::ACCESS_ABSTAIN),
+ array(array(), array('FOO'), VoterInterface::ACCESS_ABSTAIN),
+ array(array(), array('ROLE_FOO'), VoterInterface::ACCESS_DENIED),
+ array(array('ROLE_FOO'), array('ROLE_FOO'), VoterInterface::ACCESS_GRANTED),
+ array(array('ROLE_FOO'), array('FOO', 'ROLE_FOO'), VoterInterface::ACCESS_GRANTED),
+ array(array('ROLE_BAR', 'ROLE_FOO'), array('ROLE_FOO'), VoterInterface::ACCESS_GRANTED),
+ );
+ }
+
+ protected function getToken(array $roles)
+ {
+ foreach ($roles as $i => $role) {
+ $roles[$i] = new Role($role);
+ }
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $token->expects($this->once())
+ ->method('getRoles')
+ ->will($this->returnValue($roles));
+
+ return $token;
+ }
+}
diff --git a/Core/Tests/Encoder/BCryptPasswordEncoderTest.php b/Core/Tests/Encoder/BCryptPasswordEncoderTest.php
new file mode 100644
index 0000000..40de8af
--- /dev/null
+++ b/Core/Tests/Encoder/BCryptPasswordEncoderTest.php
@@ -0,0 +1,81 @@
+<?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\Component\Security\Core\Tests\Encoder;
+
+use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder;
+
+/**
+ * @author Elnur Abdurrakhimov <elnur@elnur.pro>
+ */
+class BCryptPasswordEncoderTest extends \PHPUnit_Framework_TestCase
+{
+ const PASSWORD = 'password';
+ const BYTES = '0123456789abcdef';
+ const VALID_COST = '04';
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testCostBelowRange()
+ {
+ new BCryptPasswordEncoder(3);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testCostAboveRange()
+ {
+ new BCryptPasswordEncoder(32);
+ }
+
+ public function testCostInRange()
+ {
+ for ($cost = 4; $cost <= 31; ++$cost) {
+ new BCryptPasswordEncoder($cost);
+ }
+ }
+
+ public function testResultLength()
+ {
+ $encoder = new BCryptPasswordEncoder(self::VALID_COST);
+ $result = $encoder->encodePassword(self::PASSWORD, null);
+ $this->assertEquals(60, strlen($result));
+ }
+
+ public function testValidation()
+ {
+ $encoder = new BCryptPasswordEncoder(self::VALID_COST);
+ $result = $encoder->encodePassword(self::PASSWORD, null);
+ $this->assertTrue($encoder->isPasswordValid($result, self::PASSWORD, null));
+ $this->assertFalse($encoder->isPasswordValid($result, 'anotherPassword', null));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testEncodePasswordLength()
+ {
+ $encoder = new BCryptPasswordEncoder(self::VALID_COST);
+
+ $encoder->encodePassword(str_repeat('a', 73), 'salt');
+ }
+
+ public function testCheckPasswordLength()
+ {
+ $encoder = new BCryptPasswordEncoder(self::VALID_COST);
+ $result = $encoder->encodePassword(str_repeat('a', 72), null);
+
+ $this->assertFalse($encoder->isPasswordValid($result, str_repeat('a', 73), 'salt'));
+ $this->assertTrue($encoder->isPasswordValid($result, str_repeat('a', 72), 'salt'));
+ }
+}
diff --git a/Core/Tests/Encoder/BasePasswordEncoderTest.php b/Core/Tests/Encoder/BasePasswordEncoderTest.php
new file mode 100644
index 0000000..14c488b
--- /dev/null
+++ b/Core/Tests/Encoder/BasePasswordEncoderTest.php
@@ -0,0 +1,101 @@
+<?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\Component\Security\Core\Tests\Encoder;
+
+use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder;
+
+class PasswordEncoder extends BasePasswordEncoder
+{
+ public function encodePassword($raw, $salt)
+ {
+ }
+
+ public function isPasswordValid($encoded, $raw, $salt)
+ {
+ }
+}
+
+class BasePasswordEncoderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testComparePassword()
+ {
+ $this->assertTrue($this->invokeComparePasswords('password', 'password'));
+ $this->assertFalse($this->invokeComparePasswords('password', 'foo'));
+ }
+
+ public function testDemergePasswordAndSalt()
+ {
+ $this->assertEquals(array('password', 'salt'), $this->invokeDemergePasswordAndSalt('password{salt}'));
+ $this->assertEquals(array('password', ''), $this->invokeDemergePasswordAndSalt('password'));
+ $this->assertEquals(array('', ''), $this->invokeDemergePasswordAndSalt(''));
+ }
+
+ public function testMergePasswordAndSalt()
+ {
+ $this->assertEquals('password{salt}', $this->invokeMergePasswordAndSalt('password', 'salt'));
+ $this->assertEquals('password', $this->invokeMergePasswordAndSalt('password', ''));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testMergePasswordAndSaltWithException()
+ {
+ $this->invokeMergePasswordAndSalt('password', '{foo}');
+ }
+
+ public function testIsPasswordTooLong()
+ {
+ $this->assertTrue($this->invokeIsPasswordTooLong(str_repeat('a', 10000)));
+ $this->assertFalse($this->invokeIsPasswordTooLong(str_repeat('a', 10)));
+ }
+
+ protected function invokeDemergePasswordAndSalt($password)
+ {
+ $encoder = new PasswordEncoder();
+ $r = new \ReflectionObject($encoder);
+ $m = $r->getMethod('demergePasswordAndSalt');
+ $m->setAccessible(true);
+
+ return $m->invoke($encoder, $password);
+ }
+
+ protected function invokeMergePasswordAndSalt($password, $salt)
+ {
+ $encoder = new PasswordEncoder();
+ $r = new \ReflectionObject($encoder);
+ $m = $r->getMethod('mergePasswordAndSalt');
+ $m->setAccessible(true);
+
+ return $m->invoke($encoder, $password, $salt);
+ }
+
+ protected function invokeComparePasswords($p1, $p2)
+ {
+ $encoder = new PasswordEncoder();
+ $r = new \ReflectionObject($encoder);
+ $m = $r->getMethod('comparePasswords');
+ $m->setAccessible(true);
+
+ return $m->invoke($encoder, $p1, $p2);
+ }
+
+ protected function invokeIsPasswordTooLong($p)
+ {
+ $encoder = new PasswordEncoder();
+ $r = new \ReflectionObject($encoder);
+ $m = $r->getMethod('isPasswordTooLong');
+ $m->setAccessible(true);
+
+ return $m->invoke($encoder, $p);
+ }
+}
diff --git a/Core/Tests/Encoder/EncoderFactoryTest.php b/Core/Tests/Encoder/EncoderFactoryTest.php
new file mode 100644
index 0000000..21aaae4
--- /dev/null
+++ b/Core/Tests/Encoder/EncoderFactoryTest.php
@@ -0,0 +1,172 @@
+<?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\Component\Security\Core\Tests\Encoder;
+
+use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
+use Symfony\Component\Security\Core\Encoder\EncoderFactory;
+use Symfony\Component\Security\Core\Encoder\EncoderAwareInterface;
+use Symfony\Component\Security\Core\User\User;
+use Symfony\Component\Security\Core\User\UserInterface;
+
+class EncoderFactoryTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetEncoderWithMessageDigestEncoder()
+ {
+ $factory = new EncoderFactory(array('Symfony\Component\Security\Core\User\UserInterface' => array(
+ 'class' => 'Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder',
+ 'arguments' => array('sha512', true, 5),
+ )));
+
+ $encoder = $factory->getEncoder($this->getMock('Symfony\Component\Security\Core\User\UserInterface'));
+ $expectedEncoder = new MessageDigestPasswordEncoder('sha512', true, 5);
+
+ $this->assertEquals($expectedEncoder->encodePassword('foo', 'moo'), $encoder->encodePassword('foo', 'moo'));
+ }
+
+ public function testGetEncoderWithService()
+ {
+ $factory = new EncoderFactory(array(
+ 'Symfony\Component\Security\Core\User\UserInterface' => new MessageDigestPasswordEncoder('sha1'),
+ ));
+
+ $encoder = $factory->getEncoder($this->getMock('Symfony\Component\Security\Core\User\UserInterface'));
+ $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
+ $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
+
+ $encoder = $factory->getEncoder(new User('user', 'pass'));
+ $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
+ $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
+ }
+
+ public function testGetEncoderWithClassName()
+ {
+ $factory = new EncoderFactory(array(
+ 'Symfony\Component\Security\Core\User\UserInterface' => new MessageDigestPasswordEncoder('sha1'),
+ ));
+
+ $encoder = $factory->getEncoder('Symfony\Component\Security\Core\Tests\Encoder\SomeChildUser');
+ $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
+ $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
+ }
+
+ public function testGetEncoderConfiguredForConcreteClassWithService()
+ {
+ $factory = new EncoderFactory(array(
+ 'Symfony\Component\Security\Core\User\User' => new MessageDigestPasswordEncoder('sha1'),
+ ));
+
+ $encoder = $factory->getEncoder(new User('user', 'pass'));
+ $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
+ $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
+ }
+
+ public function testGetEncoderConfiguredForConcreteClassWithClassName()
+ {
+ $factory = new EncoderFactory(array(
+ 'Symfony\Component\Security\Core\Tests\Encoder\SomeUser' => new MessageDigestPasswordEncoder('sha1'),
+ ));
+
+ $encoder = $factory->getEncoder('Symfony\Component\Security\Core\Tests\Encoder\SomeChildUser');
+ $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
+ $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
+ }
+
+ public function testGetNamedEncoderForEncoderAware()
+ {
+ $factory = new EncoderFactory(array(
+ 'Symfony\Component\Security\Core\Tests\Encoder\EncAwareUser' => new MessageDigestPasswordEncoder('sha256'),
+ 'encoder_name' => new MessageDigestPasswordEncoder('sha1'),
+ ));
+
+ $encoder = $factory->getEncoder(new EncAwareUser('user', 'pass'));
+ $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
+ $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
+ }
+
+ public function testGetNullNamedEncoderForEncoderAware()
+ {
+ $factory = new EncoderFactory(array(
+ 'Symfony\Component\Security\Core\Tests\Encoder\EncAwareUser' => new MessageDigestPasswordEncoder('sha1'),
+ 'encoder_name' => new MessageDigestPasswordEncoder('sha256'),
+ ));
+
+ $user = new EncAwareUser('user', 'pass');
+ $user->encoderName = null;
+ $encoder = $factory->getEncoder($user);
+ $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
+ $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testGetInvalidNamedEncoderForEncoderAware()
+ {
+ $factory = new EncoderFactory(array(
+ 'Symfony\Component\Security\Core\Tests\Encoder\EncAwareUser' => new MessageDigestPasswordEncoder('sha1'),
+ 'encoder_name' => new MessageDigestPasswordEncoder('sha256'),
+ ));
+
+ $user = new EncAwareUser('user', 'pass');
+ $user->encoderName = 'invalid_encoder_name';
+ $encoder = $factory->getEncoder($user);
+ }
+
+ public function testGetEncoderForEncoderAwareWithClassName()
+ {
+ $factory = new EncoderFactory(array(
+ 'Symfony\Component\Security\Core\Tests\Encoder\EncAwareUser' => new MessageDigestPasswordEncoder('sha1'),
+ 'encoder_name' => new MessageDigestPasswordEncoder('sha256'),
+ ));
+
+ $encoder = $factory->getEncoder('Symfony\Component\Security\Core\Tests\Encoder\EncAwareUser');
+ $expectedEncoder = new MessageDigestPasswordEncoder('sha1');
+ $this->assertEquals($expectedEncoder->encodePassword('foo', ''), $encoder->encodePassword('foo', ''));
+ }
+}
+
+class SomeUser implements UserInterface
+{
+ public function getRoles()
+ {
+ }
+
+ public function getPassword()
+ {
+ }
+
+ public function getSalt()
+ {
+ }
+
+ public function getUsername()
+ {
+ }
+
+ public function eraseCredentials()
+ {
+ }
+}
+
+class SomeChildUser extends SomeUser
+{
+}
+
+class EncAwareUser extends SomeUser implements EncoderAwareInterface
+{
+ public $encoderName = 'encoder_name';
+
+ public function getEncoderName()
+ {
+ return $this->encoderName;
+ }
+}
diff --git a/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.php b/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.php
new file mode 100644
index 0000000..5189fff
--- /dev/null
+++ b/Core/Tests/Encoder/MessageDigestPasswordEncoderTest.php
@@ -0,0 +1,62 @@
+<?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\Component\Security\Core\Tests\Encoder;
+
+use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
+
+class MessageDigestPasswordEncoderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testIsPasswordValid()
+ {
+ $encoder = new MessageDigestPasswordEncoder('sha256', false, 1);
+
+ $this->assertTrue($encoder->isPasswordValid(hash('sha256', 'password'), 'password', ''));
+ }
+
+ public function testEncodePassword()
+ {
+ $encoder = new MessageDigestPasswordEncoder('sha256', false, 1);
+ $this->assertSame(hash('sha256', 'password'), $encoder->encodePassword('password', ''));
+
+ $encoder = new MessageDigestPasswordEncoder('sha256', true, 1);
+ $this->assertSame(base64_encode(hash('sha256', 'password', true)), $encoder->encodePassword('password', ''));
+
+ $encoder = new MessageDigestPasswordEncoder('sha256', false, 2);
+ $this->assertSame(hash('sha256', hash('sha256', 'password', true).'password'), $encoder->encodePassword('password', ''));
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testEncodePasswordAlgorithmDoesNotExist()
+ {
+ $encoder = new MessageDigestPasswordEncoder('foobar');
+ $encoder->encodePassword('password', '');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testEncodePasswordLength()
+ {
+ $encoder = new MessageDigestPasswordEncoder();
+
+ $encoder->encodePassword(str_repeat('a', 5000), 'salt');
+ }
+
+ public function testCheckPasswordLength()
+ {
+ $encoder = new MessageDigestPasswordEncoder();
+
+ $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt'));
+ }
+}
diff --git a/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.php b/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.php
new file mode 100644
index 0000000..3e9452b
--- /dev/null
+++ b/Core/Tests/Encoder/Pbkdf2PasswordEncoderTest.php
@@ -0,0 +1,62 @@
+<?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\Component\Security\Core\Tests\Encoder;
+
+use Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder;
+
+class Pbkdf2PasswordEncoderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testIsPasswordValid()
+ {
+ $encoder = new Pbkdf2PasswordEncoder('sha256', false, 1, 40);
+
+ $this->assertTrue($encoder->isPasswordValid('c1232f10f62715fda06ae7c0a2037ca19b33cf103b727ba56d870c11f290a2ab106974c75607c8a3', 'password', ''));
+ }
+
+ public function testEncodePassword()
+ {
+ $encoder = new Pbkdf2PasswordEncoder('sha256', false, 1, 40);
+ $this->assertSame('c1232f10f62715fda06ae7c0a2037ca19b33cf103b727ba56d870c11f290a2ab106974c75607c8a3', $encoder->encodePassword('password', ''));
+
+ $encoder = new Pbkdf2PasswordEncoder('sha256', true, 1, 40);
+ $this->assertSame('wSMvEPYnFf2gaufAogN8oZszzxA7cnulbYcMEfKQoqsQaXTHVgfIow==', $encoder->encodePassword('password', ''));
+
+ $encoder = new Pbkdf2PasswordEncoder('sha256', false, 2, 40);
+ $this->assertSame('8bc2f9167a81cdcfad1235cd9047f1136271c1f978fcfcb35e22dbeafa4634f6fd2214218ed63ebb', $encoder->encodePassword('password', ''));
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testEncodePasswordAlgorithmDoesNotExist()
+ {
+ $encoder = new Pbkdf2PasswordEncoder('foobar');
+ $encoder->encodePassword('password', '');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testEncodePasswordLength()
+ {
+ $encoder = new Pbkdf2PasswordEncoder('foobar');
+
+ $encoder->encodePassword(str_repeat('a', 5000), 'salt');
+ }
+
+ public function testCheckPasswordLength()
+ {
+ $encoder = new Pbkdf2PasswordEncoder('foobar');
+
+ $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt'));
+ }
+}
diff --git a/Core/Tests/Encoder/PlaintextPasswordEncoderTest.php b/Core/Tests/Encoder/PlaintextPasswordEncoderTest.php
new file mode 100644
index 0000000..c7e0d2a
--- /dev/null
+++ b/Core/Tests/Encoder/PlaintextPasswordEncoderTest.php
@@ -0,0 +1,56 @@
+<?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\Component\Security\Core\Tests\Encoder;
+
+use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;
+
+class PlaintextPasswordEncoderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testIsPasswordValid()
+ {
+ $encoder = new PlaintextPasswordEncoder();
+
+ $this->assertTrue($encoder->isPasswordValid('foo', 'foo', ''));
+ $this->assertFalse($encoder->isPasswordValid('bar', 'foo', ''));
+ $this->assertFalse($encoder->isPasswordValid('FOO', 'foo', ''));
+
+ $encoder = new PlaintextPasswordEncoder(true);
+
+ $this->assertTrue($encoder->isPasswordValid('foo', 'foo', ''));
+ $this->assertFalse($encoder->isPasswordValid('bar', 'foo', ''));
+ $this->assertTrue($encoder->isPasswordValid('FOO', 'foo', ''));
+ }
+
+ public function testEncodePassword()
+ {
+ $encoder = new PlaintextPasswordEncoder();
+
+ $this->assertSame('foo', $encoder->encodePassword('foo', ''));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testEncodePasswordLength()
+ {
+ $encoder = new PlaintextPasswordEncoder();
+
+ $encoder->encodePassword(str_repeat('a', 5000), 'salt');
+ }
+
+ public function testCheckPasswordLength()
+ {
+ $encoder = new PlaintextPasswordEncoder();
+
+ $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt'));
+ }
+}
diff --git a/Core/Tests/Encoder/UserPasswordEncoderTest.php b/Core/Tests/Encoder/UserPasswordEncoderTest.php
new file mode 100644
index 0000000..590652d
--- /dev/null
+++ b/Core/Tests/Encoder/UserPasswordEncoderTest.php
@@ -0,0 +1,70 @@
+<?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\Component\Security\Core\Tests\Encoder;
+
+use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder;
+
+class UserPasswordEncoderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testEncodePassword()
+ {
+ $userMock = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $userMock->expects($this->any())
+ ->method('getSalt')
+ ->will($this->returnValue('userSalt'));
+
+ $mockEncoder = $this->getMock('Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface');
+ $mockEncoder->expects($this->any())
+ ->method('encodePassword')
+ ->with($this->equalTo('plainPassword'), $this->equalTo('userSalt'))
+ ->will($this->returnValue('encodedPassword'));
+
+ $mockEncoderFactory = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface');
+ $mockEncoderFactory->expects($this->any())
+ ->method('getEncoder')
+ ->with($this->equalTo($userMock))
+ ->will($this->returnValue($mockEncoder));
+
+ $passwordEncoder = new UserPasswordEncoder($mockEncoderFactory);
+
+ $encoded = $passwordEncoder->encodePassword($userMock, 'plainPassword');
+ $this->assertEquals('encodedPassword', $encoded);
+ }
+
+ public function testIsPasswordValid()
+ {
+ $userMock = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ $userMock->expects($this->any())
+ ->method('getSalt')
+ ->will($this->returnValue('userSalt'));
+ $userMock->expects($this->any())
+ ->method('getPassword')
+ ->will($this->returnValue('encodedPassword'));
+
+ $mockEncoder = $this->getMock('Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface');
+ $mockEncoder->expects($this->any())
+ ->method('isPasswordValid')
+ ->with($this->equalTo('encodedPassword'), $this->equalTo('plainPassword'), $this->equalTo('userSalt'))
+ ->will($this->returnValue(true));
+
+ $mockEncoderFactory = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface');
+ $mockEncoderFactory->expects($this->any())
+ ->method('getEncoder')
+ ->with($this->equalTo($userMock))
+ ->will($this->returnValue($mockEncoder));
+
+ $passwordEncoder = new UserPasswordEncoder($mockEncoderFactory);
+
+ $isValid = $passwordEncoder->isPasswordValid($userMock, 'plainPassword');
+ $this->assertTrue($isValid);
+ }
+}
diff --git a/Core/Tests/Exception/UsernameNotFoundExceptionTest.php b/Core/Tests/Exception/UsernameNotFoundExceptionTest.php
new file mode 100644
index 0000000..98ea374
--- /dev/null
+++ b/Core/Tests/Exception/UsernameNotFoundExceptionTest.php
@@ -0,0 +1,25 @@
+<?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\Component\Security\Core\Tests\Exception;
+
+use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
+
+class UsernameNotFoundExceptionTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetMessageData()
+ {
+ $exception = new UsernameNotFoundException('Username could not be found.');
+ $this->assertEquals(array('{{ username }}' => null), $exception->getMessageData());
+ $exception->setUsername('username');
+ $this->assertEquals(array('{{ username }}' => 'username'), $exception->getMessageData());
+ }
+}
diff --git a/Core/Tests/LegacySecurityContextInterfaceTest.php b/Core/Tests/LegacySecurityContextInterfaceTest.php
new file mode 100644
index 0000000..a45ecf9
--- /dev/null
+++ b/Core/Tests/LegacySecurityContextInterfaceTest.php
@@ -0,0 +1,31 @@
+<?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\Component\Security\Core\Tests;
+
+use Symfony\Component\Security\Core\SecurityContextInterface;
+use Symfony\Component\Security\Core\Security;
+
+/**
+ * @group legacy
+ */
+class LegacySecurityContextInterfaceTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * Test if the BC Layer is working as intended.
+ */
+ public function testConstantSync()
+ {
+ $this->assertSame(Security::ACCESS_DENIED_ERROR, SecurityContextInterface::ACCESS_DENIED_ERROR);
+ $this->assertSame(Security::AUTHENTICATION_ERROR, SecurityContextInterface::AUTHENTICATION_ERROR);
+ $this->assertSame(Security::LAST_USERNAME, SecurityContextInterface::LAST_USERNAME);
+ }
+}
diff --git a/Core/Tests/LegacySecurityContextTest.php b/Core/Tests/LegacySecurityContextTest.php
new file mode 100644
index 0000000..92d7c16
--- /dev/null
+++ b/Core/Tests/LegacySecurityContextTest.php
@@ -0,0 +1,122 @@
+<?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\Component\Security\Core\Tests;
+
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
+use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
+use Symfony\Component\Security\Core\SecurityContext;
+
+/**
+ * @group legacy
+ */
+class LegacySecurityContextTest extends \PHPUnit_Framework_TestCase
+{
+ private $tokenStorage;
+ private $authorizationChecker;
+ private $securityContext;
+
+ protected function setUp()
+ {
+ $this->tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
+ $this->authorizationChecker = $this->getMock('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface');
+ $this->securityContext = new SecurityContext($this->tokenStorage, $this->authorizationChecker);
+ }
+
+ public function testGetTokenDelegation()
+ {
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+
+ $this->tokenStorage
+ ->expects($this->once())
+ ->method('getToken')
+ ->will($this->returnValue($token));
+
+ $this->assertTrue($token === $this->securityContext->getToken());
+ }
+
+ public function testSetTokenDelegation()
+ {
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+
+ $this->tokenStorage
+ ->expects($this->once())
+ ->method('setToken')
+ ->with($token);
+
+ $this->securityContext->setToken($token);
+ }
+
+ /**
+ * @dataProvider isGrantedDelegationProvider
+ */
+ public function testIsGrantedDelegation($attributes, $object, $return)
+ {
+ $this->authorizationChecker
+ ->expects($this->once())
+ ->method('isGranted')
+ ->with($attributes, $object)
+ ->will($this->returnValue($return));
+
+ $this->assertEquals($return, $this->securityContext->isGranted($attributes, $object));
+ }
+
+ public function isGrantedDelegationProvider()
+ {
+ return array(
+ array(array(), new \stdClass(), true),
+ array(array('henk'), new \stdClass(), false),
+ array(null, new \stdClass(), false),
+ array('henk', null, true),
+ array(array(1), 'henk', true),
+ );
+ }
+
+ /**
+ * Test dedicated to check if the backwards compatibility is still working.
+ */
+ public function testOldConstructorSignature()
+ {
+ $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
+ $accessDecisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface');
+ new SecurityContext($authenticationManager, $accessDecisionManager);
+ }
+
+ /**
+ * @dataProvider oldConstructorSignatureFailuresProvider
+ * @expectedException \BadMethodCallException
+ */
+ public function testOldConstructorSignatureFailures($first, $second)
+ {
+ new SecurityContext($first, $second);
+ }
+
+ public function oldConstructorSignatureFailuresProvider()
+ {
+ $tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
+ $authorizationChecker = $this->getMock('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface');
+ $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
+ $accessDecisionManager = $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface');
+
+ return array(
+ array(new \stdClass(), new \stdClass()),
+ array($tokenStorage, $accessDecisionManager),
+ array($accessDecisionManager, $tokenStorage),
+ array($authorizationChecker, $accessDecisionManager),
+ array($accessDecisionManager, $authorizationChecker),
+ array($tokenStorage, $accessDecisionManager),
+ array($authenticationManager, $authorizationChecker),
+ array('henk', 'hans'),
+ array(null, false),
+ array(true, null),
+ );
+ }
+}
diff --git a/Core/Tests/Role/RoleHierarchyTest.php b/Core/Tests/Role/RoleHierarchyTest.php
new file mode 100644
index 0000000..df1b6a3
--- /dev/null
+++ b/Core/Tests/Role/RoleHierarchyTest.php
@@ -0,0 +1,32 @@
+<?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\Component\Security\Core\Tests\Role;
+
+use Symfony\Component\Security\Core\Role\RoleHierarchy;
+use Symfony\Component\Security\Core\Role\Role;
+
+class RoleHierarchyTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetReachableRoles()
+ {
+ $role = new RoleHierarchy(array(
+ 'ROLE_ADMIN' => array('ROLE_USER'),
+ 'ROLE_SUPER_ADMIN' => array('ROLE_ADMIN', 'ROLE_FOO'),
+ ));
+
+ $this->assertEquals(array(new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_USER'))));
+ $this->assertEquals(array(new Role('ROLE_FOO')), $role->getReachableRoles(array(new Role('ROLE_FOO'))));
+ $this->assertEquals(array(new Role('ROLE_ADMIN'), new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_ADMIN'))));
+ $this->assertEquals(array(new Role('ROLE_FOO'), new Role('ROLE_ADMIN'), new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_FOO'), new Role('ROLE_ADMIN'))));
+ $this->assertEquals(array(new Role('ROLE_SUPER_ADMIN'), new Role('ROLE_ADMIN'), new Role('ROLE_FOO'), new Role('ROLE_USER')), $role->getReachableRoles(array(new Role('ROLE_SUPER_ADMIN'))));
+ }
+}
diff --git a/Core/Tests/Role/RoleTest.php b/Core/Tests/Role/RoleTest.php
new file mode 100644
index 0000000..02be07b
--- /dev/null
+++ b/Core/Tests/Role/RoleTest.php
@@ -0,0 +1,24 @@
+<?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\Component\Security\Core\Tests\Role;
+
+use Symfony\Component\Security\Core\Role\Role;
+
+class RoleTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetRole()
+ {
+ $role = new Role('FOO');
+
+ $this->assertEquals('FOO', $role->getRole());
+ }
+}
diff --git a/Core/Tests/Role/SwitchUserRoleTest.php b/Core/Tests/Role/SwitchUserRoleTest.php
new file mode 100644
index 0000000..f0ce468
--- /dev/null
+++ b/Core/Tests/Role/SwitchUserRoleTest.php
@@ -0,0 +1,31 @@
+<?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\Component\Security\Core\Tests\Role;
+
+use Symfony\Component\Security\Core\Role\SwitchUserRole;
+
+class SwitchUserRoleTest extends \PHPUnit_Framework_TestCase
+{
+ public function testGetSource()
+ {
+ $role = new SwitchUserRole('FOO', $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
+
+ $this->assertSame($token, $role->getSource());
+ }
+
+ public function testGetRole()
+ {
+ $role = new SwitchUserRole('FOO', $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'));
+
+ $this->assertEquals('FOO', $role->getRole());
+ }
+}
diff --git a/Core/Tests/User/ChainUserProviderTest.php b/Core/Tests/User/ChainUserProviderTest.php
new file mode 100644
index 0000000..ab01f47
--- /dev/null
+++ b/Core/Tests/User/ChainUserProviderTest.php
@@ -0,0 +1,183 @@
+<?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\Component\Security\Core\Tests\User;
+
+use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
+use Symfony\Component\Security\Core\User\ChainUserProvider;
+use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
+
+class ChainUserProviderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testLoadUserByUsername()
+ {
+ $provider1 = $this->getProvider();
+ $provider1
+ ->expects($this->once())
+ ->method('loadUserByUsername')
+ ->with($this->equalTo('foo'))
+ ->will($this->throwException(new UsernameNotFoundException('not found')))
+ ;
+
+ $provider2 = $this->getProvider();
+ $provider2
+ ->expects($this->once())
+ ->method('loadUserByUsername')
+ ->with($this->equalTo('foo'))
+ ->will($this->returnValue($account = $this->getAccount()))
+ ;
+
+ $provider = new ChainUserProvider(array($provider1, $provider2));
+ $this->assertSame($account, $provider->loadUserByUsername('foo'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
+ */
+ public function testLoadUserByUsernameThrowsUsernameNotFoundException()
+ {
+ $provider1 = $this->getProvider();
+ $provider1
+ ->expects($this->once())
+ ->method('loadUserByUsername')
+ ->with($this->equalTo('foo'))
+ ->will($this->throwException(new UsernameNotFoundException('not found')))
+ ;
+
+ $provider2 = $this->getProvider();
+ $provider2
+ ->expects($this->once())
+ ->method('loadUserByUsername')
+ ->with($this->equalTo('foo'))
+ ->will($this->throwException(new UsernameNotFoundException('not found')))
+ ;
+
+ $provider = new ChainUserProvider(array($provider1, $provider2));
+ $provider->loadUserByUsername('foo');
+ }
+
+ public function testRefreshUser()
+ {
+ $provider1 = $this->getProvider();
+ $provider1
+ ->expects($this->once())
+ ->method('refreshUser')
+ ->will($this->throwException(new UnsupportedUserException('unsupported')))
+ ;
+
+ $provider2 = $this->getProvider();
+ $provider2
+ ->expects($this->once())
+ ->method('refreshUser')
+ ->will($this->returnValue($account = $this->getAccount()))
+ ;
+
+ $provider = new ChainUserProvider(array($provider1, $provider2));
+ $this->assertSame($account, $provider->refreshUser($this->getAccount()));
+ }
+
+ public function testRefreshUserAgain()
+ {
+ $provider1 = $this->getProvider();
+ $provider1
+ ->expects($this->once())
+ ->method('refreshUser')
+ ->will($this->throwException(new UsernameNotFoundException('not found')))
+ ;
+
+ $provider2 = $this->getProvider();
+ $provider2
+ ->expects($this->once())
+ ->method('refreshUser')
+ ->will($this->returnValue($account = $this->getAccount()))
+ ;
+
+ $provider = new ChainUserProvider(array($provider1, $provider2));
+ $this->assertSame($account, $provider->refreshUser($this->getAccount()));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\UnsupportedUserException
+ */
+ public function testRefreshUserThrowsUnsupportedUserException()
+ {
+ $provider1 = $this->getProvider();
+ $provider1
+ ->expects($this->once())
+ ->method('refreshUser')
+ ->will($this->throwException(new UnsupportedUserException('unsupported')))
+ ;
+
+ $provider2 = $this->getProvider();
+ $provider2
+ ->expects($this->once())
+ ->method('refreshUser')
+ ->will($this->throwException(new UnsupportedUserException('unsupported')))
+ ;
+
+ $provider = new ChainUserProvider(array($provider1, $provider2));
+ $provider->refreshUser($this->getAccount());
+ }
+
+ public function testSupportsClass()
+ {
+ $provider1 = $this->getProvider();
+ $provider1
+ ->expects($this->once())
+ ->method('supportsClass')
+ ->with($this->equalTo('foo'))
+ ->will($this->returnValue(false))
+ ;
+
+ $provider2 = $this->getProvider();
+ $provider2
+ ->expects($this->once())
+ ->method('supportsClass')
+ ->with($this->equalTo('foo'))
+ ->will($this->returnValue(true))
+ ;
+
+ $provider = new ChainUserProvider(array($provider1, $provider2));
+ $this->assertTrue($provider->supportsClass('foo'));
+ }
+
+ public function testSupportsClassWhenNotSupported()
+ {
+ $provider1 = $this->getProvider();
+ $provider1
+ ->expects($this->once())
+ ->method('supportsClass')
+ ->with($this->equalTo('foo'))
+ ->will($this->returnValue(false))
+ ;
+
+ $provider2 = $this->getProvider();
+ $provider2
+ ->expects($this->once())
+ ->method('supportsClass')
+ ->with($this->equalTo('foo'))
+ ->will($this->returnValue(false))
+ ;
+
+ $provider = new ChainUserProvider(array($provider1, $provider2));
+ $this->assertFalse($provider->supportsClass('foo'));
+ }
+
+ protected function getAccount()
+ {
+ return $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+ }
+
+ protected function getProvider()
+ {
+ return $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface');
+ }
+}
diff --git a/Core/Tests/User/InMemoryUserProviderTest.php b/Core/Tests/User/InMemoryUserProviderTest.php
new file mode 100644
index 0000000..0a1815f
--- /dev/null
+++ b/Core/Tests/User/InMemoryUserProviderTest.php
@@ -0,0 +1,83 @@
+<?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\Component\Security\Core\Tests\User;
+
+use Symfony\Component\Security\Core\User\InMemoryUserProvider;
+use Symfony\Component\Security\Core\User\User;
+
+class InMemoryUserProviderTest extends \PHPUnit_Framework_TestCase
+{
+ public function testConstructor()
+ {
+ $provider = $this->createProvider();
+
+ $user = $provider->loadUserByUsername('fabien');
+ $this->assertEquals('foo', $user->getPassword());
+ $this->assertEquals(array('ROLE_USER'), $user->getRoles());
+ $this->assertFalse($user->isEnabled());
+ }
+
+ public function testRefresh()
+ {
+ $user = new User('fabien', 'bar');
+
+ $provider = $this->createProvider();
+
+ $refreshedUser = $provider->refreshUser($user);
+ $this->assertEquals('foo', $refreshedUser->getPassword());
+ $this->assertEquals(array('ROLE_USER'), $refreshedUser->getRoles());
+ $this->assertFalse($refreshedUser->isEnabled());
+ $this->assertFalse($refreshedUser->isCredentialsNonExpired());
+ }
+
+ /**
+ * @return InMemoryUserProvider
+ */
+ protected function createProvider()
+ {
+ return new InMemoryUserProvider(array(
+ 'fabien' => array(
+ 'password' => 'foo',
+ 'enabled' => false,
+ 'roles' => array('ROLE_USER'),
+ ),
+ ));
+ }
+
+ public function testCreateUser()
+ {
+ $provider = new InMemoryUserProvider();
+ $provider->createUser(new User('fabien', 'foo'));
+
+ $user = $provider->loadUserByUsername('fabien');
+ $this->assertEquals('foo', $user->getPassword());
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testCreateUserAlreadyExist()
+ {
+ $provider = new InMemoryUserProvider();
+ $provider->createUser(new User('fabien', 'foo'));
+ $provider->createUser(new User('fabien', 'foo'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
+ */
+ public function testLoadUserByUsernameDoesNotExist()
+ {
+ $provider = new InMemoryUserProvider();
+ $provider->loadUserByUsername('fabien');
+ }
+}
diff --git a/Core/Tests/User/UserCheckerTest.php b/Core/Tests/User/UserCheckerTest.php
new file mode 100644
index 0000000..ac21781
--- /dev/null
+++ b/Core/Tests/User/UserCheckerTest.php
@@ -0,0 +1,108 @@
+<?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\Component\Security\Core\Tests\User;
+
+use Symfony\Component\Security\Core\User\UserChecker;
+
+class UserCheckerTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCheckPostAuthNotAdvancedUserInterface()
+ {
+ $checker = new UserChecker();
+
+ $this->assertNull($checker->checkPostAuth($this->getMock('Symfony\Component\Security\Core\User\UserInterface')));
+ }
+
+ public function testCheckPostAuthPass()
+ {
+ $checker = new UserChecker();
+
+ $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
+ $account->expects($this->once())->method('isCredentialsNonExpired')->will($this->returnValue(true));
+
+ $this->assertNull($checker->checkPostAuth($account));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\CredentialsExpiredException
+ */
+ public function testCheckPostAuthCredentialsExpired()
+ {
+ $checker = new UserChecker();
+
+ $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
+ $account->expects($this->once())->method('isCredentialsNonExpired')->will($this->returnValue(false));
+
+ $checker->checkPostAuth($account);
+ }
+
+ public function testCheckPreAuthNotAdvancedUserInterface()
+ {
+ $checker = new UserChecker();
+
+ $this->assertNull($checker->checkPreAuth($this->getMock('Symfony\Component\Security\Core\User\UserInterface')));
+ }
+
+ public function testCheckPreAuthPass()
+ {
+ $checker = new UserChecker();
+
+ $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
+ $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(true));
+ $account->expects($this->once())->method('isEnabled')->will($this->returnValue(true));
+ $account->expects($this->once())->method('isAccountNonExpired')->will($this->returnValue(true));
+
+ $this->assertNull($checker->checkPreAuth($account));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\LockedException
+ */
+ public function testCheckPreAuthAccountLocked()
+ {
+ $checker = new UserChecker();
+
+ $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
+ $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(false));
+
+ $checker->checkPreAuth($account);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\DisabledException
+ */
+ public function testCheckPreAuthDisabled()
+ {
+ $checker = new UserChecker();
+
+ $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
+ $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(true));
+ $account->expects($this->once())->method('isEnabled')->will($this->returnValue(false));
+
+ $checker->checkPreAuth($account);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException
+ */
+ public function testCheckPreAuthAccountExpired()
+ {
+ $checker = new UserChecker();
+
+ $account = $this->getMock('Symfony\Component\Security\Core\User\AdvancedUserInterface');
+ $account->expects($this->once())->method('isAccountNonLocked')->will($this->returnValue(true));
+ $account->expects($this->once())->method('isEnabled')->will($this->returnValue(true));
+ $account->expects($this->once())->method('isAccountNonExpired')->will($this->returnValue(false));
+
+ $checker->checkPreAuth($account);
+ }
+}
diff --git a/Core/Tests/User/UserTest.php b/Core/Tests/User/UserTest.php
new file mode 100644
index 0000000..b589b4a
--- /dev/null
+++ b/Core/Tests/User/UserTest.php
@@ -0,0 +1,101 @@
+<?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\Component\Security\Core\Tests\User;
+
+use Symfony\Component\Security\Core\User\User;
+
+class UserTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testConstructorException()
+ {
+ new User('', 'superpass');
+ }
+
+ public function testGetRoles()
+ {
+ $user = new User('fabien', 'superpass');
+ $this->assertEquals(array(), $user->getRoles());
+
+ $user = new User('fabien', 'superpass', array('ROLE_ADMIN'));
+ $this->assertEquals(array('ROLE_ADMIN'), $user->getRoles());
+ }
+
+ public function testGetPassword()
+ {
+ $user = new User('fabien', 'superpass');
+ $this->assertEquals('superpass', $user->getPassword());
+ }
+
+ public function testGetUsername()
+ {
+ $user = new User('fabien', 'superpass');
+ $this->assertEquals('fabien', $user->getUsername());
+ }
+
+ public function testGetSalt()
+ {
+ $user = new User('fabien', 'superpass');
+ $this->assertEquals('', $user->getSalt());
+ }
+
+ public function testIsAccountNonExpired()
+ {
+ $user = new User('fabien', 'superpass');
+ $this->assertTrue($user->isAccountNonExpired());
+
+ $user = new User('fabien', 'superpass', array(), true, false);
+ $this->assertFalse($user->isAccountNonExpired());
+ }
+
+ public function testIsCredentialsNonExpired()
+ {
+ $user = new User('fabien', 'superpass');
+ $this->assertTrue($user->isCredentialsNonExpired());
+
+ $user = new User('fabien', 'superpass', array(), true, true, false);
+ $this->assertFalse($user->isCredentialsNonExpired());
+ }
+
+ public function testIsAccountNonLocked()
+ {
+ $user = new User('fabien', 'superpass');
+ $this->assertTrue($user->isAccountNonLocked());
+
+ $user = new User('fabien', 'superpass', array(), true, true, true, false);
+ $this->assertFalse($user->isAccountNonLocked());
+ }
+
+ public function testIsEnabled()
+ {
+ $user = new User('fabien', 'superpass');
+ $this->assertTrue($user->isEnabled());
+
+ $user = new User('fabien', 'superpass', array(), false);
+ $this->assertFalse($user->isEnabled());
+ }
+
+ public function testEraseCredentials()
+ {
+ $user = new User('fabien', 'superpass');
+ $user->eraseCredentials();
+ $this->assertEquals('superpass', $user->getPassword());
+ }
+
+ public function testToString()
+ {
+ $user = new User('fabien', 'superpass');
+ $this->assertEquals('fabien', (string) $user);
+ }
+}
diff --git a/Core/Tests/Util/ClassUtilsTest.php b/Core/Tests/Util/ClassUtilsTest.php
new file mode 100644
index 0000000..e8f0143
--- /dev/null
+++ b/Core/Tests/Util/ClassUtilsTest.php
@@ -0,0 +1,50 @@
+<?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\Component\Security\Core\Tests\Util
+{
+ use Symfony\Component\Security\Core\Util\ClassUtils;
+
+ class ClassUtilsTest extends \PHPUnit_Framework_TestCase
+ {
+ public static function dataGetClass()
+ {
+ return array(
+ array('stdClass', 'stdClass'),
+ array('Symfony\Component\Security\Core\Util\ClassUtils', 'Symfony\Component\Security\Core\Util\ClassUtils'),
+ array('MyProject\Proxies\__CG__\stdClass', 'stdClass'),
+ array('MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__\stdClass', 'stdClass'),
+ array('MyProject\Proxies\__CG__\Symfony\Component\Security\Core\Tests\Util\ChildObject', 'Symfony\Component\Security\Core\Tests\Util\ChildObject'),
+ array(new TestObject(), 'Symfony\Component\Security\Core\Tests\Util\TestObject'),
+ array(new \Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Core\Tests\Util\TestObject(), 'Symfony\Component\Security\Core\Tests\Util\TestObject'),
+ );
+ }
+
+ /**
+ * @dataProvider dataGetClass
+ */
+ public function testGetRealClass($object, $expectedClassName)
+ {
+ $this->assertEquals($expectedClassName, ClassUtils::getRealClass($object));
+ }
+ }
+
+ class TestObject
+ {
+ }
+}
+
+namespace Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Core\Tests\Util
+{
+ class TestObject extends \Symfony\Component\Security\Core\Tests\Util\TestObject
+ {
+ }
+}
diff --git a/Core/Tests/Util/StringUtilsTest.php b/Core/Tests/Util/StringUtilsTest.php
new file mode 100644
index 0000000..faeaf25
--- /dev/null
+++ b/Core/Tests/Util/StringUtilsTest.php
@@ -0,0 +1,61 @@
+<?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\Component\Security\Core\Tests\Util;
+
+use Symfony\Component\Security\Core\Util\StringUtils;
+
+/**
+ * Data from PHP.net's hash_equals tests.
+ */
+class StringUtilsTest extends \PHPUnit_Framework_TestCase
+{
+ public function dataProviderTrue()
+ {
+ return array(
+ array('same', 'same'),
+ array('', ''),
+ array(123, 123),
+ array(null, ''),
+ array(null, null),
+ );
+ }
+
+ public function dataProviderFalse()
+ {
+ return array(
+ array('not1same', 'not2same'),
+ array('short', 'longer'),
+ array('longer', 'short'),
+ array('', 'notempty'),
+ array('notempty', ''),
+ array(123, 'NaN'),
+ array('NaN', 123),
+ array(null, 123),
+ );
+ }
+
+ /**
+ * @dataProvider dataProviderTrue
+ */
+ public function testEqualsTrue($known, $user)
+ {
+ $this->assertTrue(StringUtils::equals($known, $user));
+ }
+
+ /**
+ * @dataProvider dataProviderFalse
+ */
+ public function testEqualsFalse($known, $user)
+ {
+ $this->assertFalse(StringUtils::equals($known, $user));
+ }
+}
diff --git a/Core/Tests/Validator/Constraints/LegacyUserPasswordValidatorTest.php b/Core/Tests/Validator/Constraints/LegacyUserPasswordValidatorTest.php
new file mode 100644
index 0000000..8053732
--- /dev/null
+++ b/Core/Tests/Validator/Constraints/LegacyUserPasswordValidatorTest.php
@@ -0,0 +1,28 @@
+<?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\Component\Security\Core\Tests\Validator\Constraints;
+
+use Symfony\Component\Validator\Validation;
+
+/**
+ * @since 2.5.4
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ * @group legacy
+ */
+class LegacyUserPasswordValidatorTest extends UserPasswordValidatorTest
+{
+ protected function getApiVersion()
+ {
+ return Validation::API_VERSION_2_5_BC;
+ }
+}
diff --git a/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php b/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php
new file mode 100644
index 0000000..047c929
--- /dev/null
+++ b/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php
@@ -0,0 +1,169 @@
+<?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\Component\Security\Core\Tests\Validator\Constraints;
+
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
+use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
+use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
+use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
+use Symfony\Component\Security\Core\Validator\Constraints\UserPasswordValidator;
+use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+abstract class UserPasswordValidatorTest extends AbstractConstraintValidatorTest
+{
+ const PASSWORD = 's3Cr3t';
+
+ const SALT = '^S4lt$';
+
+ /**
+ * @var TokenStorageInterface
+ */
+ protected $tokenStorage;
+
+ /**
+ * @var PasswordEncoderInterface
+ */
+ protected $encoder;
+
+ /**
+ * @var EncoderFactoryInterface
+ */
+ protected $encoderFactory;
+
+ protected function createValidator()
+ {
+ return new UserPasswordValidator($this->tokenStorage, $this->encoderFactory);
+ }
+
+ protected function setUp()
+ {
+ $user = $this->createUser();
+ $this->tokenStorage = $this->createTokenStorage($user);
+ $this->encoder = $this->createPasswordEncoder();
+ $this->encoderFactory = $this->createEncoderFactory($this->encoder);
+
+ parent::setUp();
+ }
+
+ public function testPasswordIsValid()
+ {
+ $constraint = new UserPassword(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->encoder->expects($this->once())
+ ->method('isPasswordValid')
+ ->with(static::PASSWORD, 'secret', static::SALT)
+ ->will($this->returnValue(true));
+
+ $this->validator->validate('secret', $constraint);
+
+ $this->assertNoViolation();
+ }
+
+ public function testPasswordIsNotValid()
+ {
+ $constraint = new UserPassword(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->encoder->expects($this->once())
+ ->method('isPasswordValid')
+ ->with(static::PASSWORD, 'secret', static::SALT)
+ ->will($this->returnValue(false));
+
+ $this->validator->validate('secret', $constraint);
+
+ $this->buildViolation('myMessage')
+ ->assertRaised();
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
+ */
+ public function testUserIsNotValid()
+ {
+ $user = $this->getMock('Foo\Bar\User');
+
+ $this->tokenStorage = $this->createTokenStorage($user);
+ $this->validator = $this->createValidator();
+ $this->validator->initialize($this->context);
+
+ $this->validator->validate('secret', new UserPassword());
+ }
+
+ protected function createUser()
+ {
+ $mock = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
+
+ $mock
+ ->expects($this->any())
+ ->method('getPassword')
+ ->will($this->returnValue(static::PASSWORD))
+ ;
+
+ $mock
+ ->expects($this->any())
+ ->method('getSalt')
+ ->will($this->returnValue(static::SALT))
+ ;
+
+ return $mock;
+ }
+
+ protected function createPasswordEncoder($isPasswordValid = true)
+ {
+ return $this->getMock('Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface');
+ }
+
+ protected function createEncoderFactory($encoder = null)
+ {
+ $mock = $this->getMock('Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface');
+
+ $mock
+ ->expects($this->any())
+ ->method('getEncoder')
+ ->will($this->returnValue($encoder))
+ ;
+
+ return $mock;
+ }
+
+ protected function createTokenStorage($user = null)
+ {
+ $token = $this->createAuthenticationToken($user);
+
+ $mock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
+ $mock
+ ->expects($this->any())
+ ->method('getToken')
+ ->will($this->returnValue($token))
+ ;
+
+ return $mock;
+ }
+
+ protected function createAuthenticationToken($user = null)
+ {
+ $mock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $mock
+ ->expects($this->any())
+ ->method('getUser')
+ ->will($this->returnValue($user))
+ ;
+
+ return $mock;
+ }
+}
diff --git a/Core/User/User.php b/Core/User/User.php
index 86f1acd..bc81f7f 100644
--- a/Core/User/User.php
+++ b/Core/User/User.php
@@ -43,6 +43,11 @@ final class User implements AdvancedUserInterface
$this->roles = $roles;
}
+ public function __toString()
+ {
+ return $this->getUsername();
+ }
+
/**
* {@inheritdoc}
*/
diff --git a/Core/Validator/Constraints/UserPassword.php b/Core/Validator/Constraints/UserPassword.php
index aee4cda..35537b3 100644
--- a/Core/Validator/Constraints/UserPassword.php
+++ b/Core/Validator/Constraints/UserPassword.php
@@ -19,7 +19,7 @@ use Symfony\Component\Validator\Constraint;
*/
class UserPassword extends Constraint
{
- public $message = 'This value should be the user current password.';
+ public $message = 'This value should be the user\'s current password.';
public $service = 'security.validator.user_password';
/**
diff --git a/Core/Validator/Constraints/UserPasswordValidator.php b/Core/Validator/Constraints/UserPasswordValidator.php
index ab455f3..2dc7fee 100644
--- a/Core/Validator/Constraints/UserPasswordValidator.php
+++ b/Core/Validator/Constraints/UserPasswordValidator.php
@@ -12,20 +12,21 @@
namespace Symfony\Component\Security\Core\Validator\Constraints;
use Symfony\Component\Security\Core\User\UserInterface;
-use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
class UserPasswordValidator extends ConstraintValidator
{
- private $securityContext;
+ private $tokenStorage;
private $encoderFactory;
- public function __construct(SecurityContextInterface $securityContext, EncoderFactoryInterface $encoderFactory)
+ public function __construct(TokenStorageInterface $tokenStorage, EncoderFactoryInterface $encoderFactory)
{
- $this->securityContext = $securityContext;
+ $this->tokenStorage = $tokenStorage;
$this->encoderFactory = $encoderFactory;
}
@@ -34,7 +35,11 @@ class UserPasswordValidator extends ConstraintValidator
*/
public function validate($password, Constraint $constraint)
{
- $user = $this->securityContext->getToken()->getUser();
+ if (!$constraint instanceof UserPassword) {
+ throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\UserPassword');
+ }
+
+ $user = $this->tokenStorage->getToken()->getUser();
if (!$user instanceof UserInterface) {
throw new ConstraintDefinitionException('The User object must implement the UserInterface interface.');
diff --git a/Core/composer.json b/Core/composer.json
new file mode 100644
index 0000000..354c55e
--- /dev/null
+++ b/Core/composer.json
@@ -0,0 +1,49 @@
+{
+ "name": "symfony/security-core",
+ "type": "library",
+ "description": "Symfony Security Component - Core Library",
+ "keywords": [],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.9",
+ "paragonie/random_compat": "~1.0"
+ },
+ "require-dev": {
+ "symfony/event-dispatcher": "~2.1",
+ "symfony/expression-language": "~2.6",
+ "symfony/http-foundation": "~2.4",
+ "symfony/validator": "~2.5,>=2.5.9",
+ "psr/log": "~1.0",
+ "ircmaxell/password-compat": "1.0.*"
+ },
+ "suggest": {
+ "symfony/event-dispatcher": "",
+ "symfony/http-foundation": "",
+ "symfony/validator": "For using the user password constraint",
+ "symfony/expression-language": "For using the expression voter",
+ "ircmaxell/password-compat": "For using the BCrypt password encoder in PHP <5.5"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Component\\Security\\Core\\": "" },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7-dev"
+ }
+ }
+}
diff --git a/Core/phpunit.xml.dist b/Core/phpunit.xml.dist
new file mode 100644
index 0000000..2dc341a
--- /dev/null
+++ b/Core/phpunit.xml.dist
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit backupGlobals="false"
+ backupStaticAttributes="false"
+ colors="true"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ processIsolation="false"
+ stopOnFailure="false"
+ syntaxCheck="false"
+ bootstrap="vendor/autoload.php"
+>
+ <php>
+ <ini name="error_reporting" value="-1" />
+ </php>
+
+ <testsuites>
+ <testsuite name="Symfony Security Component Core Test Suite">
+ <directory>./Tests/</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./</directory>
+ <exclude>
+ <directory>./Resources</directory>
+ <directory>./Tests</directory>
+ <directory>./vendor</directory>
+ </exclude>
+ </whitelist>
+ </filter>
+</phpunit>