src/Security/PaymentVoter.php line 64

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/PaymentVoter.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\APIRest\AccessAPI;
  11. use App\Entity\Config\Config;
  12. use App\Entity\Config\Module;
  13. use App\Entity\HR\AccessFunction;
  14. use App\Entity\Platform\Devis\Devis;
  15. use App\Entity\Platform\Invoice\Invoice;
  16. use App\Entity\Security\Acl;
  17. use App\Entity\Security\AclPermission;
  18. use App\Services\Config\ModuleTools;
  19. class PaymentVoter extends Voter
  20. {
  21.     //--------------------------------------------------------------------------------
  22.     // is_granted constants
  23.     const IS_ACTIVE "payment_is_active";
  24.     const ADD_DEVIS "add_payment_devis";
  25.     const ADD_INVOICE "add_payment_invoice";
  26.     const LISTING "list_payments";
  27.     const LISTING_SOCIETY "list_payments_society";
  28.     const LISTING_ANY "list_payments_any";
  29.     const IS_GRANTED_CONSTANTS = array(
  30.         self::IS_ACTIVE,
  31.         self::ADD_DEVIS,
  32.         self::ADD_INVOICE,
  33.         self::LISTING,
  34.         self::LISTING_SOCIETY,
  35.         self::LISTING_ANY,
  36.     );
  37.     //--------------------------------------------------------------------------------
  38.     // acl constants
  39.     const ACL_PERM_ADD_DEVIS 'payment_devis_add';
  40.     const ACL_PERM_ADD_DEVIS_SOCIETY 'payment_devis_add_society';
  41.     const ACL_PERM_ADD_INVOICE 'payment_invoice_add';
  42.     const ACL_PERM_ADD_INVOICE_SOCIETY 'payment_invoice_add_society';
  43.     const ACL_PERM_LIST 'payment_list';
  44.     const ACL_PERM_LIST_SOCIETY 'payment_list_society';
  45.     //--------------------------------------------------------------------------------
  46.     public function __construct(ManagerRegistry $doctrineModuleTools $moduleTools)
  47.     {
  48.         $this->em $doctrine->getManager();
  49.         $this->moduleTools $moduleTools;
  50.         $this->aclRepository $this->em->getRepository(Acl::class);
  51.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  52.     }
  53.     // Plan.io Task #4453 [See AccessVoter for details]
  54.     public function supportsAttribute(string $attribute): bool
  55.     {
  56.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  57.     }
  58.     
  59.     protected function supports(string $attribute$subject null): bool
  60.     {
  61.         // if the attribute isn't one we support, return false
  62.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  63.         {
  64.             return false;
  65.         }
  66.         // only vote on Devis/Invoice objects inside this voter
  67.         if ($subject !== null && !($subject instanceof Devis || $subject instanceof Invoice))
  68.         {
  69.             return false;
  70.         }
  71.         return true;
  72.     }
  73.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  74.     {
  75.         $user $token->getUser();
  76.         // Plan.io Task #3707
  77.         if ($user instanceof AccessAPI)
  78.         {
  79.             if ($user->getAccess() === null)
  80.             {
  81.                 return false;
  82.             }
  83.             $user $user->getAccess();
  84.         }
  85.         // Plan.io Task #3707
  86.         // At this point $user is an object of Access type
  87.         // even if the $token->getUser() is AccessAPI
  88.         if (!$user instanceof Access)
  89.         {
  90.             // the user must be logged in; if not, deny access
  91.             return false;
  92.         }
  93.         // The user must have a function; if not deny access
  94.         $function $user->getFunction();
  95.         if ($function === null)        return false;
  96.         // Plan.io Task #3710 : Get current group
  97.         $currentGroup $user->getSocietyGroup();
  98.         if ($currentGroup === null)
  99.             return false;
  100.         // Module activated ?
  101.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_PAYMENT))
  102.         {
  103.             return false;
  104.         }
  105.         // Check current group affectation
  106.         if ($subject !== null)
  107.         {
  108.             $subjectSociety $subject->getSociety();
  109.             if ($subjectSociety === null)
  110.                 return false;
  111.             $subjectGroup $subjectSociety->getGroup();
  112.             if ($subjectGroup === null)
  113.                 return false;
  114.             if (!$currentGroup->equals($subjectGroup))
  115.                 return false;
  116.         }
  117.         switch ($attribute)
  118.         {
  119.             case self::IS_ACTIVE:
  120.                 return true;
  121.             case self::ADD_DEVIS:
  122.                 return $this->canAddForDevis($subject$user$function);
  123.             case self::ADD_INVOICE:
  124.                 return $this->canAddForInvoice($subject$user$function);
  125.             case self::LISTING:
  126.                 return $this->canList($user$function);
  127.             case self::LISTING_SOCIETY:
  128.                 return $this->canListSociety($user$function);
  129.             case self::LISTING_ANY:
  130.                 return $this->canListAny($user$function);
  131.         }
  132.         throw new \LogicException('This code should not be reached!');
  133.     }
  134.     // Check if the Society of the $subject
  135.     // belongs to the societies of the $access
  136.     private function checkSociety($subjectAccess $access)
  137.     {
  138.         // Get all the societies of the access
  139.         $societies $access->getSocieties();
  140.         // Get the Society of the subject
  141.         $subjectSociety $subject->getSociety();
  142.         if ($subjectSociety === null)
  143.             return false;
  144.         $found false;
  145.         foreach ($societies as $society)
  146.         {
  147.             if ($society->getId() == $subjectSociety->getId())
  148.             {
  149.                 $found true;
  150.                 break;
  151.             }
  152.         }
  153.         return $found;
  154.     }
  155.     private function canAddForDevis(Devis $devisAccess $userAccessFunction $function)
  156.     {
  157.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD_DEVIS);
  158.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD_DEVIS_SOCIETY);
  159.         if ($aclPerm === null && $aclPermSociety === null)        return false;
  160.         // Get First one
  161.         if ($aclPerm !== null)
  162.         {
  163.             $acl $this->aclRepository->findOneBy(array(
  164.                 'function'        =>    $function,
  165.                 'permission'    =>    $aclPerm
  166.             ));
  167.             if ($acl !== null)
  168.             {
  169.                 if ($acl->getValue())
  170.                 {
  171.                     // A single positive answer is enough
  172.                     return true;
  173.                 }
  174.             }
  175.         }
  176.         // If we are here it means that nothing good has been found
  177.         // Load second permission
  178.         if ($aclPermSociety !== null)
  179.         {
  180.             $acl $this->aclRepository->findOneBy(array(
  181.                 'function'        =>    $function,
  182.                 'permission'    =>    $aclPermSociety
  183.             ));
  184.             if ($acl !== null)
  185.             {
  186.                 if ($acl->getValue())
  187.                 {
  188.                     return $this->checkSociety($devis$user);
  189.                 }
  190.             }
  191.         }
  192.         // If we are here, all hope is lost
  193.         return false;
  194.     }
  195.     private function canAddForInvoice(Invoice $invoiceAccess $userAccessFunction $function)
  196.     {
  197.         // Plan.io Task #4326
  198.         // Deny on drafts
  199.         if ($invoice->isDraft())
  200.         {
  201.             return false;
  202.         }
  203.         // Get Acl_Perm
  204.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD_INVOICE);
  205.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD_INVOICE_SOCIETY);
  206.         if ($aclPerm === null && $aclPermSociety === null)        return false;
  207.         // Get First one
  208.         if ($aclPerm !== null)
  209.         {
  210.             $acl $this->aclRepository->findOneBy(array(
  211.                 'function'        =>    $function,
  212.                 'permission'    =>    $aclPerm
  213.             ));
  214.             if ($acl !== null)
  215.             {
  216.                 if ($acl->getValue())
  217.                 {
  218.                     // A single positive answer is enough
  219.                     return true;
  220.                 }
  221.             }
  222.         }
  223.         // If we are here it means that nothing good has been found
  224.         // Load second permission
  225.         if ($aclPermSociety !== null)
  226.         {
  227.             $acl $this->aclRepository->findOneBy(array(
  228.                 'function'        =>    $function,
  229.                 'permission'    =>    $aclPermSociety
  230.             ));
  231.             if ($acl !== null)
  232.             {
  233.                 if ($acl->getValue())
  234.                 {
  235.                     return $this->checkSociety($invoice$user);
  236.                 }
  237.             }
  238.         }
  239.         // If we are here, all hope is lost
  240.         return false;
  241.     }
  242.     private function canList(Access $userAccessFunction $function)
  243.     {
  244.         // If canView, then canList ;)
  245.         // Get Acl_Perm
  246.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST);
  247.         if ($aclPerm === null)        return false;
  248.         // Get Acl
  249.         $acl $this->aclRepository->findOneBy(array(
  250.             'function'        =>    $function,
  251.             'permission'    =>    $aclPerm
  252.         ));
  253.         if ($acl === null)        return false;
  254.         // Since only one acl type can exist
  255.         // we can return the result of the acl_permission
  256.         return $acl->getValue();
  257.     }
  258.     private function canListSociety(Access $userAccessFunction $function)
  259.     {
  260.         // If canView, then canList ;)
  261.         // Get Acl_Perm
  262.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST_SOCIETY);
  263.         if ($aclPerm === null)        return false;
  264.         // Get Acl
  265.         $acl $this->aclRepository->findOneBy(array(
  266.             'function'        =>    $function,
  267.             'permission'    =>    $aclPerm
  268.         ));
  269.         if ($acl === null)        return false;
  270.         // Since only one acl type can exist
  271.         // we can return the result of the acl_permission
  272.         return $acl->getValue();
  273.     }
  274.     private function canListAny(Access $userAccessFunction $function)
  275.     {
  276.         // Three Acl_Perm may exist
  277.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST);
  278.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST_SOCIETY);
  279.         // If all are null, exit
  280.         if ($aclPerm === null && $aclPermSociety === null)
  281.             return false;
  282.         // Get First one
  283.         if ($aclPerm !== null)
  284.         {
  285.             $acl $this->aclRepository->findOneBy(array(
  286.                 'function'        =>    $function,
  287.                 'permission'    =>    $aclPerm
  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 second permission
  300.         if ($aclPermSociety !== null)
  301.         {
  302.             $acl $this->aclRepository->findOneBy(array(
  303.                 'function'        =>    $function,
  304.                 'permission'    =>    $aclPermSociety
  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. }