Redirect to Dashboard

I have 3 panels - student, faculty & admin. I have configured them correctly so that student users can access only student panel, faculty users can only faculty panel and admin users can access only admin panel. Currently if the student users try to access the faculty panel or admin panel, they get 403 (Forbidden Page). But I want them to be redirected to their own dashboard with a warning. How can I achieve this? Thanks in advance.
9 Replies
Vp
Vp2w ago
Check this, you may have more idea https://www.youtube.com/watch?v=fOVjuicHo30 You may also prevent like this https://filamentphp.com/docs/4.x/users/overview#authorizing-access-to-the-panel on canAccessPanel() using panel->getId() in order to remove 403
toeknee
toeknee2w ago
I just did this with a middleware tbh as I want to redirect people if they have accessed the panel without a referrer etc too.
$currentPanel = \Filament\Facades\Filament::getCurrentPanel();
$accessiblePanels = $user->panels();
if ($currentPanel->getId() === 'faculty' && !array_key_exists('faculty', $accessiblePanels)) {
return redirect()->to(config('app.url').'/student');
}
$currentPanel = \Filament\Facades\Filament::getCurrentPanel();
$accessiblePanels = $user->panels();
if ($currentPanel->getId() === 'faculty' && !array_key_exists('faculty', $accessiblePanels)) {
return redirect()->to(config('app.url').'/student');
}
Anish
AnishOP2w ago
Thanks for the message. I have already set them correctly, defining the custom login as well as custom logout responses. After login, users are directed to their respective dashboard. But often users (we are talking about students) will just type in the url : localhost:8000/faculty or localhost:8000/admin, and they get 403 (Forbidden) Page. What I want is that when they try it they should be redirected to their dashboard. I am also trying the middleware approach. Can you share some more details?
toeknee
toeknee2w ago
Just add it as a middleware? So:
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class TenantCheck
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{

$user = Auth::user();
$currentPanel = \Filament\Facades\Filament::getCurrentPanel();
$accessiblePanels = $user->panels();
if ($currentPanel->getId() === 'faculty' && !array_key_exists('faculty', $accessiblePanels)) {
return redirect()->to(config('app.url').'/student');
}

return $next($request);
}
}
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class TenantCheck
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{

$user = Auth::user();
$currentPanel = \Filament\Facades\Filament::getCurrentPanel();
$accessiblePanels = $user->panels();
if ($currentPanel->getId() === 'faculty' && !array_key_exists('faculty', $accessiblePanels)) {
return redirect()->to(config('app.url').'/student');
}

return $next($request);
}
}
Then just include this in your filament panel providers under tenantMiddleware() if using multi-tnenat, otherwise AuthMiddleware for routes that need authentication.
Anish
AnishOP2w ago
Thanks. I have the following middleware :
<?php

namespace App\Http\Middleware;

use Closure;
use Filament\Notifications\Notification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;

use Filament\Facades\Filament;

class HandleFilamentAuthorization
{
public function handle(Request $request, Closure $next): Response
{

Log::info('HandleFilamentAuthorization middleware invoked. Checking user panel authorization.');


if (Filament::getCurrentPanel()->getId() !== $request->user()->getPanelId()) {

Log::info('User panel mismatch detected in HandleFilamentAuthorization middleware.');
Log::info('Rediecting user to their home panel.');

// Use Filament v4 notification
Notification::make()
->title('Access Denied')
->body('You are not authorized to access that resource.')
->warning()
->duration(5000)
->send();


return redirect()->intended($request->user()->getDashboardUrl());


}


return $next($request);

}
}
<?php

namespace App\Http\Middleware;

use Closure;
use Filament\Notifications\Notification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;

use Filament\Facades\Filament;

class HandleFilamentAuthorization
{
public function handle(Request $request, Closure $next): Response
{

Log::info('HandleFilamentAuthorization middleware invoked. Checking user panel authorization.');


if (Filament::getCurrentPanel()->getId() !== $request->user()->getPanelId()) {

Log::info('User panel mismatch detected in HandleFilamentAuthorization middleware.');
Log::info('Rediecting user to their home panel.');

// Use Filament v4 notification
Notification::make()
->title('Access Denied')
->body('You are not authorized to access that resource.')
->warning()
->duration(5000)
->send();


return redirect()->intended($request->user()->getDashboardUrl());


}


return $next($request);

}
}
and in all my panels
->authMiddleware([

HandleFilamentAuthorization::class,
Authenticate::class,
])
->authMiddleware([

HandleFilamentAuthorization::class,
Authenticate::class,
])
But as student user, if I try to access faculty dashboard, I get 403 (Forbidden). But I want a redirection to student dashboard. In fact the middleware is not even being hit!!! I don't see anything in the log file.
toeknee
toeknee2w ago
use debugbar to see if it is loaded
Anish
AnishOP2w ago
I loaded the debugbar. This is what I see Middleware: panel:faculty, Illuminate\Cookie\Middleware\EncryptCookies, Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse, Illuminate\Session\Middleware\StartSession, Filament\Http\Middleware\AuthenticateSession, Illuminate\View\Middleware\ShareErrorsFromSession, Illuminate\Foundation\Http\Middleware\VerifyCsrfToken, Illuminate\Routing\Middleware\SubstituteBindings, Filament\Http\Middleware\DisableBladeIconComponents, Filament\Http\Middleware\DispatchServingFilamentEvent, App\Http\Middleware\HandleFilamentAuthorization, Filament\Http\Middleware\Authenticate. but I also see an Exception. I need to look at the stack trace, before I can make more sense. Already late for today. Thanks for the help.
Vp
Vp7d ago
Just run into this problem as well and this middleware is very useful. thanks
Anish
AnishOP6d ago
OK, figured it out. Since we want to try for all routes, this middleware must be placed in the middleware array, not in authMiddleware array. Further, it must be before AuthenticateSession middleware. I created a blank middleware with just logging to check whether it is being hit or not. I saw that if I place it after AuthenticateSession middleware, it is not being hit. So, this should be the code
->middleware([
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,

// Custom middleware to check user panel authorization
HandleFilamentAuthorization::class,

AuthenticateSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
DisableBladeIconComponents::class,
DispatchServingFilamentEvent::class,
])
->middleware([
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,

// Custom middleware to check user panel authorization
HandleFilamentAuthorization::class,

AuthenticateSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
DisableBladeIconComponents::class,
DispatchServingFilamentEvent::class,
])
Also, we need to now change the code a little bit in the middleware:
php

if ( $request->user() && (Filament::getCurrentPanel()->getId() !== $request->user()->getPanelId())) {
php

if ( $request->user() && (Filament::getCurrentPanel()->getId() !== $request->user()->getPanelId())) {
This will run for non logged routes, so we need to check all the whether the user is logged or not.

Did you find this page helpful?