Laravel cannot pass multiple middleware - php

recently i created two middlewares which is one for user called device, and one other for super user which is high level of admin. This is my middleware
Role Device Middleware
<?php
namespace App\Http\Middleware;
use Closure;
class RoleDevice
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::check() && Auth::User()->role=='device'){
return $next($request);
}
return redirect()->route('login')->with('danger',"You don't have an access");
}
}
Role Device Super User
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
use User;
class RoleSuper
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::check() && Auth::User()->role=='super'){
return $next($request);
}
return redirect()->route('login')->with('danger',"You don't have an access");
}
}
after i created the middlewares, i put into the routes which is one route could access two middlewares. Here is one of my route.
Route::get('/dashboard','DashboardController#index')->middleware(['rolesuper','roledevice'])->name('dashboard');
and when i try to log in into my website, it returns
You don't have an access
which is don't pass into the middleware.
i hope i get any comments above !
thanks.

Middlewares are executed in the order the are passed. So in case first middleware returns redirect response that's it - second middleware won't be executed.
You could combine both middleware into one and pass available roles as middleware parameter or just create single middleware for this that will verify if user is authorized.

Related

Laravel Routing - Subdomain filtering

I'm using Laravel 5.4 and I'd like to filter the subdomain.
web.php
Route::group(['domain' => '{city}.localhost'], function () {
if ($city does not exist in database) {rediret to localhost};
Route::get('/', 'HomeController#home');
});
What I'd like
If subdomain exists in the database continue. Otherwise redirect to the same address but without a subdomain.
I would suggest using middleware to interrogate the $request URL and redirect accordingly, much like the RedirectIfAuthenticated middleware does.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class CheckSubdomain
{
/**
* 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)
{
// check $request->url() here...
if ($notInDatabase) {
return redirect()->route('/somewhere');
}
return $next($request);
}
}

Preload a view in laravel with different data

I am using Laravel and sentinel to develop a permission system however it was designed so that the user can select and deselect which permissions the role has from a checkbox form. I have already coded the part where they can assign permissions however I need that the checkboxes that have already been assigned are marked when the user request the page. How do you recommend approaching this? I am using a middleware
<?php
namespace App\Http\Middleware;
use Closure;
use Cartalyst\Sentinel\Laravel\Facades\Sentinel;
class PermissionsMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = Sentinel::findById(1);
$permisos = array(array_keys($user['permissions']))
return $next($request);
}
}
However, I don't know how to pass data from the middleware to the view.
I don't think it's recommended using the middleware for this purpose, but if you still want to do it that way you can try using:
View::share ( 'permisos', $permisos );
To share the 'permisos' variable with the view that's coming after the middleware.
So your code is going to look like this:
<?php
namespace App\Http\Middleware;
use Closure;
use Cartalyst\Sentinel\Laravel\Facades\Sentinel;
class PermissionsMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = Sentinel::findById(1);
$permisos = array(array_keys($user['permissions']))
View::share ( 'permisos', $permisos );
return $next($request);
}
}

passing data from middleware to view or alternative way to show specific data in every page

in my website i have a fairly complected category which i have to show in every view (in the client side) so i thought i put the code for creating category in a middleware and pass the result to views
so i've created my middleware but i cant figure out how can i pass its data to my view withouth having to do something in the controllers
i've tried these methods in my middleware
<?php
namespace App\Http\Middleware;
use Closure;
class CtegoryMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$request->merge(array("all_categories" => "abc"));
$request['all_categories']= 'abc';
return $next($request);
}
}
route :
Route::group(['middleware' => ['category' ]], function () {
Route::get('/', 'HomeController#index');
});
but in my view when i echo all_categories i get
Undefined variable: all_categories
btw i've checked by echoing something , the middleware gets triggered on the request
I think in your use case, using a globally available view variable should suffice.
<?php
namespace App\Http\Middleware;
use Closure;
class CtegoryMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$request->merge(array("all_categories" => "abc"));
$request['all_categories']= 'abc';
/**
* This variable is available globally on all your views, and sub-views
*/
view()->share('global_all_categories', 'abc');
return $next($request);
}
}
The variable is loaded once (if you do database query, the query will only execute once), and the variable is then stored in the View factory.

Laravel 5.1 ACL

I've read about the new policy features in Laravel 5.1.
It looks from the docs that a blacklist approach is chosen by default. E.g. a controller actions is possible until access is checked and denied using a policy.
Is it possible to turn this into a whitelist approach? Thus, every controller action is denied except when it's explicitly granted.
I just found a rather clean way I think, in your routes, you pass a middleware and the policy that needs to be checked.
Example code:
<?php
namespace App\Http\Middleware;
use Closure;
class PolicyMiddleware
{
/**
* Run the request filter.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string $policy The policy that will be checked
* #return mixed
*/
public function handle($request, Closure $next, $policy)
{
if (! $request->user()->can($policy)) {
// Redirect...
}
return $next($request);
}
}
And the corresponding route:
Route::put('post/{id}', ['middleware' => 'policy:policytobechecked', function ($id) {
//
}]);

How can I use laravel 5.1 middleware parameter for multiple auth and protected routes?

I'm new to laravel 5.1.
How can I use middleware parameter to protect my admin routes from users ?
something like this:
Route::group(['middleware' => 'auth:admin'], function()
/* Admin only Routes*/
{
//////
});
I have a field "role" in my "users" table that get two values:
1 for admin
2 for users
In my application, users, have their protected route.
I don't want to use packages.
You can do something like this. Inject the Guard class, then use it to check the user. You dont need to pass the parameter really. Just name your middleware 'admin' or something. The following middleware will check if the current user's role is admin, and if not, redirect to another route. You can do whatever you prefer on failure.
<?php
namespace Portal\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class Admin
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if($this->auth->user()->role != 'admin') {
return redirect()->route('not-an-admin');
}
return $next($request);
}
}
In case you do want to pass the parameter, you can do this:
public function handle($request, Closure $next, $role)
{
if($this->auth->user()->role != $role) {
return redirect()->route('roles-dont-match');
}
return $next($request);
}

Categories