From ebc0961fa8f446be21f78871624f5dba79efbbc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 17 Jul 2018 15:28:04 +0200 Subject: [PATCH] use event to override vote on task Now, the bundle dispatch an event `chill_task.vote` to override the authorization on voting on a task. If a subscriber or listener emits a vote on the event, this vote override the logic defined for the default task. --- Resources/config/services/security.yml | 1 + Security/Authorization/AuthorizationEvent.php | 89 +++++++++++++++++++ Security/Authorization/TaskVoter.php | 25 ++++++ 3 files changed, 115 insertions(+) create mode 100644 Security/Authorization/AuthorizationEvent.php diff --git a/Resources/config/services/security.yml b/Resources/config/services/security.yml index 0acc6e56f..e58fd19e3 100644 --- a/Resources/config/services/security.yml +++ b/Resources/config/services/security.yml @@ -4,6 +4,7 @@ services: arguments: - "@security.access.decision_manager" - "@chill.main.security.authorization.helper" + - '@Symfony\Component\EventDispatcher\EventDispatcherInterface' - "@logger" tags: - { name: security.voter } diff --git a/Security/Authorization/AuthorizationEvent.php b/Security/Authorization/AuthorizationEvent.php new file mode 100644 index 000000000..7cdc25b55 --- /dev/null +++ b/Security/Authorization/AuthorizationEvent.php @@ -0,0 +1,89 @@ + + */ +class AuthorizationEvent extends Event +{ + /** + * @var AbstractTask + */ + protected $task; + + /** + * + * @var string + */ + protected $attribute; + + /** + * + * @var TokenInterface + */ + protected $token; + + /** + * + * @var bool + */ + protected $vote; + + const VOTE = 'chill_task.vote'; + + public function __construct( + AbstractTask $task, + $attribute, + TokenInterface $token + ) { + $this->task = $task; + $this->attribute = $attribute; + $this->token = $token; + } + + public function getTask(): AbstractTask + { + return $this->task; + } + + public function getAttribute() + { + return $this->attribute; + } + + public function getToken(): TokenInterface + { + return $this->token; + } + + public function getVote() + { + return $this->vote; + } + + public function setVote($vote) + { + $this->vote = $vote; + + return $this; + } + + public function hasVote() + { + return $this->vote !== NULL; + } + + public function removeVote() + { + $this->vote = NULL; + } +} diff --git a/Security/Authorization/TaskVoter.php b/Security/Authorization/TaskVoter.php index ad8895892..8b8bce839 100644 --- a/Security/Authorization/TaskVoter.php +++ b/Security/Authorization/TaskVoter.php @@ -29,6 +29,8 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Entity\Person; use Symfony\Component\Security\Core\Role\Role; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Chill\TaskBundle\Security\Authorization\AuthorizationEvent; /** * @@ -66,14 +68,22 @@ class TaskVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterf * @var LoggerInterface */ protected $logger; + + /** + * + * @var EventDispatcherInterface + */ + protected $eventDispatcher; public function __construct( AccessDecisionManagerInterface $accessDecisionManager, AuthorizationHelper $authorizationHelper, + EventDispatcherInterface $eventDispatcher, LoggerInterface $logger ) { $this->accessDecisionManager = $accessDecisionManager; $this->authorizationHelper = $authorizationHelper; + $this->eventDispatcher = $eventDispatcher; $this->logger = $logger; } @@ -101,6 +111,21 @@ class TaskVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterf if (!$token->getUser() instanceof User) { return false; } + + $event = new AuthorizationEvent($subject, $attribute, $token); + + $this->eventDispatcher->dispatch(AuthorizationEvent::VOTE, $event); + + if ($event->hasVote()) { + + $this->logger->debug("The TaskVoter is overriding by " + .AuthorizationEvent::VOTE, [ + 'vote' => $event->getVote(), + 'task_id' => $subject->getId() + ]); + + return $event->getVote(); + } if ($subject instanceof AbstractTask) { if ($subject->getPerson() === null) {