In my application I can mark a user as blocked. After a blocked mark he can't do anything.
My solution was to check the status in every construct controller and if the authenticated user is marked as blocked he will redirect to the view.
But my solution isn't very good because i have dublicated code and i have to check for the actual route.
Here is my code:
public function __construct()
{
$this->middleware('auth');
$this->middleware(function ($request, $next)
{
$this->user= Auth::user();
if(strcmp(Route::currentRouteName(), 'user.password.show') != 0)
{
if(strcmp(Route::currentRouteName(), 'user.password.set') != 0)
{
if(strcmp(Route::currentRouteName(), 'user.blocked.show') != 0)
{
if($this->user->status == Userstatus::where('type', 'passwordSetFalse')->first()->id)
{
Session::flash('error', 'Bitte setzen Sie ihr Passwort!');
return Redirect::route('user.password.show');
}
else
{
return $next($request);
}
}else
{
return $next($request);
}
}
else
{
return $next($request);
}
}
else
{
return $next($request);
}
});
}
I search a solution where i put the code once and i can use it for all my controller but i have no idea where the code can be written in.
Many thanks for your help
Take a look at Laravel Middlewares. Define a middleware that checks for the user status before passing the request to the controllers, than register your middleware in app/Http/Kernel.php.
<?php
namespace App\Http\Middlewares;
class UserBlockedMiddleware
{
public function handle($request, $next)
{
$user = \Auth::user();
if($user->status == 'blocked') abort(403);
return $next($request);
}
}
To learn more on how to register a global middleware check this section in Laravel docs.
You need to read about Protecting Routes
You can attach auth middleware to routes you want to protect, or directly in the __construct of your controller
Laravel ships with an auth middleware, which is defined at Illuminate\Auth\Middleware\Authenticate
If you want your own Auth middleware you can type the following
php artisan make:middleware MyOwnAuth
Also you can actually reduce the code like that
public function __construct()
{
$this->middleware('auth');
$this->middleware(function ($request, $next) {
$this->user = Auth::user();
if (
strcmp(Route::currentRouteName(), 'user.password.show') != 0
&& strcmp(Route::currentRouteName(), 'user.password.set') != 0
&& strcmp(Route::currentRouteName(), 'user.blocked.show') != 0
&& $this->user->status == Userstatus::where('type', 'passwordSetFalse')->first()->id
) {
Session::flash('error', 'Bitte setzen Sie ihr Passwort!');
return Redirect::route('user.password.show');
};
return $next($request);
});
};
Related
I have a problem when I want to pass data to the view via the middleware to count the number of users. when not using middleware, variable from controller get to the view.
my HomeController.php
public function index()
{
$count = User::count();
return view('admin.Dashboard', compact($count);
}
my Middleware
public function handle(Request $request, Closure $next)
{
if ($request->user() && $request->user()->role == 'admin') {
return response()->view('admin.Dashboard');
} else {
return response()->view('member.dashboard');
}
return $next($request);
}
the $count variable if using middleware in route not passed to the view
my web.php
Auth::routes(['verify' => true]);
Route::get('/dashboard', 'HomeController#index')->middleware('verified', 'cekrole')->name('home');
In your middleware you are returning response (a view), so
return $next($request);
will never be executed, so neither will your controller.
User call /dashboard > Your middleware is called > if it's an admin you are returning admin.Dashboard, else member.dashboard.
But you never execute code in your Controller.
As a quick fix you could replace your Middleware by :
public function handle(Request $request, Closure $next)
{
if ($request->user() && $request->user()->role == 'admin') {
$count = User::count();
return view('admin.Dashboard', compact('count'));
}
return response()->view('member.dashboard');
}
or make those test (admin/not admin) in your controller
I've been stuck here for a while. I hope I can clearly explain the issue. I'm trying to have separate pages for admin and user. For that, I have created an admin middleware. Now when I login, it redirects me to the same page either its admin or user. I want it to go to admin dashboard when admin logs in and to the user home when user logs in. I hope the issue is clear.
Here is the AdminMiddleware code:
public function handle($request, Closure $next)
{
if(Auth::user()->user_type == 'admin') //If usertype is admin
{
return $next($request);
}
else {
return redirect('home');
}
}
Here are the routes code:
Route::get('/','HomeController#index');
//For Admin
Route::group(['middleware' => ['auth','admin']], function() {
Route::get('/admin','HomeController#home_page');
Route::get('/users-list', 'UserController#users_list');
});
Here is the HomeController code:
public function index()
{
return view('home', compact('currantWorkspace'));
}
I've added the Middleware path to kernel.php file.
I'll be happy to provide any other details if needed. Any solutions/suggestions will be highly appreciated.
Edit
I've tried this, but still issue.
protected function redirectTo(){
if (Auth::user()->user_type != 'admin') {
return 'admin';
//return redirect('/admin');
}
else {
return 'home';
//return redirect('/');
}
}
I think the redirectTo function is not working, or not checking the if/else conditions
Why don't you create an 'if, else' statement in your login function like:
if(Auth::user()->user_type == "Admin"){
return Redirect::route('dashboard');
}else if(Auth::user()->user_type == "Standard User"){
return Redirect::route('home');
}
Change the route as follows.
Route::get('/','HomeController#index')->name('home');
Route::group(['middleware' => ['auth','admin']], function()
{
Route::get('/admin','HomeController#home_page')->name('admin.home');
Route::get('/users-list', 'UserController#users_list');
});
Change the redirect statement in middleware as
public function handle($request, Closure $next)
{
if(Auth::user()->user_type == 'admin') //If usertype is admin
{
return $next($request);
}
else
{
return redirect()->route('home');
OR
return redirect('/');
}
}
There are a few problems, currently, the key thing is that the middleware you defined is not being called when anyone tries to log in.
To make it work I think you just need to add this to your LoginController.php
protected function authenticated()
{
if (Auth::user()->user_type == 'admin') {
return redirect('dashboard');
}
return redirect('home');
}
This method basically tells laravel what you want to do after the user is logged in.
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);
}
}
I have three type of users for the application, Each one have its own dashboard. I need a check that adminor any other user cannot see another user dashboard.
There is a middleware RedirectIfAuthenticated :
public function handle($request, Closure $next, $guard = null){
if (Auth::guard($guard)->check() && auth()->user()->type == 'admin'){
return redirect('/admin');
}
if (Auth::guard($guard)->check() && auth()->user()->type == 'author'){
return redirect('/author');
}
if (Auth::guard($guard)->check() && auth()->user()->type == 'client'){
return redirect('/client');
}
}
Its under guest middleware.
The above code seems good to me but when i tests it, The browser says Too many redirects.
What am i doing wrong, What will be the best way to handle it.
You may have misunderstood the purpose of that middleware. The purpose of RedirectIfAuthenticated is to redirect a user to their default authenticated page. It is not meant to block unauthenticated/unauthorised users from accessing specific areas.
What you need to do is redirect if not authorised. Since this is a simple case you can just have a middleware:
class RequireRole {
public function handle($request, Closure $next, $role) {
abort_unless(auth()->check() && auth()->user()->type == $role, 403, "You don't have permissions to access this area");
return $next($request);
}
}
Then register this middleware in your Kernel.php
protected $routeMiddleware = [
//Other middleware
"requirerole" => RequireRole::class
];
Then you can use it in your routes e.g.
Route::get('/admin', function () { /* action */ })->middleware("requirerole:admin");
However if you find yourself in need of more complex rules then take a look at Authorization
Need to modify the code a bit
public function handle($request, Closure $next, $guard = null){
if (Auth::guard($guard)->check() && auth()->user()->type == 'admin'){
return redirect('/admin');
}
if (Auth::guard($guard)->check() && auth()->user()->type == 'author'){
return redirect('/author');
}
if (Auth::guard($guard)->check() && auth()->user()->type == 'client'){
return redirect('/client');
}
return $next($request);
}
You have to add an extra check for every if statement to see if you are not already on the route where it's going to redirect to
Maybe something like:
&& $request->is('admin')
Just split your checks and keep the original return:
public function handle($request, Closure $next, $guard = null){
if (Auth::guard($guard)->check()){
if(Auth::user()->type == 'admin'){
return redirect('/admin');
}
if(Auth::user()->type == 'author'){
return redirect('/author');
}
if(Auth::user()->type == 'client'){
return redirect('/client');
}
}
return $next($request);
}
As pointed in the accepted answer, the purpose of the middleware is to redirect a user if he is authenticated.
Now if you check App\Http\Kernel.php you will see that the middleware is attached to guest route middleware variable.
So any route you assign the middleware of guest will not be accessible to an authenticated user.
To solve your problem create another middle as pointed in the accepted answer.
What you need to do is redirect if not authorised. Since this is a simple case you can
just have a middleware:
public function handle($request, Closure $next, $role) {
abort_unless(auth()->check() && auth()->user()->type == $role, 403, "You don't > have permissions to access this area");
return $next($request);
}
}
Then register this middleware in your Kernel.php
//Other middleware
"requirerole" => RequireRole::class
];
Then you can use it in your routes e.g.
Route::get('/admin', function () { /* action */ })->middleware("requirerole:admin");
In reality, you may not need to modify default files that come with laravel unless it is inevitable.
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);
}
}