src/Security/InodeVoter.php line 50

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/InodeVoter.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\Cloud\Inode;
  11. use App\Entity\Config\Config;
  12. use App\Entity\Config\Module;
  13. use App\Entity\HR\AccessFunction;
  14. use App\Entity\Security\Acl;
  15. use App\Entity\Security\AclPermission;
  16. use App\Services\Config\ModuleTools;
  17. class InodeVoter extends Voter
  18. {
  19.     const IS_ACTIVE "cloud_is_active";
  20.     const ADD "add_inode";
  21.     const VIEW "view_inode";
  22.     const EDIT "edit_inode";
  23.     const MOVE "move_inode";
  24.     const SHARE "share_inode";
  25.     const DELETE "delete_inode";
  26.     const ACL_PERM_ADD "inode_add";
  27.     const ACL_PERM_SHARE "inode_share";
  28.     const ACL_PERM_EDIT_SHARED "inode_edit_shared";
  29.     const ACL_PERM_DELETE_SHARED "inode_delete_shared";
  30.     const IS_GRANTED_CONSTANTS = array(
  31.         self::IS_ACTIVE,
  32.         self::ADD,
  33.         self::VIEW,
  34.         self::EDIT,
  35.         self::MOVE,
  36.         self::SHARE,
  37.         self::DELETE,
  38.         self::ACL_PERM_ADD,
  39.         self::ACL_PERM_SHARE,
  40.         self::ACL_PERM_EDIT_SHARED,
  41.         self::ACL_PERM_DELETE_SHARED,
  42.     );
  43.     public function __construct(ManagerRegistry $doctrineModuleTools $moduleTools)
  44.     {
  45.         $this->em $doctrine->getManager();
  46.         $this->moduleTools $moduleTools;
  47.         $this->aclRepository $this->em->getRepository(Acl::class);
  48.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  49.     }
  50.     // Plan.io Task #4453 [See AccessVoter for details]
  51.     public function supportsAttribute(string $attribute): bool
  52.     {
  53.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  54.     }
  55.     
  56.     protected function supports(string $attribute$subject): bool
  57.     {
  58.         // if the attribute isn't one we support, return false
  59.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  60.         {
  61.             return false;
  62.         }
  63.         // only vote on Inode objects inside this voter
  64.         if ($subject !== null)
  65.         {
  66.             if (!$subject instanceof Inode)
  67.             {
  68.                 return false;
  69.             }
  70.         }
  71.         return true;
  72.     }
  73.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  74.     {
  75.         $user $token->getUser();
  76.         if (!$user instanceof Access)
  77.         {
  78.             // the user must be logged in; if not, deny access
  79.             return false;
  80.         }
  81.         // The user must have a function; if not deny access
  82.         $function $user->getFunction();
  83.         if ($function === null)        return false;
  84.         // Plan.io Task #3710 : Get current group
  85.         $currentGroup $user->getSocietyGroup();
  86.         if ($currentGroup === null)
  87.             return false;
  88.         // Module activated ?
  89.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_CLOUD))
  90.         {
  91.             return false;
  92.         }
  93.         // you know $subject is a Inode object, thanks to supports
  94.         /** @var Inode $inode */
  95.         $inode $subject;
  96.         // Check current group affectation
  97.         if ($subject !== null)
  98.         {
  99.             $subjectGroup $subject->getSocietyGroup();
  100.             if ($subjectGroup === null)
  101.                 return false;
  102.             if (!$currentGroup->equals($subjectGroup))
  103.                 return false;
  104.         }
  105.         switch ($attribute)
  106.         {
  107.             case self::IS_ACTIVE:
  108.                 return true;
  109.             case self::ADD:
  110.                 return $this->canAdd($inode$user$function);
  111.             case self::VIEW:
  112.                 return $this->canView($inode$user$function);
  113.             case self::EDIT:
  114.                 return $this->canEdit($inode$user$function);
  115.             case self::MOVE:
  116.                 return $this->canMove($inode$user$function);
  117.             case self::SHARE:
  118.                 return $this->canShare($inode$user$function);
  119.             case self::DELETE:
  120.                 return $this->canDelete($inode$user$function);
  121.         }
  122.         throw new \LogicException('This code should not be reached!');
  123.     }
  124.     private function canAdd(Inode $inode nullAccess $accessAccessFunction $function)
  125.     {
  126.         // This should not happen
  127.         if ($inode === null)
  128.         {
  129.             // Get AclPermission
  130.             $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD);
  131.             if ($aclPerm === null)        return false;
  132.             // Get Acl
  133.             $acl $this->aclRepository->findOneBy(array(
  134.                 'function'        =>    $function,
  135.                 'permission'    =>    $aclPerm
  136.             ));
  137.             if ($acl === null)        return false;
  138.             return $acl->getValue();
  139.         }
  140.         // Case 1 : Inode is root or owned by the access
  141.         //     => Check ADD permission from the acl
  142.         if ($inode->isRoot() || $inode->isOwnedBy($access))
  143.         {
  144.             // Get AclPermission
  145.             $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ADD);
  146.             if ($aclPerm === null)        return false;
  147.             // Get Acl
  148.             $acl $this->aclRepository->findOneBy(array(
  149.                 'function'        =>    $function,
  150.                 'permission'    =>    $aclPerm
  151.             ));
  152.             if ($acl === null)        return false;
  153.             return $acl->getValue();
  154.         }
  155.         // Case 2 : Inode is not root, and not owned by the access
  156.         //     =>    Check if one of its parents is shared with the access
  157.         // In this case, we need to chekc acl EDIT permission
  158.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SHARED);
  159.         if ($aclPerm === null)        return false;
  160.         // Get Acl
  161.         $acl $this->aclRepository->findOneBy(array(
  162.             'function'        =>    $function,
  163.             'permission'    =>    $aclPerm
  164.         ));
  165.         if ($acl === null)        return false;
  166.         if ($acl->getValue())
  167.         {
  168.             // The access has permission to edit shared inodes
  169.             return $inode->isSharedWith($access);
  170.         }
  171.         // All hope is lost
  172.         return false;
  173.     }
  174.     private function canShare(Inode $inode nullAccess $accessAccessFunction $function)
  175.     {
  176.         // Get AclPermission
  177.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_SHARE);
  178.         if ($aclPerm === null)        return false;
  179.         // Get Acl
  180.         $acl $this->aclRepository->findOneBy(array(
  181.             'function'        =>    $function,
  182.             'permission'    =>    $aclPerm
  183.         ));
  184.         if ($acl === null)        return false;
  185.         // Since only one list type can exist for the Inodes,
  186.         // we can return the result of the acl_permission
  187.         return $acl->getValue();
  188.     }
  189.     private function canView(Inode $inode nullAccess $accessAccessFunction $function)
  190.     {
  191.         // All users can view root
  192.         if ($inode->isRoot())
  193.             return true;
  194.         // All user can view own Inodes
  195.         if ($inode->isOwnedBy($access))
  196.             return true;
  197.         // All user can view shared Inodes
  198.         if ($inode->isSharedWith($access))
  199.             return true;
  200.         return false;
  201.     }
  202.     private function canMove(Inode $inode nullAccess $accessAccessFunction $function)
  203.     {
  204.         // Deny for root
  205.         if ($inode->isRoot())
  206.             return false;
  207.         // All user can move own Inodes
  208.         if ($inode->isOwnedBy($access))
  209.             return true;
  210.         // All user can move shared Inodes
  211.         if ($inode->isSharedWith($access))
  212.             return true;
  213.         return false;
  214.     }
  215.     private function canEdit(Inode $inode nullAccess $accessAccessFunction $function)
  216.     {
  217.         if ($inode->isRoot())
  218.             return false;
  219.         // All user can edit own Inodes
  220.         if ($inode->isOwnedBy($access))
  221.             return true;
  222.         // Get AclPermission
  223.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_EDIT_SHARED);
  224.         if ($aclPerm === null)        return false;
  225.         // Get Acl
  226.         $acl $this->aclRepository->findOneBy(array(
  227.             'function'        =>    $function,
  228.             'permission'    =>    $aclPerm
  229.         ));
  230.         if ($acl === null)        return false;
  231.         if ($acl->getValue())
  232.         {
  233.             // The access has permission to edit shared inodes
  234.             return $inode->isSharedWith($access);
  235.         }
  236.         // All hope is lost
  237.         return false;
  238.     }
  239.     private function canDelete(Inode $inode nullAccess $accessAccessFunction $function)
  240.     {
  241.         if ($inode->isRoot())
  242.             return false;
  243.         // All user can delete own Inodes
  244.         if ($inode->isOwnedBy($access))
  245.             return true;
  246.         // Get AclPermission
  247.         $aclPerm $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DELETE_SHARED);
  248.         if ($aclPerm === null)        return false;
  249.         // Get Acl
  250.         $acl $this->aclRepository->findOneBy(array(
  251.             'function'        =>    $function,
  252.             'permission'    =>    $aclPerm
  253.         ));
  254.         if ($acl === null)        return false;
  255.         if ($acl->getValue())
  256.         {
  257.             // The access has permission to delete shared inodes
  258.             return $inode->isSharedWith($access);
  259.         }
  260.         // All hope is lost
  261.         return false;
  262.     }
  263. }