bouncer icon indicating copy to clipboard operation
bouncer copied to clipboard

Using forbid method with global user role

Open dzorogh opened this issue 2 years ago • 5 comments

I have a pretty simple idea, but I never quite got it right. I have read all the documentation and searched issues.

There is a list of Documents. There is a global User role, every user has it when they registered. There is a Document Editor role, some users have it.

Some documents need to be forbidden for normal users, but still visible for Editors

// every user has default 'user' role
Bouncer::assign('user')->to($readerUser);
Bouncer::assign('user')->to($editorUser); 

Bouncer::assign('editor')->to($editorUser);

Bouncer::allow('user')->to('view', Document::class);
Bouncer::forbid('user')->to('view', $classifiedDocument);

$readerUser->can('view', $classifiedDocument); // false — ok
$editorUser->can('view', $classifiedDocument); // false — not ok

The problem is that the Document Editor also lost access to those documents, because he has User role too. And we can't take away his User role, because with this role he gets access to other parts of the application.

I think about separate global roles, like Document User, which must be unassigned for Editors. Or about role levels, which was removed from this package. But none of them is a perfect solution.

What am I doing wrong, maybe there are some simple solution?

dzorogh avatar May 31 '22 15:05 dzorogh

You're not doing anything wrong.

Roles are simply a shortcut for providing permissions to a given user. So for all roles that they have, if any of them forbids an ability, it will always be forbidden.

In your scenario, it sounds like the editor users shouldn't have the user role assigned to them. And that whatever abilities you grant to user you should also grant to editor.

JosephSilber avatar May 31 '22 18:05 JosephSilber

In your scenario, it sounds like the editor users shouldn't have the user role assigned to them. And that whatever abilities you grant to user you should also grant to editor.

In my scenario, I have a lot of abilities attached to user role (maybe 50 or more), where 95% of them used for every user and every other role. And the list of user abilities likely will change often. So I tried to use global role to share that 95% of common abilities/permissions. editor role is not single — in my scenario, I have a lot of different editors, moderators, admins, etc. for different parts of the system. And documents editor doesn't have same abilities like news editor, for example.

So, if I use editor role without user role, every time I need to update user role, I must update most other editor, admin, moderator roles, just to make them not inherit 1% of forbidden user abilities.

dzorogh avatar May 31 '22 19:05 dzorogh

You other option would be to have a special role for the restrictions, and assign that to all users who are only users.

JosephSilber avatar May 31 '22 19:05 JosephSilber

In my case, it will be like 10-20 special restrictive roles. And I need to assign that role to every user (with exception to some user with roles I don't want to be restricted) when I create a new big model or section in app.

I think about it from the other side — create for each section a separate "user" role, like document user or news reader, and add these roles on registration. But the problem is the same.

Maybe it's okay to regularly update each user and change their roles, I don't know.

dzorogh avatar May 31 '22 19:05 dzorogh

Bouncer lets you grant abilities to everyone, without using any roles:

Bouncer::allowEveryone()->to('view', Document::class);

I see now that it's not documented. Gotta fix that.


So in your case, you could add all general abilities to everyone, and only add the restrictions to the user role:

Bouncer::allowEveryone()->to('view', Document::class);
Bouncer::forbid('user')->to('view', $classifiedDocument);

...and then don't assign the user role to users who have the editor role.

JosephSilber avatar May 31 '22 20:05 JosephSilber