src/Security/SocietyGroupCommandVoter.php line 21

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/SocietyGroupCommandVoter.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\SocietyGroup\SocietyGroupCommand;
  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 SocietyGroupCommandVoter extends Voter
  19. {
  20.     //--------------------------------------------------------------------------------
  21.     // is_granted constants
  22.     const ADD "add_society_group_command";
  23.     const VIEW "view_society_group_command";
  24.     const VIEW_PDF "view_pdf_society_group_command";
  25.     const EDIT "edit_society_group_command";
  26.     const EDIT_RECEIVER_SOCIETY "edit_society_group_command_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 SocietyGroupCommands, there is no need to even show the tab
  31.     const LIST = "list_society_group_commands";
  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_command_view";
  43.     const ACL_PERM_VIEW_PDF "society_group_command_view_pdf";
  44.     const ACL_PERM_EDIT "society_group_command_edit";
  45.     const ACL_PERM_LIST "society_group_command_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 SocietyGroupCommand || $subject instanceof SocietyGroupInvoice))
  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->command null;
  90.         $this->emitter null;
  91.         $this->receiver null;
  92.         if ($subject instanceof SocietyGroupCommand)
  93.         {
  94.             $this->command $subject;
  95.             $this->emitter $subject->getEmitter();
  96.             $this->receiver $subject->getReceiver();
  97.             if ($this->emitter === null || $this->receiver === null)
  98.             {
  99.                 return false;
  100.             }
  101.         }
  102.         switch ($attribute)
  103.         {
  104.             // canAdd : subject is SocietyGroupInvoice
  105.             case self::ADD:
  106.                 return $this->canAdd($subject);
  107.             case self::LIST:
  108.                 return $this->canList($user$function);
  109.             // for all those below : subject is SocietyGroupCommand
  110.             case self::VIEW:
  111.                 return $this->canView($subject$user$function);
  112.             case self::VIEW_PDF:
  113.                 return $this->canViewPdf($subject$user$function);
  114.             case self::EDIT:
  115.                 return $this->canEdit($subject$user$function);
  116.             case self::EDIT_RECEIVER_SOCIETY:
  117.                 return $this->canEditReceiverSociety($subject$user$function);
  118.         }
  119.         throw new \LogicException('This code should not be reached!');
  120.     }
  121.     private function canAdd(SocietyGroupInvoice $invoice)
  122.     {
  123.         // Only JCAF SocietyGroup can add a SocietyGroupCommand for now
  124.         if ($this->currentGroup->isNotJcaf())
  125.         {
  126.             return false;
  127.         }
  128.         // Plan.io Task #3229 Commissions
  129.         $mission $invoice->getMission();
  130.         if ($mission === null)
  131.         {
  132.             return false;
  133.         }
  134.         // Deny actions on archivedRefused objects
  135.         if ($mission->isArchivedRefused())
  136.         {
  137.             return false;
  138.         }
  139.         // Only for JCAF Devis with commission
  140.         // Plan.io Task #3229 Commissions
  141.         // Restrictions on Devis
  142.         $devis $invoice->getDevis();
  143.         if ($devis !== null)
  144.         {
  145.             if ($devis->isNotJcaf())
  146.             {
  147.                 return false;
  148.             }
  149.             if (empty($devis->getShareCommission()))
  150.             {
  151.                 return false;
  152.             }
  153.             // Deny for annulled and refused
  154.             if ($devis->isAnnulled() || $devis->isRefused())
  155.             {
  156.                 return false;
  157.             }
  158.         }
  159.         // Do we already have a SocietyGroupCommand for this SocietyGroupInvoice ?
  160.         $command $this->em->getRepository(SocietyGroupCommand::class)
  161.             ->findOneByInvoice($invoice);
  162.         if ($command !== 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_command
  196.         //             WHERE society_group_command.emitter_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_command tab if at least one command is available
  207.         // Test emitter
  208.         $command $this->em->getRepository(SocietyGroupCommand::class)
  209.             ->findOneByEmitter($this->currentGroup);
  210.         if ($command === null)
  211.         {
  212.             // None available, die hard
  213.             return false;
  214.         }
  215.         // If we are here it means that we have at least one command to show
  216.         // Test permissions
  217.         // Get Acl_Permission
  218.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST);
  219.         if ($aclPerm === null)        return false;
  220.         // Get Acl
  221.         $acl $this->aclRepository->findOneBy(array(
  222.             'function'        =>    $function,
  223.             'permission'    =>    $aclPerm
  224.         ));
  225.         if ($acl === null)        return false;
  226.         // Since only one acl type can exist
  227.         // we can return the result of the acl_permission
  228.         return $acl->getValue();
  229.         // All hope is lost
  230.         return false;
  231.     }
  232.     private function canView(SocietyGroupCommand $commandAccess $userAccessFunction $function)
  233.     {
  234.         // Both emitter and receiver can view society group commands
  235.         if (!($this->currentGroup->equals($this->emitter) || $this->currentGroup->equals($this->receiver)))
  236.         {
  237.             return false;
  238.         }
  239.         // Get Acl_Permission
  240.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW);
  241.         if ($aclPerm === null)        return false;
  242.         // Get Acl
  243.         $acl $this->aclRepository->findOneBy(array(
  244.             'function'        =>    $function,
  245.             'permission'    =>    $aclPerm
  246.         ));
  247.         if ($acl === null)        return false;
  248.         // Since only one acl type can exist
  249.         // we can return the result of the acl_permission
  250.         return $acl->getValue();
  251.         // All hope is lost
  252.         return false;
  253.     }
  254.     private function canViewPdf(SocietyGroupCommand $commandAccess $userAccessFunction $function)
  255.     {
  256.         // Both emitter and receiver can view society group commands
  257.         if (!($this->currentGroup->equals($this->emitter) || $this->currentGroup->equals($this->receiver)))
  258.         {
  259.             return false;
  260.         }
  261.         // Get Acl_Permission
  262.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW);
  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.         // All hope is lost
  274.         return false;
  275.     }
  276.     private function canEdit(SocietyGroupCommand $commandAccess $userAccessFunction $function)
  277.     {
  278.         // Only JCAF for now
  279.         if ($this->currentGroup->isNotJcaf())
  280.         {
  281.             return false;
  282.         }
  283.         $mission $command->getMission();
  284.         if ($mission === null)
  285.         {
  286.             return false;
  287.         }
  288.         // Deny edit on archivedRefused objects
  289.         if ($mission->isArchivedRefused())
  290.         {
  291.             return false;
  292.         }
  293.         // Get Acl_Permission
  294.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  295.         if ($aclPerm === null)        return false;
  296.         // Get Acl
  297.         $acl $this->aclRepository->findOneBy(array(
  298.             'function'        =>    $function,
  299.             'permission'    =>    $aclPerm
  300.         ));
  301.         if ($acl === null)        return false;
  302.         // Since only one acl type can exist
  303.         // we can return the result of the acl_permission
  304.         return $acl->getValue();
  305.         // All hope is lost
  306.         return false;
  307.     }
  308.     private function canEditReceiverSociety(SocietyGroupCommand $commandAccess $userAccessFunction $function)
  309.     {
  310.         // For now receiver can only be JCAF
  311.         // So no need to actually edit the receiver ;)
  312.         return true;
  313.     }
  314. }