How to get id in Middleware when i use user() - laravel

I have a relationship between users and roles. In middleware, I need to get roles to check if the role is 1 or 2. However, I get the following error.
"Trying to get property 'role_id' of non-object."
I am sure I have id 1 in role_id.
User Model
public function role()
{
return $this->belongsTo(Role::class, 'role_id');
}
public function handle($request, Closure $next)
{
if (!Auth()->check() && $request->user()->role_id == 1) {
return redirect()->back();
}
return $next($request);
}

Your if statement's logic is mistakenly checking if the user is logged out, while also checking the user's roles. If Auth::check() is false, then the user is not logged in and $request->user() will return null.
Removing the ! from the conditional will fix the error you're receiving.
public function handle($request, Closure $next)
{
if (Auth()->check() && $request->user()->role_id == 1) {
return redirect()->back();
}
return $next($request);
}
However, this will allow all guests to proceed, which you may not want. Assuming you want the middleware to only allow logged-in users with a specific role to proceed, use a more white-listed approach like this:
public function handle($request, Closure $next)
{
// Role ID 2 has permission to proceed
if (Auth()->check() && $request->user()->role_id == 2) {
return $next($request);
}
// Everyone else should go back, including logged-in users and guests.
return redirect()->back();
}

[Can't comment so I'm making a post.]
Aken already answered you but I'd suggest one more thing. Don't use 1 or 2 as ID's but constants:
public function handle($request, Closure $next)
{
if (Auth()->check() && $request->user()->role_id == ADMIN) {
return $next($request);
}
return redirect()->back();
}
You don't even need the comments for this one. Maybe even better:
public function handle($request, Closure $next)
{
if (Auth()->check() && $request->user()->isAdmin()) {
return $next($request);
}
return redirect()->back();
}
but you need to implement it on your own.

Related

Protecting Routes With Two middle-wares So that both users can access it

I am trying to protect a route using two middle-wares so that both expert and user can access the same route but as soon a user tries to access the route he is logged out.
I had created two middle-wares for expert and user and protect the route using these middle-wares.
Web.php
Route::group(['middleware' => ['expert','user']], function () {
Route::post('/showForm','UserController#showFormFilled');
});
User Middle ware
public function handle($request, Closure $next)
{
//////////////////// check if user is logged in ///////////////////
if(Auth::check())
{
////////////////// check user role id //////////////////////////
if(auth()->user()->role_id == 3)
{
return $next($request);
}
else if (auth()->user()->role_id==2)
{
return redirect('/expert');
}
}
else
{
return redirect('/login');
}
}
Expert Middle ware
public function handle($request, Closure $next)
{
if(Auth::check()){
if(auth()->user()->role_id == 2)
return $next($request);
else if (auth()->user()->role_id==3)
return redirect('/dashboard');
}
else {
return redirect('/login');
}
}
Both the users should be able to access the same route.
#hamzahummam - there is no way to achieve what you are looking for using the above separate-middlware-for-each-type method. Each middleware prematurely redirects [either to /dashboard or to /expert etc] the request without allowing it to passthrough other middleware. Best would be to use a third-party package that provides a more comprehensive and fine-grained access control [example: https://github.com/Zizaco/entrust]
If that's not an option, the best case would be to implement a single middleware and pass the role as parameter. See: Laravel Middleware Parameters
A minimal example would look like:
public function handle($request, Closure $next, $role)
{
// Assuming Auth::check() passes
$roleId = auth()->user()->role_id;
if ($roleId == 2 && strpos($role, 'expert') !== false) {
// Logged in user is `expert` and route allows `expert` access
return $next($request);
} else if ($roleId == 3 && strpos($role, 'user') !== false) {
// Logged in user is `user` and route allows `user` access
return $next($request);
} // and so on...
// Handle failures here
if ($roleId == 2 && strpos($role, 'expert') === false) {
// an `expert` is trying to access route that can't be accessed
return redirect('/expert-dashboard');
} // and so on...
}
You'd define routes as:
Route::group(['middleware' => ['new_middleware:expert,user' ]], function () {
Route::post('/showForm','UserController#showFormFilled');
});
Hope this helps.

Call to a member function setCookie() on null

I am trying to finish this middleware in larval that checks to make sure is subscribed to a subscription plan. If the user is not it redirects to the payment page.
public function handle($request, Closure $next)
{
if(Auth::check()){
if (Auth::user()->subscribed('main')) {
return true;
}else{
return view('payments.payment')->with('user',Auth::user());
}
}else{
abort(403, 'Unauthorized action.');
}
return $next($request);
}
I am getting this error with not much luck finding a solution Call to a member function setCookie() on null.
change
return view('payments.payment')
to
return response()->view('payments.payment')
The problem is where you are returning true. A middleware should return a response-style object, not a boolean.
Since that is your "good" path and you want to proceed with your application logic, you should replace return true; with return $next($request);
public function handle($request, Closure $next)
{
if(Auth::check()){
if (Auth::user()->subscribed('main')) {
return $next($request);
}else{
return view('payments.payment')->with('user',Auth::user());
}
}else{
abort(403, 'Unauthorized action.');
}
}
On an unrelated recommendation, you can clean up your conditional logic a bit to make your code easier to read/follow:
public function handle($request, Closure $next)
{
// If the user is not logged in, respond with a 403 error.
if ( ! Auth::check()) {
abort(403, 'Unauthorized action.');
}
// If the user is not subscribed, show a different payments page.
if ( ! Auth::user()->subscribed('main')) {
return view('payments.payment')->with('user',Auth::user());
}
// The user is subscribed; continue with the request.
return $next($request);
}
return response(view('payments.payment')->with('user',Auth::user()));
i solve by redirect to other routereturn redirect()->to('route');

