Same route defined with different middleware called last wirted route issue - php

Define the four routes with different middleware role wise.
Issue arrive is call DepartmentStaff Route every time.if i login Admin or Customer.
Call last written route every time.
//admin Route
Route::get('edit_profile', [UserController::class, 'edit_profile'])->name('edit_profile')->middleware(CheckAdminRole::class);
Route::post('profile_update', [UserController::class, 'profile_update'])->name('profile_update')->middleware(CheckAdminRole::class);
Route::get('change_password', [UserController::class, 'change_password'])->name('change_password')->middleware(CheckAdminRole::class);
Route::post('password_update', [UserController::class, 'password_update'])->name('password_update')->middleware(CheckAdminRole::class);
// Customer Route
Route::get('edit_profile', [UserController::class, 'edit_profile'])->name('edit_profile')->middleware(CheckCustomerRole::class);
Route::post('profile_update', [UserController::class, 'profile_update'])->name('profile_update')->middleware(CheckCustomerRole::class);
Route::get('change_password', [UserController::class, 'change_password'])->name('change_password')->middleware(CheckCustomerRole::class);
Route::post('password_update', [UserController::class, 'password_update'])->name('password_update')->middleware(CheckCustomerRole::class);
//DepartmentStaff Route
Route::get('edit_profile', [UserController::class, 'edit_profile'])->name('edit_profile')->middleware(CheckDepartmentStaffRole::class);
Route::post('profile_update', [UserController::class, 'profile_update'])->name('profile_update')->middleware(CheckDepartmentStaffRole::class);
Route::get('change_password', [UserController::class, 'change_password'])->name('change_password')->middleware(CheckDepartmentStaffRole::class);
Route::post('password_update', [UserController::class, 'password_update'])->name('password_update')->middleware(CheckDepartmentStaffRole::class);
//admin middleware
public function handle(Request $request, Closure $next)
{
if (auth()->user()->role == 1) {
return $next($request);
}
return redirect('error/404');
}
//customer middleware
public function handle(Request $request, Closure $next)
{
if (auth()->user()->role == 4) {
return $next($request);
}
return redirect('error/404');
}
//Department middleware
public function handle(Request $request, Closure $next)
{
if (auth()->user()->role == 2) {
return $next($request);
}
return redirect('error/404');
}

You can use only one middleware to check routes like:
//middleware
public function handle(Request $request, Closure $next)
{
if (in_array(auth()->user()->role, [1, 2, 3])) {
return $next($request);
}
return redirect('error/404');
}
And routes:
Route::get('edit_profile', [UserController::class, 'edit_profile'])->name('edit_profile')->middleware(CheckRole::class);
Route::post('profile_update', [UserController::class, 'profile_update'])->name('profile_update')->middleware(CheckRole::class);
Route::get('change_password', [UserController::class, 'change_password'])->name('change_password')->middleware(CheckRole::class);
Route::post('password_update', [UserController::class, 'password_update'])->name('password_update')->middleware(CheckRole::class);

Related

Laravel Custom Middleware: ERR_TOO_MANY_REDIRECTS

