src/Security/Voter/WriteImpliesViewVoter.php line 17

Open in your IDE?
  1. <?php
  2. namespace App\Security\Voter;
  3. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  4. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  5. use Symfony\Component\Security\Core\Security;
  6. /**
  7.  * Rola EDIT bez VIEW jest nieużywalna: okno nie pojawia się w menu, więc nie ma jak wejść w dane, które wolno edytować.
  8.  * Zamiast wypisywać tę zależność osobno dla każdego obszaru, wyliczamy ją z nazwy roli - katalog trzyma konwencję ROLE_<OBSZAR>_<CZASOWNIK>
  9.  *
  10.  * Dla roli VIEW nadanej wprost ten voter głosuje na "nie" - nie ma wtedy roli zapisu, z której
  11.  * mógłby ją wyliczyć - a przyznaje ją RoleVoter Symfony. Działa to tylko przy domyślnej
  12.  * strategii "affirmative"; przy "unanimous" role VIEW przestałyby być przyznawane.
  13.  */
  14. final class WriteImpliesViewVoter extends Voter
  15. {
  16.     private const VIEW_SUFFIX = '_VIEW';
  17.     /**
  18.      * Czasowniki, które oznaczają zmianę danych i tym samym dają podgląd tego samego obszaru.
  19.      */
  20.     private const WRITE_SUFFIXES = ['_EDIT', '_EXPORT', '_CREATOR'];
  21.     public function __construct(private readonly Security $security)
  22.     {
  23.     }
  24.     protected function supports(string $attribute, $subject): bool
  25.     {
  26.         return \str_starts_with($attribute, 'ROLE_') && \str_ends_with($attribute, self::VIEW_SUFFIX);
  27.     }
  28.     protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
  29.     {
  30.         $area = \substr($attribute, 0, -\strlen(self::VIEW_SUFFIX));
  31.         foreach (self::WRITE_SUFFIXES as $suffix) {
  32.             // isGranted(), a nie role z tokenu - dzięki temu działa też przez role_hierarchy
  33.             if ($this->security->isGranted($area . $suffix)) {
  34.                 return true;
  35.             }
  36.         }
  37.         return false;
  38.     }
  39. }