How to create middleware correctly? - laravel

Good day. I need to create a check, the id of the authorized user matches the entry from the user_id database. Help me please
Middleware CanEdit.php
<?php
namespace App\Http\Middleware;
use App\Models\Pass;
use Closure;
use Auth;
use Illuminate\Http\Request;
class CanEdit
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = Auth::user()->id;
$editor = Pass::where('user_id', $user);
if ($user == $editor) {
return $next($request);
}
return redirect('home')->with('error','You have not access');
}
}

You're never getting in the if condition because you're comparing two different classes here. If you need to check if only id's match, you could do it like this:
$user = Auth::user()->id;
$editor = Pass::where('user_id', $user)->first();
if ($user == $editor->user_id) {
return $next($request);
}
But in my opinion, this check is not necessary. Assuming that user_id field is unique in Pass table, you don't need to check if id's match, you only need to check if record exists in Pass table:
$user = Auth::user()->id;
$editor = Pass::where('user_id', $user)->exists();
if ($editor) {
return $next($request);
}
exists() method simply returns boolean depending on if the record exists in the database or not.

if (Auth::guard($guard)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
}
return $next($request);

Related

Restrict page if Auth::user()->id != user_id using middleware

i use middleware to restrict the admin page from non-admins, and i can restrict pages with a list of "patients" from other users by using a policy, but if i use a policy. I have to repeat the code can() method in every function. If i use middleware to check if the user_id in the url == Auth::user()->id. I do not need to repeat this, but how do i get the user_id from the url in my middleware?
the route
Route::get('/patients/{patient}', 'PatientController#edit')
What i have now
PatientPolicy
public function view(User $user, Patient $patient)
{
// does this patient belong to user
return $user->id == $patient->user_id;
}
PatientController
public function edit(Patient $patient)
{
// authenticate logged in user
$user = auth()->user();
// can the loged in user do this?(policy)
if($user->can('update', $patient)){
return view('patient.edit-patient', compact('patient', 'user'));
}
return view('403');
}
what i should have in a middleware
UserMiddleware
/**
* #param $request
* #param Closure $next
* #return mixed
*/
public static function handle($request, Closure $next)
{
if (Auth::check() && Auth::user()->id == User::patients()->user_id) {
return $next($request);
} else {
return redirect()->route('login');
}
}
Does somebody know how to check if the {patient} in the routes user_id == the logged in user()->id?
Since you have Illuminate\Http\Request object injected into handle function in middleware this is pretty straight forward to get patient id from url:
/**
* #param $request
* #param Closure $next
* #return mixed
*/
public static function handle($request, Closure $next)
{
$patientId = $request->patient; // patient id from url!
$patient = Patient::find($patientId);
if (!$patient) {
return redirect()->back()->with(['message' => 'Patient not found!']);
}
if (Auth::check() && (int) Auth::user()->id === (int) $patient->id) {
return $next($request);
} else {
return redirect()->route('login');
}
}
Thank you #Leorent,
Your answer helped me alot and this is how it got fixed
Route
Route::get('/patients/{patient}', 'PatientController#show')->middleware('user');
UserMiddeware
public static function handle($request, Closure $next)
{
$patientId = $request->patient->user_id; // user_id from patient in url!
if (Auth::check() && (int) Auth::user()->id == $patientId) {
return $next($request);
} else {
return redirect()->route('403');
}
}
Thanks again!

My Middleware redirects to home page everytime

I have made a quiz when the user unlocks the quiz then only the user can access the quiz page suppose 127.0.0.1:8000/quiz1. But I have unlocked the quiz, then too my middleware takes me to /home page.
I have tried this logic but it didn't worked.
<?php
namespace App\Http\Middleware;
use Closure;
use App\Theme_User;
use App\User;
use Auth;
class UnlockMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = auth()->user()->id;
$theme_user = Theme_User::find($user);
if($theme_user->unlocked == 1){
return $next($request);
}
else {
return redirect('/login');
}
}
}
In my Theme_User there is user_id and unlocked stored but that is not working for me.
You need to check if they are logged in first, like so with \Auth::check()...
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(\Auth::check()) {
$user = \Auth::user()->id;
$theme_user = Theme_User::find($user);
if($theme_user->unlocked == 1){
return $next($request);
}
// Logged in but not unlocked
}
else {
return redirect('/login');
}
}
I have no idea what the logic is meant to be behind logged in but not unlocked, you'll need to fill that gap
It might be worth checking if user is logged in before trying to get user id from auth.
public function handle($request, Closure $next)
{
if(auth()->check()) {
$user = auth()->user()->id;
$theme_user = Theme_User::find($user);
if($theme_user->unlocked == 1){
return $next($request);
}else{
return redirect('whatever_page_if_user_is_logged_in_but_not_unlocked');
}
}else {
//this only happens if user is not logged in
return redirect('/login');
}
}

