Управление пользователями / ролями / группами в FOSUserBundle
Я разрабатываю простой CRUD для управления пользователями / ролями / группами приложения, в котором я работаю. Для управления пользователями я использую FOSUserBundle
. То, что я хочу сделать, может быть достигнуто несколькими способами:
- назначение ролей группам, а затем назначение пользователей этим группам
- назначение ролей пользователям напрямую
но я понятия не имею как. Я знал, что FOSUser BaseUser
класс уже имеет столбец roles
и в документация FOSUser объясняет, как установить ManyToMany
отношения между пользователями и группами, но ничего не говорят о ролях. Единственная идея, которая приходит на ум, - создать сущность для управления ролями, а также форму для той же цели, что и то, что вы видите ниже:
Роль Субъекта
use SymfonyComponentSecurityCoreRoleRoleInterface;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineORMMapping as ORM;
/**
* @ORMTable(name="fos_role")
* @ORMEntity(repositoryClass="UserBundleEntityRepositoryRoleRepository")
*
* @see User
* @see UserBundleRoleRoleHierarchy
*
*/
class Role implements RoleInterface
{
/**
* @ORMColumn(name="id", type="integer")
* @ORMId()
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORMColumn(name="name", type="string", length=80, unique=true)
*/
private $name;
/**
* @ORMManyToOne(targetEntity="Role", inversedBy="children")
* @ORMJoinColumn(name="parent_id", referencedColumnName="id", nullable=true)
* @var Role[]
*/
private $parent;
/**
* @ORMOneToMany(targetEntity="Role", mappedBy="parent")
* @var ArrayCollection|Role[]
*/
private $children;
/**
* @ORMManyToMany(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);
}
}
Тип Ролевой Формы
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolverInterface;
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' => 'TananeUserBundleEntityRole'
));
}
/**
* @return string
*/
public function getName()
{
return 'role';
}
}
если да то что добавить в мою форму пользователя будет выглядеть такой
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,
));
}
но я не знаю, правильно ли это обрабатывать роли, так как в этом случае будет создавать новую таблицу в моей БД под названием fos_roles
где были отношения между пользователями / ролями обрабатываются, но отношения между группами / ролями остаются вне этого, тогда вот где я немного потерян и нуждаюсь в помощи от более опытных в этом, скажите мне и предупредите, если я нахожусь на пути, и это заставит их достичь того, что я объясняю в первых двух пунктах. Любые советы или помочь? Как ты с этим справляешься?
2 ответов
способ FOSUserBundle имеет дело с ролями, чтобы сохранить их в roles
столбец, который вы видели, в сериализованном формате, как это:a:1:{i:0;s:10:"ROLE_ADMIN";}
. Таким образом, нет необходимости в каких-либо других таблицах или сущностях^.
^ это в отличие от групп, которые должны быть явно настроены, представлены отдельной таблицей / сущностью и включают связанных пользователей с группами в БД. Группы позволяют определить произвольные коллекции Роли, которые затем могут быть даны каждому пользователю в виде дискретного пакета.
пользователь может быть членом любого количества ролей. Они идентифицируются строками, начинающимися с "ROLE_", вы можете просто начать использовать новую роль.
то, что роли означают для вашего приложения, полностью зависит от вас, но они довольно высокоуровневый инструмент-пользователь либо в определенной роли, либо нет.
вы ставите людей в роли либо через в Symfony консоль:
php app/console fos:user:promote testuser ROLE_ADMIN
или в PHP:
$user = $this->getUser();
$userManager = $container->get('fos_user.user_manager');
$user->addRole('ROLE_ADMIN');
$userManager->updateUser($user);
и вы можете проверить членство в PHP:
$user = $this->getUser();
if ($user->hasRole('ROLE_ADMIN'))
{
//do something
}
или через аннотации:
/**
* @Security("has_role('ROLE_ADMIN')")
*/
public function adminAction()
{
//...
или
/**
* @Security("has_role('ROLE_ADMIN')")
*/
class AdminController
{
//...
Я добавил функциональность для добавления группы по умолчанию пользователю во время регистрации, переопределив confirmAction в Registration Controller
Я перекрытая контроллер регистрация в мой пакет проекта путем определения родителю FosUserBUndle .
затем создал функцию confirmedAction и в тело функции добавил этот код
$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,
));
и он отлично сохраняется в БД с групповым назначением. Надеюсь, это поможет кому-то в нужно так же мало информации о реализации в официальном FOSUserBundle doc.