Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 - Create a Doctrine filter to select current user data

I'm building a Saas / Multitenant application using Symfony 2. I've created a Doctrine event-subscriber to add and update the owner of a row, the user who created it, the user who modified it, timestamps and so.

And now I need to implement some kind of filter so when a user is logged in, he only can see data from his company. My first though was using a Doctrine preLoad event, but this event doesn't exist... As far as I know, I must use Doctrine filters, isn't it? If so, how can this filter access user data to read the company id? Must I inject it using the Dependency Injection? Is there any standard way to accomplish my goal?

UPDATE What I'm looking for is to create some kind of Doctrine plugin/hook so everytime I call any function that fetch data from the database (find, findOneBy, etc), and the entity I'm fetching implements a particular interface, an extra 'AND company_id=:id' SQL sequence is added to the generated query, so neither the controller or the model receives data from other companies.

like image 984
mHouses Avatar asked May 19 '14 21:05

mHouses


1 Answers

For this you can use a DoctrineFilter Link from official doc Doctrine2 SQL Filters

namespace Rwmt\Bundle\RwmtBundle\DoctrineFilters;

use Doctrine\ORM\Mapping\ClassMetaData,
    Doctrine\ORM\Query\Filter\SQLFilter;

class MultiTenantFilter extends SQLFilter
{
    public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
    {
        // Check if the entity implements the MultiTenant interface
        if (!$targetEntity->reflClass->implementsInterface('Rwmt\Bundle\RwmtBundle\Entity\MultiTenant')) {
            return "";
        }

        return $targetTableAlias.'.tenant_id = ' . $this->getParameter('tenantId');
    }
}

And to set the parameter tenantId used in the filter you must enable the filter and set the parameter

$filter = $em->getFilters()->enable('multi_tenant');
$filter->setParameter('tenantId', $tenant->getId(), 'integer');

As for the MultiTenant interface is just something for the entities to implement

namespace Rwmt\Bundle\RwmtBundle\Entity;
use Rwmt\Bundle\RwmtBundle\Entity\Tenant;

interface MultiTenant
{
    public function setTenant(Tenant $tenant);
    public function getTenant();
}
like image 174
Stev Avatar answered Oct 13 '22 19:10

Stev