2012-10-11 9 views
7

Ich habe eine Sonata-Admin-Schnittstelle eingerichtet, mit der Benutzer bestimmte Inhalte erstellen können, aber wie schränke ich Benutzer von der Bearbeitung von Inhalten von anderen Benutzern erstellt?Sonata Admin - Nur zeigen, was eingeloggt Benutzer erstellt hat

Aus Gründen der Argumente meldet sich ein Benutzer an und erstellt ein Blog. In der Listenansicht von Blogs sollten nur die Blogs angezeigt werden, die von erstellt wurden.

Momentan wird alles für jeden Benutzer angezeigt - ich habe Gruppen/Rollen eingerichtet, um den Zugriff auf Admin-Bereiche zu beschränken, was gut funktioniert.

Die einzige Möglichkeit, die ich derzeit nur daran denken kann, einen bestimmten angemeldeten Benutzer Inhalte anzuzeigen, ist es, die Vorlagen zu überschreiben?

Aber sicherlich ist dies eine offensichtliche und einfache Konfigurationseinstellung?

Antwort

13

Es gibt mehr Möglichkeiten, wie nur Daten von aktuell angemeldeten Benutzer anzuzeigen:

Die erste bevorzugte Art und Weise ist Symfony's ACL zu verwenden, sind hier more informations, how it works and how to do it in Sonata.

Wenn Sie keine ACL verwenden möchten, können Sie die Standardabfragen ändern, indem Sie eine Bedingung zur SQL-Abfrage (DQL-Abfrage) hinzufügen, z. B. 'WHERE adminId = 5'. Das wird mehr Arbeit sein, aber ich werde Ihnen ein einfaches Beispiel zeigen, wie es geht.

Ändern Sie die Definition Ihrer Verwaltungsdienste in services.xml, indem Sie einen neuen Setter hinzufügen setSecurityContext. Ich werde Admin verwenden, um einige Produkte aufzulisten und zu bearbeiten.

<service id="acme_demo_admin.product" class="Acme\Bundle\DemoAdminBundle\Admin\ProductAdmin"> 
     <tag name="sonata.admin" manager_type="orm" group="product_group" label_catalogue="admin" label="Products"/> 
     <argument /> 
     <argument>Acme\Bundle\DemoAdminBundle\Entity\Product</argument> 
     <argument>AcmeDemoAdminBundle:ProductAdmin</argument> 

     <call method="setSecurityContext"> 
      <argument type="service" id="security.context" /> 
     </call> 
    </service> 

SecurityContext ist ein Dienst, der Informationen über den aktuell angemeldeten Benutzer enthält.

In Acme/Bundle/DemoAdminBundle/Admin/ProductAdmin.php Setter setSecurityContext hinzufügen und Create Methode ändern:

<?php 

namespace Acme\Bundle\DemoAdminBundle\Admin; 

use Symfony\Component\Security\Core\SecurityContextInterface; 
// ... 

class ProductAdmin extends Admin 
{ 
    /** 
    * Security Context 
    * @var \Symfony\Component\Security\Core\SecurityContextInterface 
    */ 
    protected $securityContext; 

    public function setSecurityContext(SecurityContextInterface $securityContext) 
    { 
     $this->securityContext = $securityContext; 
    } 

    protected function configureRoutes(RouteCollection $collection) 
    { 
     //remove all routes except those, you are using in admin and you can secure by yourself 
     $collection 
       ->clearExcept(array(
        'list', 
        'edit', 
       )) 
     ; 
    } 

    public function createQuery($context = 'list') 
    { 
     $queryBuilder = $this->getModelManager()->getEntityManager($this->getClass())->createQueryBuilder(); 

     //if is logged admin, show all data 
     if ($this->securityContext->isGranted('ROLE_ADMIN')) { 
      $queryBuilder->select('p') 
        ->from($this->getClass(), 'p') 
      ; 
     } else { 
      //for other users, show only data, which belongs to them 
      $adminId = $this->securityContext->getToken()->getUser()->getAdminId(); 

      $queryBuilder->select('p') 
        ->from($this->getClass(), 'p') 
        ->where('p.adminId=:adminId') 
        ->setParameter('adminId', $adminId, Type::INTEGER) 
      ; 
     } 

     $proxyQuery = new ProxyQuery($queryBuilder); 
     return $proxyQuery; 
    } 

    //... configureListFields, configureDatagridFilters etc. 
} 

Benutzer ohne Rolle SONATA_ADMIN nicht alle Datensätze sehen können.

Zweiter Schritt - sichere einige spezielle Routen, zum Beispiel bearbeiten - Sie sollten überprüfen, ob der gerade angemeldete Administrator das angegebene Produkt bearbeiten kann.

Sie können Ihre own security voter (bevorzugte Lösung) erstellen oder benutzerdefinierte CRUD-Controller verwenden.

In benutzerdefinierten CRUD-Controller: Acme/Bundle/DemoAdminBundle/Controller/ProductController.php überladen editAction.

<?php 
    namespace Acme\Bundle\DemoAdminBundle\Controller; 

    use Sonata\AdminBundle\Controller\CRUDController as Controller; 
    use Symfony\Component\Security\Core\Exception\AccessDeniedException; 


    class ProductAdminController extends Controller 
    { 
     public function editAction($id = null) 
     { 
      $request = $this->getRequest(); 
      $id = $request->get($this->admin->getIdParameter()); 

      $securityContext = $this->get('security.context'); 
      if (!$securityContext->isGranted('ROLE_ADMIN')) { 

       $adminId = $securityContext->getToken()->getUser()->getId(); 

       $accessGranted = //here you should check if user with adminId can edit product with $id 

       if (!$accessGranted) { 
        throw new AccessDeniedException(sprintf('Admin ID %s has no access to product with id %s', $adminId, $id)); 
       } 
      } 

      return parent::editAction($id); 
     } 

    } 

Wie Sie sehen können, können Sie viele Methoden und Routen überladen, um jede Funktionalität hinzuzufügen, die Sie benötigen. Aber wie gesagt, das ist mehr Arbeit, also prüfen Sie zuerst, ob Symfony's ACL (oder einfach nur einen eigenen Sicherheitsvoter erstellen) in Ihrem Projekt benötigt wird oder nicht.

+0

Für die Sicherung des Zugangs wäre es vielleicht besser mit einem [Voter] (http://symfony.com/doc/master/cookbook/security/voters.html). –

+0

In der Tat. Ich habe die Antwort aktualisiert. Vielen Dank. – pulzarraider

Verwandte Themen