Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Role Demo - Possible incorrect behavior #51

Open
olegkrivtsov opened this issue Aug 14, 2018 · 24 comments
Open

Role Demo - Possible incorrect behavior #51

olegkrivtsov opened this issue Aug 14, 2018 · 24 comments

Comments

@olegkrivtsov
Copy link
Owner

As reported here https://olegkrivtsov.github.io/using-zend-framework-3-book/html/en/Role_Based_Access_Control/Summary.html#comment-4038175770

Hi Oleg: 
I appreciate everything in this book and I have learned a lot using both every one your examples and each ones of the topic tried in this amazing book. 
I would like to implement a new RBAC basing on your example ROLEDEMO.
I created the RBAC as it be shown in the picture. 
I have defined three roles : 
- Entry Level : with permissions ( module.watch.document, module.watch.document ) 
- Regular Level: inherit permissions from Entry Level ( and has : module.export.document, module.print.document) 
- High Level: inherit permissions from Regular Level ( and has: module.create.document, module.update.document)

Then
when I test: 
- $access = $this->access('watch', ['user'=>$user]);

In my case: an user with Entry Level Role: 
$access = true
- an user with Regular Level Role: 
$access = true
- an user with High Level Role: 
$access = false
(so, if High Level role inherit permissions from Regular Level, and Regular level inherit the permissions of Entry Level Role, then High Level Role must have the permissions both Regular Level and Entry Level Role too.

Another thing I can appreciate is that :
- An user with Regular Level Role:
$access = $this->access('module.create.document', ['user'=>$user]); //true ---- WRONG
It's a little confuse because Regular Level inherit from Entry Level NO from High Level Role

However when I use the options: Edit permissions for the High Level Role, I see its direct permissions and all its inherited permissions too, as you can see on the picture uploaded. So I don't know if there is something wrong with the RbacManager.

I wanted to know if you have test the inheritance with at least 3 levels or more and if there is an specific order to add roles.
@kristofermagic
Copy link

kristofermagic commented Aug 15, 2018

Why in the RbacManager.php after checking the direct permissions and assertions, the code follows checking of the parentRoles? I think that if the role has the direct permissions, it's not necessary to check whether the permission which I'm testing belongs to any its parent roles?

public function isGranted($user, $permission, $params = null)
{
//.....
//....

    $roles = $user->getRoles();
    
    foreach ($roles as $role) {
        if ($this->rbac->isGranted($role->getName(), $permission)) {
            //...if TRUE then the role has the direct permission, so there is no needed to check parentRoles...I think....
            **_$directPermission = true;_**
            if ($params==null)
                return true;

            foreach ($this->assertionManagers as $assertionManager) {
                if ($assertionManager->assert($this->rbac, $permission, $params))
                    return true;
            }
            //I'll add the below line ...
            **_if ($directPermission)
                return true;_**
        }
     else
     {
        // Since we are pulling the user from the database again the init() function above is overridden?
        // we don't seem to be taking into account the parent roles without the following code
        $parentRoles = $role->getParentRoles();
        foreach ($parentRoles as $parentRole) {
            if ($this->rbac->isGranted($parentRole->getName(), $permission)) {
                return true;
            }
        }
    }
    
    return false;
    }
}

@sebstyle
Copy link

Just out of curiosity, should you not also check for assertions when going thru the parent roles?
Also in the RoleManager method createDefaultRolesIfNotExist() when setting default roles with a parent role the roledemo code refers to a method setParentRole() on the RoleEntity class that does not exist.

@x-dragos
Copy link

Hello Oleg,

Although it's been some time :) i can confirm this issue.

The problem is your implementation of inheritance assumes Children roles inherit from Parrent roles, and zend-permission-rbac asssumes parrents inherit all permissions from children.

i have fixxed this by fiddling with the Role entity, RoleManager and RoleController if i remember correctly. Basicly, anywhere you "add parrent", you need to "addChild" and vice-versa :)

awsome book by the way

@sebstyle
Copy link

Hello Oleg,

Although it's been some time :) i can confirm this issue.

The problem is your implementation of inheritance assumes Children roles inherit from Parrent roles, and zend-permission-rbac asssumes parrents inherit all permissions from children.

i have fixxed this by fiddling with the Role entity, RoleManager and RoleController if i remember correctly. Basicly, anywhere you "add parrent", you need to "addChild" and vice-versa :)

