Skip to content

Permission inheritance issue when working with roles. #168

Open
@QuentinPetel

Description

@QuentinPetel

I have the following roles on a project :

$roles = [
    ['id' => '1', 'name' => 'user',             'slug' => Str::slug('user'),            'description' => 'Membre du site.'],
    ...
    ['id' => '7', 'name' => 'admin_super',      'slug' => Str::slug('admin_super'),     'description' => 'Super administrateur.']
];

with the following permissions :

...
[   'id'    => '16',
    'name'  => 'public_room',
    'slug'  => [
        'view'      => true,
        'create'    => false,
        'update'    => false,
        'delete'    => false
        ],
    'description' => 'Autorisations concernant les conversations publiques.'
],
[   'id'    => '17',
    'name'  => 'public_room.manager',
    'slug'  => [
        'view'      => true,
        'create'    => true,
        'update'    => true,
        'delete'    => true
        ],
    'inherit_id' => '16',
    'description' => 'Autorisations concernant les conversations publiques. (privilèges administrateur).'
],
...

$roleUser = Role::where('slug', '=', Str::slug('user'))->first();
$roleUser->assignPermission([
    ...
    'public_room',
    ...
]);

$roleSuperAdmin = Role::where('slug', '=', Str::slug('admin_super'))->first();
$roleSuperAdmin->assignPermission([
    ...
    'public_room.manager',
    ...
]);

But for an user with this two roles, i get the followings permissions with $user->getPermissions() :

{
   "public_room":
   {
     "view":true,
     "create":false,
     "update":false,
     "delete":false
   }
}

whereas of :

{
   "public_room":
   {
     "view":true,
     "create":true,
     "update":true,
     "delete":true
   }
}

This is because of those lines in HasPermission.php :

// permissions based on role.
// more permissive permission wins
// if user has multiple roles we keep
// true values.
foreach ($this->roles as $role) {
    foreach ($role->getPermissions() as $slug => $array) {
        if ( array_key_exists($slug, $permissions) ) {
            foreach ($array as $clearance => $value) {
                **if( !array_key_exists( $clearance, $permissions[$slug] ) ) {**
                    ! $value ?: $permissions[$slug][$clearance] = true;
                }
            }
        } else {
            $permissions = array_merge($permissions, [$slug => $array]);
        }
    }
}

Because of this condition, if the key exist (view, create...), the value is never re-evaluated. So skip this line and it work just great.

foreach ($array as $clearance => $value) {
    ! $value ?: $permissions[$slug][$clearance] = true;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions