Policy to allow admins to edit models in the admin panel

ookma-kyi

Feb 9th, 2025 07:34 PM

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
bobbyiliev

Feb 9th, 2025 11:51 PM

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!

ookma-kyi

Mar 19th, 2025 12:23 PM

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

Discord Message Link