awsome book by the way

That is indeed the problem.
Least effort way of fixings this is by changing rbacManager init function from this:

$parentRoleNames = [];
foreach ($role->getParentRoles() as $parentRole) {
    $parentRoleNames[] = $parentRole->getName();
}

to this:

$parentRoleNames = [];
// Our inheritance code assumes childRoles inherit from parentRoles (sounds logical)
// Zends inheritance code assumes parentRoles inherit from childRoles (unlikely irl)
// Can't expect Zend to change their code and break existing implementations
// So this is where we swap the expected getParentRoles() with getChildRoles()
foreach ($role->getChildRoles() as $parentRole) {
    $parentRoleNames[] = $parentRole->getName();
}

Or you could rename everything in this implementation to reflect the requirements.
Either way if you do not fix this you will end up with serious security issues where in situations when admins inherit read permissions from guests, guests end up with inheriting write permissions from admins.

@x-dragos
Copy link

x-dragos commented Jul 20, 2019 via email

@x-dragos
Copy link

ok, fixxed that one too. Apparently, the way Zend creates the Rbac Object is rather wiered.

fixed it by going through the roles in reverse order.

RbacManager.php lines 83-84

$roles = $this->entityManager->getRepository(Role::class)
->findBy([], ['id'=>'DESC']);

@sebstyle
Copy link

@x-dragos
I believe the phrase you are referring to is recursive inheritance checking?
That is exactly what this code segment located at the bottom of rbacManager isGranted function does:

...
$parentRoles = $role->getParentRoles();
foreach ($parentRoles as $parentRole) {
    if ($this->rbac->isGranted($parentRole->getName(), $permission)) {
        return true;
    }
}
...

Note:
This code refers to the inheritance structure as defined by the relationships in the database.
(where children inherit from parents)
So using getParentRoles() here is indeed correct.

I work with a similar setup where admins inherit from managers and managers inherit from clients.
Manager permissions are checked with assertions where they can only view clients they actually manage.
With just the change i suggested in my previous reply everything works as intended here.
(unless i made more changes in the past that i don't recall but i don't think so)

@x-dragos
Copy link

I'll have another look but at the moment ... it looks to me like Rbac is not creating the proper object.

it overwrites the roles that it created earlyer in the process with the "last" inheritance... and it seems to miss relationships defined early in the process... at least that is how it looks in the debugger.

i'll keep looking and get back to you. (chaning the order it iterated through the ids made it work for 3 roles inheriting from eachother... but when you add a 4th in between them :) it stops working again)

@sebstyle
Copy link

sebstyle commented Jul 20, 2019

ok, fixxed that one too. Apparently, the way Zend creates the Rbac Object is rather wiered.

fixed it by going through the roles in reverse order.

RbacManager.php lines 83-84

$roles = $this->entityManager->getRepository(Role::class)
->findBy([], ['id'=>'DESC']);

I've not been in this code for a while but i do not think the sorting order is supposed to have have any impact on that.
The init function iterates thru all roles and all it does is link inheritance in a data structure that zends rbac understands and stores in cache in order to minimize database queries with complex relationships, sorts and joins.

@sebstyle
Copy link

sebstyle commented Jul 20, 2019

I'll have another look but at the moment ... it looks to me like Rbac is not creating the proper object.

it overwrites the roles that it created earlyer in the process with the "last" inheritance... and it seems to miss relationships defined early in the process... at least that is how it looks in the debugger.

i'll keep looking and get back to you. (chaning the order it iterated through the ids made it work for 3 roles inheriting from eachother... but when you add a 4th in between them :) it stops working again)

Well i don't know how much code you have modified.
I have my roles and permissions defined in a similar way modules read from module.config.php files:

