Most probably you don't add middleare in Kernel as explained here in docs https://spatie.be/docs/laravel-permission/v3/basic-usage/middleware right?
Using Spatie Permission package with Livewire
I'm Using Spatie Permission With Laravel livewire, but when I check the role in livewire component it's through middleware does not exist error
code sample
public function mount()
{
$this->middleware('permission:role-list');
}
I saw Livewire Authorization but I don't know what I'm missing here?
any help I'll be appreciated.
Yes, you are right.
but when you coming to protect the controllers, there is no method called middleware in livewire components
Seem that Liveware are using Gate Policies, see https://laravel.com/docs/7.x/authorization#creating-policies
I am not sure, but seem that you can't add middleware to a lireware route, I can see only here global middleware:
https://laravel-livewire.com/docs/2.x/file-uploads#global-middleware
@oussamasid this is my solution , a BaseComponent with custom implementation. you can also implements just a trait instead
<?php
namespace App\Http\Livewire;
use App\Models\User;
use Livewire\Component;
use Spatie\Permission\Exceptions\UnauthorizedException;
abstract class BaseComponent extends Component
{
/** override per usare spatie */
public function authorize($roleOrPermission)
{
/** @var User $user */
//check logged
$user = auth()->user();
if (! $user ) {
throw UnauthorizedException::notLoggedIn();
}
//check rule or pemission (like spatie middleware i.e. "admin|edit posts")
$rolesOrPermissions = is_array($roleOrPermission)
? $roleOrPermission
: explode('|', $roleOrPermission);
if (! $user->hasAnyRole($rolesOrPermissions) && ! $user->hasAnyPermission($rolesOrPermissions)) {
throw UnauthorizedException::forRolesOrPermissions($rolesOrPermissions);
}
}
public function render()
{
return '';
}
}
I just had the same problem and the "missing" thing from Livewire Authorization was that you can check Spatie permissions with the authorize method from the AuthorizesRequests trait.
<?php
namespace App\Http\Livewire\MyComponent;
use Livewire\Component;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class MyComponent extends Component
{
use AuthorizesRequests;
public function mount()
{
$this->authorize('my-permission');
}
}
But, this does only work for a single permission, so if you want to check multiple roles and/or permissions just use zofe's solution and use a base class or trait.
Trait example (tbh i just copied the Spatie middleware)
<?php
namespace App\Traits;
use Illuminate\Support\Facades\Auth;
use Spatie\Permission\Exceptions\UnauthorizedException;
trait AuthorizesRoleOrPermission
{
public function authorizeRoleOrPermission($roleOrPermission, $guard = null)
{
if (Auth::guard($guard)->guest()) {
throw UnauthorizedException::notLoggedIn();
}
$rolesOrPermissions = is_array($roleOrPermission)
? $roleOrPermission
: explode('|', $roleOrPermission);
if (! Auth::guard($guard)->user()->hasAnyRole($rolesOrPermissions) && ! Auth::guard($guard)->user()->hasAnyPermission($rolesOrPermissions)) {
throw UnauthorizedException::forRolesOrPermissions($rolesOrPermissions);
}
}
}
hi, what should be the file name for this trait which to store in app\traits folder
Try naming the file as AuthorizesRoleOrPermission.php and save it into the ./app/Traits/ folder (note Traits is capitalized).
If there are no ./app/Traits/ folder, just create it and create the PHP file inside it.
Then composer should find it.
Thank u very much
I resolved whit the middleware on the route
Route::middleware(['role:superadmin|admin'])->get('/clients',Clients::class)->name('clients');
Hello, I'm so late... but, I got a method to protect the livewire component inside Spatie Permissions...
I did take the spatie trait code, and made a little changes
<?php
namespace App\Traits\Admin;
use Illuminate\Support\Facades\Auth;
use Spatie\Permission\Exceptions\UnauthorizedException;
trait RoleOrPermissionSpatie
{
public function handlePermission($roleOrPermission)
{
$authGuard = Auth::guard();
if ($authGuard->guest()) {
throw UnauthorizedException::notLoggedIn();
}
$rolesOrPermissions = is_array($roleOrPermission)
? $roleOrPermission
: explode('|', $roleOrPermission);
if (! $authGuard->user()->hasAnyRole($rolesOrPermissions) && ! $authGuard->user()->hasAnyPermission($rolesOrPermissions)) {
throw UnauthorizedException::forRolesOrPermissions($rolesOrPermissions);
}
}
}
Save it into App\Traits\Admin
and... Into the livewire coponent something like that.
namespace App\Http\Livewire\Admin;
use Livewire\Component;
...
...
use App\Traits\Admin\RoleOrPermissionSpatie;
class Programas extends Component
{
use RoleOrPermissionSpatie;
public function __construct()
{
$this->handlePermission('role1|role2|permission1');
}
}
And we can use the trait like the middleware...
Sory I'am so late.
in my case.
This can be used to check the permission
abort_if(Gate::denies('user-read'), Response::HTTP_FORBIDDEN, 'Forbidden');
this can be used to check the role
$userLogIn = Auth::user();
abort_if(!($userLogIn && $userLogIn->hasRole('Admin')), Response::HTTP_FORBIDDEN, 'Forbidden');
permission checking can also be done on each method if needed.
and don't forget to add
use Illuminate\Support\Facades\Gate;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
Please or to participate in this conversation.