5
votes

I am using the SonataAdminBundle with FosUserBundle. I have a bit of problems in my dashboard.

In my application, I have resources, companies and users. An user belongs to a company, and can create resources which will belong to his company too. All this procces will be done in the dashboard, which is accessible for all roles.

What I am triying to do is that everybody could access to the dashboard, but when an user select an entity(resource) to list in the dashboard, only the entities of his companies will be shown. For example, two companies could create a vehicle(resource), but each company only will see his own vehicles(resources).

Concluding, I want that the Dashboard filter the entities of the company of the user that is connected. Is there any way to create in the Sonata a query to shown only some entities depending on the Company_Id of the user and the Company_Id of the resource mapped in the BBDD?

3

3 Answers

4
votes

The easiest way is to edit the query and check the access in edit/show actions.

Something like this:

Admin class

/**
 * {@inheritdoc}
 */
public function createQuery($context = 'list')
{
    $user = $this->getConfigurationPool()->getContainer()->get('security.context')->getToken()->getUser();

    /** @var \Sonata\DoctrineORMAdminBundle\Datagrid\ProxyQuery @query */
    $query = $this->getModelManager()->createQuery($this->getClass(), 'o');
    if (!$this->isGranted('MASTER')) {
        $query
            ->where('entity.user = :user')
            ->setParameter('user', $user)
        ;
    }

    return $query;
}

If the user is not MASTER he will only see his own entities.

You can also implement hasSubjectAccess method of the admin class like:

/**
 * Check whether the user has access to the subject
 *
 * @return bool
 */
protected function hasSubjectAccess()
{
    $user = $this->getConfigurationPool()->getContainer()->get('security.context')->getToken()->getUser();
    if (!$this->isGranted('MASTER') && $this->getSubject()->getUser() !== $user) {
        return false;
    }

    return true;
}

and perform this kind of check in edit and show forms:

/**
 * {@inheritdoc}
 */
protected function configureFormFields(FormMapper $formMapper)
{
    if (!$this->hasSubjectAccess()) {
        throw new AccessDeniedException();
    }

    // ...
}

The other way is to implement ACL. You can read more about that in the official documentation

1
votes

Finally, I get it like this:

public function createQuery($context = 'list')
    $query = $this->getModelManager()->createQuery($this->getClass(), 'entity'); 

    if ( ($this->getClass() instanceof \Sademer\CoreBundle\Entity\Resource)
     || ( is_subclass_of($this->getClass(), \Sademer\CoreBundle\Entity\Resource') ) )
    {
          $query->select ('e');
          $query->from($this->getClass(), 'e');
          $query->from('CoreBundle\Entity\Resource', 'r');
          $query->where('e.id = r.id AND r.company = :company');
          $query->setParameter('company', 5);
    }
}
1
votes

For me the createQuery() function didn't work. May be be due to the version of Sonata Admin. Anyways, what worked for me was configureDatagridFilters() function.

It does the same job as createQuery and looks something like this:

protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
    $qb = $datagridMapper
        ->getDatagrid()
        ->getQuery()
        ->getQueryBuilder();

    $qb->andWhere(
        // Your where clause here
    );
    $qb->setParameter(); // Set Parameter
}