return [
    'account_setup'             => [
        'default'               => [
            'roles'             => ['Client'],
            'level'             => 3
        ],
        'accounts'              => [
            'Administrator'     => [
                'email'         => 'admin@admin.com',
                'password'      => 'admin',
                'roles'         => ['Administrator']
            ]
        ],
        'levels'                => [
            1                   => 'Administrator',
            2                   => 'Manager',
            3                   => 'Client',
            999                 => 'Guest',
        ],
        'roles'                 => [
            'Administrator'     => [
                'description'   => 'A person who administrates accounts, roles, etc.',
                'level'         => 1,
                'parent'        => ['Manager'],
                'permissions'   => [
                    'account.admin',
                    'role.admin',
                    'permission.admin',
                ]
            ],
            'Manager'           => [
                'description'   => 'A person who can log in and view their own account and managed accounts.',
                'level'         => 2,
                'parent'        => ['Client'],
                'permissions'   => [
                    'account.view.managed',
                    'account.edit.managed',
                    'account.edit.managed.roles',
                    'account.create.managed',
                ]
            ],
            'Client'            => [
                'description'   => 'A person who can log in and has full access to their own account.',
                'level'         => 3,
                'permissions'   => [
                    'account.view.own',
                    'account.edit.own',
                ]
            ],
        ],
        'permissions'                       => [
            'account.admin'                 => 'Admin accounts',
            'role.admin'                    => 'Admin roles',
            'permission.admin'              => 'Admin permissions',
            'account.view.own'              => 'View own account',
            'account.edit.own'              => 'View own account',
            'account.view.managed'          => 'View managed account',
            'account.edit.managed'          => 'Edit managed account',
            'account.edit.managed.roles'    => 'Edit managed account roles',
            'account.create.managed'        => 'Create managed account',
        ]
    ],

This config is read when default permissions, roles and accounts are created. (in that specific order)
When i design a new module that implements a different set of permissions and roles i simply add them to that module's config file so when configs are merged all required permissions, roles and accounts are created.

I also added a level definition to the roles so that managers can add roles to clients but never a role that is of equal or lower level than their own role.

And instead of checking for default accounts on every login attempt I have a SetupController that listens to /setup/ route that is only available if no accounts exist, otherwise returns notFound or notAuthorized.
When i have a fresh install after initial database migrations i run /setup/ and everything is checked and initialized just once.

I chose to work with a predefined set of permissions and roles because adding permissions using the interface doesn't make a lot of sense since adding a permission that way does not magically add the code to check for any of them.
When i need additional permissions in the database after setup because i have changed my code to actually check for them i run a database migration to insert them.

@x-dragos
Copy link

Hello Oleg,

I figured it out. The problem was generated by the init() in RbacManager.php, specifically the fact that it had "$rbac->setCreateMissingRoles(true);" and later it was adding a role even if it was allready created, from a previous iteration. This ment that if a role was created early as a parent for another role (as it was missing at that point), it would get overwritten when the foreach loop was reaching it through iteration, loosing the child that was previously added on it.

i replaced the single line that was adding roles in the init():

$rbac->addRole($roleName, $parentRoleNames);

with this block that is handling the creation properly (specifically, if the role allready exists, it modifies that role in the rbac object, not overwriting it):

                if (!$rbac->hasRole($roleName)) $rbac->addRole($roleName, $parentRoleNames);
                else if (!empty($parentRoleNames)) {
                    $rbacRole = $rbac->getRole($roleName);
                    foreach ($parentRoleNames as $parentRoleName) {
                        if (!$rbac->hasRole($parentRoleName)) $rbac->addRole($parentRoleName);
                        $rbacParentRole = $rbac->getRole($parentRoleName);
                        $rbacRole->addParent($rbacParentRole);
                    }
                }

I haven't modified your code too much except chainging the parrent <-> child thing that i talked about earlyer :)

This module saved me a lot of work, so thanks again for creating it.

i may at some point actually redownload the repo version and create a pull request with a few fixxes. (not a big git guru... so not sure how to submit them otherwise... or even if it is possible to create the pull request from my own project)

@sebstyle
Copy link

sebstyle commented Jul 20, 2019

@x-dragos
I see what you are trying to do but doesn't that simply move the problem up one level?
What if the parent role you are checking for has parent roles?

Try the follwing..

In RbacManager->init:

...
$rbac->setCreateMissingRoles(true);
$roles = $this->entityManager->getRepository(RoleEntity::class)->findBy([], ['id'=>'ASC']);
foreach ($roles as $role) {
    $this->addRole2Rbac($role, $rbac);
}
...

In RbacManager add a method that can be called recursively:

/**
 * Recursively adds roles and their parent roles to Rbac
 * @param RoleEntity $role
 * @param Rbac $rbac
 */
private function addRole2Rbac(RoleEntity $role, Rbac $rbac) {
    $roleName               = $role->getName();
    $parentRoleNames        = [];
    // Use either getChildRoles() or getParentRoles() depending on how your 
    // Role Entity|Class|Database handles inheritance compared to how Rbac handles them 
    foreach ($role->getChildRoles() as $parentRole) {
        $parentRoleNames[]  = $parentRole->getName();
        if (!$rbac->hasRole($parentRole->getName())) {
            // Create the missing parent roles recursively
            $this->addRole2Rbac($parentRole, $rbac);
        }
    }
    // Check if one of those created parent roles happened to be this role
    if (!$rbac->hasRole($roleName)) {
        $rbac->addRole($roleName, $parentRoleNames);
        foreach ($role->getPermissions() as $permission) {
            $rbac->getRole($roleName)->addPermission($permission->getName());
        }
    }
}

Tested with up to 5 levels of inheritance with database records in random order.
Careful with infinite recursion, it might be better to use a reliable index to sort by inheritance in the db query but it think it's pretty safe.

@x-dragos
Copy link

@sebstyle

I see what you did, but i think it is the same. Can you give me an example where my code would fail.

As you said, the iteration order should not matter and it doesn't with the block in my last example.
The iteration order was the thing that pointed me in the right direction.

If the parrent has parrents it will go on the else branch when the main iteration gets to it and add them to the existing object:

                else if (!empty($parentRoleNames)) {
                    $rbacRole = $rbac->getRole($roleName);
                    foreach ($parentRoleNames as $parentRoleName) {
                        if (!$rbac->hasRole($parentRoleName)) $rbac->addRole($parentRoleName);
                        $rbacParentRole = $rbac->getRole($parentRoleName);
                        $rbacRole->addParent($rbacParentRole);
                    }
                }

There is only a diffrence in presentation in my opinion :) both pieces of code do the same thing.

