src/Security/TenderVoter.php line 25

Open in your IDE?
  1. <?php
  2. /**
  3.  * This file is part of Synapse.
  4.  *
  5.  * Copyright (C) 2020-2021 Daniel Ménard
  6.  *
  7.  * For copyright and license information, please view the
  8.  * LICENSE file that was distributed with this source code.
  9.  */
  10. declare(strict_types=1);
  11. namespace App\Security;
  12. use App\Entity\Company;
  13. use App\Entity\Tender;
  14. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  15. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  16. use Symfony\Component\Security\Core\User\UserInterface;
  17. /**
  18.  * TenderVoter.
  19.  *
  20.  * @author Daniel Ménard <daniel.menard.35@gmail.com>
  21.  */
  22. final class TenderVoter extends Voter
  23. {
  24.     /**
  25.      * L'attribut à utiliser pour déterminer si l'utilisateur peut consulter un appel d'offres.
  26.      */
  27.     public const VIEW 'view';
  28.     /**
  29.      * L'attribut à utiliser pour déterminer si l'utilisateur peut modifier un appel d'offres.
  30.      */
  31.     public const EDIT 'edit';
  32.     /**
  33.      * L'attribut à utiliser pour déterminer si l'utilisateur peut voir le budget d'un appel d'offres.
  34.      */
  35.     public const VIEW_BUDGET 'view_budget';
  36.     /**
  37.      * Liste des attributs que l'on gère.
  38.      */
  39.     private const ATTRIBUTES = [
  40.         self::VIEW => 'canView',
  41.         self::EDIT => 'canEdit',
  42.         self::VIEW_BUDGET => 'canViewBudget',
  43.     ];
  44.     /**
  45.      * {@inheritdoc}
  46.      */
  47.     final protected function supports(string $attribute$subject): bool
  48.     {
  49.         // On ne s'occupe que des objets de type Tender et des attributs qu'on connaît
  50.         return ($subject instanceof Tender) && isset(self::ATTRIBUTES[$attribute]);
  51.     }
  52.     /**
  53.      * {@inheritdoc}
  54.      */
  55.     final protected function voteOnAttribute(string $attribute$tenderTokenInterface $token): bool
  56.     {
  57.         // L'utilisateur doit être connecté
  58.         $user $token->getUser();
  59.         if (!$user instanceof UserInterface) {
  60.             return false;
  61.         }
  62.         // Un administrateur a tous les droits, quelle que soit la permission demandée
  63.         if (in_array('ROLE_ADMIN', (array) $user->getRoles())) {
  64.             return true// mauvaise pratique mais isGranted ne fonctionne pas dans les tests
  65.         }
  66.         // Teste la permission demandée
  67.         $method = [$thisself::ATTRIBUTES[$attribute]];
  68.         return $method($tender$user);
  69.     }
  70.     /**
  71.      * Teste si un utilisateur peut voir un appel d'offres.
  72.      *
  73.      * Retourne true si l'une des conditions suivantes est vraie :
  74.      * - l'utilisateur est le DDO ou le GROUPE du projet
  75.      * - l'utilisateur est le projet (accès de la forme AOxxx)
  76.      */
  77.     final protected function canView(Tender $tenderUserInterface $user): bool
  78.     {
  79.         // L'utilisateur est le DDO ou le GROUPE du projet dont fait partie le lot
  80.         if ($user instanceof Company) {
  81.             return $user === $tender->getDdo() || $user->getId() === $tender->getGroupId();
  82.         }
  83.         // L'utilisateur est le projet dont fait partie le lot (accès de la forme AOxxx)
  84.         if ($user instanceof Tender) {
  85.             return $user === $tender;
  86.         }
  87.         // Type d'utilisateur inconnu
  88.         return false;
  89.     }
  90.     /**
  91.      * Teste si un utilisateur peut modifier un appel d'offres.
  92.      *
  93.      * Retourne true si l'une des conditions suivantes est vraie :
  94.      * - l'utilisateur est le DDO ou le GROUPE du projet
  95.      * - l'utilisateur est le projet (accès de la forme AOxxx)
  96.      */
  97.     final protected function canEdit(Tender $tenderUserInterface $user): bool
  98.     {
  99.         return $this->canView($tender$user);
  100.     }
  101.     /**
  102.      * Teste si un utilisateur peut voir le budget d'un appel d'offres.
  103.      *
  104.      * Retourne true si l'une des conditions suivantes est vraie :
  105.      * - l'utilisateur est le DDO ou le GROUPE du projet
  106.      * - l'utilisateur est le projet (accès de la forme AOxxx) ET la propriété budgetIsHidden
  107.      *   du projet est à false.
  108.      */
  109.     final protected function canViewBudget(Tender $tenderUserInterface $user): bool
  110.     {
  111.         if ($user instanceof Tender && $tender->getBudgetIsHidden()) {
  112.             return false;
  113.         }
  114.         return $this->canView($tender$user);
  115.     }
  116. }