src/Security/EquipmentVoter.php line 80

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/EquipmentVoter.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\Equipment\Equipment;
  13. use App\Entity\Equipment\Note;
  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 EquipmentVoter extends Voter
  19. {
  20.     //--------------------------------------------------------------------------------
  21.     // is_granted constants
  22.     const IS_ACTIVE "equipment_is_active";
  23.     const ADD "add_equipment";
  24.     const LISTING "list_equipments";
  25.     const LISTING_SOCIETY "list_equipments_society";
  26.     const LISTING_ANY "list_equipments_any";
  27.     const VIEW "view_equipment";
  28.     const EDIT "edit_equipment";
  29.     const DELETE "delete_equipment";
  30.     const ADD_NOTE "add_equipment_note";
  31.     const EDIT_NOTE "edit_equipment_note";
  32.     const DELETE_NOTE "delete_equipment_note";
  33.     const IS_GRANTED_CONSTANTS = array(
  34.         self::IS_ACTIVE,
  35.         self::ADD,
  36.         self::LISTING,
  37.         self::LISTING_SOCIETY,
  38.         self::LISTING_ANY,
  39.         self::VIEW,
  40.         self::EDIT,
  41.         self::DELETE,
  42.         self::ADD_NOTE,
  43.         self::EDIT_NOTE,
  44.         self::DELETE_NOTE,
  45.     );
  46.     //--------------------------------------------------------------------------------
  47.     // acl constants
  48.     const ACL_PERM_ADD "equipment_add";
  49.     const ACL_PERM_LISTING "equipment_list";
  50.     const ACL_PERM_LISTING_SOCIETY "equipment_list_society";
  51.     const ACL_PERM_VIEW "equipment_view";
  52.     const ACL_PERM_VIEW_SOCIETY "equipment_view_society";
  53.     const ACL_PERM_EDIT "equipment_edit";
  54.     const ACL_PERM_EDIT_SOCIETY "equipment_edit_society";
  55.     const ACL_PERM_DELETE "equipment_delete";
  56.     const ACL_PERM_DELETE_SOCIETY "equipment_delete_society";
  57.     const ACL_PERM_ADD_NOTE "equipment_add_note";
  58.     const ACL_PERM_ADD_NOTE_SOCIETY "equipment_add_note_society";
  59.     const ACL_PERM_EDIT_NOTE "equipment_edit_note";
  60.     const ACL_PERM_EDIT_NOTE_SOCIETY "equipment_edit_note_society";
  61.     const ACL_PERM_DELETE_NOTE "equipment_delete_note";
  62.     const ACL_PERM_DELETE_NOTE_SOCIETY "equipment_delete_note_society";
  63.     //--------------------------------------------------------------------------------
  64.     public function __construct(ManagerRegistry $doctrineModuleTools $moduleTools)
  65.     {
  66.         $this->em $doctrine->getManager();
  67.         $this->moduleTools $moduleTools;
  68.         $this->aclRepository $this->em->getRepository(Acl::class);
  69.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  70.     }
  71.     // Plan.io Task #4453 [See AccessVoter for details]
  72.     public function supportsAttribute(string $attribute): bool
  73.     {
  74.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  75.     }
  76.     
  77.     protected function supports(string $attribute$subject): bool
  78.     {
  79.         // if the attribute isn't one we support, return false
  80.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  81.         {
  82.             return false;
  83.         }
  84.         // only vote on Equipment objects inside this voter
  85.         if ($subject !== null && !($subject instanceof Equipment or $subject instanceof Note))
  86.         {
  87.             return false;
  88.         }
  89.         return true;
  90.     }
  91.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  92.     {
  93.         $user $token->getUser();
  94.         if (!$user instanceof Access)
  95.         {
  96.             // the user must be logged in; if not, deny access
  97.             return false;
  98.         }
  99.         // The user must have a function; if not deny access
  100.         $function $user->getFunction();
  101.         if ($function === null)        return false;
  102.         // Plan.io Task #3710 : Get current group
  103.         $currentGroup $user->getSocietyGroup();
  104.         if ($currentGroup === null)
  105.             return false;
  106.         // Module activated ?
  107.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_EQUIPMENT))
  108.         {
  109.             return false;
  110.         }
  111.         // Check current group affectation
  112.         if ($subject !== null)
  113.         {
  114.             $subjectSociety $subject->getSociety();
  115.             if ($subjectSociety === null)
  116.                 return false;
  117.             $subjectGroup $subjectSociety->getGroup();
  118.             if ($subjectGroup === null)
  119.                 return false;
  120.             if (!$currentGroup->equals($subjectGroup))
  121.                 return false;
  122.         }
  123.         // you know $subject is a Equipment / Note object, thanks to supports
  124.         $note null;
  125.         $equipment null;
  126.         if ($subject instanceof Equipment)
  127.         {
  128.             $equipment $subject;
  129.         }
  130.         else
  131.         {
  132.             if ($subject instanceof Note)
  133.             {
  134.                 $note $subject;
  135.             }
  136.         }
  137.         switch ($attribute)
  138.         {
  139.             // Check is done before, in the voteOnAttribute
  140.             case self::IS_ACTIVE:
  141.                 return true;
  142.             case self::ADD:
  143.                 return $this->canAdd($user$function);
  144.             case self::LISTING:
  145.                 return $this->canList($user$function);
  146.             case self::LISTING_SOCIETY:
  147.                 return $this->canListSociety($user$function);
  148.             case self::LISTING_ANY:
  149.                 return $this->canListAny($user$function);
  150.             case self::VIEW:
  151.                 return $this->canView($equipment$user$function);
  152.             case self::EDIT:
  153.                 return $this->canEdit($equipment$user$function);
  154.             case self::DELETE:
  155.                 return $this->canDelete($equipment$user$function);
  156.             case self::ADD_NOTE:
  157.                 return $this->canAddNote($equipment$user$function);
  158.             case self::EDIT_NOTE:
  159.                 return $this->canEditNote($note$user$function);
  160.             case self::DELETE_NOTE:
  161.                 return $this->canDeleteNote($note$user$function);
  162.         }
  163.         throw new \LogicException('This code should not be reached!');
  164.     }
  165.     // $access is the user trying to load the resource
  166.     // $object is the resource being loaded
  167.     // Check if the Society of the resource
  168.     // belongs to the societies of the $access
  169.     private function checkSociety($objectAccess $access)
  170.     {
  171.         // Get all the societies of the access
  172.         $societies $access->getSocieties();
  173.         // Get the Society of the Equipment
  174.         $objectSociety $object->getSociety();
  175.         if ($objectSociety === null)
  176.             return false;
  177.         $found false;
  178.         foreach ($societies as $society)
  179.         {
  180.             if ($society->getId() == $objectSociety->getId())
  181.             {
  182.                 $found true;
  183.                 break;
  184.             }
  185.         }
  186.         return $found;
  187.     }
  188.     private function canAdd(Access $userAccessFunction $function)
  189.     {
  190.         // Get Acl_Permission
  191.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD);
  192.         if ($aclPerm === null)        return false;
  193.         // Get Acl
  194.         $acl $this->aclRepository->findOneBy(array(
  195.             'function'        =>    $function,
  196.             'permission'    =>    $aclPerm
  197.         ));
  198.         if ($acl === null)        return false;
  199.         // Since only one acl type can exist
  200.         // we can return the result of the acl_permission
  201.         return $acl->getValue();
  202.     }
  203.     private function canList(Access $userAccessFunction $function)
  204.     {
  205.         // Get Acl_Permission
  206.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING);
  207.         if ($aclPerm === null)        return false;
  208.         // Get Acl
  209.         $acl $this->aclRepository->findOneBy(array(
  210.             'function'        =>    $function,
  211.             'permission'    =>    $aclPerm
  212.         ));
  213.         if ($acl === null)        return false;
  214.         // Since only one acl type can exist
  215.         // we can return the result of the acl_permission
  216.         return $acl->getValue();
  217.     }
  218.     private function canListSociety(Access $userAccessFunction $function)
  219.     {
  220.         // Get Acl_Permission
  221.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_SOCIETY);
  222.         if ($aclPerm === null)        return false;
  223.         // Get Acl
  224.         $acl $this->aclRepository->findOneBy(array(
  225.             'function'        =>    $function,
  226.             'permission'    =>    $aclPerm
  227.         ));
  228.         if ($acl === null)        return false;
  229.         // Since only one acl type can exist
  230.         // we can return the result of the acl_permission
  231.         // Further filtering is done in the Controller
  232.         return $acl->getValue();
  233.     }
  234.     private function canListAny(Access $userAccessFunction $function)
  235.     {
  236.         // Two Acl_Permission may exist
  237.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING);
  238.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LISTING_SOCIETY);
  239.         // If all are null, exit
  240.         if ($aclPerm === null && $aclPermSociety === null)
  241.             return false;
  242.         // Get First one
  243.         if ($aclPerm !== null)
  244.         {
  245.             $acl $this->aclRepository->findOneBy(array(
  246.                 'function'        =>    $function,
  247.                 'permission'    =>    $aclPerm
  248.             ));
  249.             if ($acl !== null)
  250.             {
  251.                 if ($acl->getValue())
  252.                 {
  253.                     // A single positive answer is enough
  254.                     return true;
  255.                 }
  256.             }
  257.         }
  258.         // If we are here it means that nothing good has been found
  259.         // Load second permission
  260.         if ($aclPermSociety !== null)
  261.         {
  262.             $acl $this->aclRepository->findOneBy(array(
  263.                 'function'        =>    $function,
  264.                 'permission'    =>    $aclPermSociety
  265.             ));
  266.             if ($acl !== null)
  267.             {
  268.                 if ($acl->getValue())
  269.                 {
  270.                     // A single positive answer is enough
  271.                     return true;
  272.                 }
  273.             }
  274.         }
  275.         // If we are here, all hope is lost
  276.         return false;
  277.     }
  278.     private function canView(Equipment $equipmentAccess $userAccessFunction $function)
  279.     {
  280.         // Get Acl_Permissions
  281.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW);
  282.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_SOCIETY);
  283.         // If all are null, exit
  284.         if ($aclPerm === null && $aclPermSociety === null)
  285.             return false;
  286.         // Get First one
  287.         if ($aclPerm !== null)
  288.         {
  289.             $acl $this->aclRepository->findOneBy(array(
  290.                 'function'        =>    $function,
  291.                 'permission'    =>    $aclPerm
  292.             ));
  293.             if ($acl !== null)
  294.             {
  295.                 if ($acl->getValue())
  296.                 {
  297.                     // A single positive answer is enough
  298.                     return true;
  299.                 }
  300.             }
  301.         }
  302.         // If we are here it means that nothing good has been found
  303.         // Load second permission
  304.         if ($aclPermSociety !== null)
  305.         {
  306.             $acl $this->aclRepository->findOneBy(array(
  307.                 'function'        =>    $function,
  308.                 'permission'    =>    $aclPermSociety
  309.             ));
  310.             if ($acl !== null)
  311.             {
  312.                 if ($acl->getValue())
  313.                 {
  314.                     // A single positive answer is enough
  315.                     // In this case the good answer will be provided by the checkSociety
  316.                     return $this->checkSociety($equipment$user);
  317.                 }
  318.             }
  319.         }
  320.         // If we are here, all hope is lost
  321.         return false;
  322.     }
  323.     private function canEdit(Equipment $equipmentAccess $userAccessFunction $function)
  324.     {
  325.         // Three Acl_Permission may exist
  326.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  327.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_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.                     // In this case the good answer will be provided by the checkSociety
  361.                     return $this->checkSociety($equipment$user);
  362.                 }
  363.             }
  364.         }
  365.         // If we are here, all hope is lost
  366.         return false;
  367.     }
  368.     private function canDelete(Equipment $equipmentAccess $userAccessFunction $function)
  369.     {
  370.         // Three Acl_Permission may exist
  371.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DELETE);
  372.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DELETE_SOCIETY);
  373.         // If all are null, exit
  374.         if ($aclPerm === null && $aclPermSociety === null)
  375.             return false;
  376.         // Get First one
  377.         if ($aclPerm !== null)
  378.         {
  379.             $acl $this->aclRepository->findOneBy(array(
  380.                 'function'        =>    $function,
  381.                 'permission'    =>    $aclPerm
  382.             ));
  383.             if ($acl !== null)
  384.             {
  385.                 if ($acl->getValue())
  386.                 {
  387.                     // A single positive answer is enough
  388.                     return true;
  389.                 }
  390.             }
  391.         }
  392.         // If we are here it means that nothing good has been found
  393.         // Load second permission
  394.         if ($aclPermSociety !== null)
  395.         {
  396.             $acl $this->aclRepository->findOneBy(array(
  397.                 'function'        =>    $function,
  398.                 'permission'    =>    $aclPermSociety
  399.             ));
  400.             if ($acl !== null)
  401.             {
  402.                 if ($acl->getValue())
  403.                 {
  404.                     // A single positive answer is enough
  405.                     // In this case the good answer will be provided by the checkSociety
  406.                     return $this->checkSociety($equipment$user);
  407.                 }
  408.             }
  409.         }
  410.         // If we are here, all hope is lost
  411.         return false;
  412.     }
  413.     private function canAddNote(Equipment $equipmentAccess $userAccessFunction $function)
  414.     {
  415.         // Three Acl_Permission may exist
  416.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD_NOTE);
  417.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD_NOTE_SOCIETY);
  418.         // If all are null, exit
  419.         if ($aclPerm === null && $aclPermSociety === null)
  420.             return false;
  421.         // Get First one
  422.         if ($aclPerm !== null)
  423.         {
  424.             $acl $this->aclRepository->findOneBy(array(
  425.                 'function'        =>    $function,
  426.                 'permission'    =>    $aclPerm
  427.             ));
  428.             if ($acl !== null)
  429.             {
  430.                 if ($acl->getValue())
  431.                 {
  432.                     // A single positive answer is enough
  433.                     return true;
  434.                 }
  435.             }
  436.         }
  437.         // If we are here it means that nothing good has been found
  438.         // Load second permission
  439.         if ($aclPermSociety !== null)
  440.         {
  441.             $acl $this->aclRepository->findOneBy(array(
  442.                 'function'        =>    $function,
  443.                 'permission'    =>    $aclPermSociety
  444.             ));
  445.             if ($acl !== null)
  446.             {
  447.                 if ($acl->getValue())
  448.                 {
  449.                     // A single positive answer is enough
  450.                     // In this case the good answer will be provided by the checkSociety
  451.                     return $this->checkSociety($equipment$user);
  452.                 }
  453.             }
  454.         }
  455.         // If we are here, all hope is lost
  456.         return false;
  457.     }
  458.     private function canEditNote(Note $noteAccess $userAccessFunction $function)
  459.     {
  460.         // Allow editing own notes
  461.         if ($user->equals($note->getAuthor()))
  462.         {
  463.             return true;
  464.         }
  465.         // Three Acl_Permission may exist
  466.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_NOTE);
  467.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_NOTE_SOCIETY);
  468.         // If all are null, exit
  469.         if ($aclPerm === null && $aclPermSociety === null)
  470.             return false;
  471.         // Get First one
  472.         if ($aclPerm !== null)
  473.         {
  474.             $acl $this->aclRepository->findOneBy(array(
  475.                 'function'        =>    $function,
  476.                 'permission'    =>    $aclPerm
  477.             ));
  478.             if ($acl !== null)
  479.             {
  480.                 if ($acl->getValue())
  481.                 {
  482.                     // A single positive answer is enough
  483.                     return true;
  484.                 }
  485.             }
  486.         }
  487.         // If we are here it means that nothing good has been found
  488.         // Load second permission
  489.         if ($aclPermSociety !== null)
  490.         {
  491.             $acl $this->aclRepository->findOneBy(array(
  492.                 'function'        =>    $function,
  493.                 'permission'    =>    $aclPermSociety
  494.             ));
  495.             if ($acl !== null)
  496.             {
  497.                 if ($acl->getValue())
  498.                 {
  499.                     // A single positive answer is enough
  500.                     // In this case the good answer will be provided by the checkSociety
  501.                     return $this->checkSociety($note$user);
  502.                 }
  503.             }
  504.         }
  505.         // If we are here, all hope is lost
  506.         return false;
  507.     }
  508.     private function canDeleteNote(Note $noteAccess $userAccessFunction $function)
  509.     {
  510.         // Allow deleting own notes
  511.         if ($user->equals($note->getAuthor()))
  512.         {
  513.             return true;
  514.         }
  515.         // Three Acl_Permission may exist
  516.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DELETE_NOTE);
  517.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DELETE_NOTE_SOCIETY);
  518.         // If all are null, exit
  519.         if ($aclPerm === null && $aclPermSociety === null)
  520.             return false;
  521.         // Get First one
  522.         if ($aclPerm !== null)
  523.         {
  524.             $acl $this->aclRepository->findOneBy(array(
  525.                 'function'        =>    $function,
  526.                 'permission'    =>    $aclPerm
  527.             ));
  528.             if ($acl !== null)
  529.             {
  530.                 if ($acl->getValue())
  531.                 {
  532.                     // A single positive answer is enough
  533.                     return true;
  534.                 }
  535.             }
  536.         }
  537.         // If we are here it means that nothing good has been found
  538.         // Load second permission
  539.         if ($aclPermSociety !== null)
  540.         {
  541.             $acl $this->aclRepository->findOneBy(array(
  542.                 'function'        =>    $function,
  543.                 'permission'    =>    $aclPermSociety
  544.             ));
  545.             if ($acl !== null)
  546.             {
  547.                 if ($acl->getValue())
  548.                 {
  549.                     // A single positive answer is enough
  550.                     // In this case the good answer will be provided by the checkSociety
  551.                     return $this->checkSociety($note$user);
  552.                 }
  553.             }
  554.         }
  555.         // If we are here, all hope is lost
  556.         return false;
  557.     }
  558. }