<?php
namespace App\Task\Security;
use App\Task\Entity\TaskTemplate;
use App\Task\Entity\TaskTemplateItem;
use AppBundle\Entity\User;
use AppBundle\Enum\FeatureAccessEnum;
use CRMBundle\Entity\Contact;
use SettingsBundle\Enum\ModuleEnum;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
class TaskTemplateVoter extends Voter
{
public const ADD_TASK_TEMPLATE = 'ADD_TASK_TEMPLATE';
public const CHECK_TASK_TEMPLATE_ITEM = 'CHECK_TASK_TEMPLATE_ITEM';
public const EDIT_TASK_TEMPLATE = 'EDIT_TASK_TEMPLATE';
public const EDIT_TASK_TEMPLATE_ITEM = 'EDIT_TASK_TEMPLATE_ITEM';
public const DELETE_TASK_TEMPLATE = 'DELETE_TASK_TEMPLATE';
public const DELETE_TASK_TEMPLATE_ITEM = 'DELETE_TASK_TEMPLATE_ITEM';
public const GET_TASK_TEMPLATE = 'GET_TASK_TEMPLATE';
public const GET_TASK_TEMPLATE_ITEMS = 'GET_TASK_TEMPLATE_ITEMS';
public const CREATE_CONTACT_TASKS = 'CREATE_CONTACT_TASKS';
private Security $security;
public function __construct(Security $security)
{
$this->security = $security;
}
private static array $attributesAlone = [
self::ADD_TASK_TEMPLATE,
self::GET_TASK_TEMPLATE,
self::CHECK_TASK_TEMPLATE_ITEM,
];
private static array $attributesWithTaskTemplate = [
self::EDIT_TASK_TEMPLATE,
self::DELETE_TASK_TEMPLATE,
self::GET_TASK_TEMPLATE_ITEMS,
];
private static array $attributesWithTaskTemplateItem = [
self::EDIT_TASK_TEMPLATE_ITEM,
self::DELETE_TASK_TEMPLATE_ITEM,
];
protected function supports($attribute, $subject): bool
{
switch (true)
{
case in_array($attribute, self::$attributesAlone):
case in_array($attribute, self::$attributesWithTaskTemplate) && $subject instanceof TaskTemplate:
case in_array($attribute, self::$attributesWithTaskTemplateItem) && $subject instanceof TaskTemplateItem:
return true;
case $attribute === self::CREATE_CONTACT_TASKS && ($subject instanceof Contact || $subject instanceof TaskTemplate):
return true;
default:
return false;
}
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
switch ($attribute) {
case self::ADD_TASK_TEMPLATE:
case self::GET_TASK_TEMPLATE:
case self::CHECK_TASK_TEMPLATE_ITEM:
return $this->hasAccess($user);
case self::EDIT_TASK_TEMPLATE:
case self::DELETE_TASK_TEMPLATE:
case self::GET_TASK_TEMPLATE_ITEMS:
/** @var TaskTemplate $subject */
return $this->hasAccess($user) && $subject->getLawFirm() === $user->getLawFirm();
case self::EDIT_TASK_TEMPLATE_ITEM:
case self::DELETE_TASK_TEMPLATE_ITEM:
/** @var TaskTemplateItem $subject */
return $this->hasAccess($user) && $subject->getLawFirm() === $user->getLawFirm();
case self::CREATE_CONTACT_TASKS:
/** @var Contact|TaskTemplate $subject */
return $this->security->isGranted(ModuleEnum::USER_MODULE_TASK_TEMPLATE) &&
$subject->getLawFirm() === $user->getLawFirm();
default:
throw new \LogicException('This code should not be reached');
}
}
private function hasAccess(User $user): bool
{
return $this->security->isGranted(ModuleEnum::USER_MODULE_TASK_TEMPLATE) &&
$user->hasRole(FeatureAccessEnum::LAW_FIRM_ADMIN);
}
}