stechstudio / filament-impersonate

Filament plugin that makes it easy to impersonate your users
264 stars 55 forks source link

ViewException: Filament\FilamentManager::getUserName() #87

Open stuartcusackie opened 3 months ago

stuartcusackie commented 3 months ago

I'm seeing this error on a testing server:

Filament\FilamentManager::getUserName(): Argument #1 ($user) must be of type Illuminate\Database\Eloquent\Model|Illuminate\Contracts\Auth\Authenticatable, null given, called in /home/forge/mysite.ie/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php on line 355 (View: /home/forge/mysite.ie/vendor/stechstudio/filament-impersonate/resources/views/components/banner.blade.php) (View: /home/forge/mysite.ie/vendor/stechstudio/filament-impersonate/resources/views/components/banner.blade.php) (View: /home/forge/mysite.ie/vendor/stechstudio/filament-impersonate/resources/views/components/banner.blade.php) (View: /home/forge/mysite.ie/vendor/stechstudio/filament-impersonate/resources/views/components/banner.blade.php) (View: /home/forge/mysite.ie/vendor/stechstudio/filament-impersonate/resources/views/components/banner.blade.php)

I was impersonating a user when I re-migrated the database.

I think it's to do with session cookies. If I open an incognito browser then everything is fine.

Not sure what the solution is...

Saifallak commented 2 months ago

having same issue, when impersonating another guard on another panel, and then return to first panel.

kiwina commented 2 months ago

The problem is the service provider is registering the view automatically and when you use multiple guards it chokes at

@if(app('impersonate')->isImpersonating())

the solution is overriding the service provider

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Event;
use Lab404\Impersonate\Events\LeaveImpersonation;
use Lab404\Impersonate\Events\TakeImpersonation;
use ReflectionClass;
use Spatie\LaravelPackageTools\Package;
use STS\FilamentImpersonate\FilamentImpersonateServiceProvider as ServiceProvider;
use STS\FilamentImpersonate\Tables\Actions\Impersonate;

class FilamentImpersonateServiceProvider extends ServiceProvider
{
    public function configurePackage(Package $package): void
    {
        $package
            ->name(static::$name)
            ->hasRoute('web')
            ->hasConfigFile()
            ->hasTranslations()
            ->hasViews()
            ->setBasePath($this->getOriginalPackageBaseDir()); // path to the original package
    }

    // LaravelPackageTools need to know the path of the original package to load resources
    protected function getOriginalPackageBaseDir(): string
    {
        $reflector = new ReflectionClass(ServiceProvider::class);

        return dirname($reflector->getFileName());
    }

    public function bootingPackage(): void
    {
         // removed the hook FilamentView::registerRenderHook
        // path to the original package
        $this->loadViewsFrom($this->getOriginalPackageBaseDir() .'/../resources/views', 'impersonate');
        if (!class_exists(\STS\FilamentImpersonate\Impersonate::class)) {
            class_alias(Impersonate::class, \STS\FilamentImpersonate\Impersonate::class);
        }
    }
}

and override the loading of the original service provider in composer

"extra": {
    "laravel": {
      "dont-discover": [
        "stechstudio/filament-impersonate"
      ]
    }
  },

then you can add the view to your panel

->renderHook( PanelsRenderHook::BODY_END,  
static fn() => Blade::render("<x-impersonate::banner :display='auth()->user()->email'/>")
 )