2014-09-15 31 views
8

Sto sviluppando un semplice CRUD per gestire utenti/ruoli/gruppi dell'applicazione in cui lavoro. Per gestire gli utenti sto usando FOSUserBundle. Quello che voglio fare può essere fatto in diversi modi:Gestione utenti/ruoli/gruppi in FOSUserBundle

  • Assegnazione dei ruoli ai gruppi e quindi assegnare gli utenti a questi gruppi
  • Assegnazione di ruoli agli utenti direttamente

Ma non ho idea di come fare. Sapevo che la classe FOSUser BaseUser ha già una colonna roles e nello documentation di FOSUser spiega come stabilire una relazione ManyToMany tra utenti e gruppi, ma non parlare di ruoli. L'unica idea che viene in mente è quello di creare un soggetto di gestire i ruoli, nonché un modulo per lo stesso scopo, qualcosa di simile a quello che si vede qui sotto:

Ruolo Entity

use Symfony\Component\Security\Core\Role\RoleInterface; 
use Doctrine\Common\Collections\ArrayCollection; 
use Doctrine\ORM\Mapping as ORM; 

/** 
* @ORM\Table(name="fos_role") 
* @ORM\Entity(repositoryClass="UserBundle\Entity\Repository\RoleRepository") 
* 
* @see User 
* @see \UserBundle\Role\RoleHierarchy 
* 
*/ 
class Role implements RoleInterface 
{ 
    /** 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id() 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @ORM\Column(name="name", type="string", length=80, unique=true) 
    */ 
    private $name; 

    /** 
    * @ORM\ManyToOne(targetEntity="Role", inversedBy="children") 
    * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true) 
    * @var Role[] 
    */ 
    private $parent; 

    /** 
    * @ORM\OneToMany(targetEntity="Role", mappedBy="parent") 
    * @var ArrayCollection|Role[] 
    */ 
    private $children; 

    /** 
    * @ORM\ManyToMany(targetEntity="User", mappedBy="roles") 
    */ 
    private $users; 

    public function __construct($role = "") 
    { 
     if (0 !== strlen($role)) { 
      $this->name = strtoupper($role); 
     } 

     $this->users = new ArrayCollection(); 
     $this->children = new ArrayCollection(); 
    } 

    /** 
    * @see RoleInterface 
    */ 
    public function getRole() 
    { 
     return $this->name; 
    } 

    public function getId() 
    { 
     return $this->id; 
    } 

    public function setId($id) 
    { 
     $this->id = $id; 
    } 

    public function getName() 
    { 
     return $this->name; 
    } 

    public function setName($name) 
    { 
     $this->name = $name; 
    } 

    public function getUsers() 
    { 
     return $this->users; 
    } 

    public function addUser($user, $addRoleToUser = true) 
    { 
     $this->users->add($user); 
     $addRoleToUser && $user->addRole($this, false); 
    } 

    public function removeUser($user) 
    { 
     $this->users->removeElement($user); 
    } 

    public function getChildren() 
    { 
     return $this->children; 
    } 

    public function addChildren(Role $child, $setParentToChild = true) 
    { 
     $this->children->add($child); 
     $setParentToChild && $child->setParent($this, false); 
    } 

    public function getDescendant(& $descendants = array()) 
    { 
     foreach ($this->children as $role) { 
      $descendants[spl_object_hash($role)] = $role; 
      $role->getDescendant($descendants); 
     } 
     return $descendants; 
    } 

    public function removeChildren(Role $children) 
    { 
     $this->children->removeElement($children); 
    } 

    public function getParent() 
    { 
     return $this->parent; 
    } 

    public function setParent(Role $parent, $addChildToParent = true) 
    { 
     $addChildToParent && $parent->addChildren($this, false); 
     $this->parent = $parent; 
    } 

    public function __toString() 
    { 
     if ($this->children->count()) { 
      $childNameList = array(); 
      foreach ($this->children as $child) { 
       $childNameList[] = $child->getName(); 
      } 
      return sprintf('%s [%s]', $this->name, implode(', ', $childNameList)); 
     } 
     return sprintf('%s', $this->name); 
    } 
} 

Ruolo Tipo modulo

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

class RoleType extends AbstractType { 

    /** 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
       ->add('name') 
       ->add('parent'); 
    } 

    /** 
    * @param OptionsResolverInterface $resolver 
    */ 
    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'Tanane\UserBundle\Entity\Role' 
     )); 
    } 

    /** 
    * @return string 
    */ 
    public function getName() 
    { 
     return 'role'; 
    }  
} 

