2022-09-29 22:09:49 +02:00

113 lines
3.1 KiB
PHP

<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\MainBundle\Security\Authorization;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
use UnexpectedValueException;
use function in_array;
class EntityWorkflowVoter extends Voter
{
public const CREATE = 'CHILL_MAIN_WORKFLOW_CREATE';
public const DELETE = 'CHILL_MAIN_WORKFLOW_DELETE';
public const SEE = 'CHILL_MAIN_WORKFLOW_SEE';
public const SHOW_ENTITY_LINK = 'CHILL_MAIN_WORKFLOW_LINK_SHOW';
private EntityWorkflowManager $manager;
private Security $security;
public function __construct(EntityWorkflowManager $manager, Security $security)
{
$this->manager = $manager;
$this->security = $security;
}
protected function supports($attribute, $subject)
{
return $subject instanceof EntityWorkflow && in_array($attribute, self::getRoles(), true);
}
/**
* @param EntityWorkflow $subject
* @param mixed $attribute
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
switch ($attribute) {
case self::CREATE:
case self::SEE:
$handler = $this->manager->getHandler($subject);
$entityAttribute = $handler->getRoleShow($subject);
if (null === $entityAttribute) {
return true;
}
$relatedEntity = $handler->getRelatedEntity($subject);
if (null === $relatedEntity) {
return true;
}
if ($this->security->isGranted($entityAttribute, $relatedEntity)) {
return true;
}
foreach ($subject->getSteps() as $step) {
if ($step->getAllDestUser()->contains($token->getUser())) {
return true;
}
}
return false;
case self::DELETE:
return $subject->getStep() === 'initial';
case self::SHOW_ENTITY_LINK:
if ($subject->getStep() === 'initial') {
return false;
}
$currentStep = $subject->getCurrentStepChained();
if ($currentStep->isFinal()) {
return false;
}
return $currentStep->getPrevious()->getTransitionBy() === $this->security->getUser();
default:
throw new UnexpectedValueException("attribute {$attribute} not supported");
}
}
private static function getRoles(): array
{
return [
self::SEE,
self::CREATE,
self::DELETE,
self::SHOW_ENTITY_LINK,
];
}
}