src/Security/ProspectVoter.php line 76

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/ProspectVoter.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\Client\Client;
  13. use App\Entity\HR\AccessFunction;
  14. use App\Entity\Security\Acl;
  15. use App\Entity\Security\AclPermission;
  16. use App\Services\Config\ModuleTools;
  17. class ProspectVoter extends Voter
  18. {
  19.     //--------------------------------------------------------------------------------
  20.     // is_granted constants
  21.     const IS_ACTIVE "prospect_is_active";
  22.     const ADD "add_prospect";
  23.     const LISTING "list_prospects";
  24.     const LISTING_SOCIETY "list_prospects_society";
  25.     const LISTING_MANAGER "list_prospects_manager";
  26.     const LISTING_ANY "list_prospects_any";
  27.     const VIEW "view_prospect";
  28.     const EDIT "edit_prospect";
  29.     const CONVERT "convert_prospect";
  30.     const IS_GRANTED_CONSTANTS = array(
  31.         self::IS_ACTIVE,
  32.         self::ADD,
  33.         self::LISTING,
  34.         self::LISTING_SOCIETY,
  35.         self::LISTING_MANAGER,
  36.         self::LISTING_ANY,
  37.         self::VIEW,
  38.         self::EDIT,
  39.         self::CONVERT,
  40.     );
  41.     //--------------------------------------------------------------------------------
  42.     // acl constants
  43.     const ACL_PERM_ADD "prospect_add";
  44.     const ACL_PERM_LISTING "prospect_list";
  45.     const ACL_PERM_LISTING_SOCIETY "prospect_list_society";
  46.     const ACL_PERM_LISTING_MANAGER "prospect_list_manager";
  47.     const ACL_PERM_VIEW "prospect_view";
  48.     const ACL_PERM_VIEW_SOCIETY "prospect_view_society";
  49.     const ACL_PERM_VIEW_MANAGER "prospect_view_manager";
  50.     const ACL_PERM_EDIT "prospect_edit";
  51.     const ACL_PERM_EDIT_SOCIETY "prospect_edit_society";
  52.     const ACL_PERM_EDIT_MANAGER "prospect_edit_manager";
  53.     const ACL_PERM_CONVERT "prospect_convert";
  54.     const ACL_PERM_CONVERT_SOCIETY "prospect_convert_society";
  55.     const ACL_PERM_CONVERT_MANAGER "prospect_convert_manager";
  56.     //--------------------------------------------------------------------------------
  57.     public function __construct(ManagerRegistry $doctrineModuleTools $moduleTools)
  58.     {
  59.         $this->em $doctrine->getManager();
  60.         $this->moduleTools $moduleTools;
  61.         $this->aclRepository $this->em->getRepository(Acl::class);
  62.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  63.     }
  64.     // Plan.io Task #4453 [See AccessVoter for details]
  65.     public function supportsAttribute(string $attribute): bool
  66.     {
  67.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  68.     }
  69.     protected function supports(string $attribute$subject null): bool
  70.     {
  71.         // if the attribute isn't one we support, return false
  72.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  73.         {
  74.             return false;
  75.         }
  76.         // only vote on Client objects inside this voter
  77.         if ($subject !== null && !$subject instanceof Client)
  78.         {
  79.             return false;
  80.         }
  81.         return true;
  82.     }
  83.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  84.     {
  85.         $user $token->getUser();
  86.         if (!$user instanceof Access)
  87.         {
  88.             // the user must be logged in; if not, deny access
  89.             return false;
  90.         }
  91.         // The user must have a function; if not deny access
  92.         $function $user->getFunction();
  93.         if ($function === null)        return false;
  94.         // Plan.io Task #3710 : Get current group
  95.         $currentGroup $user->getSocietyGroup();
  96.         if ($currentGroup === null)
  97.             return false;
  98.         // Module activated ?
  99.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_PROSPECT))
  100.         {
  101.             return false;
  102.         }
  103.         // you know $subject is a Client object, thanks to supports
  104.         /** @var Client $prospect */
  105.         $prospect $subject;
  106.         // Really a prospect ?
  107.         if ($prospect !== null && ($prospect->isNotProspect() && $prospect->isNotOldProspect()))
  108.         {
  109.             return false;
  110.         }
  111.         // Check current group affectation
  112.         if ($subject !== null)
  113.         {
  114.             $subjectSociety $subject->getSociety();
  115.             if ($subjectSociety === null)
  116.                 return false;
  117.             $subjectGroup $subjectSociety->getGroup();
  118.             if ($subjectGroup === null)
  119.                 return false;
  120.             if (!$currentGroup->equals($subjectGroup))
  121.                 return false;
  122.         }
  123.         switch ($attribute)
  124.         {
  125.             case self::IS_ACTIVE:
  126.                 return true;
  127.             case self::ADD:
  128.                 return $this->canAdd($user$function);
  129.             case self::LISTING:
  130.                 return $this->canList($user$function);
  131.             case self::LISTING_SOCIETY:
  132.                 return $this->canListSociety($user$function);
  133.             case self::LISTING_MANAGER:
  134.                 return $this->canListManager($user$function);
  135.             case self::LISTING_ANY:
  136.                 return $this->canListAny($user$function);
  137.             case self::VIEW:
  138.                 return $this->canView($prospect$user$function);
  139.             case self::EDIT:
  140.                 return $this->canEdit($prospect$user$function);
  141.             case self::CONVERT:
  142.                 return $this->canConvert($prospect$user$function);
  143.         }
  144.         throw new \LogicException('This code should not be reached!');
  145.     }
  146.     // $access is the user trying to load the resource
  147.     // $prospect is the resource being loaded
  148.     // Check if the Society of the resource
  149.     // belongs to the societies of the $access
  150.     private function checkSociety(Client $prospectAccess $access)
  151.     {
  152.         // Get all the societies of the access
  153.         $societies $access->getSocieties();
  154.         // Get the Society of the Prospect
  155.         if ($prospect->getIndividual() === null)
  156.         {
  157.             return false;
  158.         }
  159.         $prospectSociety $prospect->getIndividual()->getSociety();
  160.         if ($prospectSociety === null)
  161.             return false;
  162.         $found false;
  163.         foreach ($societies as $society)
  164.         {
  165.             if ($society->getId() == $prospectSociety->getId())
  166.             {
  167.                 $found true;
  168.                 break;
  169.             }
  170.         }
  171.         return $found;
  172.     }
  173.     // Check if the $access is the manager / author of the $client
  174.     private function checkManager(Client $prospectAccess $access)
  175.     {
  176.         if ($prospect->getIndividual() === null)
  177.         {
  178.             return false;
  179.         }
  180.         $individual $prospect->getIndividual();
  181.         // Get manager and author
  182.         $manager $individual->getManager();
  183.         $author $individual->getAuthor();
  184.         if ($manager === null && $author === null)
  185.             return false;
  186.         if ($manager !== null)
  187.             if ($manager->getId() === $access->getId())
  188.                 return true;
  189.         if ($author !== null)
  190.             if ($author->getId() === $access->getId())
  191.                 return true;
  192.         return false;
  193.     }
  194.     private function canAdd(Access $userAccessFunction $function)
  195.     {
  196.         // Get AclPermission
  197.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD);
  198.         if ($aclPerm === null)        return false;
  199.         // Get Acl
  200.         $acl $this->aclRepository->findOneBy(array(
  201.             'function'        =>    $function,
  202.             'permission'    =>    $aclPerm
  203.         ));
  204.         if ($acl === null)        return false;
  205.         // Since only one acl type can exist
  206.         // we can return the result of the acl_permission
  207.         return $acl->getValue();
  208.     }
  209.     private function canList(Access $userAccessFunction $function)
  210.     {
  211.         // Get AclPermission
  212.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING);
  213.         if ($aclPerm === null)        return false;
  214.         // Get Acl
  215.         $acl $this->aclRepository->findOneBy(array(
  216.             'function'        =>    $function,
  217.             'permission'    =>    $aclPerm
  218.         ));
  219.         if ($acl === null)        return false;
  220.         // Since only one acl type can exist
  221.         // we can return the result of the acl_permission
  222.         return $acl->getValue();
  223.     }
  224.     private function canListSociety(Access $userAccessFunction $function)
  225.     {
  226.         // Get AclPermission
  227.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_SOCIETY);
  228.         if ($aclPerm === null)        return false;
  229.         // Get Acl
  230.         $acl $this->aclRepository->findOneBy(array(
  231.             'function'        =>    $function,
  232.             'permission'    =>    $aclPerm
  233.         ));
  234.         if ($acl === null)        return false;
  235.         // Since only one acl type can exist
  236.         // we can return the result of the acl_permission
  237.         // Further filtering is done in the Controller
  238.         return $acl->getValue();
  239.     }
  240.     private function canListManager(Access $userAccessFunction $function)
  241.     {
  242.         // Get AclPermission
  243.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_MANAGER);
  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.         // Several AclPermission may exist
  259.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING);
  260.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_SOCIETY);
  261.         $aclPermManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_MANAGER);
  262.         // If all are null, exit
  263.         if ($aclPerm === null && $aclPermSociety === null && $aclPermManager === null)
  264.             return false;
  265.         // Get First one
  266.         if ($aclPerm !== null)
  267.         {
  268.             $acl $this->aclRepository->findOneBy(array(
  269.                 'function'        =>    $function,
  270.                 'permission'    =>    $aclPerm
  271.             ));
  272.             if ($acl !== null)
  273.             {
  274.                 if ($acl->getValue())
  275.                 {
  276.                     // A single positive answer is enough
  277.                     return true;
  278.                 }
  279.             }
  280.         }
  281.         // If we are here it means that nothing good has been found
  282.         // Load second permission
  283.         if ($aclPermSociety !== null)
  284.         {
  285.             $acl $this->aclRepository->findOneBy(array(
  286.                 'function'        =>    $function,
  287.                 'permission'    =>    $aclPermSociety
  288.             ));
  289.             if ($acl !== null)
  290.             {
  291.                 if ($acl->getValue())
  292.                 {
  293.                     // A single positive answer is enough
  294.                     return true;
  295.                 }
  296.             }
  297.         }
  298.         // If we are here it means that nothing good has been found
  299.         // Load third permission
  300.         if ($aclPermManager !== null)
  301.         {
  302.             $acl $this->aclRepository->findOneBy(array(
  303.                 'function'        =>    $function,
  304.                 'permission'    =>    $aclPermManager
  305.             ));
  306.             if ($acl !== null)
  307.             {
  308.                 if ($acl->getValue())
  309.                 {
  310.                     // A single positive answer is enough
  311.                     return true;
  312.                 }
  313.             }
  314.         }
  315.         // If we are here, all hope is lost
  316.         return false;
  317.     }
  318.     private function canView(Client $prospectAccess $userAccessFunction $function)
  319.     {
  320.         // Several AclPermission may exist
  321.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW);
  322.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_SOCIETY);
  323.         $aclPermManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_MANAGER);
  324.         // If all are null, exit
  325.         if ($aclPerm === null && $aclPermSociety === null && $aclPermManager === null)
  326.             return false;
  327.         // Get First one
  328.         if ($aclPerm !== null)
  329.         {
  330.             $acl $this->aclRepository->findOneBy(array(
  331.                 'function'        =>    $function,
  332.                 'permission'    =>    $aclPerm
  333.             ));
  334.             if ($acl !== null)
  335.             {
  336.                 if ($acl->getValue())
  337.                 {
  338.                     // A single positive answer is enough
  339.                     return true;
  340.                 }
  341.             }
  342.         }
  343.         // If we are here it means that nothing good has been found
  344.         // Load second permission
  345.         if ($aclPermSociety !== null)
  346.         {
  347.             $acl $this->aclRepository->findOneBy(array(
  348.                 'function'        =>    $function,
  349.                 'permission'    =>    $aclPermSociety
  350.             ));
  351.             if ($acl !== null)
  352.             {
  353.                 if ($acl->getValue())
  354.                 {
  355.                     // A single positive answer is enough
  356.                     // In this case the good answer will be provided by the checkSociety
  357.                     return $this->checkSociety($prospect$user);
  358.                 }
  359.             }
  360.         }
  361.         // If we are here it means that nothing good has been found
  362.         // Load third permission
  363.         if ($aclPermManager !== null)
  364.         {
  365.             $acl $this->aclRepository->findOneBy(array(
  366.                 'function'        =>    $function,
  367.                 'permission'    =>    $aclPermManager
  368.             ));
  369.             if ($acl !== null)
  370.             {
  371.                 if ($acl->getValue())
  372.                 {
  373.                     // A single positive answer is enough
  374.                     // In this case the good answer will be provided by the checkSociety
  375.                     return $this->checkManager($prospect$user);
  376.                 }
  377.             }
  378.         }
  379.         // If we are here, all hope is lost
  380.         return false;
  381.     }
  382.     private function canEdit(Client $prospectAccess $userAccessFunction $function)
  383.     {
  384.         // Deny for prospects who have been converted to clients
  385.         if ($prospect->isNotProspect())
  386.         {
  387.             return false;
  388.         }
  389.         // Several AclPermission may exist
  390.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  391.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SOCIETY);
  392.         $aclPermManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_MANAGER);
  393.         // If all are null, exit
  394.         if ($aclPerm === null && $aclPermSociety === null && $aclPermManager === null)
  395.             return false;
  396.         // Get First one
  397.         if ($aclPerm !== null)
  398.         {
  399.             $acl $this->aclRepository->findOneBy(array(
  400.                 'function'        =>    $function,
  401.                 'permission'    =>    $aclPerm
  402.             ));
  403.             if ($acl !== null)
  404.             {
  405.                 if ($acl->getValue())
  406.                 {
  407.                     // A single positive answer is enough
  408.                     return true;
  409.                 }
  410.             }
  411.         }
  412.         // If we are here it means that nothing good has been found
  413.         // Load second permission
  414.         if ($aclPermSociety !== null)
  415.         {
  416.             $acl $this->aclRepository->findOneBy(array(
  417.                 'function'        =>    $function,
  418.                 'permission'    =>    $aclPermSociety
  419.             ));
  420.             if ($acl !== null)
  421.             {
  422.                 if ($acl->getValue())
  423.                 {
  424.                     // A single positive answer is enough
  425.                     // In this case the good answer will be provided by the checkSociety
  426.                     return $this->checkSociety($prospect$user);
  427.                 }
  428.             }
  429.         }
  430.         // If we are here it means that nothing good has been found
  431.         // Load third permission
  432.         if ($aclPermManager !== null)
  433.         {
  434.             $acl $this->aclRepository->findOneBy(array(
  435.                 'function'        =>    $function,
  436.                 'permission'    =>    $aclPermManager
  437.             ));
  438.             if ($acl !== null)
  439.             {
  440.                 if ($acl->getValue())
  441.                 {
  442.                     // A single positive answer is enough
  443.                     // In this case the good answer will be provided by the checkSociety
  444.                     return $this->checkManager($prospect$user);
  445.                 }
  446.             }
  447.         }
  448.         // If we are here, all hope is lost
  449.         return false;
  450.     }
  451.     private function canConvert(Client $prospectAccess $userAccessFunction $function)
  452.     {
  453.         // Deny for prospects who have been converted to clients
  454.         if ($prospect->isNotProspect())
  455.         {
  456.             return false;
  457.         }
  458.         // Several AclPermission may exist
  459.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_CONVERT);
  460.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_CONVERT_SOCIETY);
  461.         $aclPermManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_CONVERT_MANAGER);
  462.         // If all are null, exit
  463.         if ($aclPerm === null && $aclPermSociety === null && $aclPermManager === null)
  464.             return false;
  465.         // Get First one
  466.         if ($aclPerm !== null)
  467.         {
  468.             $acl $this->aclRepository->findOneBy(array(
  469.                 'function'        =>    $function,
  470.                 'permission'    =>    $aclPerm
  471.             ));
  472.             if ($acl !== null)
  473.             {
  474.                 if ($acl->getValue())
  475.                 {
  476.                     // A single positive answer is enough
  477.                     return true;
  478.                 }
  479.             }
  480.         }
  481.         // If we are here it means that nothing good has been found
  482.         // Load second permission
  483.         if ($aclPermSociety !== null)
  484.         {
  485.             $acl $this->aclRepository->findOneBy(array(
  486.                 'function'        =>    $function,
  487.                 'permission'    =>    $aclPermSociety
  488.             ));
  489.             if ($acl !== null)
  490.             {
  491.                 if ($acl->getValue())
  492.                 {
  493.                     // A single positive answer is enough
  494.                     // In this case the good answer will be provided by the checkSociety
  495.                     return $this->checkSociety($prospect$user);
  496.                 }
  497.             }
  498.         }
  499.         // If we are here it means that nothing good has been found
  500.         // Load third permission
  501.         if ($aclPermManager !== null)
  502.         {
  503.             $acl $this->aclRepository->findOneBy(array(
  504.                 'function'        =>    $function,
  505.                 'permission'    =>    $aclPermManager
  506.             ));
  507.             if ($acl !== null)
  508.             {
  509.                 if ($acl->getValue())
  510.                 {
  511.                     // A single positive answer is enough
  512.                     // In this case the good answer will be provided by the checkSociety
  513.                     return $this->checkManager($prospect$user);
  514.                 }
  515.             }
  516.         }
  517.         // If we are here, all hope is lost
  518.         return false;
  519.     }
  520. }