2012-10-11 6 views
7

Ho installato un'interfaccia di amministrazione sonata che permette agli utenti di creare contenuti specifici, ma come faccio a impedire agli utenti di modificare i contenuti creati da altri utenti?Sonata Admin - solo permetterà spettacolo quello registrato nel utente ha creato

Per motivi, un utente effettua l'accesso e crea un blog. Nella visualizzazione elenco dei blog, devono essere visualizzati solo i blog creati dall'utente.

Attualmente, tutto viene visualizzato per ogni utente - Ho impostato gruppi/ruoli per limitare l'accesso alle aree di amministrazione, che funziona bene.

L'unico modo che posso attualmente pensare di mostrare solo uno specifico contenuto degli utenti registrati, è di sostituire i modelli?

Ma, sicuramente, questa è un'impostazione di configurazione ovvia e semplice?

risposta

13

ci sono più opzioni come visualizzare solo i dati di utente attualmente connesso:

Il primo modo preferito è quello di utilizzare Symfony's ACL, qui more informations, how it works and how to do it in Sonata.

Se non si desidera utilizzare ACL, è possibile modificare le query predefinite con l'aggiunta di qualche condizione di query SQL (query DQL), per esempio 'WHERE adminId = 5'. Questo sarà più lavoro, ma ti mostrerò un esempio di base, come farlo.

Modificare la definizione dei servizi di amministrazione in services.xml aggiungendo nuovo setter setSecurityContext. Userò admin per elencare e modificare alcuni prodotti.

<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 è un servizio che contiene informazioni sull'utente attualmente registrato.

In Acme/Bundle/DemoAdminBundle/Amministratore/ProductAdmin.php aggiungere setSecurityContext setter e cambiare metodo createQuery:

<?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. 
} 

Gli utenti senza ruolo SONATA_ADMIN non possono vedere tutti i record.

Secondo passaggio - proteggere alcuni percorsi speciali, per exmaple modificare - è necessario verificare se l'amministratore attualmente loggato può modificare il prodotto specificato.

È possibile creare il own security voter (soluzione preferito) o utilizzare personalizzato CRUD Controller.

Nel controller CRUD personalizzato: Acme/Bundle/DemoAdminBundle/Controller/ProductController.php overload 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); 
     } 

    } 

Come si può vedere, è possibile sovraccaricare molti metodi e percorsi di aggiungere qualsiasi funzionalità, è necessario. Ma come ho detto prima, questo è più lavoro, così invece di metodi di sovraccarico, controllare prima se Symfony`s ACL (o semplicemente la creazione di propri votanti di sicurezza) è quello che vi serve nel progetto o meno.

+0

Per assicurare l'accesso forse sarebbe meglio con un [Voter] (http://symfony.com/doc/master/cookbook/security/voters.html). –

+0

Infatti. Ho aggiornato la risposta. Grazie. – pulzarraider

Problemi correlati