Role weights not working as expected

Notice: This thread is very old.
Bobbles
Member | 3
+
0
-

Hello all, firstly may I just say that I've been working with Nette for a week or so now, and I love how it works, so congratulations on a great Framework. The English documentation is a bit thin in places, and I can't seem to find a solution for the following issue.

I have assigned a test user two roles, “probationary”, and “troll”. The troll role should simply deny the user a few permissions. I'm aware of role weight, with the last added role having the greater weight. So I'm therefore stumped as to why my code doesn't work.

		$acl->addRole('guest');
		$acl->addRole('probationary');
		$acl->addRole('admin');
		$acl->addRole('troll');

		$acl->addResource('articles');
		$acl->addResource('links');
		$acl->addResource('pages');
		$acl->addResource('profiles');

		$acl->allow('probationary', 'profiles', 'view');

		$acl->deny('troll', 'profiles', 'view');

So from that code, I was expecting for the user not to be allowed to view profiles, but the following code returns true.

View Profiles {dump($user->isAllowed('profiles', 'view'))}

TRACY shows the user logged in as follows

Nette\Security\Identity #01
	id private => 1
	roles private => array (2)
		0 => "probationary"
		1 => "troll"
	data private => array (3)
		username => "test"
		displayname => "My Display Name"
		email => "test@test.com"

Everything works as expected when I just have one role assigned to the user. Any ideas as to what I'm doing wrong? Thanks in advance.

Majkl578
Moderator | 1364
+
0
-

I'm afraid you are slightly mixing two things here. Role weight (in the context of ACL) only works together with role inheritance. ACL is then always queried with a single role.
User class does this slightly differently – it doesn't work like inheritance, the ACL is queried for each assigned role sequentially, in the same order they were set in the Identity, and if any of them passes, user is granted the access.

Bobbles
Member | 3
+
0
-

Thanks for the reply. I have to admit I'm highly confused. Do you know of any code examples showing how this would work? Thanks

Ages
Member | 128
+
0
-

Here is basic implementation of static ACL:

config.neon

services:
        authorizatorFactory: App\Components\AuthorizatorFactory
        authorizator: @authorizatorFactory::create

AuthorizatorFactory.php

<?php

namespace App\Components;

use Nette\Security\Permission;


class AuthorizatorFactory
{
    /**
     * @return \Nette\Security\IAuthorizator
     */
    public function create() {
        $permission = new Permission();

        /* User role definition */
        $permission->addRole('guest');      //--- Anonymous user
        $permission->addRole('customer');   //--- Signed user
        $permission->addRole('admin');      //--- Admin

        /* List of resources */
        $permission->addResource('Admin');      //--- Admin
        $permission->addResource('Homepage');   //--- Articles
        $permission->addResource('Redactor');   //--- Redactor
        $permission->addResource('Shop');       //--- E-shop

        /* Permissions settings */
        $permission->allow('guest', ['Homepage', 'Shop'], ['show']);
        $permission->allow('customer', ['Homepage', 'Shop'], ['show', 'edit']);
        $permission->allow('admin', Permission::ALL, Permission::ALL);
        return $permission;
    }

}
Bobbles
Member | 3
+
0
-

Hi Ages. Thanks for taking the time out for the code. However, that part I understand and have something similar myself. My issue is more with multiple roles for a user. I create a new Identity with two roles assigned (in my case probationary and troll). I just want the troll role to take away some permissions from the assigned probationary role, but the
$acl->deny(‘troll’, ‘profiles’, ‘view’); code has no effect in the case of my original code above.

I gather from what Majkl578 said however, I'm missing a piece of the puzzle, and that's the part I don't understand.

duke
Member | 650
+
0
-

I am afraid with current implementation of Nette\Security\User it is not possible to deny access to some resources by adding a new role to the user. You can only achieve allowing more access by doing this.
Hence the only way to restrict access is to remove some roles from the user.

Ages
Member | 128
+
0
-

@Bobbles
I believe that this is correct:
troll can not view resource profiles
probationary can view resource profiles

So if your user has identities troll and probationary he can view resource profiles