ERR_TOO_MANY_REDIRECTS - Laravel 5.7 - laravel

I'm using laravel 5.7. I have a users table with a column user_type where
0 = default users
1 = Professionals
2 = Facilities
8 = Employees
9 = Managers
10 = Administrator
And another column which is boolean is_premium which returns either true or false.
I have created a middleware for admin
namespace App\Http\Middleware;
use Closure;
use Auth;
class IsAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::user() && Auth::user()->usertype == 10) {
return $next($request);
}
return redirect('/administration/dashboard');
}
}
And i have used it in the routes/web.php file as
Route::group(['prefix' => 'administration', 'middleware' => 'admin'], function(){
Route::get('/dashboard', 'Admin\DashboardController#index')->name('admin.dashboard');
});
When i visit the admin dashboard route it says
ERR_TOO_MANY_REDIRECTS
I know there is something im doing wrong...what is it?
And im assuming to create middlewares for other usertypes too and use in the routes file. Is this the right way to do?

Try false logic first:
...
public function handle($request, Closure $next)
{
if ( ! (Auth::user() && Auth::user()->usertype == 10) ) {
return redirect('/home');
}
return $next($request);
}
...

Related

Custom Middleware Not working when using Sanctum

I am using Dynamic database for my laravel API Project. I am doing that with a middleware. When I use auth:sanctum in api rout middleware not working. But normally its working fine.
Route> api.php
Route::group(['middleware'=>'database'], function() {
Route::group(['namespace' => 'App\Http\Controllers\Admin', 'middleware' => ['auth:sanctum']], function () {
Route::get('dashboard', function () {
return "conncted sucessfully to database ".\DB::connection()->getDatabaseName();
});
});
});
Middleware > Database.php
namespace App\Http\Middleware;
use Closure;
use App\Models\SoftClient;
class Database
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$route = app('router')->getRoutes()->match($request);
$prefix = $route->action['name'];
$s_client = SoftClient::where('url', $prefix)->first();
\Config::set('database.connections.multidomain.host', $s_client->db_host );
\Config::set('database.connections.multidomain.database', $s_client->db_name );
\Config::set('database.connections.multidomain.username', $s_client->db_username );
\Config::set('database.connections.multidomain.password', $s_client->db_password );
\DB::reconnect('multidomain');
return $next($request);
}
}
'database' => \App\Http\Middleware\Database::class,
I add this to Karnel.php
When I send request to dashboard I got bellow error. If I not use auth:sanctum It's working fine.
Illuminate\Database\QueryException: SQLSTATE[HY000] [1045] Access denied for user ''#'localhost' (using password: NO)
auth sanctum is used to authenticate user. Maybe you are directly accessing the routes with authenticating user.
when you check the routes with "php artisan route:list", do you see the middleware you configured with the route?
I had a similar problem, where route:list pointed me to the fact that the middleware I defined with the group wasn't actually used, and in the end I dropped the "group" and just defined the routes individually. A bit cumbersome but it worked.
if your goal is to use laravel sanctum for dynamic database connection then i use this method and it works
step 1 : copy this file Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful to our middlewear and then modify duplicate this file like this
<?php
namespace App\Http\Middleware;
use Illuminate\Routing\Pipeline;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\App;
class EnsureFrontendRequestsAreStateful
{
/**
* Handle the incoming requests.
*
* #param \Illuminate\Http\Request $request
* #param callable $next
* #return \Illuminate\Http\Response
*/
public function handle($request, $next)
{
$this->changeDatabaseConnection($request);
$this->configureSecureCookieSessions();
return (new Pipeline(app()))->send($request)->through(static::fromFrontend($request) ? [
function ($request, $next) {
$request->attributes->set('sanctum', true);
return $next($request);
},
config('sanctum.middleware.encrypt_cookies', \Illuminate\Cookie\Middleware\EncryptCookies::class),
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
config('sanctum.middleware.verify_csrf_token', \Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class),
] : [])->then(function ($request) use ($next) {
return $next($request);
});
}
protected function changeDatabaseConnection($request)
{
$encodeCc = $request->input('cc');
$cc = json_decode(base64_decode($encodeCc));
if ((!empty($cc) && $cc != 'axiasolusi')) {
$compCode = $cc;
if (App::environment() === 'local') {
$compCode = 'ess-' . $compCode;
}
} else {
$compCode = env('DB_DATABASE');
}
Config::set('database.connections.' . env("DB_CONNECTION") . '.database', $compCode);
}
/**
* Configure secure cookie sessions.
*
* #return void
*/
protected function configureSecureCookieSessions()
{
config([
'session.http_only' => true,
'session.same_site' => 'lax',
]);
}
/**
* Determine if the given request is from the first-party application frontend.
*
* #param \Illuminate\Http\Request $request
* #return bool
*/
public static function fromFrontend($request)
{
$domain = $request->headers->get('referer') ?: $request->headers->get('origin');
if (is_null($domain)) {
return false;
}
$domain = Str::replaceFirst('https://', '', $domain);
$domain = Str::replaceFirst('http://', '', $domain);
$domain = Str::endsWith($domain, '/') ? $domain : "{$domain}/";
$stateful = array_filter(config('sanctum.stateful', []));
return Str::is(Collection::make($stateful)->map(function ($uri) {
return trim($uri) . '/*';
})->all(), $domain);
}
}
step 2 : change karnel like this
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, // original
\App\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
and last step : change route api
Route::middleware('change.database')->group(function () {
Route::post('/verify-company-code', 'Api\Web\Auth#verifyCompanyCode');
Route::post('/verify-user-account', 'Api\Web\Auth#verifyUserAccount');
Route::post('/verify-user-pin', 'Api\Web\Auth#verifyUserPin');
Route::post('/forgot-password', 'Api\Web\Auth#forgotPassword');
Route::post('/reset-password', 'Api\Web\Auth#resetPassword');
});
Route::middleware(['auth:sanctum'])->group(function () {
Route::post('logout', [Auth::class, 'logout']);
Route::post('logout-all', 'Api\Web\Auth#logoutAll');
});
});

