src/Security/ExternalMessageVoter.php line 62

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/ExternalMessageVoter.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\ExternalMessage\ExternalMessage;
  14. use App\Entity\Security\Acl;
  15. use App\Entity\Security\AclPermission;
  16. use App\Services\Config\ModuleTools;
  17. class ExternalMessageVoter extends Voter
  18. {
  19.     // For now the only external messages are SMS
  20.     // So in this voter we will check if the SMS module is active
  21.     //--------------------------------------------------------------------------------
  22.     // is_granted constants
  23.     const LISTING "list_external_messages";
  24.     const LISTING_SOCIETY "list_external_messages_society";
  25.     const LISTING_ANY "list_external_messages_any";
  26.     const VIEW "view_external_message";
  27.     const EDIT "edit_external_message";
  28.     const EDIT_SOCIETY "edit_external_message_society";
  29.     const IS_GRANTED_CONSTANTS = array(
  30.         self::LISTING,
  31.         self::LISTING_SOCIETY,
  32.         self::LISTING_ANY,
  33.         self::VIEW,
  34.         self::EDIT,
  35.         self::EDIT_SOCIETY,
  36.     );
  37.     //--------------------------------------------------------------------------------
  38.     // acl constants
  39.     const ACL_PERM_LIST 'external_message_list';
  40.     const ACL_PERM_LIST_SOCIETY 'external_message_list_society';
  41.     const ACL_PERM_VIEW 'external_message_view';
  42.     const ACL_PERM_VIEW_SOCIETY 'external_message_view_society';
  43.     const ACL_PERM_EDIT 'external_message_edit';
  44.     const ACL_PERM_EDIT_SOCIETY 'external_message_edit_society';
  45.     const ACL_PERM_SOCIETY_EDIT 'external_message_society_edit';
  46.     const ACL_PERM_SOCIETY_EDIT_SOCIETY 'external_message_society_edit_society';
  47.     //--------------------------------------------------------------------------------
  48.     public function __construct(ManagerRegistry $doctrineModuleTools $moduleTools)
  49.     {
  50.         $this->em $doctrine->getManager();
  51.         $this->moduleTools $moduleTools;
  52.         $this->aclRepository $this->em->getRepository(Acl::class);
  53.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  54.     }
  55.     // Plan.io Task #4453 [See AccessVoter for details]
  56.     public function supportsAttribute(string $attribute): bool
  57.     {
  58.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  59.     }
  60.     protected function supports(string $attribute$subject null): bool
  61.     {
  62.         // if the attribute isn't one we support, return false
  63.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  64.         {
  65.             return false;
  66.         }
  67.         // only vote on ExternalMessage objects inside this voter
  68.         if ($subject !== null && !$subject instanceof ExternalMessage)
  69.         {
  70.             return false;
  71.         }
  72.         return true;
  73.     }
  74.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  75.     {
  76.         $user $token->getUser();
  77.         if (!$user instanceof Access)
  78.         {
  79.             // the user must be logged in; if not, deny access
  80.             return false;
  81.         }
  82.         // The user must have a function; if not deny access
  83.         $function $user->getFunction();
  84.         if ($function === null)        return false;
  85.         // Plan.io Task #3710 : Get current group
  86.         $currentGroup $user->getSocietyGroup();
  87.         if ($currentGroup === null)
  88.             return false;
  89.         // Module activated ?
  90.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_SMS))
  91.         {
  92.             return false;
  93.         }
  94.         // you know $subject is a ExternalMessage object, thanks to supports
  95.         /** @var ExternalMessage $externalMessage */
  96.         $externalMessage $subject;
  97.         // Check current group affectation
  98.         if ($subject !== null)
  99.         {
  100.             $subjectSociety $subject->getSociety();
  101.             if ($subjectSociety === null)
  102.                 return false;
  103.             $subjectGroup $subjectSociety->getGroup();
  104.             if ($subjectGroup === null)
  105.                 return false;
  106.             if (!$currentGroup->equals($subjectGroup))
  107.                 return false;
  108.         }
  109.         switch ($attribute)
  110.         {
  111.             case self::VIEW:
  112.                 return $this->canView($externalMessage$user$function);
  113.             case self::EDIT:
  114.                 return $this->canEdit($externalMessage$user$function);
  115.             case self::EDIT_SOCIETY:
  116.                 return $this->canEditSociety($externalMessage$user$function);
  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.         }
  124.         throw new \LogicException('This code should not be reached!');
  125.     }
  126.     // Check if the Society of the ExternalMessage
  127.     // belongs to the societies of the $access
  128.     private function checkSociety(ExternalMessage $externalMessageAccess $access)
  129.     {
  130.         // Get all the societies of the access
  131.         $societies $access->getSocieties();
  132.         // Get the Society of the ExternalMessage
  133.         $externalMessageSociety $externalMessage->getSociety();
  134.         if ($externalMessageSociety === null)
  135.             return false;
  136.         $found false;
  137.         foreach ($societies as $society)
  138.         {
  139.             if ($society->getId() == $externalMessageSociety->getId())
  140.             {
  141.                 $found true;
  142.                 break;
  143.             }
  144.         }
  145.         return $found;
  146.     }
  147.     private function canView(ExternalMessage $externalMessageAccess $userAccessFunction $function)
  148.     {
  149.         // Get Acl_Perdemands
  150.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW);
  151.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_SOCIETY);
  152.         // If all are null, exit
  153.         if ($aclPerm === null && $aclPermSociety === null)
  154.             return false;
  155.         // Get First one
  156.         if ($aclPerm !== null)
  157.         {
  158.             $acl $this->aclRepository->findOneBy(array(
  159.                 'function'        =>    $function,
  160.                 'permission'    =>    $aclPerm
  161.             ));
  162.             if ($acl !== null)
  163.             {
  164.                 if ($acl->getValue())
  165.                 {
  166.                     // A single positive answer is enough
  167.                     return true;
  168.                 }
  169.             }
  170.         }
  171.         // If we are here it means that nothing good has been found
  172.         // Load second permission
  173.         if ($aclPermSociety !== null)
  174.         {
  175.             $acl $this->aclRepository->findOneBy(array(
  176.                 'function'        =>    $function,
  177.                 'permission'    =>    $aclPermSociety
  178.             ));
  179.             if ($acl !== null)
  180.             {
  181.                 if ($acl->getValue())
  182.                 {
  183.                     // Check Society : also check author
  184.                     // Les demands appartenant à ses sociétés (et celles dont il est l'auteur)
  185.                     if ($this->checkSociety($externalMessage$user))
  186.                     {
  187.                         return true;
  188.                     }
  189.                 }
  190.             }
  191.         }
  192.         // If we are here, all hope is lost
  193.         return false;
  194.     }
  195.     private function canEdit(ExternalMessage $externalMessageAccess $userAccessFunction $function)
  196.     {
  197.         // Get Acl_Perdemands
  198.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  199.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SOCIETY);
  200.         // If all are null, exit
  201.         if ($aclPerm === null && $aclPermSociety === null)
  202.             return false;
  203.         // Get First one
  204.         if ($aclPerm !== null)
  205.         {
  206.             $acl $this->aclRepository->findOneBy(array(
  207.                 'function'        =>    $function,
  208.                 'permission'    =>    $aclPerm
  209.             ));
  210.             if ($acl !== null)
  211.             {
  212.                 if ($acl->getValue())
  213.                 {
  214.                     // A single positive answer is enough
  215.                     return true;
  216.                 }
  217.             }
  218.         }
  219.         // If we are here it means that nothing good has been found
  220.         // Load second permission
  221.         if ($aclPermSociety !== null)
  222.         {
  223.             $acl $this->aclRepository->findOneBy(array(
  224.                 'function'        =>    $function,
  225.                 'permission'    =>    $aclPermSociety
  226.             ));
  227.             if ($acl !== null)
  228.             {
  229.                 if ($acl->getValue())
  230.                 {
  231.                     // Check Society : also check author
  232.                     // Les demands appartenant à ses sociétés (et celles dont il est l'auteur)
  233.                     if ($this->checkSociety($externalMessage$user))
  234.                     {
  235.                         return true;
  236.                     }
  237.                 }
  238.             }
  239.         }
  240.         // If we are here, all hope is lost
  241.         return false;
  242.     }
  243.     private function canEditSociety(ExternalMessage $externalMessageAccess $userAccessFunction $function)
  244.     {
  245.         // Get Acl_Perdemands
  246.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_SOCIETY_EDIT);
  247.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_SOCIETY_EDIT_SOCIETY);
  248.         // If all are null, exit
  249.         if ($aclPerm === null && $aclPermSociety === null)
  250.             return false;
  251.         // Get First one
  252.         if ($aclPerm !== null)
  253.         {
  254.             $acl $this->aclRepository->findOneBy(array(
  255.                 'function'        =>    $function,
  256.                 'permission'    =>    $aclPerm
  257.             ));
  258.             if ($acl !== null)
  259.             {
  260.                 if ($acl->getValue())
  261.                 {
  262.                     // A single positive answer is enough
  263.                     return true;
  264.                 }
  265.             }
  266.         }
  267.         // If we are here it means that nothing good has been found
  268.         // Load second permission
  269.         if ($aclPermSociety !== null)
  270.         {
  271.             $acl $this->aclRepository->findOneBy(array(
  272.                 'function'        =>    $function,
  273.                 'permission'    =>    $aclPermSociety
  274.             ));
  275.             if ($acl !== null)
  276.             {
  277.                 if ($acl->getValue())
  278.                 {
  279.                     // Check Society : also check author
  280.                     // Les demands appartenant à ses sociétés (et celles dont il est l'auteur)
  281.                     if ($this->checkSociety($externalMessage$user))
  282.                     {
  283.                         return true;
  284.                     }
  285.                 }
  286.             }
  287.         }
  288.         // If we are here, all hope is lost
  289.         return false;
  290.     }
  291.     private function canList(Access $userAccessFunction $function)
  292.     {
  293.         // If canView, then canList ;)
  294.         // Get Acl_Perdemand
  295.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST);
  296.         if ($aclPerm === null)        return false;
  297.         // Get Acl
  298.         $acl $this->aclRepository->findOneBy(array(
  299.             'function'        =>    $function,
  300.             'permission'    =>    $aclPerm
  301.         ));
  302.         if ($acl === null)        return false;
  303.         // Since only one acl type can exist
  304.         // we can return the result of the acl_permission
  305.         return $acl->getValue();
  306.     }
  307.     private function canListSociety(Access $userAccessFunction $function)
  308.     {
  309.         // If canView, then canList ;)
  310.         // Get Acl_Perdemand
  311.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST_SOCIETY);
  312.         if ($aclPerm === null)        return false;
  313.         // Get Acl
  314.         $acl $this->aclRepository->findOneBy(array(
  315.             'function'        =>    $function,
  316.             'permission'    =>    $aclPerm
  317.         ));
  318.         if ($acl === null)        return false;
  319.         // Since only one acl type can exist
  320.         // we can return the result of the acl_permission
  321.         return $acl->getValue();
  322.     }
  323.     private function canListAny(Access $userAccessFunction $function)
  324.     {
  325.         // Three Acl_Perdemand may exist
  326.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST);
  327.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST_SOCIETY);
  328.         // If all are null, exit
  329.         if ($aclPerm === null && $aclPermSociety === null)
  330.             return false;
  331.         // Get First one
  332.         if ($aclPerm !== null)
  333.         {
  334.             $acl $this->aclRepository->findOneBy(array(
  335.                 'function'        =>    $function,
  336.                 'permission'    =>    $aclPerm
  337.             ));
  338.             if ($acl !== null)
  339.             {
  340.                 if ($acl->getValue())
  341.                 {
  342.                     // A single positive answer is enough
  343.                     return true;
  344.                 }
  345.             }
  346.         }
  347.         // If we are here it means that nothing good has been found
  348.         // Load second permission
  349.         if ($aclPermSociety !== null)
  350.         {
  351.             $acl $this->aclRepository->findOneBy(array(
  352.                 'function'        =>    $function,
  353.                 'permission'    =>    $aclPermSociety
  354.             ));
  355.             if ($acl !== null)
  356.             {
  357.                 if ($acl->getValue())
  358.                 {
  359.                     // A single positive answer is enough
  360.                     return true;
  361.                 }
  362.             }
  363.         }
  364.         // If we are here, all hope is lost
  365.         return false;
  366.     }
  367. }