The only functional diffrence i can see is that you dont need

$rbac->setCreateMissingRoles(true);

as you recursivly add the full parent objects.

@x-dragos
Copy link

x-dragos commented Jul 21, 2019

PS: infinite recursion is beeing tanken care of my Zend Rbac as it doesnt add circular references (it does this check for us :) ), but it would be safe in my example. If you add a circular reference, with your example it might actually loop infinitely as it doesn't check for it. As in my example it doesn't recursively call itself, it will just exit the loop when it finishes one run of all roles and all the circular references are being handled by Zend\Permission\Rbac

@sebstyle
Copy link

@x-dragos
Okay, example:
Add 3 roles that depend on each other. Administrator < Manager < Client
All 3 roles are added yes, but they do not have their children set rbac container.

print_r($rbac->getRole('Administrator'))
Zend\Permissions\Rbac\Role Object
(
    [parents:protected] => 
    [name:protected] => Administrator
    [permissions:protected] => Array
        (
            [account.admin] => 1
            [role.admin] => 1
            [permission.admin] => 1
        )
    [index:protected] => 0
    [children:protected] => Array
        (
        )
)

Children should not be empty.
Unless i missed part of your code block init exits after the 3 roles it found in database are added and never gets to the part where parents are added.

@x-dragos
Copy link

x-dragos commented Jul 23, 2019

hmmm ... can you post the full Manager Object role? want to check who is child for that one and who is parrent

@sebstyle
Copy link

sebstyle commented Jul 23, 2019

The code i use now is: (RbacManager->init)

...
$roles          = $this->entityManager->getRepository(RoleEntity::class)->findBy([]);
// Add all roles to rbac
foreach ($roles as $role) {
    $roleName   = $role->getName();
    if (!$rbac->hasRole($roleName)) {
        // Add role with permissions to Rbac
        $rbac->addRole($roleName);
        foreach ($role->getPermissions() as $permission) {
            $rbac->getRole($roleName)->addPermission($permission->getName());
        }
    }
}
// Set inheritance on rbac roles
foreach ($roles as $role) {
    $roleName           = $role->getName();
    $rbacRole           = $rbac->getRole($roleName);
    $parentRoleNames    = [];
    foreach ($role->getChildRoles() as $parentRole) {
        $parentRoleNames[] = $parentRole->getName();
    }
    if (!empty($parentRoleNames)) {
        foreach ($parentRoleNames as $parentRoleName) {
            $rbacRole->addParent($rbac->getRole($parentRoleName));
        }
    }
}
...

This sets up roles with proper inheritance:

