<?php
//------------------------------------------------------------------------------
// src/Security/PlanningVoter.php
// OK #4453 : VoterCache
//------------------------------------------------------------------------------
namespace App\Security;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use App\Entity\Access;
use App\Entity\Config\Module;
use App\Entity\Config\OptionConfig;
use App\Entity\HR\AccessFunction;
use App\Entity\Security\Acl;
use App\Entity\Security\AclPermission;
use App\Services\Config\ModuleTools;
use App\Services\LogTools;
class PlanningVoter extends Voter
{
//--------------------------------------------------------------------------------
// is_granted constants
const IS_ACTIVE = "planning_is_active";
const LOAD_GLOBAL_PLANNING = "planning_global_view";
const LOAD_INDIVIDUAL_PLANNING = "planning_individual_view";
const DECLARE_AVAILABILITIES = "planning_declare_availabilities";
const VIEW_NUMBER_GLOBAL_PLANNING = "planning_global_view_number";
const ORGANIZE_PLANNING_RESOURCES = "planning_global_organize_planning_resources";
const PLANNING_OPTIMISATION_IS_ACTIVE = "planning_optimisation_is_active";
const OPTIMISE_PLANNING = "optimise_planning";
//--------------------------------------------------------------------------------
const IS_GRANTED_CONSTANTS = array(
self::IS_ACTIVE,
self::LOAD_GLOBAL_PLANNING,
self::LOAD_INDIVIDUAL_PLANNING,
self::DECLARE_AVAILABILITIES,
self::VIEW_NUMBER_GLOBAL_PLANNING,
self::ORGANIZE_PLANNING_RESOURCES,
self::PLANNING_OPTIMISATION_IS_ACTIVE,
self::OPTIMISE_PLANNING,
);
//--------------------------------------------------------------------------------
// acl constants
const ACL_PERM_LOAD_GLOBAL_PLANNING = "planning_global_view";
const ACL_PERM_LOAD_INDIVIDUAL_PLANNING = "planning_individual_view";
const ACL_PERM_DECLARE_AVAILABILITIES = "planning_declare_availabilities";
const ACL_PERM_VIEW_NUMBER_GLOBAL_PLANNING = "planning_global_view_number";
const ACL_PERM_ORGANIZE_PLANNING_RESOURCES = "planning_global_organize_planning_resources";
const ACL_PERM_OPTIMISE_PLANNING = "optimise_planning";
//--------------------------------------------------------------------------------
public function __construct(ManagerRegistry $doctrine, ModuleTools $moduleTools, LogTools $logTools)
{
$this->em = $doctrine->getManager();
$this->moduleTools = $moduleTools;
$this->logTools = $logTools;
$this->aclRepository = $this->em->getRepository(Acl::class);
$this->aclPermissionRepository = $this->em->getRepository(AclPermission::class);
}
// Plan.io Task #4453 [See AccessVoter for details]
public function supportsAttribute(string $attribute): bool
{
return in_array($attribute, self::IS_GRANTED_CONSTANTS, true);
}
protected function supports(string $attribute, $subject = null): bool
{
// if the attribute isn't one we support, return false
if (!in_array($attribute, self::IS_GRANTED_CONSTANTS))
{
return false;
}
// No object here
return true;
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof Access)
{
// the user must be logged in; if not, deny access
return false;
}
// The user must have a function; if not deny access
$function = $user->getFunction();
if ($function === null) return false;
// Plan.io Task #3710 : Get current group
$currentGroup = $user->getSocietyGroup();
if ($currentGroup === null)
return false;
// This is needed to check HumanResource Module in canLoadGlobalPlanning
$this->currentGroup = $currentGroup;
// Module activated ?
if ($this->moduleTools->isInactiveByCode($currentGroup, Module::MODULE_PLANNING))
{
return false;
}
switch ($attribute)
{
case self::IS_ACTIVE:
return true;
case self::LOAD_GLOBAL_PLANNING:
return $this->canLoadGlobalPlanning($user, $function);
case self::LOAD_INDIVIDUAL_PLANNING:
return $this->canLoadIndividualPlanning($user, $function);
case self::DECLARE_AVAILABILITIES:
return $this->canDeclareAvailabilities($user, $function);
case self::VIEW_NUMBER_GLOBAL_PLANNING:
return $this->canViewNumberGlobalPlanning($user, $function);
case self::ORGANIZE_PLANNING_RESOURCES:
return $this->canOrganizePlanningResources($user, $function);
case self::PLANNING_OPTIMISATION_IS_ACTIVE:
return $this->planningOptimisationIsActive($user, $function);
case self::OPTIMISE_PLANNING:
return $this->canOptimisePlanning($user, $function);
}
throw new \LogicException('This code should not be reached!');
}
private function canLoadGlobalPlanning(Access $access, AccessFunction $function)
{
// Si le module Ressources humaines n'est pas activé, accès au planning individuel uniquement
if ($this->moduleTools->isInactiveByCode($this->currentGroup, Module::MODULE_HUMAN_RESOURCE))
{
return false;
}
// Get Acl_Permission
$aclPerm = $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LOAD_GLOBAL_PLANNING);
if ($aclPerm === null) return false;
// Get Acl
$acl = $this->aclRepository->findOneBy(array(
'function' => $function,
'permission' => $aclPerm
));
if ($acl === null) return false;
return $acl->getValue();
}
private function canLoadIndividualPlanning(Access $access, AccessFunction $function)
{
// Get Acl_Permission
$aclPerm = $this->aclPermissionRepository->findOneByName(self::ACL_PERM_LOAD_INDIVIDUAL_PLANNING);
if ($aclPerm === null) return false;
// Get Acl
$acl = $this->aclRepository->findOneBy(array(
'function' => $function,
'permission' => $aclPerm
));
if ($acl === null) return false;
return $acl->getValue();
}
private function canDeclareAvailabilities(Access $access, AccessFunction $function)
{
// Get Acl_Permission
$aclPerm = $this->aclPermissionRepository->findOneByName(self::ACL_PERM_DECLARE_AVAILABILITIES);
if ($aclPerm === null) return false;
// Get Acl
$acl = $this->aclRepository->findOneBy(array(
'function' => $function,
'permission' => $aclPerm
));
if ($acl === null) return false;
return $acl->getValue();
}
private function canViewNumberGlobalPlanning(Access $access, AccessFunction $function)
{
// Get Acl_Permission
$aclPerm = $this->aclPermissionRepository->findOneByName(self::ACL_PERM_VIEW_NUMBER_GLOBAL_PLANNING);
if ($aclPerm === null) return false;
// Get Acl
$acl = $this->aclRepository->findOneBy(array(
'function' => $function,
'permission' => $aclPerm
));
if ($acl === null) return false;
return $acl->getValue();
}
private function canOrganizePlanningResources(Access $access, AccessFunction $function)
{
// Si le module Ressources humaines n'est pas activé, accès au planning individuel uniquement
if ($this->moduleTools->isInactiveByCode($this->currentGroup, Module::MODULE_HUMAN_RESOURCE))
{
return false;
}
// Get Acl_Permission
$aclPerm = $this->aclPermissionRepository->findOneByName(self::ACL_PERM_ORGANIZE_PLANNING_RESOURCES);
if ($aclPerm === null) return false;
// Get Acl
$acl = $this->aclRepository->findOneBy(array(
'function' => $function,
'permission' => $aclPerm
));
if ($acl === null) return false;
return $acl->getValue();
}
private function planningOptimisationIsActive()
{
// Check if option "planning_optimisation" is active in module planning
$planningOptimisationConfig = $this->em->getRepository(OptionConfig::class)
->findOneBy(array(
'code' => OptionConfig::PLANNING_OPTIMISATION_CODE,
'societyGroup' => $this->currentGroup,
));
if ($planningOptimisationConfig !== null)
{
return $planningOptimisationConfig->getValue();
}
return false;
}
private function canOptimisePlanning(Access $access, AccessFunction $function)
{
// Check if option "planning_optimisation" is active in module planning
if (!$this->planningOptimisationIsActive())
{
return false;
}
// Get Acl_Permission
$aclPerm = $this->aclPermissionRepository->findOneByName(self::ACL_PERM_OPTIMISE_PLANNING);
if ($aclPerm === null) return false;
// Get Acl
$acl = $this->aclRepository->findOneBy(array(
'function' => $function,
'permission' => $aclPerm
));
if ($acl === null) return false;
return $acl->getValue();
}
}