spatie/laravel-permission

Call to undefined method Model::hasRole() when using permissions without roles

jedlikowski opened this issue · 6 comments

Describe the bug
Hi,

I use the package without any problems in my User models, but a need has arised to have a different model which will only have direct permissions, no roles. To achieve this, I added the HasPermissions trait to the model as well as this code to avoid creating a guard for the model (it's not a user-like model):

    protected function getDefaultGuardName(): string
    {
        return array_keys(config("auth.guards"))[0];
    }

    protected function getGuardNames(): Collection
    {
        return collect([$this->getDefaultGuardName()]);
    }

Now, when checking if my new model has a permission, a bug appeared in HasPermissions trait, hasPermissionViaRole method. This method assumes the Model has the HasRoles trait, which defines the hasRole() method. I will overload the method and return a hardcoded false, but nonetheless might be useful to first check if Model has the hasRole method before calling it.

    protected function hasPermissionViaRole(Permission $permission): bool
    {
        return $this->hasRole($permission->roles);
    }

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

  • spatie/laravel-permission package version: 5.5.12
  • laravel/framework version: 9.36.3

PHP version: 8.1.11

Database version: irrelevant

To Reproduce
Steps to reproduce the behavior:
Create a model with just the HasPermissions trait and try to check for a permission which is not directly attached to that model.

It is not a bug, documentation says that hasRoles must be used, not hasPermissions

But on user model you could add function hasPermissionViaRole

public function hasPermissionViaRole(\Spatie\Permission\Contracts\Permission $permission): bool {
    return false;
}

public function hasPermissionTo($permission, $guardName = null): bool
{
if (config('permission.enable_wildcard_permission', false)) {
return $this->hasWildcardPermission($permission, $guardName);
}
$permission = $this->filterPermission($permission, $guardName);
return $this->hasDirectPermission($permission) || $this->hasPermissionViaRole($permission);
}

Read again

But on user model you could add function hasPermissionViaRole

You can customize almost everything

I will overload the method and return a hardcoded false

Haha yeah I mentioned this approach in my initial message too :) Just thought I would suggest a simple change to support the usecase :)

I will overload the method and return a hardcoded false

Sorry i only read first and last lines, is the most obvious solution 👍

This is not a bug, use discussions section on the future