print_r($rbac->getRole('Administrator'));
Zend\Permissions\Rbac\Role Object
(
    [parents:protected] => 
    [name:protected] => Administrator
    [permissions:protected] => Array
        (
            [account.admin] => 1
            [role.admin] => 1
            [permission.admin] => 1
        )
    [index:protected] => 1
    [children:protected] => Array
        (
            [0] => Zend\Permissions\Rbac\Role Object
                (
                    [parents:protected] => Array
                        (
                            [0] => Zend\Permissions\Rbac\Role Object
 *RECURSION*
                        )
                    [name:protected] => Manager
                    [permissions:protected] => Array
                        (
                            [account.view.managed] => 1
                            [account.edit.managed] => 1
                            [account.edit.managed.roles] => 1
                            [account.create.managed] => 1
                        )
                    [index:protected] => 1
                    [children:protected] => Array
                        (
                            [0] => Zend\Permissions\Rbac\Role Object
                                (
                                    [parents:protected] => Array
                                        (
                                            [0] => Zend\Permissions\Rbac\Role Object
 *RECURSION*
                                        )
                                    [name:protected] => Client
                                    [permissions:protected] => Array
                                        (
                                            [account.view.own] => 1
                                            [account.edit.own] => 1
                                        )
                                    [index:protected] => 0
                                    [children:protected] => Array
                                        (
                                        )
                                )
                        )
                )
        )
)

Once the roles are setup with proper inheritance you no longer need the code at the bottom of RbacManager->isGranted

// Since we are pulling the user from the database again the init() function above is overridden?
// we don't seem to be taking into account the parent roles without the following code
$parentRoles = $role->getParentRoles();
foreach ($parentRoles as $parentRole) {
    if ($this->rbac->isGranted($parentRole->getName(), $permission)) {
        return true;
    }
}

[EDITED]
As per your request, the Manager role

print_r($rbac->getRole('Manager'));
Zend\Permissions\Rbac\Role Object
(
    [parents:protected] => Array
        (
            [0] => Zend\Permissions\Rbac\Role Object
                (
                    [parents:protected] => 
                    [name:protected] => Administrator
                    [permissions:protected] => Array
                        (
                            [account.admin] => 1
                            [role.admin] => 1
                            [permission.admin] => 1
                        )
                    [index:protected] => 1
                    [children:protected] => Array
                        (
                            [0] => Zend\Permissions\Rbac\Role Object
 *RECURSION*
                        )
                )
        )
    [name:protected] => Manager
    [permissions:protected] => Array
        (
            [account.view.managed] => 1
            [account.edit.managed] => 1
            [account.edit.managed.roles] => 1
            [account.create.managed] => 1
        )
    [index:protected] => 1
    [children:protected] => Array
        (
            [0] => Zend\Permissions\Rbac\Role Object
                (
                    [parents:protected] => Array
                        (
                            [0] => Zend\Permissions\Rbac\Role Object
 *RECURSION*
                        )
                    [name:protected] => Client
                    [permissions:protected] => Array
                        (
                            [account.view.own] => 1
                            [account.edit.own] => 1
                        )
                    [index:protected] => 0
                    [children:protected] => Array
                        (
                        )
                )
        )
)

@x-dragos
Copy link

well.. it apears to be in order. The only diffrence from my code is that i do the second loop inside the fist one :):

$roles = $this->entityManager->getRepository(Role::class)
                    ->findBy([], ['id'=>'ASC']);
            foreach ($roles as $role) {

                $roleName = $role->getName();

                $parentRoleNames = [];
                foreach ($role->getParentRoles() as $parentRole) {
                    $parentRoleNames[] = $parentRole->getName();
                }

                if (!$rbac->hasRole($roleName)) $rbac->addRole($roleName, $parentRoleNames);
                else if (!empty($parentRoleNames)) {
                    $rbacRole = $rbac->getRole($roleName);
                    foreach ($parentRoleNames as $parentRoleName) {
                        if (!$rbac->hasRole($parentRoleName)) $rbac->addRole($parentRoleName);
                        $rbacParentRole = $rbac->getRole($parentRoleName);
                        $rbacRole->addParent($rbacParentRole);
                    }
                }

                foreach ($role->getPermissions() as $permission) {
                    $rbac->getRole($roleName)->addPermission($permission->getName());
                }
            }

