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

bozsikarmand's avatar

How to integrate Spatie's laravel-permission with JetStream properly?

Hello,

I have a nicely working basic install of Laravel JetStream and Spatie's laravel-permission in Laravel 8.

I can assign a role to the user during registration via

$user->assignRole('visitor');
return $user;

(in CreateNewUser.php)

Can also restrict the available menu items on the user's dashboard through the permissions I have assigned to the role in my seeder files run method:

Permission::create(['name' => 'access profile']);
Permission::create(['name' => 'access logout']);

$visitor = Role::create(['name' => 'visitor']);
$visitor->givePermissionTo('access profile');

and through the can directive in the view, like:

@can('access profile')
<!-- Account Management -->
<div class="block px-4 py-2 text-xs text-gray-400">
    {{ __('Manage Account') }}
</div>

<x-jet-dropdown-link href="{{ route('profile.show') }}">
    {{ __('Profile') }}
</x-jet-dropdown-link>
@endcan

So by that, I can hide the menu item as per role but unfortunately, I can still access the functionality directly, by knowing the exact URL.

I guess I have to write a middleware to restrict access to certain functions, but how exactly?

What is the proper and accepted way to handle this problem in this stack?

Thanks! Armand So everything seems fine BUT (!)

How is it possible to forbid direct access to the hidden items? I guess in this case routes are controlled by sanctum, while roles and permissions are by Spatie's package.

Is it possible to link the two?

Thanks!

0 likes
1 reply
jlrdw's avatar

Spatie works with laravel authorization. So jestream would't affect authorization, it's the same as breeze, ui, or manual.

Just follow their documentation and you are good to go.

How is it possible to forbid direct access to the hidden items

How your query is formed, or if too much to separate, then have different sections altogether.

Think about it like this, if it takes too many if else type constructs to handle, it's time to have separate views for say an admin vs a user, but just an opinion and suggestion and example.

Edit:

I can still access the functionality directly, by knowing the exact URL.

Try this: In this forum click the "My Participation" link. And notice what you do not see. There is no id. The Auth::id is used in the query. That's why I mentioned how your query is formed.

You shouldn't have to mess with middleware to have good authorization. But that's up to you.

3 likes

Please or to participate in this conversation.