In a middleware, how can I get current logged in user?

I am creating a middleware that checks if user is currently logged in and is super admin.
This is my middleware code.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class CheckAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
// also need to check a field of user
return redirect()->guest('login');
} else {
return $next($request);
}
}
}
Actually, it's the same as the default middleware Authenticate (i.e. 'auth')
It's working well when I use it in app's routing. (app/Http/routes.php)
I need to use it with cuddy plugin middleware option. It should redirects only guest users, but it's not. Please help!
Authenticate middleware by default checks if user is guest and redirects him to login page see below
if (Auth::guard($guard)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401); //if ajax request
} else {
return redirect()->guest('login'); //redirect
}
}
Now if u want to check if user is logged and check some user fields here how it should be
public function handle($request, Closure $next, $guard = null)
{
if(Auth::check()) { //If is logged in
$user = Auth::user();
if($user->isSuperAdmin())
return $next($request);
}
return redirect('/whatever');
}
If you attach 'auth' middleware + this custom middleware. You can get rid of "Auth::check()" in the custom middleware.
Route::group(['middleware' => ['web', 'auth', 'custom']], function () {
Route::get('/url/only/for/super/users', 'Whatever#whateverController');
});
public function handle($request, Closure $next, $guard = null)
{
$user = Auth::user();
if($user->isSuperAdmin())
return $next($request);
return redirect('/whatever');
}
There is many helper functions in laravel that you can use anywhere like auth() helper, see helpers. So you can use this code anywhere:
auth()->user();

laravel 5 redirect user after login based on user's role

My 'users' table has a 'role' column and when users are registered or logged in, I want them to be redirected based on their role column. how can I do that?
I added this function to AuthController.php and everything fixed magically
public function authenticated($request , $user){
if($user->role=='super_admin'){
return redirect()->route('admin.dashboard') ;
}elseif($user->role=='brand_manager'){
return redirect()->route('brands.dashboard') ;
}
}
If you are using the Authentication system provided with Laravel you can override the redirectPath method in your Auth\AuthController.
For example, this would redirect a user with role 'admin' to /admin and any other user to /account:
public function redirectPath()
{
if (\Auth::user()->role == 'admin') {
return "/admin";
// or return route('routename');
}
return "/account";
// or return route('routename');
}
You could also use Laravel Authorization (introduced in 5.1.11) to manage role logic.
In laravel 5.7 there is no AuthController.php so you have to go Controllers\Auth\LoginController.php and add the below function,
If the redirect path needs custom generation logic you may define a redirectTo method instead of a redirectTo property
protected function redirectTo()
{
if($user->role=='super_admin'){
return '/path1';
}elseif($user->role=='brand_manager'){
return '/path2';
}
}
You can do this handle the request in the Middleware RedirectIfAuthenticated.php inside the handle function like this:
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
if (Auth::user()->role == 'admin') {
return redirect('/admin');
}else{
return redirect('/');
}
}
return $next($request);
}
I write this in case someone consider useful. If you want to redirect always and not only on Login, I did it on web.php like this:
Route::get('/home', function () {
switch(\Illuminate\Support\Facades\Auth::user()->role){
case 'admin':
return redirect(route('home.admin'));
break;
case 'employee':
return redirect(route('home.employee'));
break;
default:
return '/login';
break;
}
});
Route::get('/home/admin', 'HomeController#indexAdmin')->name('home.admin');
Route::get('/home/employee', 'HomeController#indexEmployee')->name('home.employee');
So every time they click on /home is redirect to the url you want, you could do it too with '/'.
for laravel 9 i implement the following code
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Auth;
use Spatie\Permission\Traits\HasRoles;
class LoginController extends Controller
{
use AuthenticatesUsers, HasRoles;
public function redirectTo(){
if(Auth::user()->hasAnyRole('Adm1','Adm2')){
return $this->redirectTo = route('viewAdm') ;
}elseif(Auth::user()->hasAnyRole('Usuario')){
return $this->redirectTo = route('home') ;
}
}
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}

Controller middleware

I have controller named 'AdminController'
And I have a lot of functions in there. The problem is that I dont want in every function user IF statement just like this:
public function index(Request $request)
{
if(Auth::check() && $request->user()->is_admin())
{
return view('admin.index');
}
else
{
flash()->error('You dont have permissions!');
return redirect('home');
}
}
How can I make it more simple with middleware so I could make everything work without using IF statement in every function ?
Create a middleware
php artisan make:middleware IsAdmin
Customize app/Http/Middleware/IsAdmin.php
<?php
namespace App\Http\Middleware;
use Auth;
use Closure;
class IsAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::check() && $request->user()->is_admin())
{
return $next($request);
}
flash()->error('You dont have permissions!');
return redirect('home');
}
}
Finally register and use the middleware

Resources