I just spent far too long getting PermissionDoesNotExist when trying to use givePermissionTo on either role or user objects. All of the documentation appears that you can provide the unique name string of the permission, but I finally found out I have to pass the whole permission object? Or am I doing something terribly wrong?
What I mean is:
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
$admin_role = Role::where('name','admin')->first();
$admin_role->givePermissionTo('post_new_blog');
The above gives a PermissionDoesNotExist error (the permission DOES exist). BUT:
$admin_role = Role::where('name','admin')->first();
$permission = Permission::where('name','post_new_blog')->first();
$admin_role->givePermissionTo($permission);
Works fine. Like I said in my original post, I have to pass a whole permission object to givePermissionTo(). I feel like I must be missing something obvious, that the code at the top is supposed to work according to the documentation. Laravel 5.4.
I'd really like to understand this before I proceed further - thanks in advance!
The tests seem to prove that passing a string to givePermissionTo should just work: https://github.com/spatie/laravel-permission/blob/37ed4c9243806a40c7797a203a069852e9ecfce7/tests/HasRolesTest.php#L315
Is your application using multiple guards?
No custom guards at all, certainly not multiple. I'm just getting started with this package. But, I can tell you that for example hasRole() and hasPermissionTo() do work with simple strings. It's exactly my example that is driving me crazy.
Am I missing something required that I need to useor otherwise include?
this works:
$permission1 = Permission::create(['name' => 'manage-company']);
$permission2 = Permission::create(['name' => 'manage-app']);
$this->user->givePermissionTo($permission1);
$this->user->givePermissionTo($permission2);
i have a similiar issue:
public function setUp()
{
parent::setUp();
$this->user = factory(User::class)->states('worker')->create();
Permission::create(['name' => 'manage-company']);
Permission::create(['name' => 'manage-app']);
var_dump(Permission::all()->toArray());
$this->user->givePermissionTo(['manage-company', 'manage-app']);
$this->actingAs($this->user, 'api');
}
throws:
array(2) {
[0]=>
array(5) {
["id"]=>
int(1)
["name"]=>
string(14) "manage-company"
["guard_name"]=>
string(3) "api"
["created_at"]=>
string(19) "2017-06-05 22:19:33"
["updated_at"]=>
string(19) "2017-06-05 22:19:33"
}
[1]=>
array(5) {
["id"]=>
int(2)
["name"]=>
string(10) "manage-app"
["guard_name"]=>
string(3) "api"
["created_at"]=>
string(19) "2017-06-05 22:19:33"
["updated_at"]=>
string(19) "2017-06-05 22:19:33"
}
}
Time: 383 ms, Memory: 16.00MB
There were 2 errors:
1) Tests\Feature\ShowMeTest::show_logged_in_user
Spatie\Permission\Exceptions\PermissionDoesNotExist: There is no permission named `manage-company`.
/Users/thoresuenert/dev/kussgmbh-api/vendor/spatie/laravel-permission/src/Exceptions/PermissionDoesNotExist.php:11
/Users/thoresuenert/dev/kussgmbh-api/vendor/spatie/laravel-permission/src/Models/Permission.php:83
/Users/thoresuenert/dev/kussgmbh-api/vendor/spatie/laravel-permission/src/Traits/HasPermissions.php:76
/Users/thoresuenert/dev/kussgmbh-api/vendor/spatie/laravel-permission/src/Traits/HasPermissions.php:24
/Users/thoresuenert/dev/kussgmbh-api/vendor/laravel/framework/src/Illuminate/Support/Collection.php:702
/Users/thoresuenert/dev/kussgmbh-api/vendor/spatie/laravel-permission/src/Traits/HasPermissions.php:25
/Users/thoresuenert/dev/kussgmbh-api/tests/Feature/ShowMeTest.php:23
i had web and api guard active. when i comment out "web" it works
Which is the right way to tell permission checks to use a guard?
This was a bug. I've tagged a new released that fixes this.
This is how you can check if a user has permission for a specific guard:
$permissionName = 'edit articles';
$guardName = 'api';
$user->hasPermissionTo($permissionName, $guardName);
Using 2.1.6, I am still having to use objects instead of the name string for roles/permissions. If I do:
if($user->hasPermissionTo('post new content')){ // do_stuff(); }
I get the error: There is no permission named post new content for guard web. The permission is in the database for guard "web". If I do:
$permission = Permission::where('name','post new content')->first();
if($user->hasPermissionTo($permission)){ // do_stuff(); }
That works. I am not intending to report a bug, as I think it is me that is doing something wrong. Can someone clarify what my issue is?
Disregard: This turned out to be a cache issue. It works as expected now.
Important note: I had run the artisan commands to clear cache, but that _fails silently_ if there is a filesystem permissions issue that prevents the cache files from being cleared. I only realized what was happening when I did a recursive grep through my entire site instance...
Turned out to be a cache issue too. php artisan config:cache solved the issue.
Most helpful comment
Disregard: This turned out to be a cache issue. It works as expected now.
Important note: I had run the artisan commands to clear cache, but that _fails silently_ if there is a filesystem permissions issue that prevents the cache files from being cleared. I only realized what was happening when I did a recursive grep through my entire site instance...