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

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\Vote;
  21. use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
  22. if (class_exists(\Symfony\Component\Security\Core\Security::class)) {
  23.     /**
  24.      * @internal
  25.      */
  26.     trait AclVoterTrait
  27.     {
  28.         public function vote(TokenInterface $token$subject, array $attributes)
  29.         {
  30.             return $this->doVote($token$subject$attributes);
  31.         }
  32.     }
  33. } elseif (method_exists(TokenInterface::class, 'eraseCredentials')) {
  34.     /**
  35.      * @internal
  36.      */
  37.     trait AclVoterTrait
  38.     {
  39.         public function vote(TokenInterface $tokenmixed $subject, array $attributes): int
  40.         {
  41.             return $this->doVote($token$subject$attributes);
  42.         }
  43.     }
  44. } else {
  45.     /**
  46.      * @internal
  47.      */
  48.     trait AclVoterTrait
  49.     {
  50.         public function vote(TokenInterface $tokenmixed $subject, array $attributes, ?Vote $vote null): int
  51.         {
  52.             return $this->doVote($token$subject$attributes$vote);
  53.         }
  54.     }
  55. }
  56. /**
  57.  * This voter can be used as a base class for implementing your own permissions.
  58.  *
  59.  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  60.  */
  61. class AclVoter implements VoterInterface
  62. {
  63.     use AclVoterTrait;
  64.     private $aclProvider;
  65.     private $permissionMap;
  66.     private $objectIdentityRetrievalStrategy;
  67.     private $securityIdentityRetrievalStrategy;
  68.     private $allowIfObjectIdentityUnavailable;
  69.     private $logger;
  70.     public function __construct(AclProviderInterface $aclProviderObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategySecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategyPermissionMapInterface $permissionMap, ?LoggerInterface $logger null$allowIfObjectIdentityUnavailable true)
  71.     {
  72.         $this->aclProvider $aclProvider;
  73.         $this->permissionMap $permissionMap;
  74.         $this->objectIdentityRetrievalStrategy $oidRetrievalStrategy;
  75.         $this->securityIdentityRetrievalStrategy $sidRetrievalStrategy;
  76.         $this->logger $logger;
  77.         $this->allowIfObjectIdentityUnavailable $allowIfObjectIdentityUnavailable;
  78.     }
  79.     public function supportsAttribute($attribute)
  80.     {
  81.         return \is_string($attribute) && $this->permissionMap->contains($attribute);
  82.     }
  83.     private function doVote(TokenInterface $token$subject, array $attributes, ?Vote $vote null): int
  84.     {
  85.         foreach ($attributes as $attribute) {
  86.             if (!$this->supportsAttribute($attribute)) {
  87.                 continue;
  88.             }
  89.             if (null === $masks $this->permissionMap->getMasks($attribute$subject)) {
  90.                 continue;
  91.             }
  92.             if (null === $subject) {
  93.                 if (null !== $this->logger) {
  94.                     $this->logger->debug(sprintf('Object identity unavailable. Voting to %s.'$this->allowIfObjectIdentityUnavailable 'grant access' 'abstain'));
  95.                 }
  96.                 return $this->allowIfObjectIdentityUnavailable self::ACCESS_GRANTED self::ACCESS_ABSTAIN;
  97.             } elseif ($subject instanceof FieldVote) {
  98.                 $field $subject->getField();
  99.                 $subject $subject->getDomainObject();
  100.             } else {
  101.                 $field null;
  102.             }
  103.             if ($subject instanceof ObjectIdentityInterface) {
  104.                 $oid $subject;
  105.             } elseif (null === $oid $this->objectIdentityRetrievalStrategy->getObjectIdentity($subject)) {
  106.                 if (null !== $this->logger) {
  107.                     $this->logger->debug(sprintf('Object identity unavailable. Voting to %s.'$this->allowIfObjectIdentityUnavailable 'grant access' 'abstain'));
  108.                 }
  109.                 return $this->allowIfObjectIdentityUnavailable self::ACCESS_GRANTED self::ACCESS_ABSTAIN;
  110.             }
  111.             if (!$this->supportsClass($oid->getType())) {
  112.                 return self::ACCESS_ABSTAIN;
  113.             }
  114.             $sids $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token);
  115.             try {
  116.                 $acl $this->aclProvider->findAcl($oid$sids);
  117.                 if (null === $field && $acl->isGranted($masks$sidsfalse)) {
  118.                     if (null !== $this->logger) {
  119.                         $this->logger->debug('ACL found, permission granted. Voting to grant access.');
  120.                     }
  121.                     return self::ACCESS_GRANTED;
  122.                 } elseif (null !== $field && $acl->isFieldGranted($field$masks$sidsfalse)) {
  123.                     if (null !== $this->logger) {
  124.                         $this->logger->debug('ACL found, permission granted. Voting to grant access.');
  125.                     }
  126.                     return self::ACCESS_GRANTED;
  127.                 }
  128.                 if (null !== $this->logger) {
  129.                     $this->logger->debug('ACL found, insufficient permissions. Voting to deny access.');
  130.                 }
  131.                 return self::ACCESS_DENIED;
  132.             } catch (AclNotFoundException $e) {
  133.                 if (null !== $this->logger) {
  134.                     $this->logger->debug('No ACL found for the object identity. Voting to deny access.');
  135.                 }
  136.                 return self::ACCESS_DENIED;
  137.             } catch (NoAceFoundException $e) {
  138.                 if (null !== $this->logger) {
  139.                     $this->logger->debug('ACL found, no ACE applicable. Voting to deny access.');
  140.                 }
  141.                 return self::ACCESS_DENIED;
  142.             }
  143.         }
  144.         // no attribute was supported
  145.         return self::ACCESS_ABSTAIN;
  146.     }
  147.     /**
  148.      * You can override this method when writing a voter for a specific domain
  149.      * class.
  150.      *
  151.      * @param string $class The class name
  152.      *
  153.      * @return bool
  154.      */
  155.     public function supportsClass($class)
  156.     {
  157.         return true;
  158.     }
  159. }