src/Security/CommandVoter.php line 75

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/CommandVoter.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\Platform\Command\Command;
  14. use App\Entity\Security\Acl;
  15. use App\Entity\Security\AclPermission;
  16. use App\Services\Config\ModuleTools;
  17. class CommandVoter extends Voter
  18. {
  19.     //--------------------------------------------------------------------------------
  20.     // is_granted constants
  21.     const IS_ACTIVE "command_is_active";
  22.     const ADD "add_command";
  23.     const LISTING "list_commands";
  24.     const LISTING_SOCIETY "list_commands_society";
  25.     const LISTING_MANAGER "list_commands_manager";
  26.     const LISTING_ANY "list_commands_any";
  27.     const VIEW "view_command";
  28.     const EDIT "edit_command";
  29.     const VIEW_PDF "view_pdf_command";
  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::VIEW_PDF,
  40.     );
  41.     //--------------------------------------------------------------------------------
  42.     // acl constants
  43.     const ACL_PERM_ADD "command_add";
  44.     const ACL_PERM_LISTING "command_list";
  45.     const ACL_PERM_LISTING_SOCIETY "command_list_society";
  46.     const ACL_PERM_LISTING_MANAGER "command_list_manager";
  47.     const ACL_PERM_VIEW "command_view";
  48.     const ACL_PERM_VIEW_SOCIETY "command_view_society";
  49.     const ACL_PERM_VIEW_MANAGER "command_view_manager";
  50.     const ACL_PERM_EDIT "command_edit";
  51.     const ACL_PERM_EDIT_SOCIETY "command_edit_society";
  52.     const ACL_PERM_EDIT_MANAGER "command_edit_manager";
  53.     const ACL_PERM_VIEW_PDF "command_view_pdf";
  54.     const ACL_PERM_VIEW_PDF_SOCIETY "command_view_pdf_society";
  55.     const ACL_PERM_VIEW_PDF_MANAGER "command_view_pdf_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 Command objects inside this voter
  77.         if ($subject !== null && !$subject instanceof Command)
  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_COMMAND))
  100.         {
  101.             return false;
  102.         }
  103.         // Check supplier also
  104.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_SUPPLIER))
  105.         {
  106.             return false;
  107.         }
  108.         // Check product / template also
  109.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_PRODUCT))
  110.         {
  111.             return false;
  112.         }
  113.         // you know $subject is a Command object, thanks to supports
  114.         /** @var Command $command */
  115.         $command $subject;
  116.         // Check current group affectation
  117.         if ($subject !== null)
  118.         {
  119.             $subjectSociety $subject->getSociety();
  120.             if ($subjectSociety === null)
  121.                 return false;
  122.             $subjectGroup $subjectSociety->getGroup();
  123.             if ($subjectGroup === null)
  124.                 return false;
  125.             if (!$currentGroup->equals($subjectGroup))
  126.                 return false;
  127.         }
  128.         switch ($attribute)
  129.         {
  130.             case self::IS_ACTIVE:
  131.                 return true;
  132.             case self::ADD:
  133.                 return $this->canAdd($user$function);
  134.             case self::LISTING:
  135.                 return $this->canList($user$function);
  136.             case self::LISTING_SOCIETY:
  137.                 return $this->canListSociety($user$function);
  138.             case self::LISTING_MANAGER:
  139.                 return $this->canListManager($user$function);
  140.             case self::LISTING_ANY:
  141.                 return $this->canListAny($user$function);
  142.             case self::VIEW:
  143.                 return $this->canView($command$user$function);
  144.             case self::EDIT:
  145.                 return $this->canEdit($command$user$function);
  146.             case self::VIEW_PDF:
  147.                 return $this->canViewPdf($command$user$function);
  148.         }
  149.         throw new \LogicException('This code should not be reached!');
  150.     }
  151.     // $access is the user trying to load the resource
  152.     // $command is the resource being loaded
  153.     // Check if the Society of the resource
  154.     // belongs to the societies of the $access
  155.     private function checkSociety(Command $commandAccess $access)
  156.     {
  157.         // Get all the societies of the access
  158.         $societies $access->getSocieties();
  159.         // Get the Society of the Command
  160.         $commandSociety $command->getSociety();
  161.         if ($commandSociety === null)
  162.             return false;
  163.         $found false;
  164.         foreach ($societies as $society)
  165.         {
  166.             if ($society->getId() == $commandSociety->getId())
  167.             {
  168.                 $found true;
  169.                 break;
  170.             }
  171.         }
  172.         return $found;
  173.     }
  174.     // Check if the $access is the manager / author of the $command
  175.     private function checkManager(Command $commandAccess $access)
  176.     {
  177.         // Get manager
  178.         $manager $command->getManager();
  179.         $author $command->getAuthor();
  180.         $accessCommand $command->getAccess();
  181.         if ($manager === null && $author === null)
  182.             return false;
  183.         if ($manager !== null)
  184.             if ($manager->getId() === $access->getId())
  185.                 return true;
  186.         if ($author !== null)
  187.             if ($author->getId() === $access->getId())
  188.                 return true;
  189.         if ($accessCommand !== null)
  190.             if ($accessCommand->getId() === $access->getId())
  191.                 return true;
  192.         return false;
  193.     }
  194.     private function canAdd(Access $userAccessFunction $function)
  195.     {
  196.         // Get Acl_Permission
  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 Acl_Permission
  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 Acl_Permission
  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 Acl_Permission
  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.         // Two Acl_Permission 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(Command $commandAccess $userAccessFunction $function)
  319.     {
  320.         // Get Acl_Permissions
  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($command$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 checkOwn
  375.                     return $this->checkManager($command$user);
  376.                 }
  377.             }
  378.         }
  379.         // If we are here, all hope is lost
  380.         return false;
  381.     }
  382.     private function canEdit(Command $commandAccess $userAccessFunction $function)
  383.     {
  384.         // Plan.io Task #4036
  385.         // Always deny edit on PunchOut Commands if the module is inactive
  386.         if ($command->isPunchOut())
  387.         {
  388.             if ($this->moduleTools->isInactiveByCode($command->getSocietyGroup(), Module::MODULE_PUNCHOUT))
  389.             {
  390.                 return false;
  391.             }
  392.         }
  393.         // Three Acl_Permission may exist
  394.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  395.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SOCIETY);
  396.         $aclPermManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_MANAGER);
  397.         // If all are null, exit
  398.         if ($aclPerm === null && $aclPermSociety === null && $aclPermManager === null)
  399.             return false;
  400.         // Get First one
  401.         if ($aclPerm !== null)
  402.         {
  403.             $acl $this->aclRepository->findOneBy(array(
  404.                 'function'        =>    $function,
  405.                 'permission'    =>    $aclPerm
  406.             ));
  407.             if ($acl !== null)
  408.             {
  409.                 if ($acl->getValue())
  410.                 {
  411.                     // A single positive answer is enough
  412.                     return true;
  413.                 }
  414.             }
  415.         }
  416.         // If we are here it means that nothing good has been found
  417.         // Load second permission
  418.         if ($aclPermSociety !== null)
  419.         {
  420.             $acl $this->aclRepository->findOneBy(array(
  421.                 'function'        =>    $function,
  422.                 'permission'    =>    $aclPermSociety
  423.             ));
  424.             if ($acl !== null)
  425.             {
  426.                 if ($acl->getValue())
  427.                 {
  428.                     // A single positive answer is enough
  429.                     // In this case the good answer will be provided by the checkSociety
  430.                     return $this->checkSociety($command$user);
  431.                 }
  432.             }
  433.         }
  434.         // If we are here it means that nothing good has been found
  435.         // Load third permission
  436.         if ($aclPermManager !== null)
  437.         {
  438.             $acl $this->aclRepository->findOneBy(array(
  439.                 'function'        =>    $function,
  440.                 'permission'    =>    $aclPermManager
  441.             ));
  442.             if ($acl !== null)
  443.             {
  444.                 if ($acl->getValue())
  445.                 {
  446.                     // A single positive answer is enough
  447.                     // In this case the good answer will be provided by the checkOwn
  448.                     return $this->checkManager($command$user);
  449.                 }
  450.             }
  451.         }
  452.         // If we are here, all hope is lost
  453.         return false;
  454.     }
  455.     private function canViewPdf(Command $commandAccess $userAccessFunction $function)
  456.     {
  457.         // Three Acl_Permission may exist
  458.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_PDF);
  459.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_PDF_SOCIETY);
  460.         $aclPermManager $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_PDF_MANAGER);
  461.         // If all are null, exit
  462.         if ($aclPerm === null && $aclPermSociety === null && $aclPermManager === null)
  463.             return false;
  464.         // Get First one
  465.         if ($aclPerm !== null)
  466.         {
  467.             $acl $this->aclRepository->findOneBy(array(
  468.                 'function'        =>    $function,
  469.                 'permission'    =>    $aclPerm
  470.             ));
  471.             if ($acl !== null)
  472.             {
  473.                 if ($acl->getValue())
  474.                 {
  475.                     // A single positive answer is enough
  476.                     return true;
  477.                 }
  478.             }
  479.         }
  480.         // If we are here it means that nothing good has been found
  481.         // Load second permission
  482.         if ($aclPermSociety !== null)
  483.         {
  484.             $acl $this->aclRepository->findOneBy(array(
  485.                 'function'        =>    $function,
  486.                 'permission'    =>    $aclPermSociety
  487.             ));
  488.             if ($acl !== null)
  489.             {
  490.                 if ($acl->getValue())
  491.                 {
  492.                     // A single positive answer is enough
  493.                     // In this case the good answer will be provided by the checkSociety
  494.                     return $this->checkSociety($command$user);
  495.                 }
  496.             }
  497.         }
  498.         // If we are here it means that nothing good has been found
  499.         // Load third permission
  500.         if ($aclPermManager !== null)
  501.         {
  502.             $acl $this->aclRepository->findOneBy(array(
  503.                 'function'        =>    $function,
  504.                 'permission'    =>    $aclPermManager
  505.             ));
  506.             if ($acl !== null)
  507.             {
  508.                 if ($acl->getValue())
  509.                 {
  510.                     // A single positive answer is enough
  511.                     // In this case the good answer will be provided by the checkOwn
  512.                     return $this->checkManager($command$user);
  513.                 }
  514.             }
  515.         }
  516.         // If we are here, all hope is lost
  517.         return false;
  518.     }
  519. }