I have multiple users with multiple permissions. A user can belong to the only single role but that role can have multiple permissions like create
, read
, update
, delete
. And I have a RoleMiddleware
. I am authenticating the user in roleMiddleware
. But how can I protect routes
in RoleMiddleware
against a specific user?
For Example, I have a route create-case
which can only be accessed by the operator
or by Admin
else everyone redirects to 404 error
how Can I deal with it in RoleMiddleware
.
I have written basic code for authentication where every user with their roles is authenticated but I am getting how can I code in middleware so ever route when a user hits it may go to the RoleMiddleware
where middleware Authenticate
route to the Role and then give him the access.
Role Middleware
class RoleMiddleware
{
public function handle($request, Closure $next, $permission = null)
{
if (Auth::check() === false)
{
return redirect('login');
}
elseif (Auth::check() === true)
{
$roles = Role::all()->pluck('slug');
if (is_null($request->user()) )
{
abort(404);
}
if (!$request->user()->hasRole($roles))
{
abort(404);
}
if ($request->user())
{
if ($request->user()->hasRole($roles))
{
return $next($request);
}
}
}
}
}
Case Controller:
<?php
namespace App\Http\Controllers\Cases;
use App\Http\Controllers\Controller;
use App\Http\Requests\CaseStoreRequest;
use Illuminate\Support\Facades\Auth;
use Session;
class CaseController extends Controller
{
use DropzoneFileUploadTraits;
public function __construct()
{
$this->middleware('role');
}
public function index()
{
$data['portal'] = Portal::all();
$data['operators'] = Operator::all();
return view('case', $data);
}
public function caseList()
{
$user = new User();
$isAdmin = $user->isAdmin();
$loggedIn = Auth::id();
$cases = Cases::with('patients', 'portal')
->when(!$isAdmin, function ($query) use ($loggedIn) {
return $query->where('user_id', $loggedIn);
})->orderBy('created_at', 'desc')->get();
$data['cases'] = $cases;
return view('case_list', $data);
}
}
Route:
Route::get('create-case', 'Cases\CaseController@index')->name('create-case');
Route::post('case-submit', 'Cases\CaseController@caseSubmit')->name('case-submit');
Route::post('edit-patient-case-submit', 'Cases\CaseController@editPatientCaseSubmit')->name('edit-patient-case-submit');
Route::get('case-list', 'Cases\CaseController@caseList')->name('case-list');
Best way to do that in a clean manner would be to create policies on the targeted entities. Laravel policies allow you to :
Bind a route authorization logic to a policy action
Easily call a policy action result from anywhere else in the project (views, controllers and so on).
The subject is well covered in Laravel documentation so I suggest you go there and take a look. Do not forget to register the policy and bind it to your model.
Apart from that this should do the trick.
class CasePolicy
{
use HandlesAuthorization;
public function create(User $user){
$roles = ['operator','Admin']
return $user->hasRole($roles);
}
}
Then in your route file :
Route::get('create-case', 'Cases\CaseController@index')->name('create-case')->middleware('can:create,App\Case');