summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabien Potencier <fabien.potencier@gmail.com>2011-05-30 14:28:54 +0200
committerFabien Potencier <fabien.potencier@gmail.com>2011-05-30 14:28:54 +0200
commit2798d3b4b0f385df4547aaceedf8eac93111520c (patch)
treefd0237dd131869bf5d61fe33c2a564a8c6efd081
parent127c65198b16c3f7a48fa5d19a315b3e34527178 (diff)
parent2acac06004a24699d9a5c257d143446272b88d38 (diff)
downloadsymfony-security-2798d3b4b0f385df4547aaceedf8eac93111520c.zip
symfony-security-2798d3b4b0f385df4547aaceedf8eac93111520c.tar.gz
symfony-security-2798d3b4b0f385df4547aaceedf8eac93111520c.tar.bz2
merged origin/master
-rw-r--r--Acl/Dbal/MutableAclProvider.php4
-rw-r--r--Acl/Domain/ObjectIdentity.php2
-rw-r--r--Acl/Domain/RoleSecurityIdentity.php2
-rw-r--r--Acl/Domain/UserSecurityIdentity.php4
-rw-r--r--Acl/Permission/BasicPermissionMap.php4
-rw-r--r--Acl/Permission/PermissionMapInterface.php5
-rw-r--r--Acl/Voter/AclVoter.php63
-rw-r--r--Core/Exception/SessionUnavailableException.php27
-rw-r--r--Http/Firewall/AbstractAuthenticationListener.php11
-rw-r--r--Http/Firewall/UsernamePasswordFormAuthenticationListener.php2
10 files changed, 79 insertions, 45 deletions
diff --git a/Acl/Dbal/MutableAclProvider.php b/Acl/Dbal/MutableAclProvider.php
index 62667c8..9050cf8 100644
--- a/Acl/Dbal/MutableAclProvider.php
+++ b/Acl/Dbal/MutableAclProvider.php
@@ -246,6 +246,10 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf
}
$this->regenerateAncestorRelations($acl);
+ $childAcls = $this->findAcls($this->findChildren($acl->getObjectIdentity(), false));
+ foreach ($childAcls as $childOid) {
+ $this->regenerateAncestorRelations($childAcls[$childOid]);
+ }
}
// this includes only updates of existing ACEs, but neither the creation, nor
diff --git a/Acl/Domain/ObjectIdentity.php b/Acl/Domain/ObjectIdentity.php
index f55f8a5..e691689 100644
--- a/Acl/Domain/ObjectIdentity.php
+++ b/Acl/Domain/ObjectIdentity.php
@@ -20,7 +20,7 @@ use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
-class ObjectIdentity implements ObjectIdentityInterface
+final class ObjectIdentity implements ObjectIdentityInterface
{
private $identifier;
private $type;
diff --git a/Acl/Domain/RoleSecurityIdentity.php b/Acl/Domain/RoleSecurityIdentity.php
index d3694e6..67ad59e 100644
--- a/Acl/Domain/RoleSecurityIdentity.php
+++ b/Acl/Domain/RoleSecurityIdentity.php
@@ -19,7 +19,7 @@ use Symfony\Component\Security\Core\Role\Role;
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
-class RoleSecurityIdentity implements SecurityIdentityInterface
+final class RoleSecurityIdentity implements SecurityIdentityInterface
{
private $role;
diff --git a/Acl/Domain/UserSecurityIdentity.php b/Acl/Domain/UserSecurityIdentity.php
index ac63080..d81eaaf 100644
--- a/Acl/Domain/UserSecurityIdentity.php
+++ b/Acl/Domain/UserSecurityIdentity.php
@@ -20,7 +20,7 @@ use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
-class UserSecurityIdentity implements SecurityIdentityInterface
+final class UserSecurityIdentity implements SecurityIdentityInterface
{
private $username;
private $class;
@@ -40,7 +40,7 @@ class UserSecurityIdentity implements SecurityIdentityInterface
throw new \InvalidArgumentException('$class must not be empty.');
}
- $this->username = $username;
+ $this->username = (string) $username;
$this->class = $class;
}
diff --git a/Acl/Permission/BasicPermissionMap.php b/Acl/Permission/BasicPermissionMap.php
index 18006ff..dcf49df 100644
--- a/Acl/Permission/BasicPermissionMap.php
+++ b/Acl/Permission/BasicPermissionMap.php
@@ -84,10 +84,10 @@ class BasicPermissionMap implements PermissionMapInterface
/**
* {@inheritDoc}
*/
- public function getMasks($permission)
+ public function getMasks($permission, $object)
{
if (!isset($this->map[$permission])) {
- throw new \InvalidArgumentException(sprintf('The permission "%s" is not supported by this implementation.', $permission));
+ return null;
}
return $this->map[$permission];
diff --git a/Acl/Permission/PermissionMapInterface.php b/Acl/Permission/PermissionMapInterface.php
index bc4ca08..fb41cc9 100644
--- a/Acl/Permission/PermissionMapInterface.php
+++ b/Acl/Permission/PermissionMapInterface.php
@@ -25,9 +25,10 @@ interface PermissionMapInterface
* these bitmasks.
*
* @param string $permission
- * @return array
+ * @param object $object
+ * @return array may return null if permission/object combination is not supported
*/
- function getMasks($permission);
+ function getMasks($permission, $object);
/**
* Whether this map contains the given permission
diff --git a/Acl/Voter/AclVoter.php b/Acl/Voter/AclVoter.php
index 7bd8610..0e1567d 100644
--- a/Acl/Voter/AclVoter.php
+++ b/Acl/Voter/AclVoter.php
@@ -57,58 +57,45 @@ class AclVoter implements VoterInterface
public function vote(TokenInterface $token, $object, array $attributes)
{
- $firstCall = true;
foreach ($attributes as $attribute) {
- if (!$this->supportsAttribute($attribute)) {
+ if (null === $masks = $this->permissionMap->getMasks($attribute, $object)) {
continue;
}
- if ($firstCall) {
- $firstCall = false;
-
- if (null === $object) {
- if (null !== $this->logger) {
- $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain'));
- }
-
- return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
- } else if ($object instanceof FieldVote) {
- $field = $object->getField();
- $object = $object->getDomainObject();
- } else {
- $field = null;
+ if (null === $object) {
+ if (null !== $this->logger) {
+ $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain'));
}
- if ($object instanceof ObjectIdentityInterface) {
- $oid = $object;
- } else if (null === $oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($object)) {
- if (null !== $this->logger) {
- $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain'));
- }
+ return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
+ } else if ($object instanceof FieldVote) {
+ $field = $object->getField();
+ $object = $object->getDomainObject();
+ } else {
+ $field = null;
+ }
- return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
+ if ($object instanceof ObjectIdentityInterface) {
+ $oid = $object;
+ } else if (null === $oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($object)) {
+ if (null !== $this->logger) {
+ $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain'));
}
- $sids = $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token);
- try {
- $acl = $this->aclProvider->findAcl($oid, $sids);
- } catch (AclNotFoundException $noAcl) {
- if (null !== $this->logger) {
- $this->logger->debug('No ACL found for the object identity. Voting to deny access.');
- }
-
- return self::ACCESS_DENIED;
- }
+ return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
}
+ $sids = $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token);
try {
- if (null === $field && $acl->isGranted($this->permissionMap->getMasks($attribute), $sids, false)) {
+ $acl = $this->aclProvider->findAcl($oid, $sids);
+
+ if (null === $field && $acl->isGranted($masks, $sids, false)) {
if (null !== $this->logger) {
$this->logger->debug('ACL found, permission granted. Voting to grant access');
}
return self::ACCESS_GRANTED;
- } else if (null !== $field && $acl->isFieldGranted($field, $this->permissionMap->getMasks($attribute), $sids, false)) {
+ } else if (null !== $field && $acl->isFieldGranted($field, $masks, $sids, false)) {
if (null !== $this->logger) {
$this->logger->debug('ACL found, permission granted. Voting to grant access');
}
@@ -121,6 +108,12 @@ class AclVoter implements VoterInterface
}
return self::ACCESS_DENIED;
+ } catch (AclNotFoundException $noAcl) {
+ if (null !== $this->logger) {
+ $this->logger->debug('No ACL found for the object identity. Voting to deny access.');
+ }
+
+ return self::ACCESS_DENIED;
} catch (NoAceFoundException $noAce) {
if (null !== $this->logger) {
$this->logger->debug('ACL found, no ACE applicable. Voting to deny access.');
diff --git a/Core/Exception/SessionUnavailableException.php b/Core/Exception/SessionUnavailableException.php
new file mode 100644
index 0000000..a00c897
--- /dev/null
+++ b/Core/Exception/SessionUnavailableException.php
@@ -0,0 +1,27 @@
+<?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;
+
+/**
+ * This exception is thrown when no session is available.
+ *
+ * Possible reasons for this are:
+ *
+ * a) The session timed-out because the user waited too long.
+ * b) The user has disabled cookies, and a new session is started on each
+ * request.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class SessionUnavailableException extends AuthenticationException
+{
+} \ No newline at end of file
diff --git a/Http/Firewall/AbstractAuthenticationListener.php b/Http/Firewall/AbstractAuthenticationListener.php
index e2e1ed6..f2be84e 100644
--- a/Http/Firewall/AbstractAuthenticationListener.php
+++ b/Http/Firewall/AbstractAuthenticationListener.php
@@ -18,6 +18,7 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
+use Symfony\Component\Security\Core\Exception\SessionUnavailableException;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\CoreEvents;
@@ -128,6 +129,14 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
return;
}
+ if (!$request->hasSession()) {
+ throw new \RuntimeException('This authentication method requires a session.');
+ }
+
+ if (!$request->hasPreviousSession()) {
+ throw new SessionUnavailableException('Your session has timed-out, or you have disabled cookies.');
+ }
+
if ($returnValue instanceof TokenInterface) {
$this->sessionStrategy->onAuthentication($request, $returnValue);
@@ -227,7 +236,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
if (null !== $this->successHandler) {
$response = $this->successHandler->onAuthenticationSuccess($request, $token);
} else {
- $path = $this->determineTargetUrl($request);
+ $path = strtr($this->determineTargetUrl($request), '{_locale}', $session->getLocale());
$response = new RedirectResponse(0 !== strpos($path, 'http') ? $request->getUriForPath($path) : $path, 302);
}
diff --git a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
index 51546c0..e76b1bf 100644
--- a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
+++ b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
@@ -63,7 +63,7 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
}
if (null !== $this->csrfProvider) {
- $csrfToken = $request->get($this->options['csrf_parameter']);
+ $csrfToken = $request->get($this->options['csrf_parameter'], null, true);
if (false === $this->csrfProvider->isCsrfTokenValid($this->options['intention'], $csrfToken)) {
throw new InvalidCsrfTokenException('Invalid CSRF token.');