Search code examples
phplaravellaravel-permission

Spatie's Laravel Permission and policies don't work together


Excuse my English, it's from a translator. I am using Spatie to control the permissions of my application, for example, each module I have to see, create, update and delete and so far so good, now, I want to implement Policies to prevent a user from modifying models that do not belong to him. I think I followed the documentation right but I don't know if it conflicts with Spatie.

Model

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Estudiante extends Model
{
    use HasFactory;
    

.....
}

Policy

namespace App\Policies;

use App\Models\Estudiante;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class EstudiantePolicy
{
    use HandlesAuthorization;




public function view(User $user, Estudiante $estudiante)
    {
        //solo de prueba
        return true;
    }
 }

AuthServiceProvider

class AuthServiceProvider extends ServiceProvider
{
    ...
    protected $policies = [
        Estudiante::class => EstudiantePolicy::class,
    ];
    
public function boot()
    {
        $this->registerPolicies();

        Gate::before(function ($user, $ability){
            return $user->account == "SuperAdmin" ?? null;
        });
    }       

}

With Spatie I check if that CRUD operation is authorized and it works perfectly.

    $this->authorize('ver-ficha-estudiante')

Controller

    public function edit(Estudiante $estudiante)
    {
        //Tambien he probado con $user->can('view', $estudiante)
        if($this->authorize('update', $estudiante)){
            echo "bien";
        }
    }

Route

Route::group(["middleware" => ["auth"]], function()
{
    Route::resource("ficha_estudiantes", FichaEstudianteController::class);

});

Apparently the policy is never called because not always returning true works and I already have it registered.

Any help I appreciate


Solution

  • I think you need to correct the logic in your Gate. You're using the ternary operator and Null coalescing at the same time. I think the correct logic is:

    Gate::before(function ($user, $ability){
         return $user->account == "SuperAdmin" ? true : false;
    });
    

    Moreover, I think you shouldn't use policies and spatie permissions simultaneously. I'm working on a project in which I'm just using spatie permissions without policies and its working fine. I hope it would help you. Thanks