Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FOSUserBundle, Relation between User (roles) and Group (roles)?

I am getting a bit confused with the roles in FOSUserBundle. The User entity also has roles column by which we can assign multiple roles to the user. According to the answer posted at Managing users/roles/groups in FOSUserBundle, we do not need separate entity or tables to manage user roles.

I have also implemented Group of FOSUserBundle which also contains set of roles and user can be assigned to these roles. So, far I have understood here is we group can be created to assign set of roles so that similar roles can be accessed using group.

Now, where I am stuck is that, what is the purpose of using groups if set of roles can be managed from User Entity alone or how can I merge the roles from User entity and Group entity or something I am missing here?

like image 210
San Thapa Avatar asked Oct 20 '22 15:10

San Thapa


1 Answers

Q: what is the purpose of using groups if set of roles can be managed from User Entity alone

A: the Answer could be extracted from Using Groups With FOSUserBundle:

Symfony2 supports role inheritance so inheriting roles from groups is not always needed. If the role inheritance is enough for your use case, it is better to use it instead of groups as it is more efficient (loading the groups triggers the database).


Q: If you ask yourself: what is a Group of Roles? or when I need to use a Group of Roles?

A: In substance a "Group" contains a set of roles, classified by common traits (like a category for an e-commerce). For example, users of a Control Panel application, with a ROLE_ADMIN as common role, might belong to a MANAGER group, while others belongs to the REVISER (it depends on what you need). Categorizing user roles into groups makes it easier to control the access of large numbers of users to a specific tool or service. So use or not groups of roles depends entirely by what you want to do with your application and by the quantity of interactions that users can have with.


Q: how can I merge the roles from User entity and Group entity or something I am missing here?

A: If the role inheritance is not enough and you want to use "groups", You need to create an association between User -> Group -> Role entities like this implementation example:

User Entity:

use Doctrine\Common\Collections\ArrayCollection;

/**
 * USER ManyToMany with GROUP Unidirectional association
 * @var ArrayCollection
 * @ORM\ManyToMany(targetEntity="Group")
 * @ORM\JoinTable(name="user_groups")
 * @Assert\Valid
 */
protected $groups;

public function __construct()
{
    $this->groups = new ArrayCollection(); <-- add this line to the constructor
}

/**
 * Get all Groups added to the administrator
 * @return ArrayCollection $groups
 */
public function getGroups()
{
    return $this->groups;
}

/**
 * Add Group $group to the administrator
 *
 * @param \Group $group
 * @return void
 */
public function addGroup(Group $group)
{
    if (!$this->groups->contains($group)) {
        $this->groups->add($group);
    }
}

/**
 * Remove Group from the user
 * @param \Group $group
 * @return void
 */
public function removeGroup(Group $group)
{
    if ($this->groups->contains($group)) {
        $this->groups->removeElement($group);
    }
}

/**
 * Get all Roles added to the User
 * @return array
 */
public function getRoles()
{
    $roles = [];
    /** @var ArrayCollection $groups */
    $groups = $this->getGroups();

    foreach ($groups as $group) {
        $roles = array_merge($roles, $group->getRoles()->toArray());
    }

    $roles = array_unique($roles);

    # store the roles in the property to be serialized
    $this->roles = $roles;

    return $roles;
}

Group Entity:

/**
 * GROUP ManyToMany with ROLE Unidirectional Association
 * @var ArrayCollection
 * @ORM\ManyToMany(targetEntity="Role")
 * @ORM\JoinTable(name="user_group_roles")
 * @Assert\Valid
 */
protected $roles;

public function __construct()
{
    $this->roles       = new ArrayCollection();
}

/**
 * Return all Roles added to this Group
 *
 * @return \Doctrine\Common\Collections\ArrayCollection $roles
 */
public function getRoles()
{
    return $this->roles;
}

/**
 * Add Role $role to the Group
 *
 * @param Role $role
 * @return void
 */
public function addRole(Role $role)
{
    if (! $this->roles->contains($role)) {
        $this->roles->add($role);
    }
}

/**
 * Remove Role from the Group
 *
 * @param Role $role
 * @return void
 */
public function removeRole(Role $role)
{
    if ($this->roles->contains($role)) {
        $this->roles->removeElement($role);
    }
}

That's all. Hope that help you.

like image 183
gp_sflover Avatar answered Oct 23 '22 00:10

gp_sflover