Problems with canAccessPanel what is the filament.app.tenant route?

Really struggling with multiple panels in my app. I have 2 internal panels, app and admin, and one external panel, client. An internal user can login just fine, but having all kinds of problems getting the user logged in on the client panel.
when the user logs in, I either get the credentials don't match error (see screenshot), or I get a 403, and the route that is giving the 403 is filament.app.tenant which is not in the route list and I have no idea what it is.
public function canAccessPanel(Panel $panel): bool
{
dd(Route::currentRouteName()); //shows "filament.app.tenant"
//dd($panel->getId()); // shows "app", but client user should be "client"
if (str_ends_with($this->email, '@mydomain.com')) {
return $this->isInternal() && $this->hasVerifiedEmail();
} else {
return $this->hasVerifiedEmail();
}
public function canAccessPanel(Panel $panel): bool
{
dd(Route::currentRouteName()); //shows "filament.app.tenant"
//dd($panel->getId()); // shows "app", but client user should be "client"
if (str_ends_with($this->email, '@mydomain.com')) {
return $this->isInternal() && $this->hasVerifiedEmail();
} else {
return $this->hasVerifiedEmail();
}
i'm pretty sure the problem is my canAccessPanel method, but I'm unsure of what I should even be doing. The panel is "app" when it gets to this method, but the panel should be "client", so how and where do I make sure that's happening? Do I set the panel to the correct one from the canAccessPanel method?
No description
Solution:
Once I figured that out, it seems I just need to tweak my getDefaultTenant() method on my User model to return an empty model in the event that the user isn't internal, which then causes the redirect controller to return the panel url instead of trying to redirect to the tenant registration page. ```php public function getDefaultTenant(Panel $panel): ?Model {...
Jump to solution
2 Replies
Jon Mason
Jon Mason3mo ago
If I change the panel based on the current user attempting to login:
if (!$this->isInternal()) {
$panel = Filament::getPanel('client');
}
if (!$this->isInternal()) {
$panel = Filament::getPanel('client');
}
I get a 404 error, and it's going to the filament.app.tenant route. Really confused. from debug bar I found that the location where it's ultimately failing is in the RedirectToTenantController:
class RedirectToTenantController
{
public function __invoke(): RedirectResponse
{
$panel = Filament::getCurrentPanel();
$tenant = Filament::getUserDefaultTenant(Filament::auth()->user());
dd($tenant); //tenant is empty.
if (!$tenant) {
return $this->redirectToTenantRegistration($panel);
}

$url = $panel->getUrl($tenant);

if (blank($url)) {
abort(404);
}

return redirect($url);
}
class RedirectToTenantController
{
public function __invoke(): RedirectResponse
{
$panel = Filament::getCurrentPanel();
$tenant = Filament::getUserDefaultTenant(Filament::auth()->user());
dd($tenant); //tenant is empty.
if (!$tenant) {
return $this->redirectToTenantRegistration($panel);
}

$url = $panel->getUrl($tenant);

if (blank($url)) {
abort(404);
}

return redirect($url);
}
This panel doesn't have tenancy, so the tenant is empty for this user. I'm realizing that's likely the root cause of this issue, but I don't know how to fix it. I I don't have any tenancy features enabled on my panel. I tried to add this in my Authentication middleware:
$user = $guard->user();

$panel = Filament::getCurrentPanel();

//this is my attempt to set the panel myself as a fallback, but it's always null.
if (!$user->isInternal() && $panel->getId() !== 'client') {
dump('here'); //gets here
$clientPanel = Filament::getPanel('client');
$panel = Filament::setCurrentPanel($clientPanel);
}

dd($panel); //null

abort_if($user instanceof FilamentUser ? (!$user->canAccessPanel($panel)) : (config('app.env') !== 'local'), 403);
$user = $guard->user();

$panel = Filament::getCurrentPanel();

//this is my attempt to set the panel myself as a fallback, but it's always null.
if (!$user->isInternal() && $panel->getId() !== 'client') {
dump('here'); //gets here
$clientPanel = Filament::getPanel('client');
$panel = Filament::setCurrentPanel($clientPanel);
}

dd($panel); //null

abort_if($user instanceof FilamentUser ? (!$user->canAccessPanel($panel)) : (config('app.env') !== 'local'), 403);
ok, stupid on my part, but i didn't realize that setCurrentPanel doesn't return the panel after setting it, so that part is working, but I'm still getting a 404 error after this point somewhere.
Solution
Jon Mason
Jon Mason3mo ago
Once I figured that out, it seems I just need to tweak my getDefaultTenant() method on my User model to return an empty model in the event that the user isn't internal, which then causes the redirect controller to return the panel url instead of trying to redirect to the tenant registration page.
public function getDefaultTenant(Panel $panel): ?Model
{
if (auth()->user()->isInternal()) {
return $this->latestTeam;
}

return new Team();
}
public function getDefaultTenant(Panel $panel): ?Model
{
if (auth()->user()->isInternal()) {
return $this->latestTeam;
}

return new Team();
}