I'm using Laravel Breeze + Inertia (React) and want to implement custom auth.
I'm having infinite redirection (ERR_TOO_MANY_REDIRECTS) when visiting /dashboard on this middleware.
Route::get('register', [RegisteredUserController::class, 'create'])
->name('register');
Route::post('register', [RegisteredUserController::class, 'store']);
Route::get('login', [AuthenticatedSessionController::class, 'create'])
->name('login');
Route::post('login', [AuthenticatedSessionController::class, 'store']);
Route::middleware(['custom_auth'])->group(function () {
Route::get('/dashboard', function () {
return Inertia::render('Dashboard');
})->name('dashboard');
});
class CustomAuthMiddleware
{
public function handle(Request $request, Closure $next)
{
if (session()->has('user_data')) {
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
}
This works:
namespace App\Http\Middleware;
class RedirectIfAuthenticated
{
public function handle(Request $request, Closure $next, ...$guards)
{
if (session()->has('user_data')) {
return redirect()->route('users.index');
}
return $next($request);
}
}
namespace App\Http\Middleware;
class CustomAuthMiddleware
{
public function handle(Request $request, Closure $next)
{
if (session()->has('user_data')) {
return $next($request);
}
return redirect('login');
}
}
Route::middleware('guest')->group(function () {
Route::get('register', [AuthController::class, 'register'])
->name('register');
Route::post('register', [AuthController::class, 'registerPost']);
Route::get('login', [AuthController::class, 'login'])
->name('login');
Route::post('login', [AuthController::class, 'loginPost']);
});
Route::middleware('custom_auth')->group(function () {
Route::get('/', function () { return redirect()->route('users.index'); });
Route::resource('users', UserController::class);
});

Laravel Routing "Route [dashboard] not defined?

I'm trying to config an user/admin environment in my laravel page, and whenever I try group the routes, I'll get one of the mentioned error back. What am I doing wrong? I tried both formats, same error.
web.php
//supposed user dashboard
Route::group(['middleware' => ['auth', 'user']], function () {
Route::get('/dashboard', 'DashboardController#index')->name('dashboard');
});
//supposed admin dashboard
Route::group(['middleware' => ['auth', 'admin']], function () {
Route::get('/dashboard', [AdminDashController::class, 'index']);
});
eg AdminDashController:
public function index()
{
return view("admin_dashboard");
}
DashboardController does the same, but returning user view.
I'm new to laravel, I appriciate any help!
Update:
I tried the solution below, my result is that I'm now getting "Route [user.dashboard] not defined." error...
My web.php
Route::group(['middleware' => ['auth', 'user']], function () {
Route::get('/dashboard', [UserDashController::class, 'index'])->name('user.dashboard');
});
// admin dashboard
Route::group(['middleware' => ['auth', 'admin']], function () {
Route::get('/dashboard', [AdminDashController::class, 'index'])->name('admin.dashboard');
});
my AdminDashController and UserDashController:
public function index()
{
return view('user_dashboard');
}
AND
public function index()
{
return view('admin_dashboard');
}
I have a RedirectIfAuthenticated.php
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
/** #var User $user */
$user = Auth::guard($guard);
// to admin dashboard
if ($user->hasRole('admin')) {
return redirect()->route('admin.dashboard');
}
// to user dashboard
else if ($user->hasRole('user')) {
return redirect(route('user.dashboard'));
}
}
}
return $next($request);
}
Also having an Admin and User redirect:
AdminAuthenticated.php:
public function handle(Request $request, Closure $next)
{
if( Auth::check() )
{
/** #var User $user */
$user = Auth::user();
// if user is not admin take him to his dashboard
if ( $user->hasRole('user') ) {
return redirect()->route('user.dashboard');
}
// allow admin to proceed with request
else if ( $user->hasRole('admin') ) {
return $next($request);
}
}
abort(403); // permission denied error
}
UserAuthenticated
public function handle(Request $request, Closure $next)
{
if( Auth::check() )
{
/** #var User $user */
$user = Auth::user();
// if user is admin take him to his dashboard
if ( $user->hasRole('admin') ) {
return redirect(route('admin.dashboard'));
}
// allow user to proceed with request
else if ( $user->hasRole('user') ) {
return $next($request);
}
}
abort(403); // permission denied error
}
Update 2:
I replaced the routing in web.php as follows:
Route::middleware(['auth','user'])->group(function () {
Route::prefix('user')->group(function () {
Route::get('/dashboard', [UserDashController::class, 'index'])->name('user.dashboard');
});
});
Route::middleware(['auth','admin'])->group(function () {
Route::prefix('admin')->group(function () {
Route::get('/dashboard', [AdminDashController::class, 'index'])->name('admin.dashboard');
});
});
Still same error: "Route [user.dashboard] not defined."
The problem may be in your route name. One route has a named dashboard another was not. Use the below code hope this will resolve your problem
// user dashboard
Route::group(['middleware' => ['auth', 'user']], function () {
Route::get('/dashboard', 'DashboardController#index')->name('user.dashboard');
});
// admin dashboard
Route::group(['middleware' => ['auth', 'admin']], function () {
Route::get('/dashboard', 'DashboardController#index')->name('admin.dashboard);
})
use the route name in stead of url.
in my case, instead using your code below :
Route::group(['middleware' => ['auth', 'user']], function () {
Route::get('/dashboard', [UserDashController::class, 'index'])->name('user.dashboard');
});
// admin dashboard
Route::group(['middleware' => ['auth', 'admin']], function () {
Route::get('/dashboard', [AdminDashController::class, 'index'])->name('user.dashboard');
});
i use my own code, so define the middleware first and use prefix on it :
Route::middleware(['auth','user'])->group(function () {
Route::prefix('user')->group(function () {
Route::get('/dashboard', [UserDashController::class, 'index'])->name('user.dashboard');
});
});
Route::middleware(['auth','admin'])->group(function () {
Route::prefix('admin')->group(function () {
Route::get('/dashboard', [AdminDashController::class, 'index'])->name('admin.dashboard');
});
});
maybe you should differentiate routing between dashboard for admin and user. you can use like this : /admin/dashboard and /user/dashboard
edit :
i think there's some typo on your code :
// to admin dashboard
if ($user->hasRole('admin')) {
return redirect(route('admin.dashboard'));
}
return redirect route should typed like this : return redirect()->route('admin.dashboard)

Laravel 8 same route multiple middleware using OR condition

Hello i tried to use middleware like the code below to validate OR operator
Route::get('/page', [Controller::class, 'index'])->middleware(['mid1','mid2']);
in this example it uses the AND operator not OR I used also groups like this
Route::group(['middleware' => 'mid1'], function () {
Route::get('/page', [Controller::class, 'index']);
});
Route::group(['middleware' => 'mid2'], function () {
Route::get('/page', [Controller::class, 'index']);
});
but using groups with same route the second route in the group is the only one readable.
Any help please
There's nothing builtin in laravel to do such a thing.
You can create another middle-ware to contain both conditions you need to apply.
In you middleware:
public function handle($request, Closure $next) {
if (condition1 || condition2) {
return $request($next);
}
abort('statusCode');
}
I agree with #Faesal. It would be best to combine two middleware logic into one middleware.
public function handle($request, Closure $next) {
if (your condition) {
//logic inside mid1 handler
}else{
//logic inside mid2 handler
}
}
Although it is not recommended but you can put your conditions in route file.
if(your conditions){
Route::group(['middleware' => 'mid1'], function () {
Route::get('/page', [Controller::class, 'index']);
});
}else{
Route::group(['middleware' => 'mid2'], function () {
Route::get('/page', [Controller::class, 'index']);
});
}

prefix and middleware not working for some reason. for some routes

so im trying to put my localization as prefix on my website domain so i made a middleware the puts the localization lang on the url ever time you try to open a page heres my middleware
public function handle($request, Closure $next)
{
if ($request->method() === 'GET') {
$segment = $request->segment(1);
if (!in_array($segment, config('app.locales'))) {
$segments = $request->segments();
$fallback = session('locale') ?: config('app.fallback_locale');
$segments = array_prepend($segments, $fallback);
return redirect()->to(implode('/', $segments));
}
session(['locale' => $segment]);
app()->setLocale($segment);
}
return $next($request);
}
and i added the middleware to the routemiddleware
protected $routeMiddleware = [
'Locate' => \App\Http\Middleware\Locale::class,
];
and i did put a prefix and middleware to all my routes like this
Route::prefix('{lang?}')->middleware('Locate')->group(function() {
Route::get('logout', '\App\Http\Controllers\Auth\LoginController#logout')->name('logout');
Route::get('/home', 'HomeController#index')->name('home');
Route::get('/admin/login', function () {
return view('admin.auth.login');
})->name('AdminLogin');
Route::get('/contact-us', 'ContactUsController#Contactus')->name('ContactUs');
Route::post('/contact-us', 'ContactUsController#PostContactus')->name('PostContactUs');
Route::prefix('auth')->group(function () {
Route::get('/login', function () {
return view('auth.login');
})->name('Login');
Route::post('/login', 'Auth\LoginController#Login')->name('userslogin');
});
Route::prefix('search')->group(function () {
Route::get('/categories', 'search\SearchController#Categories')->name('Categories');
Route::get('/filter/{categoryseo}', 'search\SearchController#filter')->name('InstructorsSearch');
//sending categoryseo to the filter page so i can put it in hidden input in the filter page and use it to get the list
Route::get('/list', 'search\SearchController#InstructorList')->name('InstructorsSearchList');
Route::get('/profile/{userid?}', 'search\SearchController#instructorprofile')->name('InstructorProfile');
});
});
for some reason pages like /home gets the to the middleware and change as i wanted like this /en/home , as for other like search/categories it wont even notice my middleware but i tried to remove the prefix of the localization and just put my middleware it worked and it notice my middleware. using laravel 5.5

Laravel middleware to skip route group

Let's say I have the following routes file:
Route::group(['middleware' => 'foo.only'], function () {
Route::get('/', 'FooController#index');
Route::get('/about', 'FooController#about');
});
Route::get('/', 'BarController#index');
Route::get('/about', 'BarController#about');
In my FooOnlyMiddleware handler I have something like:
public function handle($request, $next)
{
if ($foo == true) {
return $next($request);
}
else {
// skip the entire route group and move onto the next route
}
}
How do I do this so that if $foo = false it will skip the entire route group and move onto the bar routes?
This won't work, as both of your foo and bar routes are the same:
Route::get('/', 'FooController#index');
Route::get('/', 'BarController#index');
The bar route will never be reached.
Here is one way to accomplish the conditional routes you want:
Your routes:
Route::group(['middleware' => 'foo.only'], function () {
Route::get('/', 'FooController#index');
Route::get('/about', 'FooController#about');
});
Route::get('bar/', 'BarController#index');
Route::get('bar/about', 'BarController#about');
FooOnlyMiddleware:
public function handle($request, $next)
{
if ($foo == true) {
return $next($request);
}
else {
return redirect('/bar/'.$request->route()->uri());
}
}
Of course, this would be valid if every route using the FooOnlyMiddleware, has an equivalent bar route. Otherwise, just redirect to any route you want.

Categories