src/Security/PlanningResourceVoter.php line 64

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/PlanningResourceVoter.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\Config\Config;
  11. use App\Entity\Config\Module;
  12. use App\Entity\HR\AccessFunction;
  13. use App\Entity\Planning\PlanningResource;
  14. use App\Entity\Security\Acl;
  15. use App\Entity\Security\AclPermission;
  16. use App\Services\Config\ModuleTools;
  17. class PlanningResourceVoter extends Voter
  18. {
  19.     //--------------------------------------------------------------------------------
  20.     // is_granted constants
  21.     const ADD "add_planning_resource";
  22.     const ADD_SOCIETY "add_planning_resource_society";
  23.     const ADD_ANY "add_planning_resource_any";
  24.     const LISTING "list_planning_resources";
  25.     const LISTING_SOCIETY "list_planning_resources_society";
  26.     const LISTING_ANY "list_planning_resources_any";
  27.     const EDIT "edit_planning_resource";
  28.     // Needed for altering the order of the planning resources
  29.     const EDIT_ANY "edit_planning_resource_any";
  30.     const IS_GRANTED_CONSTANTS = array(
  31.         self::ADD,
  32.         self::ADD_SOCIETY,
  33.         self::ADD_ANY,
  34.         self::LISTING,
  35.         self::LISTING_SOCIETY,
  36.         self::LISTING_ANY,
  37.         self::EDIT,
  38.         self::EDIT_ANY,
  39.     );
  40.     //--------------------------------------------------------------------------------
  41.     // acl constants
  42.     const ACL_PERM_ADD "planning_resource_add";
  43.     const ACL_PERM_ADD_SOCIETY "planning_resource_add_society";
  44.     const ACL_PERM_LISTING "planning_resource_list";
  45.     const ACL_PERM_LISTING_SOCIETY "planning_resource_list_society";
  46.     const ACL_PERM_EDIT "planning_resource_edit";
  47.     const ACL_PERM_EDIT_SOCIETY "planning_resource_edit_society";
  48.     //--------------------------------------------------------------------------------
  49.     public function __construct(ManagerRegistry $doctrineModuleTools $moduleTools)
  50.     {
  51.         $this->em $doctrine->getManager();
  52.         $this->moduleTools $moduleTools;
  53.         $this->aclRepository $this->em->getRepository(Acl::class);
  54.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  55.     }
  56.     // Plan.io Task #4453 [See AccessVoter for details]
  57.     public function supportsAttribute(string $attribute): bool
  58.     {
  59.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  60.     }
  61.     
  62.     protected function supports(string $attribute$subject): bool
  63.     {
  64.         // if the attribute isn't one we support, return false
  65.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  66.         {
  67.             return false;
  68.         }
  69.         // only vote on PlanningResource objects inside this voter
  70.         if ($subject !== null && !$subject instanceof PlanningResource)
  71.         {
  72.             return false;
  73.         }
  74.         return true;
  75.     }
  76.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  77.     {
  78.         $user $token->getUser();
  79.         if (!$user instanceof Access)
  80.         {
  81.             // the user must be logged in; if not, deny access
  82.             return false;
  83.         }
  84.         // The user must have a function; if not deny access
  85.         $function $user->getFunction();
  86.         if ($function === null)        return false;
  87.         // Plan.io Task #3710 : Get current group
  88.         $currentGroup $user->getSocietyGroup();
  89.         if ($currentGroup === null)
  90.             return false;
  91.         // you know $subject is a PlanningResource object, thanks to supports
  92.         /** @var PlanningResource $planningResource */
  93.         $planningResource $subject;
  94.         // Check current group affectation
  95.         if ($subject !== null)
  96.         {
  97.             $subjectSociety $subject->getSociety();
  98.             if ($subjectSociety === null)
  99.                 return false;
  100.             $subjectGroup $subjectSociety->getGroup();
  101.             if ($subjectGroup === null)
  102.                 return false;
  103.             if (!$currentGroup->equals($subjectGroup))
  104.                 return false;
  105.         }
  106.         switch ($attribute)
  107.         {
  108.             case self::ADD:
  109.                 return $this->canAdd($user$function);
  110.             case self::ADD_SOCIETY:
  111.                 return $this->canAddSociety($user$function);
  112.             case self::ADD_ANY:
  113.                 return $this->canAddAny($user$function);
  114.             case self::LISTING:
  115.                 return $this->canList($user$function);
  116.             case self::LISTING_SOCIETY:
  117.                 return $this->canListSociety($user$function);
  118.             case self::LISTING_ANY:
  119.                 return $this->canListAny($user$function);
  120.             case self::EDIT:
  121.                 return $this->canEdit($planningResource$user$function);
  122.             case self::EDIT_ANY:
  123.                 return $this->canEditAny($user$function);
  124.         }
  125.         throw new \LogicException('This code should not be reached!');
  126.     }
  127.     // $access is the user trying to load the resource
  128.     // $planningResource is the resource being loaded
  129.     // Check if the Society of the resource
  130.     // belongs to the societies of the $access
  131.     private function checkSociety(PlanningResource $planningResourceAccess $access)
  132.     {
  133.         // Get all the societies of the access
  134.         $societies $access->getSocieties();
  135.         // Get the Society of the PlanningResource
  136.         $planningResourceSociety $planningResource->getSociety();
  137.         if ($planningResourceSociety === null)
  138.             return false;
  139.         $found false;
  140.         foreach ($societies as $society)
  141.         {
  142.             if ($society->getId() == $planningResourceSociety->getId())
  143.             {
  144.                 $found true;
  145.                 break;
  146.             }
  147.         }
  148.         return $found;
  149.     }
  150.     private function canAdd(Access $userAccessFunction $function)
  151.     {
  152.         // Get AclPermission
  153.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD);
  154.         if ($aclPerm === null)        return false;
  155.         // Get Acl
  156.         $acl $this->aclRepository->findOneBy(array(
  157.             'function'        =>    $function,
  158.             'permission'    =>    $aclPerm
  159.         ));
  160.         if ($acl === null)        return false;
  161.         // Since only one acl type can exist
  162.         // we can return the result of the acl_permission
  163.         return $acl->getValue();
  164.     }
  165.     private function canAddSociety(Access $userAccessFunction $function)
  166.     {
  167.         // Get AclPermission
  168.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD_SOCIETY);
  169.         if ($aclPerm === null)        return false;
  170.         // Get Acl
  171.         $acl $this->aclRepository->findOneBy(array(
  172.             'function'        =>    $function,
  173.             'permission'    =>    $aclPerm
  174.         ));
  175.         if ($acl === null)        return false;
  176.         // Since only one acl type can exist
  177.         // we can return the result of the acl_permission
  178.         // Further filtering is done in the Controller
  179.         return $acl->getValue();
  180.     }
  181.     private function canAddAny(Access $userAccessFunction $function)
  182.     {
  183.         // Two AclPermission may exist
  184.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD);
  185.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD_SOCIETY);
  186.         // If both are null, exit
  187.         if ($aclPerm === null && $aclPermSociety === null)
  188.             return false;
  189.         // Get First one
  190.         if ($aclPerm !== null)
  191.         {
  192.             $acl $this->aclRepository->findOneBy(array(
  193.                 'function'        =>    $function,
  194.                 'permission'    =>    $aclPerm
  195.             ));
  196.             if ($acl !== null)
  197.             {
  198.                 if ($acl->getValue())
  199.                 {
  200.                     // A single positive answer is enough
  201.                     return true;
  202.                 }
  203.             }
  204.         }
  205.         // If we are here it means that nothing good has been found
  206.         // Load second permission
  207.         if ($aclPermSociety !== null)
  208.         {
  209.             $acl $this->aclRepository->findOneBy(array(
  210.                 'function'        =>    $function,
  211.                 'permission'    =>    $aclPermSociety
  212.             ));
  213.             if ($acl !== null)
  214.             {
  215.                 if ($acl->getValue())
  216.                 {
  217.                     // A single positive answer is enough
  218.                     return true;
  219.                 }
  220.             }
  221.         }
  222.         // If we are here, all hope is lost
  223.         return false;
  224.     }
  225.     private function canList(Access $userAccessFunction $function)
  226.     {
  227.         // Get AclPermission
  228.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING);
  229.         if ($aclPerm === null)        return false;
  230.         // Get Acl
  231.         $acl $this->aclRepository->findOneBy(array(
  232.             'function'        =>    $function,
  233.             'permission'    =>    $aclPerm
  234.         ));
  235.         if ($acl === null)        return false;
  236.         // Since only one acl type can exist
  237.         // we can return the result of the acl_permission
  238.         return $acl->getValue();
  239.     }
  240.     private function canListSociety(Access $userAccessFunction $function)
  241.     {
  242.         // Get AclPermission
  243.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_SOCIETY);
  244.         if ($aclPerm === null)        return false;
  245.         // Get Acl
  246.         $acl $this->aclRepository->findOneBy(array(
  247.             'function'        =>    $function,
  248.             'permission'    =>    $aclPerm
  249.         ));
  250.         if ($acl === null)        return false;
  251.         // Since only one acl type can exist
  252.         // we can return the result of the acl_permission
  253.         // Further filtering is done in the Controller
  254.         return $acl->getValue();
  255.     }
  256.     private function canListAny(Access $userAccessFunction $function)
  257.     {
  258.         // Two AclPermission may exist
  259.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING);
  260.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_SOCIETY);
  261.         // If both are null, exit
  262.         if ($aclPerm === null && $aclPermSociety === null)
  263.             return false;
  264.         // Get First one
  265.         if ($aclPerm !== null)
  266.         {
  267.             $acl $this->aclRepository->findOneBy(array(
  268.                 'function'        =>    $function,
  269.                 'permission'    =>    $aclPerm
  270.             ));
  271.             if ($acl !== null)
  272.             {
  273.                 if ($acl->getValue())
  274.                 {
  275.                     // A single positive answer is enough
  276.                     return true;
  277.                 }
  278.             }
  279.         }
  280.         // If we are here it means that nothing good has been found
  281.         // Load second permission
  282.         if ($aclPermSociety !== null)
  283.         {
  284.             $acl $this->aclRepository->findOneBy(array(
  285.                 'function'        =>    $function,
  286.                 'permission'    =>    $aclPermSociety
  287.             ));
  288.             if ($acl !== null)
  289.             {
  290.                 if ($acl->getValue())
  291.                 {
  292.                     // A single positive answer is enough
  293.                     return true;
  294.                 }
  295.             }
  296.         }
  297.         // If we are here, all hope is lost
  298.         return false;
  299.     }
  300.     private function canEdit(PlanningResource $planningResource nullAccess $userAccessFunction $function)
  301.     {
  302.         // Two AclPermission may exist
  303.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  304.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SOCIETY);
  305.         // If both are null, exit
  306.         if ($aclPerm === null && $aclPermSociety === null)
  307.             return false;
  308.         // Get First one
  309.         if ($aclPerm !== null)
  310.         {
  311.             $acl $this->aclRepository->findOneBy(array(
  312.                 'function'        =>    $function,
  313.                 'permission'    =>    $aclPerm
  314.             ));
  315.             if ($acl !== null)
  316.             {
  317.                 if ($acl->getValue())
  318.                 {
  319.                     // A single positive answer is enough
  320.                     return true;
  321.                 }
  322.             }
  323.         }
  324.         // If we are here it means that nothing good has been found
  325.         // Load second permission
  326.         if ($aclPermSociety !== null)
  327.         {
  328.             $acl $this->aclRepository->findOneBy(array(
  329.                 'function'        =>    $function,
  330.                 'permission'    =>    $aclPermSociety
  331.             ));
  332.             if ($acl !== null)
  333.             {
  334.                 if ($acl->getValue())
  335.                 {
  336.                     // A single positive answer is enough
  337.                     // In this case the good answer will be provided by the checkSociety
  338.                     return $this->checkSociety($planningResource$user);
  339.                 }
  340.             }
  341.         }
  342.         // If we are here, all hope is lost
  343.         return false;
  344.     }
  345.     private function canEditAny(Access $userAccessFunction $function)
  346.     {
  347.         // Two AclPermission may exist
  348.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  349.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SOCIETY);
  350.         // If both are null, exit
  351.         if ($aclPerm === null && $aclPermSociety === null)
  352.             return false;
  353.         // Get First one
  354.         if ($aclPerm !== null)
  355.         {
  356.             $acl $this->aclRepository->findOneBy(array(
  357.                 'function'        =>    $function,
  358.                 'permission'    =>    $aclPerm
  359.             ));
  360.             if ($acl !== null)
  361.             {
  362.                 if ($acl->getValue())
  363.                 {
  364.                     // A single positive answer is enough
  365.                     return true;
  366.                 }
  367.             }
  368.         }
  369.         // If we are here it means that nothing good has been found
  370.         // Load second permission
  371.         if ($aclPermSociety !== null)
  372.         {
  373.             $acl $this->aclRepository->findOneBy(array(
  374.                 'function'        =>    $function,
  375.                 'permission'    =>    $aclPermSociety
  376.             ));
  377.             if ($acl !== null)
  378.             {
  379.                 if ($acl->getValue())
  380.                 {
  381.                     // A single positive answer is enough
  382.                     return true;
  383.                 }
  384.             }
  385.         }
  386.         // If we are here, all hope is lost
  387.         return false;
  388.     }
  389. }