src/Security/AccessApiVoter.php line 56

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/AccessApiVoter.php
  4. //------------------------------------------------------------------------------
  5. namespace App\Security;
  6. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  7. use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
  8. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  9. use Doctrine\Persistence\ManagerRegistry;
  10. use App\Entity\Access;
  11. use App\Entity\APIRest\AccessAPI;
  12. use App\Entity\Config\Config;
  13. use App\Entity\Config\Module;
  14. use App\Entity\HR\AccessFunction;
  15. use App\Entity\Security\Acl;
  16. use App\Entity\Security\AclPermission;
  17. use App\Services\Config\ModuleTools;
  18. class AccessApiVoter extends Voter
  19. {
  20.     //--------------------------------------------------------------------------------
  21.     // is_granted constants
  22.     const IS_ACTIVE "mobile_api_is_active";
  23.     const ACTIVATE_DEACTIVATE "activate_deactivate_mobile_api_user";
  24.     const ACTIVATE_DEACTIVATE_FOR_ACCESS "activate_deactivate_mobile_api_user_for_access";
  25.     const LISTING "list_api_accesses";
  26.     const LISTING_SOCIETY "list_api_accesses_society";
  27.     const LISTING_ANY "list_api_accesses_any";
  28.     const IS_GRANTED_CONSTANTS = array(
  29.         self::IS_ACTIVE,
  30.         self::ACTIVATE_DEACTIVATE,
  31.         self::ACTIVATE_DEACTIVATE_FOR_ACCESS,
  32.         self::LISTING,
  33.         self::LISTING_SOCIETY,
  34.         self::LISTING_ANY,
  35.     );
  36.     //--------------------------------------------------------------------------------
  37.     // acl constants
  38.     const ACL_PERM_ACTIVATE_DEACTIVATE 'mobile_api_activate_deactivate_user';
  39.     const ACL_PERM_ACTIVATE_DEACTIVATE_SOCIETY 'mobile_api_activate_deactivate_user_society';
  40.     //--------------------------------------------------------------------------------
  41.     public function __construct(AccessDecisionManagerInterface $accessDecisionManagerManagerRegistry $doctrineModuleTools $moduleTools)
  42.     {
  43.         $this->accessDecisionManager $accessDecisionManager;
  44.         $this->em $doctrine->getManager();
  45.         $this->moduleTools $moduleTools;
  46.         $this->aclRepository $this->em->getRepository(Acl::class);
  47.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  48.     }
  49.     protected function supports(string $attribute$subject null): bool
  50.     {
  51.         // if the attribute isn't one we support, return false
  52.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  53.         {
  54.             return false;
  55.         }
  56.         // only vote on Access / AccessAPI objects inside this voter
  57.         if ($subject !== null && !($subject instanceof Access || $subject instanceof AccessAPI))
  58.         {
  59.             return false;
  60.         }
  61.         return true;
  62.     }
  63.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  64.     {
  65.         $user $token->getUser();
  66.         if (!$user instanceof Access)
  67.         {
  68.             // the user must be logged in; if not, deny access
  69.             return false;
  70.         }
  71.         // The user must have a function; if not deny access
  72.         $function $user->getFunction();
  73.         if ($function === null)        return false;
  74.         // Plan.io Task #3710 : Get current group
  75.         $currentGroup $user->getSocietyGroup();
  76.         if ($currentGroup === null)
  77.             return false;
  78.         // Module activated ?
  79.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_MOBILE_API))
  80.         {
  81.             return false;
  82.         }
  83.         $subjectAccess null;
  84.         $subjectAccessApi null;
  85.         if ($subject instanceof Access)
  86.         {
  87.             $subjectAccess $subject;
  88.             $subjectAccessApi $subject->getAccessAPI();
  89.         }
  90.         if ($subject instanceof AccessAPI)
  91.         {
  92.             $subjectAccess $subject->getAccess();
  93.             $subjectAccessApi $subject;
  94.         }
  95.         // Check current group affectation
  96.         if ($subjectAccess !== null)
  97.         {
  98.             $subjectSociety $subjectAccess->getSociety();
  99.             if ($subjectSociety === null)
  100.                 return false;
  101.             $subjectGroup $subjectSociety->getGroup();
  102.             if ($subjectGroup === null)
  103.                 return false;
  104.             if (!$currentGroup->equals($subjectGroup))
  105.                 return false;
  106.         }
  107.         switch ($attribute)
  108.         {
  109.             case self::IS_ACTIVE:
  110.                 return true;
  111.             case self::ACTIVATE_DEACTIVATE:
  112.             {
  113.                 return $this->canChangeState($subjectAccessApi$user$function);
  114.             }
  115.             case self::ACTIVATE_DEACTIVATE_FOR_ACCESS:
  116.             {
  117.                 if ($subjectAccess !== null && $subjectAccessApi === null)
  118.                 {
  119.                     // Creation case
  120.                     return $this->canAddForAccess($subjectAccess$user$function);
  121.                 }
  122.                 return $this->canChangeState($subjectAccessApi$user$function);
  123.             }
  124.             case self::LISTING:
  125.             {
  126.                 return $this->accessDecisionManager->decide($token, ['list_accesses']);
  127.             }
  128.             case self::LISTING_SOCIETY:
  129.             {
  130.                 return $this->accessDecisionManager->decide($token, ['list_accesses_society']);
  131.             }
  132.             case self::LISTING_ANY:
  133.             {
  134.                 return $this->accessDecisionManager->decide($token, ['list_accesses_any']);
  135.             }
  136.         }
  137.         throw new \LogicException('This code should not be reached!');
  138.     }
  139.     // $access is the user trying to load the resource
  140.     // $cost is the resource being loaded
  141.     // Check if the Society of the resource
  142.     // belongs to the societies of the $access
  143.     private function checkSociety(Access $subjectAccess $access)
  144.     {
  145.         // Get all the societies of the access
  146.         $societies $access->getSocieties();
  147.         // Get the Society of the Demand
  148.         $subjectSociety $subject->getSociety();
  149.         if ($subjectSociety === null)
  150.             return false;
  151.         $found false;
  152.         foreach ($societies as $society)
  153.         {
  154.             if ($society->getId() == $subjectSociety->getId())
  155.             {
  156.                 $found true;
  157.                 break;
  158.             }
  159.         }
  160.         return $found;
  161.     }
  162.     private function canChangeState(AccessAPI $accessApiAccess $userAccessFunction $function)
  163.     {
  164.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ACTIVATE_DEACTIVATE);
  165.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ACTIVATE_DEACTIVATE_SOCIETY);
  166.         // If all are null, exit
  167.         if ($aclPerm === null && $aclPermSociety === null)
  168.             return false;
  169.         // Get First one
  170.         if ($aclPerm !== null)
  171.         {
  172.             $acl $this->aclRepository->findOneBy(array(
  173.                 'function'        =>    $function,
  174.                 'permission'    =>    $aclPerm
  175.             ));
  176.             if ($acl !== null)
  177.             {
  178.                 if ($acl->getValue())
  179.                 {
  180.                     // A single positive answer is enough
  181.                     return true;
  182.                 }
  183.             }
  184.         }
  185.         // If we are here it means that nothing good has been found
  186.         // Load second permission
  187.         if ($aclPermSociety !== null)
  188.         {
  189.             $acl $this->aclRepository->findOneBy(array(
  190.                 'function'        =>    $function,
  191.                 'permission'    =>    $aclPermSociety
  192.             ));
  193.             if ($acl !== null)
  194.             {
  195.                 if ($acl->getValue())
  196.                 {
  197.                     return $this->checkSociety($accessApi->getAccess(), $user);
  198.                 }
  199.             }
  200.         }
  201.         // If we are here, all hope is lost
  202.         return false;
  203.     }
  204.     private function canAddForAccess(Access $accessAccess $userAccessFunction $function)
  205.     {
  206.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ACTIVATE_DEACTIVATE);
  207.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ACTIVATE_DEACTIVATE_SOCIETY);
  208.         // If all are null, exit
  209.         if ($aclPerm === null && $aclPermSociety === null)
  210.             return false;
  211.         // Get First one
  212.         if ($aclPerm !== null)
  213.         {
  214.             $acl $this->aclRepository->findOneBy(array(
  215.                 'function'        =>    $function,
  216.                 'permission'    =>    $aclPerm
  217.             ));
  218.             if ($acl !== null)
  219.             {
  220.                 if ($acl->getValue())
  221.                 {
  222.                     // A single positive answer is enough
  223.                     return true;
  224.                 }
  225.             }
  226.         }
  227.         // If we are here it means that nothing good has been found
  228.         // Load second permission
  229.         if ($aclPermSociety !== null)
  230.         {
  231.             $acl $this->aclRepository->findOneBy(array(
  232.                 'function'        =>    $function,
  233.                 'permission'    =>    $aclPermSociety
  234.             ));
  235.             if ($acl !== null)
  236.             {
  237.                 if ($acl->getValue())
  238.                 {
  239.                     return $this->checkSociety($access$user);
  240.                 }
  241.             }
  242.         }
  243.         // If we are here, all hope is lost
  244.         return false;
  245.     }
  246. }