both solutions work

@sebstyle
Copy link

@x-dragos nope.

                // When rbac is initialized it contains no roles; 
                // So hasRole() is always false and addRole() is always executed
                if (!$rbac->hasRole($roleName)) $rbac->addRole($roleName, $parentRoleNames);
                else if (!empty($parentRoleNames)) {
                    // Because hasRole() is always false this code never gets executed
                    $rbacRole = $rbac->getRole($roleName);
                    foreach ($parentRoleNames as $parentRoleName) {
                        if (!$rbac->hasRole($parentRoleName)) $rbac->addRole($parentRoleName);
                        $rbacParentRole = $rbac->getRole($parentRoleName);
                        $rbacRole->addParent($rbacParentRole);
                    }
                }

@x-dragos
Copy link

that is not true.
if you go with the debuger through that loop you will notice the following (depending on the order and inheritance between the roles)

for the sake fo this example lets asume Agent -> Manager -> Administrator as 3 roles , inheriting eachother, Admin beeing the top parent.
Lets asume it loops through them in this order: Agent, Manager, Admin.

in the first loop, when adding agent with this parent (Manager) , due to :

$rbac->setCreateMissingRoles(true);

it will add the Manager role also. At that point there will be 2 roles already in the rbac object (Agent with parent Manager, and Manager with child Agent). Manager will not have it's parrent yet.

on the second loop, it will go to the else branch, as Manager already exists, and only add Admin as it's parrent.

Hope i have made this as clear as i can :) as i can post a recording of the debuger, but if you put a breakpoint in init, and delete the cache... add a watch on $rbac and see it's memebers change while looping.

@sebstyle
Copy link

My bad, it's clear, i just assumed the setCreateMissingRoles option was set to false.
If you are certain, all is good, just making sure you know, since it's kinda critical code. :)
Either way, this issue is solved for me.

@billmbillson
Copy link

I have never used Doctrine so I could be completely wrong, but I think this may be caused by a mix-up in annotations for the $parentRoles and $childRoles properties in the Role entity (roledemo/module/User/src/Entity/Role.php):

    /**
     * @ORM\ManyToMany(targetEntity="User\Entity\Role", inversedBy="childRoles")
     * @ORM\JoinTable(name="role_hierarchy",
     *      joinColumns={@ORM\JoinColumn(name="child_role_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="parent_role_id", referencedColumnName="id")}
     *      )
     */
    private $parentRoles;
    
    /**
     * @ORM\ManyToMany(targetEntity="User\Entity\Role", mappedBy="parentRoles")
     * @ORM\JoinTable(name="role_hierarchy",
     *      joinColumns={@ORM\JoinColumn(name="parent_role_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="child_role_id", referencedColumnName="id")}
     *      )
     */
    protected $childRoles;

Shouldn't the joinColumn for the $parentRoles be "parent_rold_id" and the joinColumn for $childRoles be "child_role_id"?

If this is true, you won't have to confuse yourself in the RbacManager with code like
foreach ($role->getChildRoles() as $parentRole).

@x-dragos
Copy link

x-dragos commented Aug 16, 2019 via email

@erkinaka
Copy link

I have never used Doctrine so I could be completely wrong, but I think this may be caused by a mix-up in annotations for the $parentRoles and $childRoles properties in the Role entity (roledemo/module/User/src/Entity/Role.php):

    /**
     * @ORM\ManyToMany(targetEntity="User\Entity\Role", inversedBy="childRoles")
     * @ORM\JoinTable(name="role_hierarchy",
     *      joinColumns={@ORM\JoinColumn(name="child_role_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="parent_role_id", referencedColumnName="id")}
     *      )
     */
    private $parentRoles;
    
    /**
     * @ORM\ManyToMany(targetEntity="User\Entity\Role", mappedBy="parentRoles")
     * @ORM\JoinTable(name="role_hierarchy",
     *      joinColumns={@ORM\JoinColumn(name="parent_role_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="child_role_id", referencedColumnName="id")}
     *      )
     */
    protected $childRoles;

Shouldn't the joinColumn for the $parentRoles be "parent_rold_id" and the joinColumn for $childRoles be "child_role_id"?

If this is true, you won't have to confuse yourself in the RbacManager with code like
foreach ($role->getChildRoles() as $parentRole).

Yes, it works for inheritance for roles

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants