Do not redirect if guest? - laravel

Is there a way to use guest middleware yet, if the request->expectsJson() it does not redirect, just errors? (Like the auth middleware).
Or would I need to write custom middleware?

You can make your own middleware inspired by RedirectIfAuthenticated:
app/Http/Middleware/AbortIfAuthenticated.php
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AbortIfAuthenticated
{
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
abort(403, "Not allowed");
}
}
return $next($request);
}
}
Then replace the middleware by your own in app/Http/Kernel.php
(Or add a new one)
protected $routeMiddleware = [
...
'guest' => \App\Http\Middleware\AbortIfAuthenticated::class,
...
];

Related

Issues with Middleware | Too few arguments to function App\Http\Middleware\HasPermission::handle()

This is the error I'm receiving when I try to load my index page
Too few arguments to function App\Http\Middleware\HasPermission::handle(), 2 passed in /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php on line 180 and exactly 3 expected
I'm using Spatie's Roles and Permissions Package, and have created a custom middleware HasPermission, to check if the user has the permissions to access and utilise the page they are trying to view.
This is the middleware
namespace App\Http\Middleware;
use Closure;
use Spatie\Permission\Models\Permission;
class HasPermission
{
public function handle($request, Closure $next,$permissions)
{
$permissions_array = explode('|', $permissions);
foreach($permissions_array as $permission){
if (!$request->user()->hasPermission($permission)){
return redirect()->back();
}
}
return $next($request);
}
}
The controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\User;
use Spatie\Permission\Models\Role;
use DB;
use Hash;
use Illuminate\Support\Arr;
use App\Http\Middleware\HasPermission;
class UserController extends Controller
{
public function __construct() {
$this->middleware('permission:usermgmt.users|usermgmt.users.create|usermgmt.users.edit|users.delete', ['only' => ['index','store']]);
$this->middleware('permission:usermgmt.users.create', ['only' => ['create','store']]);
$this->middleware('permission:usermgmt.users.edit', ['only' => ['edit','update']]);
$this->middleware('permission:users.delete', ['only' => ['destroy']]);
}
And my routes
Route::middleware('HasPermission')->group(function() {
Route::get('/usermgmt/users', [App\Http\Controllers\UserController::class, 'index'])->name('usermgmt.users');
Route::resource('users', UserController::class);
Route::get('add-user', [App\Http\Controllers\UserController::class, 'create'])->name('usermgmt.users.create');
Route::delete('users/{user}',[App\Http\Controllers\UserController::class, 'destroy'])->name('users.destroy');
Route::get('users/{user}/edit', [App\Http\Controllers\UserController::class, 'edit'])->name('usermgmt.users.edit');
});
I have added the HasPermission middleware class to the Kernel.php, but am struggling to understand why I am receiving that error.
Any help would be appreciated, cheers.
I tried initially removing the Route Middleware Group and instead trying to do everything in the controller, and tried something like the below
$this->middleware(HasPermission::class, ['usermgmt.users','usermgmt.users.create','usermgmt.users.edit','users.delete'], ['only' => ['index','store']]);
But this would give me the same error as before.
Did you try this way:
public function handle(Request $request, Closure $next, ...$permissions)
{
foreach($permissions as $permission){
if (!$request->user()->hasPermission($permission)){
return redirect()->back();
}
}
return $next($request);
}
The in your controller, change the syntax:
$this->middleware('permission:usermgmt.users,usermgmt.users.create,usermgmt.users.edit,users.delete', ['only' => ['index','store']]);

How can I use multiple middlewares on the same route name in Laravel 9?

I want my /dashboard page to be a different panel in 2 different user types. And return to home screen if not logged in. I created 2 middlewares to check if logged in user is "employer" or "employee". Whatever I do, I can't seem to make it work, it's been 2 days. I created middlewares and routes by following some very sketchy tutorials, it may hurt your eyes, be aware.
My route:
Route::get('/dashboard', function () {
return view('welcome');
})->name('welcome');
Route::prefix('admin')->middleware([\App\Http\Middleware\isEmployer::class])->group( function () {
Route::get("/dashboard", function (){
return view("employer.dashboard");
})->name("dashboard");
});
Route::prefix('store')->middleware([\App\Http\Middleware\isEmployee::class])->group( function(){
Route::get("/dashboard", function (){
return view("employee.dashboard");
})->name("dashboard");
});
isEmployee middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class isEmployee
{
public function handle(Request $request, Closure $next)
{
if(Auth::user())
{
if (Auth::user()->role == "employee")
{
return $next($request);
}
}
return response()->view('welcome');
}
}
isEmployer middleware :
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class isEmployer
{
public function handle(Request $request, Closure $next)
{
if(Auth::user())
{
if (Auth::user()->role == "employer")
{
return $next($request);
}
}
return response()->view('welcome');
}
}
What I want to achieve is:
if not logged in : return welcome view
if logged in as employer : return employer.dashboard view
if logged in as employee : return employee.dashboard view
Let's start from some refactoring:
Make your routes/web.php a bit more readable:
Route::view('/dashboard', 'welcome')->name('welcome');
Route::prefix('admin')->name('admin.')->middleware('role:employer')->group(function() {
Route::view('/dashboard', 'employer.dashboard')->name("dashboard");
});
Route::prefix('store')->name('store.')->middleware('role:employee')->group(function() {
Route::view('/dashboard', 'employee.dashboard')->name("dashboard");
});
Now let's create a middleware that will check not only for one role, but for any role you give as a parameter:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class HasRole
{
public function handle(Request $request, Closure $next, string $role)
{
if (Auth::user()?->role != $role) {
return redirect()->route('welcome');
}
return $next($request);
}
}
Now, create an alias in your app/Http/Kernel.php so you could use it like i wrote it in routes file role:<role_here>:
protected $routeMiddleware = [
// ...
'role' => \App\Http\Middleware\HasRole::class,
];
Now for your question - how to use multiple middlewares for one route. It is simple:
$route->middleware(['middleware1', 'middleware2']);
You may attach them to groups or single routes:
Route::prefix('some_group')->middleware(['middleware1', 'middleware2'])->group(function() {
Route::view("some.view")->middleware('middleware3')->name("some.view");
});
You can read more info about Laravel's middlewares here, and understand what responsibility chain is (pattern which middleware implements) under the hood. Also take a look at SOLID principles, mainly at DRY one. Have a good day =)

Laravel,Can I use auth('api')->user() in Middleware?

I Would like to use auth('api')->user() in Middleware ,But felt that it wouldn't work.
And I don't use Auth::check() Because it Return null
P.S. auth('api')->user() Can use in my Controller.
-This code check online/offline user-
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Carbon\Carbon;
class LastUserActivity
{
public function handle($request, Closure $next)
{
$user = auth('api')->user();
if (isset($user)) {
$expiresAt = Carbon::now()->addMinutes(1);
Cache::put('user-is-online-' . $user->ID, true, $expiresAt);
}
return $next($request);
}
}

Auth::User() gives null in laravel 5.2

I am new to laravel. I am using multi authentication in my application. User and Admin are 2 type of user in my application. Iam developing change password for admin after logged in to application through admin's profile page. now I want to get logged in admin user detail so that i have use below code in my controller
if (Auth::guard('admin')->check()) {
$user = Auth::id();
echo '<pre>';
dd($user);
exit;
}
I have also add following code in controller
use App\Http\Controllers\Adminauth;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Admin;
use Session;
use DB;
use App\Http\Controllers\Controller;
use Auth;
In route.php i have write following code
Route::group(['middleware' => ['admin']], function () {
//Login Routes...
Route::auth();
Route::get('admin/profile/change_password', 'Admin\AdminController#change_password');
});
But i am not able to get admin user detail. can anyone help me to solve this problem.
Try this
public function __construct() {
$this->middleware('auth:admin');
$this->middleware(function ($request, $next) {
$user = $this->user = Auth::user();
dd($user);
});
}
In routes
Route::get('/', function () {
//return view('welcome');
return view('auth.login');
});
Auth::user() is working only under auth middleware. You may call auth middleware on controller or call it on routes, but not on both.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class YourController extends Controller
{
public function __construct()
{
$this->middleware('auth')
}
public function yourFunction(Request $request)
{
$user = \Auth::user();
dd($user);
}
}
<?php
Route::get('your-uri', function () {
$user = \Auth::user();
dd($user);
})->middleware('auth');

Laravel: how to check middleware in blade template

i've created Middleware
php artisan make:middleware isTeacher
in App/Http/isTeacher.php i've placed the check:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class isTeacher
{
public function handle($request, Closure $next)
{
$user = Auth::user();
if($user && $user->capability == 3)
{
return $next($request);
}
else
return redirect('/login');
}
}
than, i've defined the middleware in app/Http/Kernel.php
protected $routeMiddleware = [
...
'auth.teacher' => \App\Http\Middleware\isTeacher::class,
...
];
The question is: how I check the teacher capability in blade template?
I'm trying with this:
#if (Auth::isTeacher())
but doesn't work
any help are appreciated
The blade directive only needs to return true or false, nothing else.
You could just do the following in the boot() method of the AppServiceProvider.php
Blade::if('teacher', function () {
return auth()->user() && $user->capability == 3;
});
Then you will be able to do the following in blade templates:
#teacher
Only teachers will see this
#endteacher
Well there is an issue here Middlewares are used to filter HTTP requests or its outter layer of the onion in laravel app. It is not defined to be used in blade to decide which part of html should be rendered.
You can filter a controller function to only be usable if it passes the middleware (if authenticated for example) and the controller only runs the function if it passes on the middleware.
When using Auth in blades you are not using a middleware but a facade whan you could do its use Session for your case like:
In your middleware
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class isTeacher
{
public function handle($request, Closure $next)
{
$user = Auth::user();
if($user && $user->capability == 3)
{
\session('isTeacher', true);
return $next($request);
}
return redirect('/login');
}
Then in your blades do like:
#if (Session::get('isTeacher', 0));
This will show content only to teachers, if session its not set it will fall back to 0 or false.
In this scenario, using middleware is not really the solution. I will rather suggest blade directive, which allows you to create a custom blade function like:
#author
//Do something
#else
//Something else
#endauthor
To use the above syntax, you can register a new blade directive in your AppServiceProvider.php file
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Blade::directive('author', function () {
$isAuth = false;
// check if the user authenticated is teacher
if (auth()->user() && auth()->user()->capability == 3) {
$isAuth = true;
}
return "<?php if ($isAuth) { ?>";
});
Blade::directive('endauthor', function () {
return "<?php } ?>";
});
}
}
After the above changes in the AppServiceProvider.php file, run php artisan view:clear
For a better understanding, you can refer to the documentation here
This is an improved version of Prince Lionel's answer. Pay attention to the return value of Blade::directive callback function.
#author
//Do something
#else
//Something else
#endauthor
AppServiceProvider.php
namespace App\Providers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Blade::directive('author', function () {
$isAuth = false;
// check if the user authenticated is teacher
if (auth()->user() && auth()->user()->capability == 3) {
$isAuth = true;
}
return "<?php if (" . intval($isAuth) . ") { ?>";
});
Blade::directive('endauthor', function () {
return "<?php } ?>";
});
}
}

Resources