vendor/symfony/security-acl/Voter/AclVoter.php line 54

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Security\Acl\Voter;
  11. use Psr\Log\LoggerInterface;
  12. use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
  13. use Symfony\Component\Security\Acl\Exception\NoAceFoundException;
  14. use Symfony\Component\Security\Acl\Model\AclProviderInterface;
  15. use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
  16. use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface;
  17. use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface;
  18. use Symfony\Component\Security\Acl\Permission\PermissionMapInterface;
  19. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  20. use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
  21. if (class_exists(\Symfony\Component\Security\Core\Security::class)) {
  22.     /**
  23.      * @internal
  24.      */
  25.     trait AclVoterTrait
  26.     {
  27.         public function vote(TokenInterface $token$subject, array $attributes)
  28.         {
  29.             return $this->doVote($token$subject$attributes);
  30.         }
  31.     }
  32. } else {
  33.     /**
  34.      * @internal
  35.      */
  36.     trait AclVoterTrait
  37.     {
  38.         public function vote(TokenInterface $tokenmixed $subject, array $attributes): int
  39.         {
  40.             return $this->doVote($token$subject$attributes);
  41.         }
  42.     }
  43. }
  44. /**
  45.  * This voter can be used as a base class for implementing your own permissions.
  46.  *
  47.  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  48.  */
  49. class AclVoter implements VoterInterface
  50. {
  51.     use AclVoterTrait;
  52.     private $aclProvider;
  53.     private $permissionMap;
  54.     private $objectIdentityRetrievalStrategy;
  55.     private $securityIdentityRetrievalStrategy;
  56.     private $allowIfObjectIdentityUnavailable;
  57.     private $logger;
  58.     public function __construct(AclProviderInterface $aclProviderObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategySecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategyPermissionMapInterface $permissionMapLoggerInterface $logger null$allowIfObjectIdentityUnavailable true)
  59.     {
  60.         $this->aclProvider $aclProvider;
  61.         $this->permissionMap $permissionMap;
  62.         $this->objectIdentityRetrievalStrategy $oidRetrievalStrategy;
  63.         $this->securityIdentityRetrievalStrategy $sidRetrievalStrategy;
  64.         $this->logger $logger;
  65.         $this->allowIfObjectIdentityUnavailable $allowIfObjectIdentityUnavailable;
  66.     }
  67.     public function supportsAttribute($attribute)
  68.     {
  69.         return \is_string($attribute) && $this->permissionMap->contains($attribute);
  70.     }
  71.     private function doVote(TokenInterface $token$subject, array $attributes): int
  72.     {
  73.         foreach ($attributes as $attribute) {
  74.             if (!$this->supportsAttribute($attribute)) {
  75.                 continue;
  76.             }
  77.             if (null === $masks $this->permissionMap->getMasks($attribute$subject)) {
  78.                 continue;
  79.             }
  80.             if (null === $subject) {
  81.                 if (null !== $this->logger) {
  82.                     $this->logger->debug(sprintf('Object identity unavailable. Voting to %s.'$this->allowIfObjectIdentityUnavailable 'grant access' 'abstain'));
  83.                 }
  84.                 return $this->allowIfObjectIdentityUnavailable self::ACCESS_GRANTED self::ACCESS_ABSTAIN;
  85.             } elseif ($subject instanceof FieldVote) {
  86.                 $field $subject->getField();
  87.                 $subject $subject->getDomainObject();
  88.             } else {
  89.                 $field null;
  90.             }
  91.             if ($subject instanceof ObjectIdentityInterface) {
  92.                 $oid $subject;
  93.             } elseif (null === $oid $this->objectIdentityRetrievalStrategy->getObjectIdentity($subject)) {
  94.                 if (null !== $this->logger) {
  95.                     $this->logger->debug(sprintf('Object identity unavailable. Voting to %s.'$this->allowIfObjectIdentityUnavailable 'grant access' 'abstain'));
  96.                 }
  97.                 return $this->allowIfObjectIdentityUnavailable self::ACCESS_GRANTED self::ACCESS_ABSTAIN;
  98.             }
  99.             if (!$this->supportsClass($oid->getType())) {
  100.                 return self::ACCESS_ABSTAIN;
  101.             }
  102.             $sids $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token);
  103.             try {
  104.                 $acl $this->aclProvider->findAcl($oid$sids);
  105.                 if (null === $field && $acl->isGranted($masks$sidsfalse)) {
  106.                     if (null !== $this->logger) {
  107.                         $this->logger->debug('ACL found, permission granted. Voting to grant access.');
  108.                     }
  109.                     return self::ACCESS_GRANTED;
  110.                 } elseif (null !== $field && $acl->isFieldGranted($field$masks$sidsfalse)) {
  111.                     if (null !== $this->logger) {
  112.                         $this->logger->debug('ACL found, permission granted. Voting to grant access.');
  113.                     }
  114.                     return self::ACCESS_GRANTED;
  115.                 }
  116.                 if (null !== $this->logger) {
  117.                     $this->logger->debug('ACL found, insufficient permissions. Voting to deny access.');
  118.                 }
  119.                 return self::ACCESS_DENIED;
  120.             } catch (AclNotFoundException $e) {
  121.                 if (null !== $this->logger) {
  122.                     $this->logger->debug('No ACL found for the object identity. Voting to deny access.');
  123.                 }
  124.                 return self::ACCESS_DENIED;
  125.             } catch (NoAceFoundException $e) {
  126.                 if (null !== $this->logger) {
  127.                     $this->logger->debug('ACL found, no ACE applicable. Voting to deny access.');
  128.                 }
  129.                 return self::ACCESS_DENIED;
  130.             }
  131.         }
  132.         // no attribute was supported
  133.         return self::ACCESS_ABSTAIN;
  134.     }
  135.     /**
  136.      * You can override this method when writing a voter for a specific domain
  137.      * class.
  138.      *
  139.      * @param string $class The class name
  140.      *
  141.      * @return bool
  142.      */
  143.     public function supportsClass($class)
  144.     {
  145.         return true;
  146.     }
  147. }