Laravel 5.4 Middleware for Admin and User Role - php

I created two Middleware called "MustBeAdmin" and "MustBeUser" to make sure depending on the user login I redirect them to the right page and restrict unauthorized content. Currently everything is working fine and redirects work well too. But the Logic I wrote behind the scene seems wrong to me and its weird it still works. If I write the logic that seems right to me atleast, it does not seem to work as expected.
Users table
id (1,2,3,...)
name
role (1,2,3,...)
Roles table
id (1,2,3,...)
role (Student, Admin,...)
MustBeAdmin middleware
public function handle($request, Closure $next)
{
if($request->user()->role == 2)
{
return $next($request);
}
else
{
return redirect('/admin/users');
}
}
MustBeUser middleware:
public function handle($request, Closure $next)
{
if($request->user()->role == 1)
{
return $next($request);
}
else
{
return redirect('/admin/users');
}
}
kernel.php
'admin' => \App\Http\Middleware\MustBeAdmin::class,
'user' => \App\Http\Middleware\MustBeUser::class,
As you can see I have registered middlewares in kernel.
I am getting results exactly what I need but I doubt if the logic in middleware is correct?
1 = Student
2 = Admin
if you see in MustBeAdmin middleware I am comparing if user role is 2 (admin) then do next($request) and in MustBeUser middleware I am comparing if user role is 1 (Student) then do next($request) and I set else to /Admin directory.
I feel its wrong, what do you think?

You are not checking the authenticated users details in your Middleware. The middleware should be something like:
//for student
public function handle($request, Closure $next)
{
if ( Auth::check() && Auth::user()->role == 1 )
{
return $next($request);
}
return redirect('/admin');
}
//for admin
public function handle($request, Closure $next)
{
if ( Auth::check() && Auth::user()->role == 2 )
{
return $next($request);
}
return redirect('/student');
}
You should check my detailed answer on the same topic here

Yes, It can be handled in one common file.
Here is the code
public function handle($request, Closure $next)
{
$user = User::find(Auth::id());
$roles = [];
foreach ($user->roles as $key => $value) {
array_push($roles, $value->pivot->role_id);
}
$routeName = Route::getFacadeRoot()->current()->uri();
$route = explode('/', $routeName);
if ($route[0] == "teacher") {
if (in_array(2, $roles)) {
return $next($request);
} else {
return response('Unauthorized.', 401);
}
} elseif ($route[0] == "student") {
if (in_array(1, $roles)) {
return $next($request);
} else {
return response('Unauthorized.', 401);
}
} elseif ($route[0] == "admin") {
if (Auth::user()->admin == 1) {
return $next($request);
} else {
return response('Unauthorized.', 401);
}
} else {
if (!Auth::user()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('admin-panel/auth/login');
}
}
}
return $next($request);
}
You can alter the logic according to your need.

Related

Laravel 5.8 use middleware for 1 user type in api and app

I'm trying to implement a middleware in Laravel 5.8 which checks if a value is true for a model Customer. I want the app routes to redirect to a route ('login'), for the api routes I want to give a 401 response. I think I'm overseeing something.
This is my Middleware which works for the app routes, but I can't get the middleware to handle the unauthorized requests ($user['dropshipping'] === false) correctly..
public function handle($request, Closure $next)
{
$user = Auth::user();
if($user instanceof Customer) {
if ($user->guard(['web'])['dropshipping']) {
return $next($request);
} elseif($user->guard(['customer-api'])['dropshipping']) {
return $next($request);
} else {
return redirect(route('login'))->with('error', 'Account not activated, please contact TWM BV.');
}
} else {
return $next($request);
}
}
Guards are associated to Auth not to users.
So you can use Auth::guard('guard-name') or auth()->guard('guard')
public function handle($request, Closure $next)
{
$user = Auth::user();
if($user instanceof Customer) {
if (auth()->guard('web')->user()->dropshipping) {
return $next($request);
} elseif(auth()->guard('customer-api')->user()->dropshipping) {
return $next($request);
} else {
return redirect(route('login'))->with('error', 'Account not activated, please contact TWM BV.');
}
} else {
return $next($request);
}
}

How to send a string or an array to laravel middleware

