mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 14:43:49 +00:00
create voter which blocks deletion if a workflow exists
This commit is contained in:
@@ -256,6 +256,13 @@ class ChillMainExtension extends Extension implements
|
||||
'channels' => ['chill'],
|
||||
]);
|
||||
|
||||
$container->prependExtensionConfig('security', [
|
||||
'access_decision_manager' => [
|
||||
'strategy' => 'unanimous',
|
||||
'allow_if_all_abstain' => false,
|
||||
],
|
||||
]);
|
||||
|
||||
//add crud api
|
||||
$this->prependCruds($container);
|
||||
}
|
||||
|
@@ -55,6 +55,30 @@ class EntityWorkflowRepository implements ObjectRepository
|
||||
return (int) $qb->getQuery()->getSingleScalarResult();
|
||||
}
|
||||
|
||||
public function countRelatedWorkflows(array $relateds): int
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('w');
|
||||
|
||||
$orX = $qb->expr()->orX();
|
||||
$i = 0;
|
||||
|
||||
foreach ($relateds as $related) {
|
||||
$orX->add(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('w.relatedEntityClass', ':entity_class_' . $i),
|
||||
$qb->expr()->eq('w.relatedEntityId', ':entity_id_' . $i)
|
||||
)
|
||||
);
|
||||
$qb
|
||||
->setParameter('entity_class_' . $i, $related['entityClass'])
|
||||
->setParameter('entity_id_' . $i, $related['entityId']);
|
||||
++$i;
|
||||
}
|
||||
$qb->where($orX);
|
||||
|
||||
return $qb->select('COUNT(w)')->getQuery()->getSingleScalarResult();
|
||||
}
|
||||
|
||||
public function find($id): ?EntityWorkflow
|
||||
{
|
||||
return $this->repository->find($id);
|
||||
|
@@ -0,0 +1,65 @@
|
||||
<?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\Repository\Workflow\EntityWorkflowRepository;
|
||||
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
use function in_array;
|
||||
use function is_object;
|
||||
|
||||
class WorkflowEntityDeletionVoter extends Voter
|
||||
{
|
||||
private EntityWorkflowRepository $entityWorkflowRepository;
|
||||
|
||||
/**
|
||||
* @var iterable|EntityWorkflowHandlerInterface[]
|
||||
*/
|
||||
private iterable $handlers;
|
||||
|
||||
public function __construct($handlers, EntityWorkflowRepository $entityWorkflowRepository)
|
||||
{
|
||||
$this->handlers = $handlers;
|
||||
$this->entityWorkflowRepository = $entityWorkflowRepository;
|
||||
}
|
||||
|
||||
protected function supports($attribute, $subject)
|
||||
{
|
||||
if (!is_object($subject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($this->handlers as $handler) {
|
||||
if ($handler->isObjectSupported($subject)
|
||||
&& in_array($attribute, $handler->getDeletionRoles($subject), true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
||||
{
|
||||
foreach ($this->handlers as $handler) {
|
||||
if ($handler->isObjectSupported($subject)) {
|
||||
return 0 === $this->entityWorkflowRepository->countRelatedWorkflows(
|
||||
$handler->getRelatedObjects($subject)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException('no handlers found');
|
||||
}
|
||||
}
|
@@ -15,12 +15,19 @@ use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
|
||||
|
||||
interface EntityWorkflowHandlerInterface
|
||||
{
|
||||
/**
|
||||
* @return array|string[]
|
||||
*/
|
||||
public function getDeletionRoles(): array;
|
||||
|
||||
public function getEntityData(EntityWorkflow $entityWorkflow, array $options = []): array;
|
||||
|
||||
public function getEntityTitle(EntityWorkflow $entityWorkflow, array $options = []): string;
|
||||
|
||||
public function getRelatedEntity(EntityWorkflow $entityWorkflow): ?object;
|
||||
|
||||
public function getRelatedObjects(object $object): array;
|
||||
|
||||
/**
|
||||
* Return a string representing the role required for seeing the workflow.
|
||||
*
|
||||
@@ -33,6 +40,8 @@ interface EntityWorkflowHandlerInterface
|
||||
|
||||
public function getTemplateData(EntityWorkflow $entityWorkflow, array $options = []): array;
|
||||
|
||||
public function isObjectSupported(object $object): bool;
|
||||
|
||||
public function supports(EntityWorkflow $entityWorkflow, array $options = []): bool;
|
||||
|
||||
public function supportsFreeze(EntityWorkflow $entityWorkflow, array $options = []): bool;
|
||||
|
@@ -75,3 +75,9 @@ services:
|
||||
$locker: '@Chill\MainBundle\Security\PasswordRecover\PasswordRecoverLocker'
|
||||
tags:
|
||||
- { name: security.voter }
|
||||
|
||||
Chill\MainBundle\Security\Authorization\WorkflowEntityDeletionVoter:
|
||||
autoconfigure: true
|
||||
autowire: true
|
||||
arguments:
|
||||
$handlers: !tagged_iterator chill_main.workflow_handler
|
||||
|
Reference in New Issue
Block a user