Trying to get property 'status' of non-object

I want create role admin and member in login multi user laravel
My Code in Middleware CheckStatus (chek role)
<?php
namespace App\Http\Middleware;
use Closure;
use App\User;
class CekStatus
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = \App\User::where('email', $request->email)->first();
if ($user->status == 'admin') {
return redirect('admin/dashboard');
} elseif ($user->status == 'member') {
return redirect('member/dashboard');
}
return $next($request);
}
}
When I process login , I've get error Trying to get property 'status' of non-object
Please check the users table, is there any user which not belong to any role. Assign the rule to each user then it will work perfectly.
You can check the relation using tinker
php artisan tinker

Laravel group multiple Middleware

In my application I have three user roles:
user
editor
admin
When editor logs into the admin section, some of the sections are hidden (users manage, system information etc.) and of course, the admin can see everything.
So, for this purpose I've created two middleware: Admin and Editor. This is the code.
Admin middleware.
<?php
namespace App\Http\Middleware;
use Illuminate\Support\Facades\Auth;
use Closure;
class Admin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::check()) {
if(Auth::user()->role_id == 3) {
return $next($request);
}
}
return redirect('/');
}
}
Editor middleware:
<?php
namespace App\Http\Middleware;
use Illuminate\Support\Facades\Auth;
use Closure;
class Editor
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::check()) {
if(Auth::user()->role_id == 2) {
return $next($request);
}
}
return redirect('/');
}
}
Here's the part of the Kernel:
protected $routeMiddleware = [
'admin' => \App\Http\Middleware\Admin::class,
'editor' => \App\Http\Middleware\Editor::class,
];
Now I'm trying to build the routes that will be available to those user roles.
If I do it only for the admin or the editor, it works fine, but when I combine them, the one user can login and the other cannot.
Here's the code only for the admin and it works fine.
Route::middleware('admin')->group(function(){
Route::get('/admin', 'PagesController#adminIndex');
Route::resource('/admin/pages', 'PagesController');
Route::resource('/admin/news', 'NewsController');
Route::resource('/admin/users', 'UsersController');
...
});
I've tried to combine them with this code, but it's not working (cannot login into the admin section at all):
Route::middleware(['admin', 'editor'])->group(function(){
Route::get('/admin', 'PagesController#adminIndex');
Route::resource('/admin/pages', 'PagesController');
Route::resource('/admin/news', 'NewsController');
Route::resource('/admin/users', 'UsersController');
...
});
How can I solve this problem?
P.S. Later I want to build a logic for the User role too, so there's must a way to combine the routes.
You can solve the problem with help of Middleware Parameters and instead of several middlewares for each role use only one universal middleware with roles as parameters.
For example:
protected $routeMiddleware = [
'checkRole' => \App\Http\Middleware\CheckRole::class,
];
Middleware:
<?php
namespace App\Http\Middleware;
use Illuminate\Support\Facades\Auth;
use Closure;
class CheckRole
{
public function handle($request, Closure $next, ...$roles)
{
$roleIds = ['user' => 1, 'editor' => 2, 'admin' => 3];
$allowedRoleIds = [];
foreach ($roles as $role)
{
if(isset($roleIds[$role]))
{
$allowedRoleIds[] = $roleIds[$role];
}
}
$allowedRoleIds = array_unique($allowedRoleIds);
if(Auth::check()) {
if(in_array(Auth::user()->role_id, $allowedRoleIds)) {
return $next($request);
}
}
return redirect('/');
}
}
Routes:
Route::middleware(['checkRole:admin,editor'])->group(function(){
//Your routes
});
It should be like below.
Route::middleware(['auth'])->group(function(){
//common routes will goes here
Route::middleware(['admin'])->group(function(){//admin routes will goes here
Route::get('/admin', 'PagesController#adminIndex');
Route::resource('/admin/pages', 'PagesController');
Route::resource('/admin/news', 'NewsController');
Route::resource('/admin/users', 'UsersController');
});
Route::middleware(['editor'])->group(function(){
//editor routes goes here.
});
});
The problem is that your middleware(['admin', 'editor']) is checking the both roles i.e. admin,editor for user and you have only one role for user. That is reason why it is not working
There are great packages out there for managing the user roles which are easy to use . I suggest you to use Spatie Laravel Permission if you want tutorials on it watch Bitfumes Video

Disable Login in Laravel 5.2

In Laravel 5.2, I have added has_login field in the users table.
Where do I add logic to prevent user logging in if has_login is value 0 in the users table? I use AuthController.php for authentication and use AuthenticatesAndRegistersUsers without using login() / authenticate() functions in AuthController.hp file. Login work fine.
I personally tend to do this in the middleware, but you can also do it outside of that.
Here's a middleware example:
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RequireHasLogin
{
/**
* 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::guard($guard)->user()->has_login)
{
Auth::logout();
if ($request->ajax() || $request->wantsJson())
{
return response('Unauthorized.', 401);
}
return redirect()->guest('/auth/login');
}
}
return $next($request);
}
}
Though I think some people do this too:
Auth::guard()->attempt(["email" => $email, "password" => $password, "has_login" => true])
This should point you in the right direction -
https://laravel.com/docs/master/authentication#authenticating-users

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();

Resources