src/Security/MissionVoter.php line 128

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/MissionVoter.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\Client\Client;
  13. use App\Entity\Config\Config;
  14. use App\Entity\Config\Module;
  15. use App\Entity\HR\AccessFunction;
  16. use App\Entity\Mission\Mission;
  17. use App\Entity\Security\Acl;
  18. use App\Entity\Security\AclPermission;
  19. use App\Entity\Webapp\Document;
  20. use App\Services\LogTools;
  21. use App\Services\Config\ModuleTools;
  22. use App\Services\Mission\MissionSecurityTools;
  23. class MissionVoter extends Voter
  24. {
  25.     //--------------------------------------------------------------------------------
  26.     // is_granted constants
  27.     const IS_ACTIVE "mission_is_active";
  28.     const IS_ACTIVE_SHARING "mission_sharing_is_active";
  29.     const ADD "add_mission";
  30.     const ADD_OR_CONVERT "add_mission_or_convert_devis_simulation";
  31.     const LISTING "list_missions";
  32.     const LISTING_SOCIETY "list_missions_society";
  33.     const LISTING_AUTHOR "list_missions_author";
  34.     const LISTING_ANY "list_missions_any";
  35.     const VIEW "view_mission";
  36.     const EDIT "edit_mission";
  37.     const EDIT_SOCIETY "edit_mission_society";
  38.     const EDIT_MANAGER "edit_mission_manager";
  39.     const SHARE "share_mission";
  40.     // Plan.io Task #3304
  41.     const PAY_OWNER "pay_mission_owner";
  42.     // Plan.io Task #4071
  43.     const ADD_CHILD "add_mission_child";
  44.     // Plan.Io Task #4247
  45.     const MERGE "merge_mission";
  46.     const MERGE_TOOL "merge_tool_mission";
  47.     const IS_GRANTED_CONSTANTS = array(
  48.         self::IS_ACTIVE,
  49.         self::IS_ACTIVE_SHARING,
  50.         self::ADD,
  51.         self::ADD_OR_CONVERT,
  52.         self::LISTING,
  53.         self::LISTING_SOCIETY,
  54.         self::LISTING_AUTHOR,
  55.         self::LISTING_ANY,
  56.         self::VIEW,
  57.         self::EDIT,
  58.         self::EDIT_SOCIETY,
  59.         self::EDIT_MANAGER,
  60.         self::SHARE,
  61.         self::PAY_OWNER,
  62.         self::ADD_CHILD,
  63.         self::MERGE,
  64.         self::MERGE_TOOL,
  65.     );
  66.     //--------------------------------------------------------------------------------
  67.     // acl constants
  68.     const ACL_PERM_ADD 'mission_add';
  69.     const ACL_PERM_LIST 'mission_list';
  70.     const ACL_PERM_LIST_SOCIETY 'mission_list_society';
  71.     const ACL_PERM_LIST_AUTHOR 'mission_list_author';
  72.     const ACL_PERM_VIEW 'mission_view';
  73.     const ACL_PERM_VIEW_SOCIETY 'mission_view_society';
  74.     const ACL_PERM_VIEW_AUTHOR 'mission_view_author';
  75.     const ACL_PERM_VIEW_TASK 'mission_view_task';
  76.     const ACL_PERM_EDIT 'mission_edit';
  77.     const ACL_PERM_EDIT_SOCIETY 'mission_edit_society';
  78.     const ACL_PERM_EDIT_AUTHOR 'mission_edit_author';
  79.     const ACL_PERM_EDIT_TASK 'mission_edit_task';
  80.     const ACL_PERM_SOCIETY_EDIT 'mission_society_edit';
  81.     const ACL_PERM_SOCIETY_EDIT_SOCIETY 'mission_society_edit_society';
  82.     const ACL_PERM_SOCIETY_EDIT_AUTHOR 'mission_society_edit_author';
  83.     const ACL_PERM_SHARE 'mission_share';
  84.     const ACL_PERM_SHARE_SOCIETY 'mission_share_society';
  85.     const ACL_PERM_SHARE_AUTHOR 'mission_share_author';
  86.     const ACL_PERM_MANAGER_EDIT 'mission_edit_manager';
  87.     const ACL_PERM_MANAGER_EDIT_SOCIETY 'mission_edit_manager_society';
  88.     const ACL_PERM_MANAGER_EDIT_AUTHOR 'mission_edit_manager_author';
  89.     // Plan.io Task #4247
  90.     const ACL_PERM_MERGE "mission_merge";
  91.     const ACL_PERM_MERGE_SOCIETY "mission_merge_society";
  92.     //--------------------------------------------------------------------------------
  93.     public function __construct(AccessDecisionManagerInterface $accessDecisionManagerManagerRegistry $doctrineModuleTools $moduleToolsLogTools $logToolsMissionSecurityTools $missionSecurityTools)
  94.     {
  95.         $this->accessDecisionManager $accessDecisionManager;
  96.         $this->em $doctrine->getManager();
  97.         $this->moduleTools $moduleTools;
  98.         $this->logTools $logTools;
  99.         $this->missionSecurityTools $missionSecurityTools;
  100.         $this->aclRepository $this->em->getRepository(Acl::class);
  101.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  102.     }
  103.     // Plan.io Task #4453 [See AccessVoter for details]
  104.     public function supportsAttribute(string $attribute): bool
  105.     {
  106.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  107.     }
  108.     protected function supports(string $attribute$subject): bool
  109.     {
  110.         // $this->logTools->ploopLog("[MissionVoter][supports] attribute = $attribute");
  111.         // if the attribute isn't one we support, return false
  112.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  113.         {
  114.             return false;
  115.         }
  116.         // Only vote on Mission and Client objects inside this voter
  117.         if ($subject !== null && !($subject instanceof Mission || $subject instanceof Client))
  118.         {
  119.             return false;
  120.         }
  121.         return true;
  122.     }
  123.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  124.     {
  125.         $user $token->getUser();
  126.         // Plan.io Task #3707
  127.         if ($user instanceof AccessAPI)
  128.         {
  129.             if ($user->getAccess() === null)
  130.             {
  131.                 return false;
  132.             }
  133.             $user $user->getAccess();
  134.         }
  135.         // Plan.io Task #3707
  136.         // At this point $user is an object of Access type
  137.         // even if the $token->getUser() is AccessAPI
  138.         if (!$user instanceof Access)
  139.         {
  140.             // the user must be logged in; if not, deny access
  141.             return false;
  142.         }
  143.         // The user must have a function; if not deny access
  144.         $function $user->getFunction();
  145.         if ($function === null)
  146.         {
  147.             return false;
  148.         }
  149.         // Plan.io Task #3710 : Get current group
  150.         $currentGroup $user->getSocietyGroup();
  151.         if ($currentGroup === null)
  152.             return false;
  153.         $this->currentGroup $currentGroup;
  154.         // Module activated ?
  155.         if (
  156.             $this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_MISSION) &&
  157.             $this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_MISSION_LIGHT) &&
  158.             $this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_MISSION_PLUS)
  159.             )
  160.         {
  161.             return false;
  162.         }
  163.         // This one also needs clients or clients light
  164.         if (
  165.             $this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_CLIENT) &&
  166.             $this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_CLIENT_LIGHT)
  167.             )
  168.         {
  169.             return false;
  170.         }
  171.         $client null;
  172.         $mission null;
  173.         if ($subject instanceof Mission)
  174.         {
  175.             // you know $subject is a Mission object, thanks to supports
  176.             /** @var Mission $mission */
  177.             $mission $subject;
  178.             // Check current group affectation
  179.             // This also includes mission sharing
  180.             //        mission.society.group = currentGroup
  181.             //        OR
  182.             //        mission.getSocietyGroupOwner = currentGroup
  183.             if ($mission !== null)
  184.             {
  185.                 $missionSociety $mission->getSociety();
  186.                 if ($missionSociety === null)
  187.                 {
  188.                     return false;
  189.                 }
  190.                 $missionSocietyGroup $missionSociety->getGroup();
  191.                 if ($missionSocietyGroup === null)
  192.                 {
  193.                     return false;
  194.                 }
  195.                 $missionSocietyGroupOwner $mission->getSocietyGroupOwner();
  196.                 if ($missionSocietyGroupOwner === null)
  197.                 {
  198.                     return false;
  199.                 }
  200.                 // Checking ...
  201.                 if (!$currentGroup->equals($missionSocietyGroup) && !$currentGroup->equals($missionSocietyGroupOwner))
  202.                 {
  203.                     return false;
  204.                 }
  205.                 // Special case of archived missions
  206.                 // This should only be visible by owner, since the owner is the one who archived them
  207.                 if ($mission->isArchivedRefused())
  208.                 {
  209.                     if (!$currentGroup->equals($missionSocietyGroupOwner))
  210.                     {
  211.                         return false;
  212.                     }
  213.                 }
  214.             }
  215.         }
  216.         else
  217.         {
  218.             if ($subject instanceof Client)
  219.             {
  220.                 /** @var Client $client */
  221.                 $client $subject;
  222.             }
  223.         }
  224.         switch ($attribute)
  225.         {
  226.             case self::IS_ACTIVE:
  227.             {
  228.                 return true;
  229.             }
  230.             case self::IS_ACTIVE_SHARING:
  231.             {
  232.                 if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_MISSION_PLUS))
  233.                 {
  234.                     return false;
  235.                 }
  236.                 return true;
  237.             }
  238.             // We can create a mission without a client
  239.             // (the client can be created at the same time as the mission)
  240.             // So the client parameter is optional
  241.             case self::ADD:
  242.                 return $this->canAdd($user$function$client);
  243.             case self::ADD_OR_CONVERT:
  244.                 return $this->canAddOrConvert($user$function$token$client);
  245.             case self::ADD_CHILD:
  246.             {
  247.                 if ($mission === null) return false;
  248.                 return $this->canAddChild($mission$user$function);
  249.             }
  250.             case self::VIEW:
  251.                 return $this->canView($mission$user$function);
  252.             case self::EDIT:
  253.                 return $this->canEdit($mission$user$function);
  254.             case self::EDIT_SOCIETY:
  255.                 return $this->canEditSociety($mission$user$function);
  256.             case self::EDIT_MANAGER:
  257.                 return $this->canEditManager($mission$user$function);
  258.             case self::SHARE:
  259.                 return $this->canShare($mission$user$function);
  260.             case self::PAY_OWNER:
  261.                 return $this->canPayMissionOwner($mission);
  262.             case self::LISTING:
  263.                 return $this->canList($user$function);
  264.             case self::LISTING_SOCIETY:
  265.                 return $this->canListSociety($user$function);
  266.             case self::LISTING_AUTHOR:
  267.                 return $this->canListAuthor($user$function);
  268.             case self::LISTING_ANY:
  269.                 return $this->canListAny($user$function);
  270.             case self::MERGE:
  271.                 return $this->canMerge($mission$user$function);
  272.             case self::MERGE_TOOL:
  273.                 return $this->canUseMergeTool($user$function);
  274.         }
  275.         throw new \LogicException('This code should not be reached!');
  276.     }
  277.     // $access is the user trying to load the resource
  278.     // $mission is the resource being loaded
  279.     // Check if the Author of the Mission is the Access
  280.     private function checkAuthor(Mission $missionAccess $access)
  281.     {
  282.         // Get the Society of the Mission
  283.         $missionAuthor $mission->getAuthor();
  284.         if ($missionAuthor === null)
  285.             return false;
  286.         if ($access->getId() == $missionAuthor->getId())
  287.             return true;
  288.         return false;
  289.     }
  290.     // Check if the $access is connected to any task of the mission
  291.     private function checkTask(Mission $missionAccess $access)
  292.     {
  293.         if (empty($mission->getTasks()))
  294.             return false;
  295.         foreach ($mission->getTasks() as $task)
  296.         {
  297.             foreach ($task->getPlanningResources() as $resource)
  298.             {
  299.                 if ($resource->getAccess() !== null)
  300.                 {
  301.                     if ($access->equals($resource->getAccess()))
  302.                     {
  303.                         return true;
  304.                     }
  305.                 }
  306.             }
  307.         }
  308.         return false;
  309.     }
  310.     // Check if the Society of the Mission
  311.     // belongs to the societies of the $access
  312.     private function checkSociety(Mission $missionAccess $access)
  313.     {
  314.         // Get all the societies of the access
  315.         $societies $access->getSocieties();
  316.         // Get the Society of the Mission
  317.         // If the mission was created by the currentGroup, get the mission.society
  318.         // If the mission was shared with the currentGroup, get the mission.societyOwner
  319.         $missionSociety $mission->getSociety();
  320.         if ($missionSociety === null)
  321.             return false;
  322.         $found false;
  323.         foreach ($societies as $society)
  324.         {
  325.             if ($society->getId() == $missionSociety->getId())
  326.             {
  327.                 $found true;
  328.                 break;
  329.             }
  330.         }
  331.         return $found;
  332.     }
  333.     // Check if the Society of the Mission
  334.     // belongs to the societies of the $access
  335.     private function checkSocietyOwner(Mission $missionAccess $access)
  336.     {
  337.         // Get all the societies of the access
  338.         $societies $access->getSocieties();
  339.         // Get the Society of the Mission
  340.         // If the mission was created by the currentGroup, get the mission.society
  341.         // If the mission was shared with the currentGroup, get the mission.societyOwner
  342.         $missionSociety $mission->getSocietyOwner();
  343.         if ($missionSociety === null)
  344.             return false;
  345.         $found false;
  346.         foreach ($societies as $society)
  347.         {
  348.             if ($society->getId() == $missionSociety->getId())
  349.             {
  350.                 $found true;
  351.                 break;
  352.             }
  353.         }
  354.         return $found;
  355.     }
  356.     private function canAdd(Access $userAccessFunction $function$client null)
  357.     {
  358.         // We can create a mission without a client
  359.         // (the client can be created at the same time as the mission)
  360.         // So the client parameter is optional
  361.         if ($client !== null)
  362.         {
  363.             // Individuals only for now
  364.             $individual $client->getIndividual();
  365.             if ($individual !== null)
  366.             {
  367.                 // Only allow creating missions for the individuals who belong tp the current group
  368.                 if (!$individual->getSocietyGroup()->equals($this->currentGroup))
  369.                 {
  370.                     return false;
  371.                 }
  372.             }
  373.             else
  374.             {
  375.                 // Plan.io Task #3582 : No Stores as Receivers for now
  376.                 return false;
  377.             }
  378.         }
  379.         // Module activated ?
  380.         // MISSION_LIGHT cannot add Missions
  381.         if ($this->moduleTools->isInactiveByCode($this->currentGroupModule::MODULE_MISSION) && $this->moduleTools->isInactiveByCode($this->currentGroupModule::MODULE_MISSION_PLUS))
  382.         {
  383.             return false;
  384.         }
  385.         // Get Acl_Permission
  386.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD);
  387.         if ($aclPerm === null)        return false;
  388.         // Get Acl
  389.         $acl $this->aclRepository->findOneBy(array(
  390.             'function'        =>    $function,
  391.             'permission'    =>    $aclPerm
  392.         ));
  393.         if ($acl === null)        return false;
  394.         // Since only one acl type can exist
  395.         // we can return the result of the acl_permission
  396.         return $acl->getValue();
  397.     }
  398.     private function canAddOrConvert(Access $userAccessFunction $function$token$client null)
  399.     {
  400.         if ($this->canAdd($user$function$client))
  401.         {
  402.             return true;
  403.         }
  404.         if ($this->accessDecisionManager->decide($token, ['convert_devis_simulation']))
  405.         {
  406.             return true;
  407.         }
  408.         return false;
  409.     }
  410.     private function canAddChild(Mission $parentAccess $userAccessFunction $function)
  411.     {
  412.         // Check object restrictions because they are simpler
  413.         $reason $parent->whyCannotAddChildren();
  414.         if ($reason 0)
  415.         {
  416.             // $this->logTools->errorLog("[MissionVoter][canAddChild] The reason we cannot add a child for ".$parent->displayForLog()." is ".$reason);
  417.         }
  418.         if (!$parent->canAddChild())
  419.         {
  420.             return false;
  421.         }
  422.         // Decide based on Add permissions
  423.         return $this->canAdd($user$function$parent->getReceiver());
  424.     }
  425.     private function canView(Mission $missionAccess $userAccessFunction $function)
  426.     {
  427.         // Get Acl_Permissions
  428.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW);
  429.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_SOCIETY);
  430.         $aclPermAuthor $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_AUTHOR);
  431.         $aclPermTask $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_TASK);
  432.         // If all are null, exit
  433.         if ($aclPerm === null && $aclPermSociety === null && $aclPermAuthor === null && $aclPermTask === null)
  434.             return false;
  435.         // Get First one
  436.         if ($aclPerm !== null)
  437.         {
  438.             $acl $this->aclRepository->findOneBy(array(
  439.                 'function'        =>    $function,
  440.                 'permission'    =>    $aclPerm
  441.             ));
  442.             if ($acl !== null)
  443.             {
  444.                 if ($acl->getValue())
  445.                 {
  446.                     // A single positive answer is enough
  447.                     return true;
  448.                 }
  449.             }
  450.         }
  451.         // If we are here it means that nothing good has been found
  452.         // Load second permission
  453.         if ($aclPermSociety !== null)
  454.         {
  455.             $acl $this->aclRepository->findOneBy(array(
  456.                 'function'        =>    $function,
  457.                 'permission'    =>    $aclPermSociety
  458.             ));
  459.             if ($acl !== null)
  460.             {
  461.                 if ($acl->getValue())
  462.                 {
  463.                     // Check Society : also check author
  464.                     // Les missions appartenant Ã  ses sociétés (et celles dont il est l'auteur)
  465.                     if ($this->checkAuthor($mission$user))
  466.                     {
  467.                         return true;
  468.                     }
  469.                     // When a mission is shared, the author can still view it
  470.                     if ($this->checkSociety($mission$user) || $this->checkSocietyOwner($mission$user))
  471.                     {
  472.                         return true;
  473.                     }
  474.                 }
  475.             }
  476.         }
  477.         // If we are here it means that nothing good has been found
  478.         // Load third permission
  479.         if ($aclPermAuthor !== null)
  480.         {
  481.             $acl $this->aclRepository->findOneBy(array(
  482.                 'function'        =>    $function,
  483.                 'permission'    =>    $aclPermAuthor
  484.             ));
  485.             if ($acl !== null)
  486.             {
  487.                 if ($acl->getValue())
  488.                 {
  489.                     // A single positive answer is enough
  490.                     // In this case the good answer will be provided by the checkSociety
  491.                     return $this->checkAuthor($mission$user);
  492.                 }
  493.             }
  494.         }
  495.         // If we are here it means that nothing good has been found
  496.         // Load fourth permission
  497.         if ($aclPermTask !== null)
  498.         {
  499.             $acl $this->aclRepository->findOneBy(array(
  500.                 'function'        =>    $function,
  501.                 'permission'    =>    $aclPermTask,
  502.             ));
  503.             if ($acl !== null)
  504.             {
  505.                 if ($acl->getValue())
  506.                 {
  507.                     // A single positive answer is enough
  508.                     // In this case the good answer will be provided by the checkSociety
  509.                     return $this->checkTask($mission$user);
  510.                 }
  511.             }
  512.         }
  513.         // If we are here, all hope is lost
  514.         return false;
  515.     }
  516.     private function canEdit(Mission $missionAccess $userAccessFunction $function)
  517.     {
  518.         // Plan.io Task #4071 : Deny on children
  519.         // Not anymore ;)
  520.         // if ($mission->isChild())
  521.         // {
  522.         //     return false;
  523.         // }
  524.         // Deny edit on archivedRefused objects
  525.         if ($mission->isArchivedRefused())
  526.         {
  527.             return false;
  528.         }
  529.         // Get Acl_Permissions
  530.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  531.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SOCIETY);
  532.         $aclPermAuthor $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_AUTHOR);
  533.         $aclPermTask $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_TASK);
  534.         // If all are null, exit
  535.         if ($aclPerm === null && $aclPermSociety === null && $aclPermAuthor === null && $aclPermTask === null)
  536.             return false;
  537.         // Get First one
  538.         if ($aclPerm !== null)
  539.         {
  540.             $acl $this->aclRepository->findOneBy(array(
  541.                 'function'        =>    $function,
  542.                 'permission'    =>    $aclPerm
  543.             ));
  544.             if ($acl !== null)
  545.             {
  546.                 if ($acl->getValue())
  547.                 {
  548.                     // Both author and owner can edit
  549.                     return true;
  550.                     // // When a mission is shared, the author cannot edit it
  551.                     // if (!$mission->isShared())
  552.                     // {
  553.                     //     // Not shared
  554.                     //     return true;
  555.                     // }
  556.                     // else
  557.                     // {
  558.                     //     // Shared
  559.                     //     // The author cannot edit / The owner can edit
  560.                     //     if ($mission->isSharedWithSocietyGroup($this->currentGroup))
  561.                     //     {
  562.                     //         return true;
  563.                     //     }
  564.                     // }
  565.                 }
  566.             }
  567.         }
  568.         // If we are here it means that nothing good has been found
  569.         // Load second permission
  570.         if ($aclPermSociety !== null)
  571.         {
  572.             $acl $this->aclRepository->findOneBy(array(
  573.                 'function'        =>    $function,
  574.                 'permission'    =>    $aclPermSociety
  575.             ));
  576.             if ($acl !== null)
  577.             {
  578.                 if ($acl->getValue())
  579.                 {
  580.                     // Check Society : also check author
  581.                     // Les missions appartenant Ã  ses sociétés (et celles dont il est l'auteur)
  582.                     if ($this->checkAuthor($mission$user))
  583.                     {
  584.                         return true;
  585.                     }
  586.                     // Both author and owner can edit
  587.                     // However, if the mission is shared,
  588.                     // we are filtering using societyOwner instead of society
  589.                     // Only one of the two conditions below can be true at a time
  590.                     if ($this->checkSociety($mission$user) || $this->checkSocietyOwner($mission$user))
  591.                     {
  592.                         return true;
  593.                     }
  594.                     // // When a mission is shared, the author cannot edit it
  595.                     // if (!$mission->isShared())
  596.                     // {
  597.                     //     // Not shared : check society
  598.                     //     if ($this->checkSociety($mission, $user))
  599.                     //     {
  600.                     //         return true;
  601.                     //     }
  602.                     // }
  603.                     // else
  604.                     // {
  605.                     //     // Shared
  606.                     //     // The author cannot edit / The owner can edit
  607.                     //     if ($mission->isSharedWithSocietyGroup($this->currentGroup))
  608.                     //     {
  609.                     //         if ($this->checkSocietyOwner($mission, $user))
  610.                     //         {
  611.                     //             return true;
  612.                     //         }
  613.                     //     }
  614.                     // }
  615.                 }
  616.             }
  617.         }
  618.         // If we are here it means that nothing good has been found
  619.         // Load third permission
  620.         if ($aclPermAuthor !== null)
  621.         {
  622.             $acl $this->aclRepository->findOneBy(array(
  623.                 'function'        =>    $function,
  624.                 'permission'    =>    $aclPermAuthor
  625.             ));
  626.             if ($acl !== null)
  627.             {
  628.                 if ($acl->getValue())
  629.                 {
  630.                     // A single positive answer is enough
  631.                     // In this case the good answer will be provided by the checkSociety
  632.                     return $this->checkAuthor($mission$user);
  633.                 }
  634.             }
  635.         }
  636.         // If we are here it means that nothing good has been found
  637.         // Load fourth permission
  638.         if ($aclPermTask !== null)
  639.         {
  640.             $acl $this->aclRepository->findOneBy(array(
  641.                 'function'        =>    $function,
  642.                 'permission'    =>    $aclPermTask,
  643.             ));
  644.             if ($acl !== null)
  645.             {
  646.                 if ($acl->getValue())
  647.                 {
  648.                     // A single positive answer is enough
  649.                     // In this case the good answer will be provided by the checkSociety
  650.                     return $this->checkTask($mission$user);
  651.                 }
  652.             }
  653.         }
  654.         // If we are here, all hope is lost
  655.         return false;
  656.     }
  657.     private function canEditSociety(Mission $missionAccess $userAccessFunction $function)
  658.     {
  659.         // Deny edit on archivedRefused objects
  660.         if ($mission->isArchivedRefused())
  661.         {
  662.             return false;
  663.         }
  664.         // Get Acl_Permissions
  665.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_SOCIETY_EDIT);
  666.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_SOCIETY_EDIT_SOCIETY);
  667.         $aclPermAuthor $this->aclPermissionRepository->findOneByName(self::ACL_PERM_SOCIETY_EDIT_AUTHOR);
  668.         // If all are null, exit
  669.         if ($aclPerm === null && $aclPermSociety === null && $aclPermAuthor === null)
  670.             return false;
  671.         // Get First one
  672.         if ($aclPerm !== null)
  673.         {
  674.             $acl $this->aclRepository->findOneBy(array(
  675.                 'function'        =>    $function,
  676.                 'permission'    =>    $aclPerm
  677.             ));
  678.             if ($acl !== null)
  679.             {
  680.                 if ($acl->getValue())
  681.                 {
  682.                     // Both author and owner can edit
  683.                     return true;
  684.                 }
  685.             }
  686.         }
  687.         // If we are here it means that nothing good has been found
  688.         // Load second permission
  689.         if ($aclPermSociety !== null)
  690.         {
  691.             $acl $this->aclRepository->findOneBy(array(
  692.                 'function'        =>    $function,
  693.                 'permission'    =>    $aclPermSociety
  694.             ));
  695.             if ($acl !== null)
  696.             {
  697.                 if ($acl->getValue())
  698.                 {
  699.                     // Check Society : also check author
  700.                     // Les missions appartenant Ã  ses sociétés (et celles dont il est l'auteur)
  701.                     if ($this->checkAuthor($mission$user))
  702.                     {
  703.                         return true;
  704.                     }
  705.                     // Both author and owner can edit
  706.                     // However, if the mission is shared,
  707.                     // we are filtering using societyOwner instead of society
  708.                     // Only one of the two conditions below can be true at a time
  709.                     if ($this->checkSociety($mission$user) || $this->checkSocietyOwner($mission$user))
  710.                     {
  711.                         return true;
  712.                     }
  713.                 }
  714.             }
  715.         }
  716.         // If we are here it means that nothing good has been found
  717.         // Load third permission
  718.         if ($aclPermAuthor !== null)
  719.         {
  720.             $acl $this->aclRepository->findOneBy(array(
  721.                 'function'        =>    $function,
  722.                 'permission'    =>    $aclPermAuthor
  723.             ));
  724.             if ($acl !== null)
  725.             {
  726.                 if ($acl->getValue())
  727.                 {
  728.                     // A single positive answer is enough
  729.                     // In this case the good answer will be provided by the checkSociety
  730.                     return $this->checkAuthor($mission$user);
  731.                 }
  732.             }
  733.         }
  734.         // If we are here, all hope is lost
  735.         return false;
  736.     }
  737.     private function canEditManager($missionAccess $userAccessFunction $function)
  738.     {
  739.         // Deny edit on archivedRefused objects
  740.         if ($mission !== null && $mission->isArchivedRefused())
  741.         {
  742.             return false;
  743.         }
  744.         // Get Acl_Permissions
  745.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_MANAGER_EDIT);
  746.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_MANAGER_EDIT_SOCIETY);
  747.         $aclPermAuthor $this->aclPermissionRepository->findOneByName(self::ACL_PERM_MANAGER_EDIT_AUTHOR);
  748.         // If all are null, exit
  749.         if ($aclPerm === null && $aclPermSociety === null && $aclPermAuthor === null)
  750.             return false;
  751.         // Get First one
  752.         if ($aclPerm !== null)
  753.         {
  754.             $acl $this->aclRepository->findOneBy(array(
  755.                 'function'        =>    $function,
  756.                 'permission'    =>    $aclPerm
  757.             ));
  758.             if ($acl !== null)
  759.             {
  760.                 if ($acl->getValue())
  761.                 {
  762.                     // Both author and owner can edit
  763.                     return true;
  764.                 }
  765.             }
  766.         }
  767.         // If we are here it means that nothing good has been found
  768.         // Load second permission
  769.         if ($aclPermSociety !== null)
  770.         {
  771.             $acl $this->aclRepository->findOneBy(array(
  772.                 'function'        =>    $function,
  773.                 'permission'    =>    $aclPermSociety
  774.             ));
  775.             if ($acl !== null)
  776.             {
  777.                 if ($acl->getValue())
  778.                 {
  779.                     if ($mission !== null)
  780.                     {
  781.                         // Check Society : also check author
  782.                         // Les missions appartenant Ã  ses sociétés (et celles dont il est l'auteur)
  783.                         if ($this->checkAuthor($mission$user))
  784.                         {
  785.                             return true;
  786.                         }
  787.                         // Both author and owner can edit
  788.                         // However, if the mission is shared,
  789.                         // we are filtering using societyOwner instead of society
  790.                         // Only one of the two conditions below can be true at a time
  791.                         if ($this->checkSociety($mission$user) || $this->checkSocietyOwner($mission$user))
  792.                         {
  793.                             return true;
  794.                         }
  795.                     }
  796.                     else
  797.                     {
  798.                         return $acl->getValue();
  799.                     }
  800.                 }
  801.             }
  802.         }
  803.         // If we are here it means that nothing good has been found
  804.         // Load third permission
  805.         if ($aclPermAuthor !== null)
  806.         {
  807.             $acl $this->aclRepository->findOneBy(array(
  808.                 'function'        =>    $function,
  809.                 'permission'    =>    $aclPermAuthor
  810.             ));
  811.             if ($acl !== null)
  812.             {
  813.                 if ($acl->getValue())
  814.                 {
  815.                     if ($mission !== null)
  816.                     {
  817.                         // A single positive answer is enough
  818.                         // In this case the good answer will be provided by the checkSociety
  819.                         return $this->checkAuthor($mission$user);
  820.                     }
  821.                     else
  822.                     {
  823.                         return $acl->getValue();
  824.                     }
  825.                 }
  826.             }
  827.         }
  828.         // If we are here, all hope is lost
  829.         return false;
  830.     }
  831.     private function canShare(Mission $missionAccess $userAccessFunction $function)
  832.     {
  833.         // Module activated ?
  834.         if ($this->moduleTools->isInactiveByCode($this->currentGroupModule::MODULE_MISSION_PLUS))
  835.         {
  836.             return false;
  837.         }
  838.         // Plan.io Task #4031 #4024 #4071
  839.         if ($this->missionSecurityTools->cannotBeShared($mission))
  840.         {
  841.             return false;
  842.         }
  843.         // Get Acl_Permissions
  844.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_SHARE);
  845.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_SHARE_SOCIETY);
  846.         $aclPermAuthor $this->aclPermissionRepository->findOneByName(self::ACL_PERM_SHARE_AUTHOR);
  847.         // If all are null, exit
  848.         if ($aclPerm === null && $aclPermSociety === null && $aclPermAuthor === null)
  849.             return false;
  850.         // Get First one
  851.         if ($aclPerm !== null)
  852.         {
  853.             $acl $this->aclRepository->findOneBy(array(
  854.                 'function'        =>    $function,
  855.                 'permission'    =>    $aclPerm
  856.             ));
  857.             if ($acl !== null)
  858.             {
  859.                 if ($acl->getValue())
  860.                 {
  861.                     // A single positive answer is enough
  862.                     return true;
  863.                 }
  864.             }
  865.         }
  866.         // If we are here it means that nothing good has been found
  867.         // Load second permission
  868.         if ($aclPermSociety !== null)
  869.         {
  870.             $acl $this->aclRepository->findOneBy(array(
  871.                 'function'        =>    $function,
  872.                 'permission'    =>    $aclPermSociety
  873.             ));
  874.             if ($acl !== null)
  875.             {
  876.                 if ($acl->getValue())
  877.                 {
  878.                     // Check Society : also check author
  879.                     // Les missions appartenant Ã  ses sociétés (et celles dont il est l'auteur)
  880.                     if ($this->checkSociety($mission$user))
  881.                     {
  882.                         return true;
  883.                     }
  884.                     else
  885.                     {
  886.                         $this->checkAuthor($mission$user);
  887.                     }
  888.                 }
  889.             }
  890.         }
  891.         // If we are here it means that nothing good has been found
  892.         // Load third permission
  893.         if ($aclPermAuthor !== null)
  894.         {
  895.             $acl $this->aclRepository->findOneBy(array(
  896.                 'function'        =>    $function,
  897.                 'permission'    =>    $aclPermAuthor
  898.             ));
  899.             if ($acl !== null)
  900.             {
  901.                 if ($acl->getValue())
  902.                 {
  903.                     // A single positive answer is enough
  904.                     // In this case the good answer will be provided by the checkSociety
  905.                     return $this->checkAuthor($mission$user);
  906.                 }
  907.             }
  908.         }
  909.         // If we are here, all hope is lost
  910.         return false;
  911.     }
  912.     private function canPayMissionOwner(Mission $mission)
  913.     {
  914.         // Plan.io Task #3304
  915.         // Not paid, obviously :)
  916.         if ($mission->ownerWasPaid())
  917.         {
  918.             return false;
  919.         }
  920.         // Restricted to JCAF society group
  921.         if ($this->currentGroup->isNotJcaf())
  922.         {
  923.             return false;
  924.         }
  925.         // Restricted to JCAF missions
  926.         if ($mission->authorIsNotJcaf())
  927.         {
  928.             return false;
  929.         }
  930.         if ($mission->isNotJcaf())
  931.         {
  932.             return false;
  933.         }
  934.         // Mission should be shared
  935.         if ($mission->isNotShared())
  936.         {
  937.             return false;
  938.         }
  939.         // The mission should have a finished RFI not requiring another intervention
  940.         $docs $this->em->getRepository(Document::class)
  941.             ->findByMission($mission);
  942.         if (count($docs) < 1)
  943.         {
  944.             return false;
  945.         }
  946.         $found false;
  947.         foreach ($docs as $doc)
  948.         {
  949.             if ($doc->getRfi() !== null)
  950.             {
  951.                 if ($doc->getRfi()->doesNotRequireReintervention())
  952.                 {
  953.                     $found true;
  954.                     break;
  955.                 }
  956.             }
  957.         }
  958.         if (!$found)
  959.         {
  960.             return false;
  961.         }
  962.         // All looks good
  963.         return true;
  964.     }
  965.     private function canList(Access $userAccessFunction $function)
  966.     {
  967.         // If canView, then canList ;)
  968.         // Get Acl_Permission
  969.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST);
  970.         if ($aclPerm === null)        return false;
  971.         // Get Acl
  972.         $acl $this->aclRepository->findOneBy(array(
  973.             'function'        =>    $function,
  974.             'permission'    =>    $aclPerm
  975.         ));
  976.         if ($acl === null)        return false;
  977.         // Since only one acl type can exist
  978.         // we can return the result of the acl_permission
  979.         return $acl->getValue();
  980.     }
  981.     private function canListSociety(Access $userAccessFunction $function)
  982.     {
  983.         // If canView, then canList ;)
  984.         // Get Acl_Permission
  985.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST_SOCIETY);
  986.         if ($aclPerm === null)        return false;
  987.         // Get Acl
  988.         $acl $this->aclRepository->findOneBy(array(
  989.             'function'        =>    $function,
  990.             'permission'    =>    $aclPerm
  991.         ));
  992.         if ($acl === null)        return false;
  993.         // Since only one acl type can exist
  994.         // we can return the result of the acl_permission
  995.         return $acl->getValue();
  996.     }
  997.     private function canListAuthor(Access $userAccessFunction $function)
  998.     {
  999.         // If canView, then canList ;)
  1000.         // Get Acl_Permission
  1001.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST_AUTHOR);
  1002.         if ($aclPerm === null)        return false;
  1003.         // Get Acl
  1004.         $acl $this->aclRepository->findOneBy(array(
  1005.             'function'        =>    $function,
  1006.             'permission'    =>    $aclPerm
  1007.         ));
  1008.         if ($acl === null)        return false;
  1009.         // Since only one acl type can exist
  1010.         // we can return the result of the acl_permission
  1011.         return $acl->getValue();
  1012.     }
  1013.     private function canListAny(Access $userAccessFunction $function)
  1014.     {
  1015.         // Three Acl_Permission may exist
  1016.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST);
  1017.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST_SOCIETY);
  1018.         $aclPermAuthor $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LIST_AUTHOR);
  1019.         // If all are null, exit
  1020.         if ($aclPerm === null && $aclPermSociety === null && $aclPermAuthor === null)
  1021.             return false;
  1022.         // Get First one
  1023.         if ($aclPerm !== null)
  1024.         {
  1025.             $acl $this->aclRepository->findOneBy(array(
  1026.                 'function'        =>    $function,
  1027.                 'permission'    =>    $aclPerm
  1028.             ));
  1029.             if ($acl !== null)
  1030.             {
  1031.                 if ($acl->getValue())
  1032.                 {
  1033.                     // A single positive answer is enough
  1034.                     return true;
  1035.                 }
  1036.             }
  1037.         }
  1038.         // If we are here it means that nothing good has been found
  1039.         // Load second permission
  1040.         if ($aclPermSociety !== null)
  1041.         {
  1042.             $acl $this->aclRepository->findOneBy(array(
  1043.                 'function'        =>    $function,
  1044.                 'permission'    =>    $aclPermSociety
  1045.             ));
  1046.             if ($acl !== null)
  1047.             {
  1048.                 if ($acl->getValue())
  1049.                 {
  1050.                     // A single positive answer is enough
  1051.                     return true;
  1052.                 }
  1053.             }
  1054.         }
  1055.         // If we are here it means that nothing good has been found
  1056.         // Load third permission
  1057.         if ($aclPermAuthor !== null)
  1058.         {
  1059.             $acl $this->aclRepository->findOneBy(array(
  1060.                 'function'        =>    $function,
  1061.                 'permission'    =>    $aclPermAuthor
  1062.             ));
  1063.             if ($acl !== null)
  1064.             {
  1065.                 if ($acl->getValue())
  1066.                 {
  1067.                     // A single positive answer is enough
  1068.                     return true;
  1069.                 }
  1070.             }
  1071.         }
  1072.         // If we are here, all hope is lost
  1073.         return false;
  1074.     }
  1075.     // Plan.io Task #4247
  1076.     private function canMerge(Mission $missionAccess $userAccessFunction $accessFunction)
  1077.     {
  1078.         // Two Acl_Permission may exist
  1079.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_MERGE);
  1080.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_MERGE_SOCIETY);
  1081.         // If all are null, exit
  1082.         if ($aclPerm === null && $aclPermSociety === null)
  1083.             return false;
  1084.         // Get First one
  1085.         if ($aclPerm !== null)
  1086.         {
  1087.             $acl $this->aclRepository->findOneBy(array(
  1088.                 'function'        =>    $accessFunction,
  1089.                 'permission'    =>    $aclPerm
  1090.             ));
  1091.             if ($acl !== null)
  1092.             {
  1093.                 if ($acl->getValue())
  1094.                 {
  1095.                     // A single positive answer is enough
  1096.                     return true;
  1097.                 }
  1098.             }
  1099.         }
  1100.         // If we are here it means that nothing good has been found
  1101.         // Load second permission
  1102.         if ($aclPermSociety !== null)
  1103.         {
  1104.             $acl $this->aclRepository->findOneBy(array(
  1105.                 'function'        =>    $accessFunction,
  1106.                 'permission'    =>    $aclPermSociety
  1107.             ));
  1108.             if ($acl !== null)
  1109.             {
  1110.                 if ($acl->getValue())
  1111.                 {
  1112.                     // A single positive answer is enough
  1113.                     // In this case the good answer will be provided by the checkSociety
  1114.                     return $this->checkSociety($mission$user);
  1115.                 }
  1116.             }
  1117.         }
  1118.         // If we are here, all hope is lost
  1119.         return false;
  1120.     }
  1121.     // Plan.io Task #4247
  1122.     // We need to know if the user can access the merge tool
  1123.     // Specific merge permissions will be checked later
  1124.     private function canUseMergeTool(Access $userAccessFunction $accessFunction)
  1125.     {
  1126.         // Two Acl_Permission may exist
  1127.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_MERGE);
  1128.         $aclPermSociety $this->aclPermissionRepository->findOneByName(self::ACL_PERM_MERGE_SOCIETY);
  1129.         // If all are null, exit
  1130.         if ($aclPerm === null && $aclPermSociety === null)
  1131.             return false;
  1132.         // Get First one
  1133.         if ($aclPerm !== null)
  1134.         {
  1135.             $acl $this->aclRepository->findOneBy(array(
  1136.                 'function'        =>    $accessFunction,
  1137.                 'permission'    =>    $aclPerm
  1138.             ));
  1139.             if ($acl !== null)
  1140.             {
  1141.                 if ($acl->getValue())
  1142.                 {
  1143.                     // A single positive answer is enough
  1144.                     return true;
  1145.                 }
  1146.             }
  1147.         }
  1148.         // If we are here it means that nothing good has been found
  1149.         // Load second permission
  1150.         if ($aclPermSociety !== null)
  1151.         {
  1152.             $acl $this->aclRepository->findOneBy(array(
  1153.                 'function'        =>    $accessFunction,
  1154.                 'permission'    =>    $aclPermSociety
  1155.             ));
  1156.             if ($acl !== null)
  1157.             {
  1158.                 if ($acl->getValue())
  1159.                 {
  1160.                     // A single positive answer is enough
  1161.                     return true;
  1162.                 }
  1163.             }
  1164.         }
  1165.         // If we are here, all hope is lost
  1166.         return false;
  1167.     }
  1168. }