Policy to allow admins to edit models in the admin panel
I am using the following code inside the policy class for the Duel model to prevent users from editing the model unless they are the opponent. However I want admins to be able to edit the model inside the filament panel.
/**
* Determine whether the user can update the model.
*/
public function update(User $user, Duel $duel): bool
{
\Log::info("Filament Auth Check: " . Filament::auth()->check());
\Log::info("User is Admin: " . $user->hasRole('admin'));
if (Filament::auth()->check() && $user->hasRole('admin')) {
return true;
}
return $user->id === $duel->opponent->user->id;
}
After debugging my code I get the following output:
[2025-02-07 19:23:01] local.INFO: Filament Auth Check: 1
[2025-02-07 19:23:01] local.INFO: User is Admin: 1
I noticed Filament::auth()->check() is always returning true, even if the admin panel isn't being accessed.
I even tried this variation:
/**
* Determine whether the user can update the model.
*/
public function update(User $user, Duel $duel): bool
{
\Log::info("Filament Auth Check: " . Filament::auth()->check());
\Log::info("User is Admin: " . $user->hasRole('admin'));
if (Filament::auth()->check() && $user->hasRole('admin')) {
if (request()->routeIs('filament.resources.models.edit')) {
return true;
}
}
return $user->id === $duel->opponent->user->id;
}
The issue is the filament check code always return false and admins can't edit the model inside the admin panel.
I then tried simplifying my check but, nope that didn't work either.
public function update(User $user, Duel $duel): bool
{
\Log::info("User is admin: " . $user->hasRole('admin'));
\Log::info("Route: " . request()->route()->uri());
if (request()->routeIs('filament.resources.models.edit') && $user->hasRole('admin')) {
return true;
}
if ($user->id === $duel->opponent->user->id) {
return true;
}
return false;
}
Log:
[2025-02-09 22:18:39] local.INFO: User is admin: 1
[2025-02-09 22:18:39] local.INFO: Route: admin/duels
[2025-02-09 22:18:49] local.INFO: User is admin: 1
[2025-02-09 22:18:49] local.INFO: Route: admin/duels/{record}/edit
Hi,
It looks like Filament::auth()->check()
is always returning true because Filament maintains its own authentication state, even outside the admin panel. Instead, try using Filament::getCurrentPanel()
to check if the request is actually coming from Filament.
Update your policy to:
public function update(User $user, Duel $duel): bool
{
if (Filament::getCurrentPanel() && $user->hasRole('admin')) {
return true;
}
return $user->id === $duel->opponent->user->id;
}
Let me know if this helps!
It seems they may of broken that bit as code as (Filament::getCurrentPanel()
always returns true. From the discord discussion:
However it seems the user is able to access the route no matter what. Here is the policy code:
/**
* Determine whether the user can update the model.
*/
public function update(User $user, Duel $duel): bool
{
if (Filament::getCurrentPanel() && $user->hasRole('admin')) {
Log::info('Panel accessed!');
Log::info('Panel: ' . Filament::getCurrentPanel()->getId());
return true;
}
Log::info('user id: ' . $user->id);
Log::info('opponent id: ' . $duel->opponent->user->id);
return $user->id === $duel->opponent->user->id;
}
I managed to track it down to this bit of code:
if (Filament::getCurrentPanel() && $user->hasRole('admin')) {
Adding a bit of logging it seems even if I access the route outside the admin panel Filament::getCurrentPanel()
always returns true. To be more specific the line Log::info('Panel: ' . Filament::getCurrentPanel()->getId());
returns admin
even if I am accessing the route itself and not in the admin panel. I can't tell if this is a bug with Filament so I am posting it here.
Thanks