src/Security/ModuleAccessVoter.php line 21

Open in your IDE?
  1. <?php
  2. namespace App\Security;
  3. use App\Entity\User;
  4. use App\Service\Security\PermissionChecker;
  5. use Psr\Log\LoggerInterface;
  6. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  7. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  8. /**
  9.  * ModuleAccessVoter — @IsGranted ile route'lara deklaratif modul/section kapisi.
  10.  *
  11.  * Attribute grameri (FE getPermission / getFeatureAccess ile birebir):
  12.  *   - "MODULE:<moduleKey>:<r|c|u|d>"            ornek: MODULE:billing:u
  13.  *   - "SECTION:<moduleKey>:<sectionKey>:<r|u>"  ornek: SECTION:project:payment_report:r
  14.  *
  15.  * Report-only modu ($enforce=false): gercek karari LOGLAR ama bloklamadan gecirir.
  16.  * Boylece eksik grant / yanlis key'ler canlida kesfedilir, sonra enforce'a gecilir.
  17.  */
  18. class ModuleAccessVoter extends Voter
  19. {
  20.     private $permissionChecker;
  21.     private $logger;
  22.     private $enforce;
  23.     public function __construct(PermissionChecker $permissionCheckerLoggerInterface $loggerbool $permissionEnforce)
  24.     {
  25.         $this->permissionChecker $permissionChecker;
  26.         $this->logger $logger;
  27.         $this->enforce $permissionEnforce;
  28.     }
  29.     protected function supports($attribute$subject)
  30.     {
  31.         return is_string($attribute)
  32.             && (strpos($attribute'MODULE:') === || strpos($attribute'SECTION:') === 0);
  33.     }
  34.     protected function voteOnAttribute($attribute$subjectTokenInterface $token)
  35.     {
  36.         $user $token->getUser();
  37.         if (!$user instanceof User) {
  38.             return false// kimlik yok -> deny (auth katmani zaten kapi)
  39.         }
  40.         $allowed $this->resolve($user$attribute);
  41.         // Report-only: bloklama, sadece logla -> eksikleri kesfet.
  42.         if (!$this->enforce) {
  43.             if (!$allowed) {
  44.                 $this->logger->warning('[permission report-only] would-deny', [
  45.                     'user'      => method_exists($user'getEmail') ? $user->getEmail() : null,
  46.                     'attribute' => $attribute
  47.                 ]);
  48.             }
  49.             return true;
  50.         }
  51.         return $allowed;
  52.     }
  53.     private function resolve(User $userstring $attribute): bool
  54.     {
  55.         $parts explode(':'$attribute);
  56.         $type  $parts[0];
  57.         if ($type === 'MODULE' && count($parts) === 3) {
  58.             return $this->permissionChecker->moduleCan($user$parts[1], $parts[2]);
  59.         }
  60.         if ($type === 'SECTION' && count($parts) === 4) {
  61.             return $this->permissionChecker->sectionCan($user$parts[1], $parts[2], $parts[3]);
  62.         }
  63.         // Tanimsiz format -> guvenli taraf: enforce'ta deny.
  64.         $this->logger->error('[permission] malformed attribute', ['attribute' => $attribute]);
  65.         return false;
  66.     }
  67. }