src/Security/SocietyGroupInvoiceVoter.php line 64

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/SocietyGroupInvoiceVoter.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\Devis\Devis;
  14. use App\Entity\Platform\SocietyGroup\SocietyGroupInvoice;
  15. use App\Entity\Security\Acl;
  16. use App\Entity\Security\AclPermission;
  17. use App\Services\Config\ModuleTools;
  18. class SocietyGroupInvoiceVoter extends Voter
  19. {
  20.     //--------------------------------------------------------------------------------
  21.     // is_granted constants
  22.     const ADD "add_society_group_invoice";
  23.     const VIEW "view_society_group_invoice";
  24.     const VIEW_PDF "view_pdf_society_group_invoice";
  25.     const EDIT "edit_society_group_invoice";
  26.     const EDIT_RECEIVER_SOCIETY "edit_society_group_invoice_receiver_society";
  27.     // This one is tricky
  28.     // We don't actually care for permissions here
  29.     // We just want to know if there is anything to display
  30.     // If the SocietyGroup has no SocietyGroupInvoices, there is no need to even show the tab
  31.     const LIST = "list_society_group_invoices";
  32.     const IS_GRANTED_CONSTANTS = array(
  33.         self::ADD,
  34.         self::VIEW,
  35.         self::VIEW_PDF,
  36.         self::EDIT,
  37.         self::EDIT_RECEIVER_SOCIETY,
  38.         self::LIST,
  39.     );
  40.     //--------------------------------------------------------------------------------
  41.     // acl constants
  42.     const ACL_PERM_VIEW "society_group_invoice_view";
  43.     const ACL_PERM_VIEW_PDF "society_group_invoice_view_pdf";
  44.     const ACL_PERM_EDIT "society_group_invoice_edit";
  45.     const ACL_PERM_LIST "society_group_invoice_list";
  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 Invoice / Devis objects inside this voter
  67.         if ($subject !== null && !($subject instanceof SocietyGroupInvoice || $subject instanceof Devis))
  68.         {
  69.             return false;
  70.         }
  71.         return true;
  72.     }
  73.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  74.     {
  75.         $user $token->getUser();
  76.         if (!$user instanceof Access)
  77.         {
  78.             // the user must be logged in; if not, deny access
  79.             return false;
  80.         }
  81.         // The user must have a function; if not deny access
  82.         $function $user->getFunction();
  83.         if ($function === null)        return false;
  84.         // Plan.io Task #3710 : Get current group
  85.         $currentGroup $user->getSocietyGroup();
  86.         if ($currentGroup === null)
  87.             return false;
  88.         $this->currentGroup $currentGroup;
  89.         $this->devis null;
  90.         $this->invoice null;
  91.         $this->emitter null;
  92.         $this->receiver null;
  93.         if ($subject instanceof SocietyGroupInvoice)
  94.         {
  95.             $this->invoice $subject;
  96.             $this->emitter $subject->getEmitter();
  97.             $this->receiver $subject->getReceiver();
  98.             if ($this->emitter === null || $this->receiver === null)
  99.             {
  100.                 return false;
  101.             }
  102.         }
  103.         switch ($attribute)
  104.         {
  105.             // canAdd : subject is Devis
  106.             case self::ADD:
  107.                 return $this->canAdd($subject);
  108.             case self::LIST:
  109.                 return $this->canList($user$function);
  110.             // for all those below : subject is Invoice
  111.             case self::VIEW:
  112.                 return $this->canView($subject$user$function);
  113.             case self::VIEW_PDF:
  114.                 return $this->canViewPdf($subject$user$function);
  115.             case self::EDIT:
  116.                 return $this->canEdit($subject$user$function);
  117.             case self::EDIT_RECEIVER_SOCIETY:
  118.                 return $this->canEditReceiverSociety($subject$user$function);
  119.         }
  120.         throw new \LogicException('This code should not be reached!');
  121.     }
  122.     private function canAdd(Devis $devis)
  123.     {
  124.         // Deny for annulled and refused
  125.         if ($devis->isAnnulled() || $devis->isRefused())
  126.         {
  127.             return false;
  128.         }
  129.         // Only JCAF SocietyGroup can add a SocietyGroupInvoice for now
  130.         if ($this->currentGroup->isNotJcaf())
  131.         {
  132.             return false;
  133.         }
  134.         // Only for JCAF Devis with commission
  135.         // Plan.io Task #3229 Commissions
  136.         $mission $devis->getMission();
  137.         if ($mission === null)
  138.         {
  139.             return false;
  140.         }
  141.         // Deny actions on archivedRefused objects
  142.         if ($mission->isArchivedRefused())
  143.         {
  144.             return false;
  145.         }
  146.         // Only for JCAF Devis with commission
  147.         // Plan.io Task #3229 Commissions
  148.         // Restrictions on Devis
  149.         if ($devis !== null)
  150.         {
  151.             if ($devis->isNotJcaf())
  152.             {
  153.                 return false;
  154.             }
  155.             if (empty($devis->getShareCommission()))
  156.             {
  157.                 return false;
  158.             }
  159.         }
  160.         // Do we already have a SocietyGroupInvoice for this Devis ?
  161.         $invoice $this->em->getRepository(SocietyGroupInvoice::class)->findOneByDevis($devis);
  162.         if ($invoice !== null)
  163.         {
  164.             return false;
  165.         }
  166.         // Restrictions on Mission
  167.         if ($mission !== null)
  168.         {
  169.             if ($mission->getSocietyGroupAuthor() === null)
  170.             {
  171.                 return false;
  172.             }
  173.             if ($mission->getSocietyGroupAuthor()->isNotJcaf())
  174.             {
  175.                 return false;
  176.             }
  177.             if (empty($mission->getCommissionAmount()) && empty($mission->getCommissionPercentage()))
  178.             {
  179.                 return false;
  180.             }
  181.         }
  182.         // If we are here all went well
  183.         return true;
  184.     }
  185.     private function canList(Access $userAccessFunction $function)
  186.     {
  187.         // Always show tab for JCAF SocietyGroup
  188.         if ($this->currentGroup->isJcaf())
  189.         {
  190.             return true;
  191.         }
  192.         // if ($this->currentGroup->isNotJcaf())
  193.         // {
  194.         //     $sql = "SELECT COUNT(*) as nb
  195.         //             FROM society_group_invoice
  196.         //             WHERE society_group_invoice.receiver_society_group_id = ".$this->currentGroup->getId();
  197.         //     $stmt = $this->em->getConnection()->prepare($sql);
  198.         //     $stmt->execute();
  199.         //     $result = $stmt->fetch()['nb'];
  200.         //     if ($result < 1)
  201.         //     {
  202.         //         return false;
  203.         //     }
  204.         // }
  205.         // If the current society group is not JCAF
  206.         // only show the society_group_invoice tab if at least one invoice is available
  207.         // Test receiver
  208.         $invoice $this->em->getRepository(SocietyGroupInvoice::class)->findOneByReceiver($this->currentGroup);
  209.         if ($invoice === null)
  210.         {
  211.             // None available, die hard
  212.             return false;
  213.         }
  214.         // If we are here it means that we have at least one invoice to show
  215.         // Test permissions
  216.         // Get Acl_Permission
  217.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST);
  218.         if ($aclPerm === null)        return false;
  219.         // Get Acl
  220.         $acl $this->aclRepository->findOneBy(array(
  221.             'function'        =>    $function,
  222.             'permission'    =>    $aclPerm
  223.         ));
  224.         if ($acl === null)        return false;
  225.         // Since only one acl type can exist
  226.         // we can return the result of the acl_permission
  227.         return $acl->getValue();
  228.         // All hope is lost
  229.         return false;
  230.     }
  231.     private function canView(SocietyGroupInvoice $invoiceAccess $userAccessFunction $function)
  232.     {
  233.         // Both emitter and receiver can view society group invoices
  234.         if (!($this->currentGroup->equals($this->emitter) || $this->currentGroup->equals($this->receiver)))
  235.         {
  236.             return false;
  237.         }
  238.         // Get Acl_Permission
  239.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW);
  240.         if ($aclPerm === null)        return false;
  241.         // Get Acl
  242.         $acl $this->aclRepository->findOneBy(array(
  243.             'function'        =>    $function,
  244.             'permission'    =>    $aclPerm
  245.         ));
  246.         if ($acl === null)        return false;
  247.         // Since only one acl type can exist
  248.         // we can return the result of the acl_permission
  249.         return $acl->getValue();
  250.         // All hope is lost
  251.         return false;
  252.     }
  253.     private function canViewPdf(SocietyGroupInvoice $invoiceAccess $userAccessFunction $function)
  254.     {
  255.         // Both emitter and receiver can view society group invoices
  256.         if (!($this->currentGroup->equals($this->emitter) || $this->currentGroup->equals($this->receiver)))
  257.         {
  258.             return false;
  259.         }
  260.         // Get Acl_Permission
  261.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_PDF);
  262.         if ($aclPerm === null)        return false;
  263.         // Get Acl
  264.         $acl $this->aclRepository->findOneBy(array(
  265.             'function'        =>    $function,
  266.             'permission'    =>    $aclPerm
  267.         ));
  268.         if ($acl === null)        return false;
  269.         // Since only one acl type can exist
  270.         // we can return the result of the acl_permission
  271.         return $acl->getValue();
  272.         // All hope is lost
  273.         return false;
  274.     }
  275.     private function canEdit(SocietyGroupInvoice $invoiceAccess $userAccessFunction $function)
  276.     {
  277.         // Only the emitter of a SocietyGroupInvoice can edit it
  278.         // For now the emitter is always Jcaf ;)
  279.         if (!$this->currentGroup->equals($this->emitter))
  280.         {
  281.             return false;
  282.         }
  283.         // Plan.io Task #3229 Commissions
  284.         // Only JCAF SocietyGroup can edit a SocietyGroupInvoice for now
  285.         if ($this->currentGroup->isNotJcaf())
  286.         {
  287.             return false;
  288.         }
  289.         $mission $invoice->getMission();
  290.         if ($mission === null)
  291.         {
  292.             return false;
  293.         }
  294.         // Deny edit on archivedRefused objects
  295.         if ($mission->isArchivedRefused())
  296.         {
  297.             return false;
  298.         }
  299.         // No edditing on annulled invoices
  300.         if ($invoice->isAnnulled())
  301.         {
  302.             return false;
  303.         }
  304.         // No edditing on invoices that have been "annuled" (with credit)
  305.         // $credit = $this->em->getRepository('IcodPlatformBundle:Invoice')
  306.         //     ->findOneByCreditInvoice($invoice);
  307.         // if ($credit !== null)
  308.         //     return false;
  309.         // Get Acl_Permission
  310.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  311.         if ($aclPerm === null)        return false;
  312.         // Get Acl
  313.         $acl $this->aclRepository->findOneBy(array(
  314.             'function'        =>    $function,
  315.             'permission'    =>    $aclPerm
  316.         ));
  317.         if ($acl === null)        return false;
  318.         // Since only one acl type can exist
  319.         // we can return the result of the acl_permission
  320.         return $acl->getValue();
  321.         // All hope is lost
  322.         return false;
  323.     }
  324.     private function canEditReceiverSociety(SocietyGroupInvoice $invoiceAccess $userAccessFunction $function)
  325.     {
  326.         // Plan.io Task #3229 Commissions
  327.         // Only the receiver of a SocietyGroupInvoice can edit its receiver
  328.         if (!$this->currentGroup->equals($this->receiver))
  329.         {
  330.             return false;
  331.         }
  332.         $mission $invoice->getMission();
  333.         if ($mission === null)
  334.         {
  335.             return false;
  336.         }
  337.         // Deny edit on archivedRefused objects
  338.         if ($mission->isArchivedRefused())
  339.         {
  340.             return false;
  341.         }
  342.         // No edditing on annulled invoices
  343.         if ($invoice->isAnnulled())
  344.         {
  345.             return false;
  346.         }
  347.         // No edditing on invoices that have been "annuled" (with credit)
  348.         // $credit = $this->em->getRepository('IcodPlatformBundle:Invoice')
  349.         //     ->findOneByCreditInvoice($invoice);
  350.         // if ($credit !== null)
  351.         //     return false;
  352.         // Get Acl_Permission
  353.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  354.         if ($aclPerm === null)        return false;
  355.         // Get Acl
  356.         $acl $this->aclRepository->findOneBy(array(
  357.             'function'        =>    $function,
  358.             'permission'    =>    $aclPerm
  359.         ));
  360.         if ($acl === null)        return false;
  361.         // Since only one acl type can exist
  362.         // we can return the result of the acl_permission
  363.         return $acl->getValue();
  364.         // All hope is lost
  365.         return false;
  366.     }
  367. }