bouncer
bouncer copied to clipboard
Using forbid method with global user role
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?
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
.
In your scenario, it sounds like the
editor
users shouldn't have theuser
role assigned to them. And that whatever abilities you grant touser
you should also grant toeditor
.
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.
You other option would be to have a special role for the restrictions, and assign that to all users who are only user
s.
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.
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.