Se sì, quali dovrebbe aggiungere al mio modulo utente sarebbe simile a questa

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
      ->add('username', 'text') 
      ->add('email', 'email') 
      ->add('enabled', null, array(
       'label' => 'Habilitado', 
       'required' => false 
      )) 
      ->add('rolesCollection', 'entity', array(
       'class' => 'UserBundle:Role', 
       'multiple' => true, 
       'expanded' => true, 
       'attr' => array('class' => 'single-line-checks') 
      )) 
      ->add('groups', 'entity', array(
       'class' => 'UserBundle:Group', 
       'multiple' => true, 
       'expanded' => true, 
    )); 
} 

Ma io non so se è il modo giusto per gestire i ruoli dal momento che in questo caso sarebbe la creazione di una nuova tabella nel mio DB chiamato fos_roles dove sono state le relazioni tra utenti/ruoli vengono gestiti, ma le relazioni tra i gruppi/i ruoli restano fuori, quindi è lì che sono un po 'perso e ho bisogno di aiuto dai più esperti che mi dicono e avvisano se sono sulla buona strada e questo li farebbe ottenere ciò che spiego nei primi due punti. Qualche consiglio o aiuto? come lo gestisci?

risposta

26

Symfony Roles

Il modo offerte FOSUserBundle con ruoli è quello di memorizzarli nella colonna roles che hai visto, in un formato serializzato in questo modo: a:1:{i:0;s:10:"ROLE_ADMIN";}. Quindi non c'è bisogno di altre tabelle o entità ^.

^Ciò è in contrasto con i gruppi, che devono essere configurati in modo esplicito, sono rappresentati da una tabella/entità separata e coinvolgono gli utenti relativi ai gruppi nel DB. I gruppi consentono di definire raccolte arbitrarie di ruoli che possono quindi essere fornite a ciascun utente come pacchetto discreto.

Un utente può essere membro di un numero qualsiasi di ruoli. Sono identificati da stringhe che iniziano con "ROLE_", puoi iniziare a utilizzare un nuovo ruolo.

Ciò che i ruoli significano per l'applicazione è completamente a voi, ma sono piuttosto uno strumento di alto livello - un utente è in un ruolo particolare o non lo è.

È mettere le persone in ruoli sia attraverso il Symfony console:

php app/console fos:user:promote testuser ROLE_ADMIN 

O in PHP:

$user = $this->getUser(); 
$userManager = $container->get('fos_user.user_manager'); 
$user->addRole('ROLE_ADMIN'); 
$userManager->updateUser($user); 

E si può provare l'appartenenza a PHP:

$user = $this->getUser(); 
if ($user->hasRole('ROLE_ADMIN')) 
{ 
    //do something 
} 

o utilizzando Annotations :

/** 
* @Security("has_role('ROLE_ADMIN')") 
*/ 
public function adminAction() 
{ 
    //... 

o

/** 
* @Security("has_role('ROLE_ADMIN')") 
*/ 
class AdminController 
{ 
    //... 
+4

Perché sono serializzazione dei dati in MySQL? odore di codice – user3886650

3

ho aggiunto la funzionalità per aggiungere gruppo di default per l'utente durante la registrazione sovrascrivendo il confirmAction nel controller Registrazione

Quello che ho fatto è che ho overrided il controller registrazione nel mio progetto Bundle definendo il genitore su FosUserBUndle.

poi creato una funzione confirmedAction e nel corpo della funzione ha aggiunto questo codice

$repository = $em->getRepository('AdminAdminBundle:Group'); 
     $group = $repository->findOneByName('staff'); 

     $em = $this->getDoctrine()->getEntityManager(); 
     $user = $this->getUser(); 
     $user->addGroup($group); 

     $userManager = $this->get('fos_user.user_manager'); 

     $userManager->updateUser($user); 

     if (!is_object($user) || !$user instanceof FOS\UserBundle\Model\UserInterface) { 
      throw new AccessDeniedException('This user does not have access to this section.'); 
     } 

     return $this->render('FOSUserBundle:Registration:confirmed.html.twig', array(
      'user' => $user, 
     )); 

Ed è perfettamente salvato in db con assegnazione di gruppo. Spero che questo aiuti alcuni dei più bisognosi dato che ci sono poche informazioni sull'implementazione nel documento ufficiale di fosuserbundle.