How to write or use two levels of user permissions at once?

I have two levels in middleware and it does not work well, then how to write middleware in two levels at once?
public function __construct()
{
$this->middleware('auth');
$this->middleware('Admin');
$this->middleware('Teacher');
}
I also have this, i want to check that this page is only accessible by admin and teacher, but in writing the code it does not work well and how to write it right?
#if (Auth::check() && Auth::user()->level == 'Admin')
#elseif (Auth::check() && Auth::user()->level == 'Teacher')
#endif
If you can help me in solving this problem i am very grateful
in my experience i did that using a middleware ..
Middleware
public function handle($request, Closure $next, $roles)
{
$roles = explode('|',$roles);
$user = User::find($request->user()->id);
foreach($user->intRoles as $myRole)
{
if(in_array($myRole->role_id, $roles))
{
return $next($request);
}
}
return redirect()->back();
}
Route
Route::group( ['middleware' => 'rolePermissions:1|2|3'], function(){
Route::get('/users',['as'=>'users', 'uses'=>'PagesController#users']);
});
mydomain.com/users will only be accessible for those users who have roles (id) of 1, 2, or 3 ..
You have 2 separate middleware for checking user level. This forces both the conditions and doesn't work the way you want. You need a single middleware to check the user level and pass parameters to it.
Assume we have this middleware named as access.
public function handle($request, Closure $next, $levels)
{
$userLevels = explode(',', $levels);
if (Auth::check() && in_array(Auth::user()->level, $userLevels)) {
return $next($request);
}
return redirect('/home');
}
In your controller add this
public function __construct()
{
$this->middleware(['auth', 'access:Admin,Student']);
}

Check username in Laravel Middleware

I need to check the user is logged in and check their username in my Middleware of which verifies if they are an admin or not to limit access to a certain page. How do I get their username?
Using Auth::user() gives me an error from another Middleware.
ErrorException in VerifyCsrfToken.php line 136:
Trying to get property of non-object
Route
Route::get('admin', ['middleware' => 'admin', function() {
echo "You're an admin!";
}]);
Middleware
class VerifyAdmin
{
public function handle($request, Closure $next, $guard = null)
{
if (Auth::user()->username == "enayet123")
return $next($request);
}
}
You have to return
return $next($request);
even if your conditional fails so the next middleware can have the request. If you move that outside the conditional if, that should fix your problem.
Your code should look like this:
class VerifyAdmin
{
public function handle($request, Closure $next, $guard = null)
{
if (Auth::user()->username == "enayet123") {
// Do the thing you want ... (return or redirect to somewhere else)
redirect()->route('homepage');
}
return $next($request);
}
}
You should always return $next($request) which is necessary to pass the code / request from a particular middleware
In order to get the users details such as username/email you need to use $request->user() rather than Auth::user()
You should then check if the user is an admin by creating a method within the User model and calling that in the Middleware
class VerifyAdmin
{
public function handle($request, Closure $next, $guard = null)
{
$user = $request->user();
if ($user && $user->isAdmin()) {
return $next($request);
}
return redirect('/');
}
}

StaffMiddleware And AdminMiddleware Laravel 5.3

I have 2 Middlewares.
My StaffMiddleware
public function handle($request, Closure $next)
{
if( $request->user()->role->name != 'staff'){
return redirect()->route('store');
}
return $next($request);
}
My AdminMiddleware
public function handle($request, Closure $next)
{
if( $request->user()->role->name != 'admin'){
return redirect()->route('store');
}
return $next($request);
}
The Problem is my UnitController
public function __construct(UnitInterface $unit){
$this->middleware('staff');
$this->middleware('admin);
$this->unit = $unit;
}
It should work either the role is a staff or an admin. Do I need to create another Middleware to combine them both?
This completely depends on the way your Middleware is designed. As you can see from your code, it simple redirects if the role is not staff or not admin so there would be no way for you to have an OR logic.
However, you could use middleware parameters to avoid this.
$this->middleware('role:admin,staff');
This will use the role middleware and pass admin and staff as parameters.
Then you can use these parameters in your middleware:
public function handle($request, Closure $next, ...$params)
{
if(!in_array($request->user()->role->name, $params)){
return redirect()->route('store');
}
return $next($request);
}
This captures the additional parameters into an array $params in which you can check if the user's role matches one of the parameters.
**try this**
public function __construct(UnitInterface $unit){
$this->middleware(function ($request, $next) {
if($request->user()->role->name == 'staff' || $request->user()->role->name == 'admin')
{
return $next($request);
}
return redirect()->route('store')
});
}
No middleware

Resources