jeffgreco13 / filament-breezy

MIT License
760 stars 130 forks source link

Another route has already been assigned name: when using Multiple domains on Panels (multiple) #388

Open eelco2k opened 2 months ago

eelco2k commented 2 months ago

Error when using multiple domains in a panel:

Unable to prepare route [two-factor-authentication] for serialization. Another route has already been assigned name [filament.central-admin.auth.two-factor].

  at vendor/laravel/framework/src/Illuminate/Routing/AbstractRouteCollection.php:247
    243▕             $route->name($this->generateRouteName());
    244▕ 
    245▕             $this->add($route);
    246▕         } elseif (! is_null($symfonyRoutes->get($name))) {
  ➜ 247▕             throw new LogicException("Unable to prepare route [{$route->uri}] for serialization. Another route has already been assigned name [{$name}].");
    248▕         }
    249▕ 
    250▕         $symfonyRoutes->add($route->getName(), $route->toSymfonyRoute());
    251▕ 

The fix is that the name of the route should contain the domain suffixed in the route name in web.php. like so: ->name(!empty($domain) ? "{$panelId}.{$domain}." : "{$panelId}.")

Route::domain($domain)
                    ->middleware($panel->getMiddleware())
                    ->name(!empty($domain) ? "{$panelId}.{$domain}." : "{$panelId}.")
                    ->prefix($panel->getPath())
eelco2k commented 2 months ago

nevermind, issue was within another package... fixed will close issue

eelco2k commented 1 week ago

Actually this still applies when using multiple domains

see example when using php artisan route:list

GET|HEAD   localhost/two-factor-authentication ................................ localhost.filament.central-admin.auth.two-factor › Jeffgreco13\FilamentBreezy › TwoFactorPage
GET|HEAD   10.0.0.120/two-factor-authentication .............................. 10.0.0.120.filament.central-admin.auth.two-factor › Jeffgreco13\FilamentBreezy › TwoFactorPage
GET|HEAD   central.lan/two-factor-authentication ............................ central.lan.filament.central-admin.auth.two-factor › Jeffgreco13\FilamentBreezy › TwoFactorPage
GET|HEAD   admin.lan/two-factor-authentication .......... admin.lan.filament.admin-portal.auth.two-factor › Jeffgreco13\FilamentBreezy › TwoFactorPage
GET|HEAD   client.lan/two-factor-authentication ........ client.lan.filament.client-portal.auth.two-factor › Jeffgreco13\FilamentBreezy › TwoFactorPage

so the line with the ->name("{$panelId}.")

should be replaced with: ->name(!empty($domain) ? "{$domain}.{$panelId}." : "{$panelId}.")

furthermore MustTwoFactor.php should be changed as such:

<?php

use Filament\Facades\Filament;
use Illuminate\Support\Facades\Route;

Route::name('')->group(function () {
    foreach (Filament::getPanels() as $panel) {
        $panelId = $panel->getId();
        $domains = $panel->getDomains();
        $hasTenancy = $panel->hasTenancy();

        foreach ((empty($domains) ? [null] : $domains) as $domain) {
            Route::domain($domain)
                ->middleware($panel->getMiddleware())
                ->name(!empty($domain) ? "{$domain}.filament.{$panelId}." : "filament.{$panelId}.")
                ->prefix($panel->getPath())
                ->group(function () use ($panel, $hasTenancy) {
                    if ($panel->hasPlugin('filament-breezy')) {
                        $route = $hasTenancy ? '/{tenant}/two-factor-authentication' : '/two-factor-authentication';
                        $action = filament('filament-breezy')->getTwoFactorRouteAction();

                        Route::get($route, $action)->name('auth.two-factor');
                    }
                });
        }
    }
});
eelco2k commented 1 week ago

this way you make sure you always prepend the Route::domain() in front of the Route ->name() which makes that specific route always unique per domain.