I'm working on Laravel and try to make anACL system. I have a Role Middleware From myController I've sent Role to my RoleMiddleware two way.
first one is send string.
$this->middleware('HasRole:User|Admin|Author');
this way i'm get a string when use dd() function.
and the second way is.
$this->middleware('HasRole:User,Admin,Author');
this way i'm get an array when use dd() function.
but this array only contains a single value.
result like this.
array:1 [▼
0 => "User"
]
other two value Admin & Author doesn't appear in this array.
How can i work both way string & array
Here is my middleware.
public function handle($request, Closure $next,$role='')
{
$roles=is_array($role)? $role: explode('|', $role);
dd($roles);
if($request->user()===null)
{
return response('Insufficient Access',401);
}
if($request->user()->hasAnyRole($roles) || !$roles)
{
return $next($request);
}
return response('Insufficient Permission',401);
//return $next($request);
}
I know maybe not exactly the answer to your question, but I recommend you to use laravel authorization instead middleware. see this doc
I prefer to use this code for your problem in the controller:
$this->authorize('update', $post);
or:
if ($user->can('create', Post::class)) {
// Executes the "create" method on the relevant policy...
}
then inside the policy file, you should specify the statement like:
if ($user->isSuperAdmin() || $user->id === $post->user_id) {
return true;
}
if you want middleware to automatically convert your string to array then middleware $role params should be like this
public function handle($request, Closure $next, ...$roles)
{
dd($roles);
if($request->user()===null)
{
return response('Insufficient Access',401);
}
if($request->user()->hasAnyRole($roles) || !$roles)
{
return $next($request);
}
return response('Insufficient Permission',401);
//return $next($request);
}
Then use it like this $this->middleware('HasRole:User,Admin,Author');
OR
But if you want some other character to separate your roles like | then the code should be
public function handle($request, Closure $next, $role = '')
{
$roles = explode('|', $role);
dd($roles);
if($request->user()===null)
{
return response('Insufficient Access',401);
}
if($request->user()->hasAnyRole($roles) || !$roles)
{
return $next($request);
}
return response('Insufficient Permission',401);
//return $next($request);
}
And use it like $this->middleware('HasRole:User|Admin|Author');
You can use both, just add some code in your middleware.
public function handle($request, Closure $next,...$role)
{
//add two line
$str_role=explode('|',$role[0]);
$roleString=$str_role;
$roles=is_array($role)? $role : is_array($roleString)? $roleString : null;
//dd($roles);
if($request->user()===null)
{
return response('Insufficient Access',401);
}
if($request->user()->hasAnyRole($roles) || !$roles)
{
return $next($request);
}
return response('Insufficient Permission',401);
//return $next($request);
}
NOW, you can use.
$this->middleware('HasRole:User|Admin|Author');
OR,
$this->middleware('HasRole:User,Admin,Author');

Laravel Quickadmin - User Role Redirect

I am using laravel quickadmin to create an admin section
https://github.com/LaravelDaily/quickadmin
It allows to create roles and users based on roles. How can i redirect users of a specific role into website and not admin.
Many thanks
change the following in the middleware
public function handle($request, Closure $next)
{
if ($request->user() != null && $request->user()->permissionCan($request)) {
return $next($request);
}
abort(403);
return false;
}
to (alter "specific role" and "your route" as you wish)
public function handle($request, Closure $next)
{
if ($request->user() != null && $request->user()->permissionCan($request)) {
$response = $next($request);
if( $request->user()->role() == 'specific role'){
redirect()->route('your route');
}
return $response;
}
abort(403);
return false;
}

Auth doesn't work on custom middleware

I have modified Login function in LoginController and this is what I have written
public function login(Request $request)
{
$data = $request->all();
if($this->validateLogin((array)$data))
{
$cred = $request->email;
$cred_p = $request->password;
//if()
$user = User::select('id', 'password')->where('email','=',$cred)->first();
if(count($user) == 1)
{
if(Hash::check($cred_p, $user->password))
{
$user_id = $user->id;
$status = User_status::select('is_active', 'is_completed')->where('user_id','=',$user_id)-> first();
$active = $status->is_active;
//dd($status->is_active);
if($active == 0)
{
return redirect()->to('/login')->withErrors(['status'=>"Your account is blocked. Please contact administrator or visit here <a href='/support/acount-blocked'>Support Center</a>"]);
}
else
{
$this->attemptLogin($request);
$this->sendLoginResponse($request);
}
}
else
{
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
}
else
{
return $this->sendFailedLoginResponse($request);
}
}
else
{
return $this->sendFailedLoginResponse($request);
}
}
This seems to work fine and Auth::user() is working but when I add new middleware that is IsCompletedMiddleware and I check dd(Auth::user()); this returns null value.
public function handle($request, Closure $next)
{
/*if(Auth::user()->status->is_completed == 0)
{
return redirect()->to('/profile/management/complete');
}*/
return $next($request);
}
I have also included use Auth; in the header of middleware but it always returns null value. And in other controllers Auth::user() returns proper user. Why is this so? And what is missing. Please help thank you.
In your middleware you have to get the user is doing the request, try to do this:
public function handle($request, Closure $next)
{
$request = $next($request);
if($request->user()->status->is_completed == 0){
return redirect()->to('/profile/management/complete');
}
return $request;
}

Laravel 5 middleware Auth check not working

i want to show a 404 error page if the user try to access to de admin page if he is not logged or if he dont have the 'Admin' type. This work fine if the user is logged in, if not the user access to the admin panel. If i remove the if(Auth::check()) the script shows a Trying to get property of non-object error.
class AdminMiddleware {
public function handle($request, Closure $next)
{
if(Auth::check()){
if ($request->user()->type != 'Admin'){
return abort(404);
}
}
return $next($request);
}
}
Try this
class AdminMiddleware {
public function handle($request, Closure $next)
{
if(Auth::check()){
if ($request->user()->type != 'Admin'){
return abort(404);
}
}else{
return abort(404);
}
return $next($request);
}
}
It should check if user is logged in and if so check if hes and admin, if hes not logged in show him the 404
or a shorter version
class AdminMiddleware {
public function handle($request, Closure $next)
{
if(Auth::check() && $request->user()->type == 'Admin'){
return $next($request);
}
return abort(404);
}
}

Categories