Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

kimmel's avatar
Level 8

Spatie\laravel-permission Can, hasPermissionTo, and getAllPermissions do not match

Has anyone run into a situation with spatie\laravel-permission where the permission checks don't match up? I have an app that will never authorize a user if I have not added the permission directly to the user instead of a role. In this example, this user is assigned a role with the permission 'support.manage'. If I execute these three commands, you can see the permission is granted through the role but both hasPermissionTo and can return false.

dump(auth()->user()->hasPermissionTo('support.manage')); returns false

dump(auth()->user()->getAllPermissions()); returns Illuminate\Database\Eloquent\Collection {#3389 ▼ // app/Http/Middleware/AdminGuard.php:20 #items: array:2 [▼ 0 => App\Models
Permission {#2711 ▶} 1 => App\Models
Permission {#2902 ▼ #connection: "pgsql" #table: "permissions" #primaryKey: "id" #keyType: "int" +incrementing: true #with: [] #withCount: [] +preventsLazyLoading: false #perPage: 15 +exists: true +wasRecentlyCreated: false #escapeWhenCastingToString: false #attributes: array:7 [▼ "id" => 101 "name" => "support.manage" "guard_name" => "web" "created_at" => "2024-11-21 11:37:42" "updated_at" => "2024-11-21 11:37:42" "description" => "Support System Access" "deleted_at" => null ] #original: array:9 [▶] #changes: [] #casts: array:1 [▶] #classCastCache: [] #attributeCastCache: [] #dateFormat: null #appends: [] #dispatchesEvents: [] #observables: [] #relations: array:1 [▶] #touches: [] +timestamps: true +usesUniqueIds: false #hidden: [] #visible: [] #fillable: [] #guarded: array:1 [▶] -roleClass: null -permissionClass: null -wildcardClass: null -wildcardPermissionsIndex: ? array #forceDeleting: false } ] #escapeWhenCastingToString: false }

dd(auth()->user()->can('support.manage')); returns false

0 likes
5 replies
LaryAI's avatar
Level 58

The issue you're experiencing with the Spatie Laravel Permission package often arises from caching problems or misconfigurations. Here are some steps to troubleshoot and resolve the issue:

  1. Clear Cache: The most common issue is related to caching. Laravel caches roles and permissions, so if you've made changes, you need to clear the cache.

    Run the following command to clear the cache:

    php artisan cache:clear
    php artisan config:clear
    php artisan route:clear
    php artisan view:clear
    php artisan permission:cache-reset
    
  2. Check Role and Permission Assignment: Ensure that the role is correctly assigned to the user and that the permission is correctly assigned to the role.

    You can verify this by checking your database tables:

    • users table for user entries.
    • roles table for role entries.
    • permissions table for permission entries.
    • role_has_permissions table to ensure the role has the correct permissions.
    • model_has_roles table to ensure the user has the correct role.
  3. Verify Configuration: Ensure that your config/permission.php file is correctly set up. Specifically, check that the cache settings are correct and that the models and table_names are pointing to the correct classes and tables.

  4. Check Middleware: If you're using middleware to check permissions, ensure that it's correctly applied in your routes or controllers.

  5. Debugging: Add some debugging statements to ensure that the user and role are being fetched correctly. For example:

    $user = auth()->user();
    $role = $user->roles()->first();
    $permissions = $role ? $role->permissions : collect();
    
    dump($user->name);
    dump($role ? $role->name : 'No role assigned');
    dump($permissions->pluck('name'));
    
  6. Update Package: Ensure that you are using the latest version of the Spatie Laravel Permission package. Sometimes bugs are fixed in newer releases.

  7. Check for Custom Logic: If you have any custom logic that overrides the default behavior of the package, ensure that it is not interfering with the permission checks.

By following these steps, you should be able to identify and resolve the issue with permission checks not matching up. If the problem persists, consider providing more context or code snippets for further assistance.

kimmel's avatar
Level 8

And yes I have cleared the cache many, many times.

Thunderson's avatar

Please wrap your code with backticks to active code highlight. Read The * Manual

// do not use hasPermissionTo to check direct permission
$user->hasDirectPermission('support.manage')
kimmel's avatar
kimmel
OP
Best Answer
Level 8

It appears to be something with the package. I was able to correct it by overriding the hasPermissionViaRole function in the User model. Thanks for the unhelpful reply though. Read The Question.

For others, the overridden function that worked was

protected function hasPermissionViaRole(Permission $permission): bool
    {
        if (is_a($this, Role::class)) {
            return false; // Roles themselves do not inherit permissions from other roles
        }
        //this is the override below
        // Ensure roles are loaded and check if any of the user's roles match the permission's roles
        return $this->roles->contains(function (Role $role) use ($permission) {
            return $role->permissions->contains('id', $permission->id);
        });
    }
Thunderson's avatar

@kimmel i already used this package and i never had this issue, i think you wrong somewhere. edit the vendor code is allways a bad pratice.

Please or to participate in this conversation.