Closed KCahuete closed 6 years ago
If someone is looking for a way to do this, I manage to make this security check by adding a listener on kernel.controller.
services.yml
mybundle.listener.before_controller:
class: MybundleBundle\Listener\BeforeControllerListener
arguments: ["@security.token_storage", "@mgilet.notification"]
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
BeforeControllerListener
<?php
namespace MybundleBundle\Listener;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Mgilet\NotificationBundle\Controller\NotificationController;
use Mgilet\NotificationBundle\Manager\NotificationManager;
class BeforeControllerListener
{
protected $tokenStorage;
protected $notificationManager;
public function __construct(TokenStorage $tokenStorage, NotificationManager $notificationManager)
{
$this->tokenStorage = $tokenStorage;
$this->notificationManager = $notificationManager;
}
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
$request = $event->getRequest();
if (!is_array($controller)) {
// not an object but a different kind of callable. Do nothing
return;
}
$controllerObject = $controller[0];
// skip initializing for exceptions
if ($controllerObject instanceof ExceptionController) {
return;
}
/**
* Security check of MgiletNotificationBundle
* Not allowing access of controller if notifiable entity is not matching current user
*/
if($controllerObject instanceof NotificationController && $notifiable = $request->attributes->get('notifiable')) {
if($this->notificationManager->getNotifiableInterface($this->notificationManager->getNotifiableEntityById($notifiable)) != $this->getUser())
throw new AccessDeniedException();
}
}
/**
* Get a user from the Security Token Storage.
* Equivalent of controller getUser() method
*
* @return mixed
*/
protected function getUser()
{
if (!$this->tokenStorage) {
return;
}
if (null === $token = $this->tokenStorage->getToken()) {
return;
}
if (!\is_object($user = $token->getUser())) {
// e.g. anonymous authentication
return;
}
return $user;
}
}
This is a great example, thanks !
The bundle is intended to be used with any entity (not only users) so this could be a nice addition in the docs for common use cases 👍
Hi Maximilien, I saw that everyone can access the routes, and see the notifications, mark them as seen, etc. Shouldn't there be some control to be sure that the current user is matching the notifiable entity?