spatie/laravel-permission

[v6] There is no permission named '1' for guard 'web'.

falkonerX72 opened this issue · 4 comments

Describe the bug
I'm using basic spatie settings for controlling roles&permissions in my laravel 10 project.

The issue is that I keep facing :

**Spatie \ Permission \ Exceptions \ PermissionDoesNotExist
PHP 8.2.4 10.30.0
There is no permission named `whatever***` for guard `web`.** 

which happened since upgrading to v6-6.0.1 while using standard commands such as

  1. $role->syncPermissions($permissions); and 2. $user->assignRole($request->roles);

also I'm using default laravel 'web' guard.

When I'm downgrading to V5.11 or 5.8 I get no error and everything works perfectly !

Versions
You can use composer show to get the version numbers of:

  • spatie/laravel-permission package version: 6 - 6.0.1
  • illuminate/framework package: v10.30.0 Laravel Framework.

PHP version:
8.2.4

Database version:

MariaDB 10.4.28

To Reproduce
Steps to reproduce the behavior:

Here is my example code and/or tests showing the problem in my app:

 $role = Role::findOrFail($id);
        $permissions = $request->permission;

        if (!empty($permissions)) {
            $role->syncPermissions($permissions);
        }

&

   if ($request->roles) {
            $user->assignRole($request->roles);
        }

Example Application
Here is a link to my Github repo containing a minimal Laravel application which shows my problem:

https://github.com/falkonerX72/L.estate

Environment (please complete the following information, because it helps us investigate better):

  • OS: windows
  • Version 11

Seems like the same #2530 (comment) (again)

1. Due to the improved ULID/UUID/GUID support, any package methods which accept a Permission or Role `id` must pass that `id` as an `integer`. If you pass it as a numeric string, the functions will attempt to lookup the role/permission as a string. In such cases you may see errors such as `There is no permission named '123' for guard 'web'.` (where `'123'` is being treated as a string because it was passed as a string instead of as an integer). This also applies to arrays of id's: if it's an array of strings we will do a lookup on the name instead of on the id. **This will mostly only affect UI pages** because an HTML Request is received as string data. **The solution is simple:** if you're passing integers to a form field, then convert them back to integers when using that field's data for calling functions to grant/assign/sync/remove/revoke permissions and roles.

  1. Due to the improved ULID/UUID/GUID support, any package methods which accept a Permission or Role id must pass that id as an integer. If you pass it as a numeric string, the functions will attempt to lookup the role/permission as a string. In such cases you may see errors such as There is no permission named '123' for guard 'web'. (where '123' is being treated as a string because it was passed as a string instead of as an integer). This also applies to arrays of id's: if it's an array of strings we will do a lookup on the name instead of on the id. This will mostly only affect UI pages because an HTML Request is received as string data. The solution is simple: if you're passing integers to a form field, then convert them back to integers when using that field's data for calling functions to grant/assign/sync/remove/revoke permissions and roles. One way to convert an array of permissions id's from strings to integers is: collect($validated['permission'])->map(fn($val)=>(int)$val)

Example Application
Here is a link to my Github repo containing a minimal Laravel application which shows my problem:

https://github.com/falkonerX72/L.estate

The link doesn't work

Dear contributor,

because this issue seems to be inactive for quite some time now, I've automatically closed it. If you feel this issue deserves some attention from my human colleagues feel free to reopen it.

for whoever comes here, here is how i solved it. it might not be the most efficient but it works in a pinch:

        $numericRoleArray = [];
        foreach($request->roles as $role) {
            $numericRoleArray[] = intval($role);
        }

        $numericPermissionArray = [];
        foreach($request->permissions as $permission) {
            $numericPermissionArray[] = intval($permission);
        }

        $user->syncRoles($numericRoleArray);
        $user->syncPermissions($numericPermissionArray);
        ```