vendor/symfony/security-core/Authorization/TraceableAccessDecisionManager.php line 25

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <[email protected]>
  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\Core\Authorization;
  11. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  12. use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
  13. /**
  14.  * Decorates the original AccessDecisionManager class to log information
  15.  * about the security voters and the decisions made by them.
  16.  *
  17.  * @author Javier Eguiluz <[email protected]>
  18.  *
  19.  * @internal
  20.  */
  21. class TraceableAccessDecisionManager implements AccessDecisionManagerInterface
  22. {
  23.     private $manager;
  24.     private $strategy;
  25.     private $voters = [];
  26.     private $decisionLog = []; // All decision logs
  27.     private $currentLog = [];  // Logs being filled in
  28.     public function __construct(AccessDecisionManagerInterface $manager)
  29.     {
  30.         $this->manager $manager;
  31.         if ($this->manager instanceof AccessDecisionManager) {
  32.             // The strategy and voters are stored in a private properties of the decorated service
  33.             $reflection = new \ReflectionProperty(AccessDecisionManager::class, 'strategy');
  34.             $reflection->setAccessible(true);
  35.             $this->strategy $reflection->getValue($manager);
  36.             $reflection = new \ReflectionProperty(AccessDecisionManager::class, 'voters');
  37.             $reflection->setAccessible(true);
  38.             $this->voters $reflection->getValue($manager);
  39.         }
  40.     }
  41.     /**
  42.      * {@inheritdoc}
  43.      *
  44.      * @param bool $allowMultipleAttributes Whether to allow passing multiple values to the $attributes array
  45.      */
  46.     public function decide(TokenInterface $token, array $attributes$object null/*, bool $allowMultipleAttributes = false*/): bool
  47.     {
  48.         $currentDecisionLog = [
  49.             'attributes' => $attributes,
  50.             'object' => $object,
  51.             'voterDetails' => [],
  52.         ];
  53.         $this->currentLog[] = &$currentDecisionLog;
  54.         $result $this->manager->decide($token$attributes$object< \func_num_args() && func_get_arg(3));
  55.         $currentDecisionLog['result'] = $result;
  56.         $this->decisionLog[] = array_pop($this->currentLog); // Using a stack since decide can be called by voters
  57.         return $result;
  58.     }
  59.     /**
  60.      * Adds voter vote and class to the voter details.
  61.      *
  62.      * @param array $attributes attributes used for the vote
  63.      * @param int   $vote       vote of the voter
  64.      */
  65.     public function addVoterVote(VoterInterface $voter, array $attributesint $vote)
  66.     {
  67.         $currentLogIndex = \count($this->currentLog) - 1;
  68.         $this->currentLog[$currentLogIndex]['voterDetails'][] = [
  69.             'voter' => $voter,
  70.             'attributes' => $attributes,
  71.             'vote' => $vote,
  72.         ];
  73.     }
  74.     public function getStrategy(): string
  75.     {
  76.         // The $strategy property is misleading because it stores the name of its
  77.         // method (e.g. 'decideAffirmative') instead of the original strategy name
  78.         // (e.g. 'affirmative')
  79.         return null === $this->strategy '-' strtolower(substr($this->strategy6));
  80.     }
  81.     /**
  82.      * @return iterable|VoterInterface[]
  83.      */
  84.     public function getVoters(): iterable
  85.     {
  86.         return $this->voters;
  87.     }
  88.     public function getDecisionLog(): array
  89.     {
  90.         return $this->decisionLog;
  91.     }
  92. }
  93. if (!class_exists(DebugAccessDecisionManager::class, false)) {
  94.     class_alias(TraceableAccessDecisionManager::class, DebugAccessDecisionManager::class);
  95. }