src/Security/Voter/ContentCriteriaVoter.php line 9

Open in your IDE?
  1. <?php
  2. namespace App\Security\Voter;
  3. use App\Entity\User;
  4. use Psr\Log\LoggerInterface;
  5. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  6. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  7. class ContentCriteriaVoter extends Voter
  8. {
  9.     protected function supports(string $attribute$subject): bool
  10.     {
  11.         // Vérifie l'attribut et que le sujet est un objet
  12.         return $attribute === 'VIEW_CONTENT' && is_object($subject);
  13.     }
  14. private LoggerInterface $logger;
  15.     public function __construct(LoggerInterface $logger)
  16.     {
  17.         $this->logger $logger;
  18.     }
  19.     /**
  20.      * @param string $attribute
  21.      * @param mixed $subject (Content entity)
  22.      * @param TokenInterface $token
  23.      * @return bool
  24.      */
  25.    protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  26. {
  27.     $user $token->getUser();
  28.     if (!$user instanceof User) {
  29.         return false;
  30.     }
  31.     // Récupère les critères du user et du contenu
  32.     $userCriteria $this->getUserCriteria($user);
  33.     $contentCriteria $this->getContentCriteria($subject);
  34.     // Pour chaque critère, vérifie l'intersection (au moins un en commun si requis)
  35.     foreach ($contentCriteria as $key => $required) {
  36.         // Si pas de critère requis côté contenu, on ignore
  37.         if (empty($required)) {
  38.             continue;
  39.         }
  40.         $userValue $userCriteria[$key] ?? [];
  41.         if (is_iterable($required)) {
  42.             $requiredIds = [];
  43.             foreach ($required as $item) {
  44.                 if (method_exists($item'getId')) {
  45.                     $requiredIds[] = $item->getId();
  46.                 } else {
  47.                     $requiredIds[] = (string)$item;
  48.                 }
  49.             }
  50.             // Si après extraction des IDs, critère vide, on ignore
  51.             if (empty($requiredIds)) {
  52.                 continue;
  53.             }
  54.             $userIds = [];
  55.             foreach ($userValue as $item) {
  56.                 if (method_exists($item'getId')) {
  57.                     $userIds[] = $item->getId();
  58.                 } else {
  59.                     $userIds[] = (string)$item;
  60.                 }
  61.             }
  62.             if (empty(array_intersect($requiredIds$userIds))) {
  63.                 $this->logger->info("Access denied on criterion '$key'", [
  64.                     'required' => $requiredIds,
  65.                     'user' => $userIds
  66.                 ]);
  67.                 return false;
  68.             }
  69.         } else {
  70.             if ($userValue != $required) {
  71.                 $this->logger->info("Access denied on simple criterion '$key'", [
  72.                     'required' => $required,
  73.                     'user' => $userValue
  74.                 ]);
  75.                 return false;
  76.             }
  77.         }
  78.     }
  79.     return true;
  80. }
  81.     private function getUserCriteria(User $user): array
  82.     {
  83.         // Utilise uniquement les méthodes existantes sur User
  84.         return [
  85.             'instances' => method_exists($user'getInstances') ? $user->getInstances() : [],
  86.             'criteria1Items' => method_exists($user'getCriteria1Items') ? $user->getCriteria1Items() : [],
  87.             'criteria2Items' => method_exists($user'getCriteria2Items') ? $user->getCriteria2Items() : [],
  88.             'criteria3Items' => method_exists($user'getCriteria3Items') ? $user->getCriteria3Items() : [],
  89.             'criteria4Items' => method_exists($user'getCriteria4Items') ? $user->getCriteria4Items() : [],
  90.             'criteria5Items' => method_exists($user'getCriteria5Items') ? $user->getCriteria5Items() : [],
  91.         ];
  92.     }
  93.     private function getContentCriteria($content): array
  94.     {
  95.         // Utilise uniquement les méthodes existantes sur le contenu
  96.         return [
  97.             'instances' => method_exists($content'getInstances') ? $content->getInstances() : [],
  98.             'criteria1Items' => method_exists($content'getCriteria1Items') ? $content->getCriteria1Items() : [],
  99.             'criteria2Items' => method_exists($content'getCriteria2Items') ? $content->getCriteria2Items() : [],
  100.             'criteria3Items' => method_exists($content'getCriteria3Items') ? $content->getCriteria3Items() : [],
  101.             'criteria4Items' => method_exists($content'getCriteria4Items') ? $content->getCriteria4Items() : [],
  102.             'criteria5Items' => method_exists($content'getCriteria5Items') ? $content->getCriteria5Items() : [],
  103.         ];
  104.     }
  105. }