Closed hasak closed 3 years ago
Can you share your use-case for why you would want this?
For example:
To change role's abilities in frontend, I would need something like:
<input type="checkbox" {{$role->can('add',$model)?"checked":""}}>
where $role
and $model
are going through foreach.
Another example: I want to check for all roles that have specific ability (in controller or model)
The way I was doing it until now is:
$dummy->can(...)
Which I don't find elegant at all, and it is for some reason buggy when used in a loop (somehow it is lagging behind the rest of the code, but I will inspect this more in detail and create issue with more details)
You don't want to check if $role->can('add', $model)
, since that doesn't check for a specific ability. It would return true
if you have previously done any of the following:
Bouncer::allow($role)->everything()
Bouncer::allow($role)->toManage(TheModelType::class)
Bouncer::allow($role)->to('add', TheModelType::class)
Bouncer::allow($role)->to('add', $model)
Your code should only care about item 4 in that list.
So in essence, you're not trying to go through the gate, because you don't want to simply check if the user can perform the given action (as you would check before the action is actually performed). Rather, you want to check whether the role actually has this specific ability in the list you get from $role->getAbilities()
.
>>> $user->role->can('do-something')
^ "select * from `abilities` where (exists (select * from `roles` inner join `permissions` on `roles`.`id` = `permissions`.`entity_id` where `permissions`.`ability_id` = `abilities`.`id` and `permissions`.`forbidden` = ? and `permissions`.`entity_type` = ? and (exists (select * from `roles` inner join `assigned_roles` on `roles`.`id` = `assigned_roles`.`entity_id` where `assigned_roles`.`role_id` = `roles`.`id` and `assigned_roles`.`entity_type` = ? and `roles`.`id` = ?) or `level` < (select max(level) from `roles` where exists (select * from `roles` inner join `assigned_roles` on `roles`.`id` = `assigned_roles`.`entity_id` where `assigned_roles`.`role_id` = `roles`.`id` and `assigned_roles`.`entity_type` = ? and `roles`.`id` = ?)))) or exists (select * from `roles` inner join `permissions` on `roles`.`id` = `permissions`.`entity_id` where `permissions`.`ability_id` = `abilities`.`id` and `permissions`.`forbidden` = ? and `permissions`.`entity_type` = ? and `roles`.`id` = ?) or exists (select * from `permissions` where `permissions`.`ability_id` = `abilities`.`id` and `permissions`.`forbidden` = ? and `entity_id` is null)) and `only_owned` = ? and (`name` = ? and `entity_type` is null or (`name` = ? and (`entity_type` is null or `entity_type` = ?)))"
^ array:14 [
0 => false
1 => "roles"
2 => "Silber\Bouncer\Database\Role"
3 => 1
4 => "Silber\Bouncer\Database\Role"
5 => 1
6 => false
7 => "Silber\Bouncer\Database\Role"
8 => 1
9 => false
10 => false
11 => "do-something"
12 => "*"
13 => "*"
I've changed this line to dump the query, since I'm using custom models with morph map Silber\Bouncer\Database\Role
should be renamed to roles
I was reading the code again and just found that someone added use Silber\Bouncer\Database\Role;
on the User model so it was overriding my custom Role... smh
Is it possible to have something like:
$role->can($ability,$model);
instead of assigning role to an user and then checking$user->can(...)
?