src/Security/TaskVoter.php line 102

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/TaskVoter.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\Config\Config;
  13. use App\Entity\Config\Module;
  14. use App\Entity\HR\AccessFunction;
  15. use App\Entity\Planning\Task;
  16. use App\Entity\Platform\Society;
  17. use App\Entity\Mission\Mission;
  18. use App\Entity\Security\Acl;
  19. use App\Entity\Security\AclPermission;
  20. use App\Entity\Security\AclPlanning;
  21. use App\Services\LogTools;
  22. use App\Services\Config\ModuleTools;
  23. class TaskVoter extends Voter
  24. {
  25.     //--------------------------------------------------------------------------------
  26.     // is_granted constants
  27.     const ADD "add_task";
  28.     const VIEW "view_task";
  29.     const EDIT "edit_task";
  30.     const DELETE "delete_task";
  31.     // There are used to set default permissions in the custom tables
  32.     // Plan.io Task #4089
  33.     const DECIDE_ADD_TYPE "add_task_type";
  34.     const DECIDE_VIEW_TYPE_ALL "view_task_type_all";
  35.     const DECIDE_VIEW_TYPE_SOCIETY "view_task_type_society";
  36.     const DECIDE_VIEW_TYPE_OWN "view_task_type_own";
  37.     const DECIDE_EDIT_TYPE_ALL "edit_task_type_all";
  38.     const DECIDE_EDIT_TYPE_SOCIETY "edit_task_type_society";
  39.     const DECIDE_EDIT_TYPE_OWN "edit_task_type_own";
  40.     const DECIDE_DELETE_TYPE_ALL "delete_task_type_all";
  41.     const DECIDE_DELETE_TYPE_SOCIETY "delete_task_type_society";
  42.     const DECIDE_DELETE_TYPE_OWN "delete_task_type_own";
  43.     // Plan.io Task #3534
  44.     const LISTING "list_tasks";
  45.     const IS_GRANTED_CONSTANTS = array(
  46.         self::ADD,
  47.         self::VIEW,
  48.         self::EDIT,
  49.         self::DELETE,
  50.         self::LISTING,
  51.         self::DECIDE_ADD_TYPE,
  52.         self::DECIDE_VIEW_TYPE_ALL,
  53.         self::DECIDE_VIEW_TYPE_SOCIETY,
  54.         self::DECIDE_VIEW_TYPE_OWN,
  55.         self::DECIDE_EDIT_TYPE_ALL,
  56.         self::DECIDE_EDIT_TYPE_SOCIETY,
  57.         self::DECIDE_EDIT_TYPE_OWN,
  58.         self::DECIDE_DELETE_TYPE_ALL,
  59.         self::DECIDE_DELETE_TYPE_SOCIETY,
  60.         self::DECIDE_DELETE_TYPE_OWN,
  61.     );
  62.     //--------------------------------------------------------------------------------
  63.     // acl constants
  64.     const ACL_PERM_ADD "task_add";
  65.     const ACL_PERM_VIEW "task_view";
  66.     const ACL_PERM_VIEW_SOCIETY "task_view_society";
  67.     const ACL_PERM_VIEW_OWN "task_view_own";
  68.     const ACL_PERM_EDIT "task_edit";
  69.     const ACL_PERM_EDIT_SOCIETY "task_edit_society";
  70.     const ACL_PERM_EDIT_OWN "task_edit_own";
  71.     const ACL_PERM_DELETE "task_delete";
  72.     const ACL_PERM_DELETE_SOCIETY "task_delete_society";
  73.     const ACL_PERM_DELETE_OWN "task_delete_own";
  74.     //--------------------------------------------------------------------------------
  75.     public function __construct(AccessDecisionManagerInterface $accessDecisionManagerManagerRegistry $doctrineModuleTools $moduleToolsLogTools $logTools)
  76.     {
  77.         $this->accessDecisionManager $accessDecisionManager;
  78.         $this->em $doctrine->getManager();
  79.         $this->moduleTools $moduleTools;
  80.         $this->logTools $logTools;
  81.         $this->aclRepository $this->em->getRepository(Acl::class);
  82.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  83.         $this->aclPlanningRepository $this->em->getRepository(AclPlanning::class);
  84.     }
  85.     // Plan.io Task #4453 [See AccessVoter for details]
  86.     public function supportsAttribute(string $attribute): bool
  87.     {
  88.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  89.     }
  90.     protected function getAclPlanning($taskAccess $access)
  91.     {
  92.         // Get the Society from the Task
  93.         if ($task !== null)
  94.         {
  95.             $society $task->getSociety();
  96.         }
  97.         else
  98.         {
  99.             // Exception : Add mode
  100.             // For now ADD is global for all the Societies of the Access
  101.             $society $access->getSociety();
  102.         }
  103.         if ($society === null)
  104.         {
  105.             return null;
  106.         }
  107.         $permission $this->aclPlanningRepository->findOneBy(array(
  108.             'access'    =>    $access,
  109.             'society'    =>    $society,
  110.         ));
  111.         return $permission;
  112.     }
  113.     // This is global to view and view_own
  114.     protected function checkViewConditions(Task $taskAccess $access)
  115.     {
  116.         $mission $task->getMission();
  117.         $viewerSocietyGroup $access->getSocietyGroup();
  118.         // First of all, check if this is a SharedTask viewed from the Emitter.Side
  119.         // Plan.io Task #4024 #4091
  120.         // $currentGroup is the one trying to access the Task
  121.         if ($task->isSharedBy($viewerSocietyGroup))
  122.         {
  123.             if ($mission !== null)
  124.             {
  125.                 // Task is shared by $currentGroup and has a Mission
  126.                 // So the $currentGroup can view the Task
  127.                 return true;
  128.             }
  129.             // Task is shared by $currentGroup and has no Mission
  130.             // This should be redirected to edit_shared
  131.             return false;
  132.         }
  133.         // All view conditions have been met
  134.         return true;
  135.     }
  136.     // This is global to edit and edit_own
  137.     protected function checkEditConditions(Task $taskAccess $access)
  138.     {
  139.         // Deny edit on archivedRefused objects
  140.         $isArchivedRefused $task->isArchivedRefused();
  141.         if ($isArchivedRefused)
  142.         {
  143.             return false;
  144.         }
  145.         // Task plan.io #3898 : Task with status IsInvoicedFinished
  146.         if ($task->isInvoicedFinished())
  147.         {
  148.             return false;
  149.         }
  150.         // Task plan.io #4118 : Deny if parent/task is readonly (TaskInfoRekto)
  151.         if ($task->getHelpParent() !== null)
  152.         {
  153.             $helpParent $task->getHelpParent();
  154.             if ($helpParent->getTaskInfoRekto() !== null && $helpParent->getTaskInfoRekto()->getReadonlyTask())
  155.             {
  156.                 return false;
  157.             }
  158.         }
  159.         else
  160.         {
  161.             if ($task->getTaskInfoRekto() !== null && $task->getTaskInfoRekto()->getReadonlyTask())
  162.             {
  163.                 return false;
  164.             }
  165.         }
  166.         $mission $task->getMission();
  167.         $viewerSocietyGroup $access->getSocietyGroup();
  168.         // Plan.io Task #3260
  169.         // SharedTask : mission.author # mission.owner
  170.         // The author should only be able to view or delete its own tasks
  171.         if ($task->isShared() && $mission !== null)
  172.         {
  173.             if ($mission->getSocietyGroupOwner() !== null)
  174.             {
  175.                 // The SocietyGroup viewing the Task is the Author, not the Owner
  176.                 if (!$mission->getSocietyGroupOwner()->equals($viewerSocietyGroup))
  177.                 {
  178.                     return false;
  179.                 }
  180.             }
  181.         }
  182.         // First of all, check if this is a SharedTask viewed from the Emitter.Side
  183.         // Plan.io Task #4024 #4091
  184.         // $currentGroup is the one trying to access the Task
  185.         if ($task->isSharedBy($viewerSocietyGroup))
  186.         {
  187.             if ($mission === null)
  188.             {
  189.                 // Task is shared by $currentGroup and has a Mission
  190.                 // So the $currentGroup can edit the Task
  191.                 return true;
  192.             }
  193.             // Task is shared by $currentGroup and has a Mission
  194.             // Deny edit
  195.             return false;
  196.         }
  197.         // All view conditions have been met
  198.         return true;
  199.     }
  200.     // This is global to delete and delete_own
  201.     protected function checkDeleteConditions(Task $taskAccess $access)
  202.     {
  203.         $mission $task->getMission();
  204.         $viewerSocietyGroup $access->getSocietyGroup();
  205.         // Deny delete on archivedRefused objects
  206.         $isArchivedRefused $task->isArchivedRefused();
  207.         if ($isArchivedRefused)
  208.         {
  209.             return false;
  210.         }
  211.         // First of all, check if this is a SharedTask viewed from the Emitter.Side
  212.         // Plan.io Task #4024 #4091
  213.         // $currentGroup is the one trying to access the Task
  214.         if ($task->isSharedBy($viewerSocietyGroup))
  215.         {
  216.             if ($mission === null)
  217.             {
  218.                 // Task is shared by $currentGroup and has no Mission
  219.                 // So the $currentGroup can delete the Task
  220.                 return true;
  221.             }
  222.             // Task is shared by $currentGroup and has a Mission
  223.             // Deny edit
  224.             return false;
  225.         }
  226.         // All view conditions have been met
  227.         return true;
  228.     }
  229.     protected function decide_canViewOwn(Task $taskAccess $access)
  230.     {
  231.         $result $this->checkViewConditions($task$access);
  232.         if ($result === false)
  233.         {
  234.             return false;
  235.         }
  236.         $permission $this->getAclPlanning($task$access);
  237.         if ($permission === null)
  238.         {
  239.             return false;
  240.         }
  241.         if ($permission->canViewOwn())
  242.         {
  243.             return $this->checkOwn($task$access);
  244.         }
  245.         return false;
  246.     }
  247.     protected function decide_canView(Task $taskAccess $access)
  248.     {
  249.         $result $this->checkViewConditions($task$access);
  250.         if ($result === false)
  251.         {
  252.             return false;
  253.         }
  254.         $viewerSocietyGroup $access->getSocietyGroup();
  255.         $mission $task->getMission();
  256.         // The Task has ShareData, and we are viewing it from the Emitter side
  257.         if ($task->isSharedBy($viewerSocietyGroup))
  258.         {
  259.             if ($mission !== null)
  260.             {
  261.                 return true;
  262.                 // We have a Mission attached and we are viewing the task from the Emitter Side
  263.                 // => Open Special View
  264.                 // redirects to "icod_platform_task_view_shared_emitter_side"
  265.                 // Shared Task with no Mission viewed from the Emitter Side
  266.                 // Edit is granted
  267.                 // Since Edit is Tested before View, this code should never be reached
  268.                 // But just in case, return true
  269.                 // Since view is a sub-permission of edit ;)
  270.             }
  271.             return true;
  272.             // We don't have a Mission attached and we are viewing the task from the Emitter Side
  273.             // => Open Special Edit
  274.             // redirects to "icod_platform_task_edit_shared_emitter_side"
  275.         }
  276.         $permission $this->getAclPlanning($task$access);
  277.         if ($permission === null)
  278.         {
  279.             return false;
  280.         }
  281.         if ($permission->canView())
  282.         {
  283.             return true;
  284.         }
  285.         // If the user has can_view_own and the task is its own,
  286.         // then this method should return true
  287.         if ($permission->canViewOwn())
  288.         {
  289.             return $this->checkOwn($task$access);
  290.         }
  291.         return false;
  292.     }
  293.     protected function decide_canEditOwn(Task $taskAccess $access)
  294.     {
  295.         $result $this->checkEditConditions($task$access);
  296.         if ($result === false)
  297.         {
  298.             return false;
  299.         }
  300.         // All global view conditions have been met
  301.         $permission $this->getAclPlanning($task$access);
  302.         if ($permission === null)
  303.         {
  304.             return false;
  305.         }
  306.         if ($permission->canEditOwn())
  307.         {
  308.             return $this->checkOwn($task$access);
  309.         }
  310.         return false;
  311.     }
  312.     protected function decide_canEdit(Task $taskAccess $access)
  313.     {
  314.         $result $this->checkEditConditions($task$access);
  315.         if ($result === false)
  316.         {
  317.             return false;
  318.         }
  319.         $viewerSocietyGroup $access->getSocietyGroup();
  320.         $mission $task->getMission();
  321.         // The Task has ShareData, and we are viewing it from the Emitter side
  322.         if ($task->isSharedBy($viewerSocietyGroup))
  323.         {
  324.             if ($mission !== null)
  325.             {
  326.                 return false;
  327.                 // We have a Mission attached and we are viewing the task from the Emitter Side
  328.                 // => Open Special View
  329.                 // redirects to "icod_platform_task_view_shared_emitter_side"
  330.                 // Shared Task with a Mission attached viewed from the Emitter Side
  331.                 // Edit is not granted
  332.             }
  333.             return true;
  334.             // We don't have a Mission attached and we are viewing the task from the Emitter Side
  335.             // => Open Special Edit
  336.             // redirects to "icod_platform_task_edit_shared_emitter_side"
  337.         }
  338.         // All global view conditions have been met
  339.         $permission $this->getAclPlanning($task$access);
  340.         if ($permission === null)
  341.         {
  342.             return false;
  343.         }
  344.         if ($permission->canEdit())
  345.         {
  346.             return true;
  347.         }
  348.         // If the user has can_edit_own and the task is its own,
  349.         // then this method should return true
  350.         if ($permission->canEditOwn())
  351.         {
  352.             return $this->checkOwn($task$access);
  353.         }
  354.         return false;
  355.     }
  356.     protected function decide_canDeleteOwn(Task $taskAccess $access)
  357.     {
  358.         $result $this->checkDeleteConditions($task$access);
  359.         if ($result === false)
  360.         {
  361.             return false;
  362.         }
  363.         // All global view conditions have been met
  364.         $permission $this->getAclPlanning($task$access);
  365.         if ($permission === null)
  366.         {
  367.             return false;
  368.         }
  369.         if ($permission->canDeleteOwn())
  370.         {
  371.             return $this->checkOwn($task$access);
  372.         }
  373.         return false;
  374.     }
  375.     protected function decide_canDelete(Task $taskAccess $access)
  376.     {
  377.         $result $this->checkDeleteConditions($task$access);
  378.         if ($result === false)
  379.         {
  380.             return false;
  381.         }
  382.         // All global view conditions have been met
  383.         $permission $this->getAclPlanning($task$access);
  384.         if ($permission === null)
  385.         {
  386.             return false;
  387.         }
  388.         if ($permission->canDelete())
  389.         {
  390.             return true;
  391.         }
  392.         // If the user has can_delete_own and the task is its own,
  393.         // then this method should return true
  394.         if ($permission->canDeleteOwn())
  395.         {
  396.             return $this->checkOwn($task$access);
  397.         }
  398.         return false;
  399.     }
  400.     protected function supports(string $attribute$subject null): bool
  401.     {
  402.         // if the attribute isn't one we support, return false
  403.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  404.         {
  405.             return false;
  406.         }
  407.         // Only vote on Task and Mission objects inside this voter
  408.         // Plan.io Task #4089 : Added $society for the ADD part
  409.         if ($subject !== null && !($subject instanceof Task || $subject instanceof Mission || $subject instanceof Society))
  410.         {
  411.             return false;
  412.         }
  413.         return true;
  414.     }
  415.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  416.     {
  417.         $user $token->getUser();
  418.         // Plan.io Task #3707
  419.         if ($user instanceof AccessAPI)
  420.         {
  421.             if ($user->getAccess() === null)
  422.             {
  423.                 return false;
  424.             }
  425.             $user $user->getAccess();
  426.         }
  427.         // Plan.io Task #3707
  428.         // At this point $user is an object of Access type
  429.         // even if the $token->getUser() is AccessAPI
  430.         if (!$user instanceof Access)
  431.         {
  432.             // the user must be logged in; if not, deny access
  433.             return false;
  434.         }
  435.         // The user must have a function; if not deny access
  436.         $function $user->getFunction();
  437.         if ($function === null)        return false;
  438.         // Plan.io Task #3710 : Get current group
  439.         $currentGroup $user->getSocietyGroup();
  440.         if ($currentGroup === null)
  441.             return false;
  442.         // This is needed to check HumanResource Module in canLoadGloablPlanning
  443.         $this->currentGroup $currentGroup;
  444.         // Module activated ?
  445.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_PLANNING))
  446.         {
  447.             return false;
  448.         }
  449.         $task null;
  450.         $mission null;
  451.         if ($subject instanceof Task)
  452.         {
  453.             /** @var Task $task */
  454.             $task $subject;
  455.             // Check current group affectation
  456.             if ($subject !== null)
  457.             {
  458.                 // $this->logTools->ploopLog("[TaskVoter][voteOnAttribute] ".$subject->displayForLog());
  459.                 // Plan.io Task #4024
  460.                 // Handle Shared Tasks
  461.                 if ($subject->isSharedBy($currentGroup))
  462.                 {
  463.                     // $this->logTools->ploopLog("[TaskVoter][voteOnAttribute] subject->isSharedBy(currentGroup)");
  464.                 }
  465.                 else
  466.                 {
  467.                     // $this->logTools->ploopLog("[TaskVoter][voteOnAttribute] subject->isSharedBy(currentGroup) NOPE");
  468.                     $subjectSociety $subject->getSociety();
  469.                     if ($subjectSociety === null)
  470.                     {
  471.                         // $this->logTools->ploopLog("[TaskVoter][voteOnAttribute] subject->isSharedBy(currentGroup) NOPE: Die.Hard.001");
  472.                         return false;
  473.                     }
  474.                     $subjectGroup $subjectSociety->getGroup();
  475.                     if ($subjectGroup === null)
  476.                     {
  477.                         // $this->logTools->ploopLog("[TaskVoter][voteOnAttribute] subject->isSharedBy(currentGroup) NOPE: Die.Hard.002");
  478.                         return false;
  479.                     }
  480.                     // $this->logTools->ploopLog("[TaskVoter][voteOnAttribute] currentGroup = ".$currentGroup->displayForLog());
  481.                     // $this->logTools->ploopLog("[TaskVoter][voteOnAttribute] subjectGroup = ".$subjectGroup->displayForLog());
  482.                     if (!$currentGroup->equals($subjectGroup))
  483.                     {
  484.                         // $this->logTools->ploopLog("[TaskVoter][voteOnAttribute] subject->isSharedBy(currentGroup) NOPE: Die.Hard.003");
  485.                         return false;
  486.                     }
  487.                 }
  488.             }
  489.         }
  490.         else
  491.         {
  492.             if ($subject instanceof Mission)
  493.             {
  494.                 /** @var Mission $mission */
  495.                 $mission $subject;
  496.                 // Plan.io Task #3517, modified by #4453
  497.                 if (!$this->accessDecisionManager->decide($token, ['view_mission'], $mission))
  498.                 {
  499.                     return false;
  500.                 }
  501.             }
  502.         }
  503.         switch ($attribute)
  504.         {
  505.             // This is different from the Devis, because we can create a task outside a mission
  506.             // So the mission parameter is optional
  507.             // Plan.io Task #4089 : ADD $subject can be either Mission or Society
  508.             case self::ADD:
  509.                 return $this->canAdd($user$function$subject);
  510.             case self::VIEW:
  511.                 return $this->canView($task$user);
  512.             case self::EDIT:
  513.                 return $this->canEdit($task$user);
  514.             case self::DELETE:
  515.                 return $this->canDelete($task$user);
  516.             case self::DECIDE_ADD_TYPE:
  517.                 return $this->decideOn(self::DECIDE_ADD_TYPE$function);
  518.             case self::DECIDE_VIEW_TYPE_ALL:
  519.                 return $this->decideOn(self::DECIDE_VIEW_TYPE_ALL$function);
  520.             case self::DECIDE_VIEW_TYPE_SOCIETY:
  521.                 return $this->decideOn(self::DECIDE_VIEW_TYPE_SOCIETY$function);
  522.             case self::DECIDE_VIEW_TYPE_OWN:
  523.                 return $this->decideOn(self::DECIDE_VIEW_TYPE_OWN$function);
  524.             case self::DECIDE_EDIT_TYPE_ALL:
  525.                 return $this->decideOn(self::DECIDE_EDIT_TYPE_ALL$function);
  526.             case self::DECIDE_EDIT_TYPE_SOCIETY:
  527.                 return $this->decideOn(self::DECIDE_EDIT_TYPE_SOCIETY$function);
  528.             case self::DECIDE_EDIT_TYPE_OWN:
  529.                 return $this->decideOn(self::DECIDE_EDIT_TYPE_OWN$function);
  530.             case self::DECIDE_DELETE_TYPE_ALL:
  531.                 return $this->decideOn(self::DECIDE_DELETE_TYPE_ALL$function);
  532.             case self::DECIDE_DELETE_TYPE_SOCIETY:
  533.                 return $this->decideOn(self::DECIDE_DELETE_TYPE_SOCIETY$function);
  534.             case self::DECIDE_DELETE_TYPE_OWN:
  535.                 return $this->decideOn(self::DECIDE_DELETE_TYPE_OWN$function);
  536.             case self::LISTING:
  537.                 return $this->canList($user$function);
  538.         }
  539.         throw new \LogicException('This code should not be reached!');
  540.     }
  541.     // $access is the user trying to load the resource
  542.     // $task is the resource being loaded
  543.     // Check if the Society of the resource
  544.     // belongs to the societies of the $access
  545.     private function checkSociety(Task $taskAccess $access)
  546.     {
  547.         // Get all the societies of the access
  548.         $societies $access->getSocieties();
  549.         // Get the Society of the Task
  550.         $taskSociety $task->getSociety();
  551.         if ($taskSociety === null)
  552.             return false;
  553.         // Check if the original society is accepted
  554.         foreach ($societies as $society)
  555.         {
  556.             if ($society->getId() == $taskSociety->getId())
  557.             {
  558.                 return true;
  559.                 break;
  560.             }
  561.         }
  562.         // Next check the new societies
  563.         // Get resources
  564.         $resources $task->getPlanningResources();
  565.         if ($resources === null || count($resources) < 1)
  566.             return false;
  567.         foreach ($resources as $res)
  568.         {
  569.             if ($res->getSociety() !== null)
  570.             {
  571.                 foreach ($societies as $society)
  572.                 {
  573.                     if ($society->getId() == $res->getSociety()->getId())
  574.                     {
  575.                         return true;
  576.                         break;
  577.                     }
  578.                 }
  579.             }
  580.         }
  581.         return false;
  582.     }
  583.     // Check if the $access is one of the resources of the $task
  584.     private function checkOwn(Task $taskAccess $access)
  585.     {
  586.         // Get resources
  587.         $resources $task->getPlanningResources();
  588.         if ($resources === null || count($resources) < 1)
  589.             return false;
  590.         foreach ($resources as $res)
  591.         {
  592.             if ($res->getAccess() !== null)
  593.             {
  594.                 if ($res->getAccess()->getId() == $access->getId())
  595.                 {
  596.                     return true;
  597.                     break;
  598.                 }
  599.             }
  600.         }
  601.         return false;
  602.     }
  603.     private function decideOn($typeAccessFunction $function)
  604.     {
  605.         $aclPerm null;
  606.         switch($type)
  607.         {
  608.             // Plan.io Task #4089
  609.             case self::DECIDE_ADD_TYPE:
  610.             {
  611.                 $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD);
  612.                 break;
  613.             }
  614.             case self::DECIDE_VIEW_TYPE_ALL:
  615.             {
  616.                 $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW);
  617.                 break;
  618.             }
  619.             case self::DECIDE_VIEW_TYPE_SOCIETY:
  620.             {
  621.                 $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_SOCIETY);
  622.                 break;
  623.             }
  624.             case self::DECIDE_VIEW_TYPE_OWN:
  625.             {
  626.                 $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_OWN);
  627.                 break;
  628.             }
  629.             case self::DECIDE_EDIT_TYPE_ALL:
  630.             {
  631.                 $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  632.                 break;
  633.             }
  634.             case self::DECIDE_EDIT_TYPE_SOCIETY:
  635.             {
  636.                 $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SOCIETY);
  637.                 break;
  638.             }
  639.             case self::DECIDE_EDIT_TYPE_OWN:
  640.             {
  641.                 $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_OWN);
  642.                 break;
  643.             }
  644.             case self::DECIDE_DELETE_TYPE_ALL:
  645.             {
  646.                 $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DELETE);
  647.                 break;
  648.             }
  649.             case self::DECIDE_DELETE_TYPE_SOCIETY:
  650.             {
  651.                 $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DELETE_SOCIETY);
  652.                 break;
  653.             }
  654.             case self::DECIDE_DELETE_TYPE_OWN:
  655.             {
  656.                 $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DELETE_OWN);
  657.                 break;
  658.             }
  659.         }
  660.         if ($aclPerm === null)        return false;
  661.         // Get Acl
  662.         $acl $this->aclRepository->findOneBy(array(
  663.             'function'        =>    $function,
  664.             'permission'    =>    $aclPerm
  665.         ));
  666.         if ($acl === null)        return false;
  667.         return $acl->getValue();
  668.     }
  669.     // Plan.io Task #4089 : $subject can be either Mission or Society
  670.     private function canAdd(Access $accessAccessFunction $function$subject null)
  671.     {
  672.         if ($subject !== null)
  673.         {
  674.             if ($subject instanceof Mission)
  675.             {
  676.                 $mission $subject;
  677.                 // When a mission is shared, the author cannot edit it
  678.                 // Deny actions on archivedRefused objects
  679.                 if ($mission->isArchivedRefused())
  680.                 {
  681.                     return false;
  682.                 }
  683.                 if ($mission->isShared())
  684.                 {
  685.                     if ($mission->isSharedBySocietyGroup($this->currentGroup))
  686.                     {
  687.                         return false;
  688.                     }
  689.                 }
  690.             }
  691.         }
  692.         /*
  693.         // Specific access permissions are prioritary
  694.         // Since we need the Society, get it from the Mission or the actual Society sent via the $subject
  695.         $society = $access->getSociety();
  696.         if ($subject !== null)
  697.         {
  698.             if ($subject instanceof Mission)
  699.             {
  700.                 $society = $subject->getSociety();
  701.                 // For now the only case where the $subject is a Mission for the ADD
  702.                 // is when using maps
  703.                 // So maybe replace this with the actual Society
  704.                 // TODO : (also) check how this plays out
  705.                 // in the context of adding tasks for shared missions, receiver side
  706.             }
  707.             else
  708.             {
  709.                 if ($subject instanceof Society)
  710.                 {
  711.                     $society = $subject;
  712.                 }
  713.             }
  714.         }
  715.         */
  716.         // Check permission
  717.         // For now ADD is global for all the Societies of the Access
  718.         // Thus the third param set to true
  719.         $permission $this->getAclPlanning(null$access);
  720.         if ($permission === null)
  721.         {
  722.             return false;
  723.         }
  724.         if ($permission->canAdd())
  725.         {
  726.             return true;
  727.         }
  728.         // If we are here, all hope is lost
  729.         return false;
  730.     }
  731.     public function canView(Task $taskAccess $access)
  732.     {
  733.         if ($this->decide_canView($task$access))
  734.         {
  735.             return true;
  736.         }
  737.         if ($this->decide_canViewOwn($task$access))
  738.         {
  739.             return true;
  740.         }
  741.         // If we are here, all hope is lost
  742.         return false;
  743.     }
  744.     public function canEdit(Task $taskAccess $access)
  745.     {
  746.         if ($this->decide_canEdit($task$access))
  747.         {
  748.             return true;
  749.         }
  750.         if ($this->decide_canEditOwn($task$access))
  751.         {
  752.             return true;
  753.         }
  754.         // If we are here, all hope is lost
  755.         return false;
  756.     }
  757.     public function canDelete(Task $taskAccess $access)
  758.     {
  759.         if ($this->decide_canDelete($task$access))
  760.         {
  761.             return true;
  762.         }
  763.         if ($this->decide_canDeleteOwn($task$access))
  764.         {
  765.             return true;
  766.         }
  767.         // If we are here, all hope is lost
  768.         return false;
  769.     }
  770.     // Plan.io Task #3534
  771.     // Can List is actually a mix of view and edit
  772.     private function canList(Access $accessAccessFunction $function)
  773.     {
  774.         $perms = array();
  775.         $perms[] = $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW);
  776.         $perms[] = $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_SOCIETY);
  777.         $perms[] = $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT);
  778.         $perms[] = $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SOCIETY);
  779.         $perms[] = $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_OWN);
  780.         foreach ($perms as $perm)
  781.         {
  782.             if ($perm !== null)
  783.             {
  784.                 $acl $this->aclRepository->findOneBy(array(
  785.                     'function'        =>    $function,
  786.                     'permission'    =>    $perm
  787.                 ));
  788.                 if ($acl !== null)
  789.                 {
  790.                     if ($acl->getValue())
  791.                     {
  792.                         // A single positive answer is enough
  793.                         return true;
  794.                     }
  795.                 }
  796.             }
  797.         }
  798.         return false;
  799.     }
  800. }