Symfony: Security context in doctrine filters
I one of my recent projects, I wanted to use doctrine filters to dynamically alter queries based on, which role the currently logged-in user had. I wanted to use this to automatically filter inactive entities - based on the `active` property, when the user is not an admin user.
My first approach was to use Symfony's dependency injection, which however, does not work with Doctrine filters. There wasn't a clear solution to this neither in the Symfony nor the Doctrine documentation. So needed to experiment a little. I finally found a solution, using the `loadClassMetadata` event in Doctrine. So I created an event listener:
<?php
namespace MyVendor\MyPackage\EventListener;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Events;
use Symfony\Bundle\SecurityBundle\Security;
#[AsDoctrineListener(event: Events::loadClassMetadata)]
class DoctrineFilterSecurityListener
{
public function __construct(protected Security $security)
{
}
public function __invoke(LoadClassMetadataEventArgs $event): void
{
foreach ($event->getEntityManager()->getFilters()->getEnabledFilters() as $filter) {
if (is_callable([$filter, 'setSecurity'])) {
$filter->setSecurity($this->security);
}
}
}
}
My filter looked like this:
<?php
namespace MyVendor\MyPackage\Doctrine\Filter;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\Filter\SQLFilter;
use Symfony\Bundle\SecurityBundle\Security;
use MyVendor\MyPackage\Entity\Story;
class StoryActiveFilter extends SQLFilter
{
protected Security $security;
public function setSecurity(Security $security): void
{
$this->security = $security;
}
public function addFilterConstraint(ClassMetadata $targetEntity, string $targetTableAlias): string
{
if ($targetEntity->getReflectionClass()->getName() === Story::class && !$this->security->isGranted('ROLE_ADMIN')) {
return sprintf('%s.active = 1', $targetTableAlias);
}
return '';
}
}
Feel free to use, adapt and share. Leave a comment below and help me improve my articles.
Dette website bruger Disqus for at vise kommentarer. På grund af databeskyttelsesregler (GDPR) skal du godkende brugen af eksterne tjenester som Disqus.
Vis kommentarer