src/Security/AdvancedNotificationVoter.php line 21

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/AdvancedNotificationVoter.php
  4. //------------------------------------------------------------------------------
  5. namespace App\Security;
  6. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  7. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  8. use Doctrine\Persistence\ManagerRegistry;
  9. use App\Entity\Access;
  10. use App\Entity\APIRest\AccessAPI;
  11. use App\Entity\Config\Config;
  12. use App\Entity\Config\Module;
  13. use App\Entity\HR\AccessFunction;
  14. use App\Entity\Ding\AdvancedNotification;
  15. use App\Entity\Security\Acl;
  16. use App\Entity\Security\AclPermission;
  17. use App\Services\Config\ModuleTools;
  18. class AdvancedNotificationVoter extends Voter
  19. {
  20.     //--------------------------------------------------------------------------------
  21.     // is_granted constants
  22.     const IS_ACTIVE "advanced_notification_is_active";
  23.     const LISTING "list_advanced_notifications";
  24.     const LISTING_SOCIETY "list_advanced_notifications_society";
  25.     const LISTING_ANY "list_advanced_notifications_any";
  26.     const CHECK "check_advanced_notification";
  27.     const IS_GRANTED_CONSTANTS = array(
  28.         self::IS_ACTIVE,
  29.         self::LISTING,
  30.         self::LISTING_SOCIETY,
  31.         self::LISTING_ANY,
  32.         self::CHECK,
  33.     );
  34.     //--------------------------------------------------------------------------------
  35.     // acl constants
  36.     const ACL_PERM_LIST 'advanced_notification_list';
  37.     const ACL_PERM_LIST_SOCIETY 'advanced_notification_list_society';
  38.     //--------------------------------------------------------------------------------
  39.     public function __construct(ManagerRegistry $doctrineModuleTools $moduleTools)
  40.     {
  41.         $this->em $doctrine->getManager();
  42.         $this->moduleTools $moduleTools;
  43.         $this->aclRepository $this->em->getRepository(Acl::class);
  44.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  45.     }
  46.     // Plan.io Task #4453 [See AccessVoter for details]
  47.     public function supportsAttribute(string $attribute): bool
  48.     {
  49.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  50.     }
  51.     protected function supports(string $attribute$subject null): bool
  52.     {
  53.         // if the attribute isn't one we support, return false
  54.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  55.         {
  56.             return false;
  57.         }
  58.         // only vote on AdvancedNotification objects inside this voter
  59.         if ($subject !== null && !$subject instanceof AdvancedNotification)
  60.         {
  61.             return false;
  62.         }
  63.         return true;
  64.     }
  65.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  66.     {
  67.         $user $token->getUser();
  68.         // Plan.io Task #3707
  69.         if ($user instanceof AccessAPI)
  70.         {
  71.             if ($user->getAccess() === null)
  72.             {
  73.                 return false;
  74.             }
  75.             $user $user->getAccess();
  76.         }
  77.         // Plan.io Task #3707
  78.         // At this point $user is an object of Access type
  79.         // even if the $token->getUser() is AccessAPI
  80.         if (!$user instanceof Access)
  81.         {
  82.             // the user must be logged in; if not, deny access
  83.             return false;
  84.         }
  85.         // The user must have a function; if not deny access
  86.         $function $user->getFunction();
  87.         if ($function === null)        return false;
  88.         // Plan.io Task #3710 : Get current group
  89.         $currentGroup $user->getSocietyGroup();
  90.         if ($currentGroup === null)
  91.             return false;
  92.         // Module activated ?
  93.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_ADVANCED_NOTIFICATION))
  94.         {
  95.             return false;
  96.         }
  97.         // you know $subject is a AdvancedNotification object, thanks to supports
  98.         /** @var AdvancedNotification $advancedNotification */
  99.         $advancedNotification $subject;
  100.         // Check current group affectation
  101.         if ($subject !== null)
  102.         {
  103.             $subjectSociety $subject->getSociety();
  104.             if ($subjectSociety === null)
  105.                 return false;
  106.             $subjectGroup $subjectSociety->getGroup();
  107.             if ($subjectGroup === null)
  108.                 return false;
  109.             if (!$currentGroup->equals($subjectGroup))
  110.                 return false;
  111.         }
  112.         switch ($attribute)
  113.         {
  114.             // Check is done before, in the voteOnAttribute
  115.             case self::IS_ACTIVE:
  116.                 return true;
  117.             case self::LISTING:
  118.                 return $this->canList($user$function);
  119.             case self::LISTING_SOCIETY:
  120.                 return $this->canListSociety($user$function);
  121.             case self::LISTING_ANY:
  122.                 return $this->canListAny($user$function);
  123.             case self::CHECK:
  124.                 return $this->canCheck($user$function$advancedNotification);
  125.         }
  126.         throw new \LogicException('This code should not be reached!');
  127.     }
  128.     // Check if the Society of the AdvancedNotification
  129.     // belongs to the societies of the $access
  130.     private function checkSociety(AdvancedNotification $advancedNotificationAccess $access)
  131.     {
  132.         // Get all the societies of the access
  133.         $societies $access->getSocieties();
  134.         // Get the Society of the Demand
  135.         $advancedNotificationSociety $advancedNotification->getSociety();
  136.         if ($advancedNotificationSociety === null)
  137.             return false;
  138.         $found false;
  139.         foreach ($societies as $society)
  140.         {
  141.             if ($society->equals($advancedNotificationSociety))
  142.             {
  143.                 $found true;
  144.                 break;
  145.             }
  146.         }
  147.         return $found;
  148.     }
  149.     private function canList(Access $userAccessFunction $function)
  150.     {
  151.         // Get Acl_Permission
  152.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST);
  153.         if ($aclPerm === null)        return false;
  154.         // Get Acl
  155.         $acl $this->aclRepository->findOneBy(array(
  156.             'function'        =>    $function,
  157.             'permission'    =>    $aclPerm
  158.         ));
  159.         if ($acl === null)        return false;
  160.         // Since only one acl type can exist
  161.         // we can return the result of the acl_permission
  162.         return $acl->getValue();
  163.     }
  164.     private function canListSociety(Access $userAccessFunction $function)
  165.     {
  166.         // Get Acl_Permission
  167.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST_SOCIETY);
  168.         if ($aclPerm === null)        return false;
  169.         // Get Acl
  170.         $acl $this->aclRepository->findOneBy(array(
  171.             'function'        =>    $function,
  172.             'permission'    =>    $aclPerm
  173.         ));
  174.         if ($acl === null)        return false;
  175.         // Since only one acl type can exist
  176.         // we can return the result of the acl_permission
  177.         return $acl->getValue();
  178.     }
  179.     private function canListAny(Access $userAccessFunction $function)
  180.     {
  181.         // Three Acl_Permission may exist
  182.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST);
  183.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST_SOCIETY);
  184.         // If all are null, exit
  185.         if ($aclPerm === null && $aclPermSociety === null)
  186.             return false;
  187.         // Get First one
  188.         if ($aclPerm !== null)
  189.         {
  190.             $acl $this->aclRepository->findOneBy(array(
  191.                 'function'        =>    $function,
  192.                 'permission'    =>    $aclPerm
  193.             ));
  194.             if ($acl !== null)
  195.             {
  196.                 if ($acl->getValue())
  197.                 {
  198.                     // A single positive answer is enough
  199.                     return true;
  200.                 }
  201.             }
  202.         }
  203.         // If we are here it means that nothing good has been found
  204.         // Load second permission
  205.         if ($aclPermSociety !== null)
  206.         {
  207.             $acl $this->aclRepository->findOneBy(array(
  208.                 'function'        =>    $function,
  209.                 'permission'    =>    $aclPermSociety
  210.             ));
  211.             if ($acl !== null)
  212.             {
  213.                 if ($acl->getValue())
  214.                 {
  215.                     // A single positive answer is enough
  216.                     return true;
  217.                 }
  218.             }
  219.         }
  220.         // If we are here, all hope is lost
  221.         return false;
  222.     }
  223.     private function canCheck(Access $userAccessFunction $functionAdvancedNotification $advancedNotification)
  224.     {
  225.         // Get Acl_Perdemands
  226.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST);
  227.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST_SOCIETY);
  228.         // If all are null, exit
  229.         if ($aclPerm === null && $aclPermSociety === null)
  230.             return false;
  231.         // Get First one
  232.         if ($aclPerm !== null)
  233.         {
  234.             $acl $this->aclRepository->findOneBy(array(
  235.                 'function'        =>    $function,
  236.                 'permission'    =>    $aclPerm
  237.             ));
  238.             if ($acl !== null)
  239.             {
  240.                 if ($acl->getValue())
  241.                 {
  242.                     // A single positive answer is enough
  243.                     return true;
  244.                 }
  245.             }
  246.         }
  247.         // If we are here it means that nothing good has been found
  248.         // Load second permission
  249.         if ($aclPermSociety !== null)
  250.         {
  251.             $acl $this->aclRepository->findOneBy(array(
  252.                 'function'        =>    $function,
  253.                 'permission'    =>    $aclPermSociety
  254.             ));
  255.             if ($acl !== null)
  256.             {
  257.                 if ($acl->getValue())
  258.                 {
  259.                     // Check Society
  260.                     if ($this->checkSociety($advancedNotification$user))
  261.                     {
  262.                         return true;
  263.                     }
  264.                 }
  265.             }
  266.         }
  267.         // If we are here, all hope is lost
  268.         return false;
  269.     }
  270. }