I am trying to set permission to access an action to two different user roles Admin, Normal_User as shown below.
Route::group([\'middleware\' => [\'role_c
Instead of adding multiple arguments to your handle method and having to update it every time you add a new role to your application, you can make it dynamic.
Middleware
/**
* Handle an incoming request.
*
* @param $request
* @param Closure $next
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function handle($request, Closure $next) {
$roles = array_slice(func_get_args(), 2); // [default, admin, manager]
foreach ($roles as $role) {
try {
Role::whereName($role)->firstOrFail(); // make sure we got a "real" role
if (Auth::user()->hasRole($role)) {
return $next($request);
}
} catch (ModelNotFoundException $exception) {
dd('Could not find role ' . $role);
}
}
Flash::warning('Access Denied', 'You are not authorized to view that content.'); // custom flash class
return redirect('/');
}
Route
Route::group(['middleware' => ['role_check:default,admin,manager']], function() {
Route::get('/user/{user_id}', array('uses' => 'UserController@showUserDashboard', 'as' => 'showUserDashboard'));
});
This will check if the authenticated user has at least one of the roles provided and if so, passes the request to the next middleware stack. Of course the hasRole()
method and the roles themselves will need to be implemented by you.
//please take note there must be space between ... $roles
//on your route make sure there is no space in between the roles
'checkRole:staff,admin'
public function handle($request, Closure $next, ... $roles)
{
foreach($roles as $role){
if ($request->user()->hasRole($role)){
return $next($request);
}
}
abort(404);
}
you can try this out also
Route::group(['middleware' => 'role:webdev|admin'], function () {
});
public function handle($request, Closure $next, $role)
{
$roles = collect(explode('|',$role));
if (! $request->user()->hasRole($roles)) {
abort(404, 'No Way');
}
return $next($request);
}
To add multiple parameters, you need to seperate them with a comma:
Route::group(['middleware' => ['role_check:Normal_User,Admin']], function() {
Route::get('/user/{user_id}', array('uses' => 'UserController@showUserDashboard', 'as' => 'showUserDashboard'));
});
Then you have access them to in your middleware like so:
public function handle($request, Closure $next, $role1, $role2) {..}
The logic from there is up to you to implement, there is no automatic way to say "OR".
In the middleware class
<?php
namespace App\Http\Middleware;
use Closure;
use function abort;
use function array_flip;
use function array_key_exists;
use function array_slice;
use function func_get_args;
class MustBeOFUserType
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$roles = array_slice(func_get_args(), 2); // ['admin', 'author']
//flip $roles to get ['admin' => 0, 'author' => 1];
if (!auth()->guest() && array_key_exists(auth()->user()->role->name, array_flip($roles))) {
return $next($request);
}
abort(423, 'Sorry you are not authrized !');
}
}
in the web.php OR route file
Route::get('/usertype', function() {
return response(['Accessed'], 200);
})->middleware([
'App\Http\Middleware\MustBeOFUserType:admin,author'
]);
Remember space on ':admin,author' like ':admin, author' will result into errors
For sanity check and if your a TDD person like I am use this to test the middleware
<?php
namespace Tests\Feature;
use App\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use function factory;
class MustBeOFUserTypeTest extends TestCase
{
use RefreshDatabase;
/** @test * */
public function it_accepts_the_admin()
{
$this->signIn(factory(User::class)->states('administrator')->create());
$this->get('/usertype')->assertStatus(200);
}
/** @test * */
public function it_rejects_normal_users()
{
$this->signIn();
$this->get('/usertype')->assertStatus(423);
}
/** @test **/
public function it_accepts_authors()
{
$this->signIn(factory(User::class)->states('author')->create());
$this->get('/usertype')->assertStatus(200);
}
public function signIn($user = null)
{
$u = $user ?: factory('App\User')->states('normal')->create();
$this->be($u);
return $this;
}
}
You can use the 3 dot (...) syntax in PHP 5.6+
Your middleware's handle function
public function handle($request, Closure $next, ...$roles)
{
foreach($roles as $role){
if ($request->user()->hasRole($role)){
return $next($request);
}
}
abort(404);
}
This super easy dynamic implementation might come handy for someone, in your middlewear file checkRole.php:
public function handle($request, Closure $next, ... $roles)
{
$found = false;
foreach ($roles as $role) {
if (session('type') == $role) {
$found = true; break;
}
}
if (!$found) {
return back()->with('error','Access denied!');
}
return $next($request);
}
and call the middlewear from web.php with as much parameter you need to pass:
Route::get('/approve', 'aController@approve') ->middleware('roles:admin');
Route::get('/dashboard','bController@dashboard')->middleware('roles:admin,user');
also don't forget to modify the middlewear key name in your Kernel.php:
'roles' => \App\Http\Middleware\checkRole::class,