I am using Sentinel to authenticate users and as the auth Middleware.
Middleware code:
public function handle($request, Closure $next)
{
var_dump(Sentinel::guest()); // prints false
if (Sentinel::guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('/login');
}
}
return $next($request);
}
Controller code:
public function getAccount() {
var_dump(Sentinel::guest()); // prints true
return Sentinel::getUser();
}
routes.php
Route::group(['middleware' => ['auth']], function () {
Route::get('api/v1/temp/users/account', 'App\Http\Controllers\UsersController#getAccount');
}
Then if i browse to api/v1/temp/users/account the var_dump() in the Middleware is printing false, while the var_dump() inside the controller is printing true which seems a nonsense.
What's wrong?
It turned out i was using the native facade instead of the Laravel facade Cartalyst\Sentinel\Laravel\Facades\Sentinel. That fixed.
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'm new to laravel I have created middleware for my each role but when I add it to my route it won't work.
If I add single middleware to my route it works fine but when I add second and third one It will not work.
It won't shows the route to authorized user it redirect it to home,
My User Model:
public function IsAdmin()
{
if($this->role_id =='1')
{
return true;
}
else
{
return false;
}
}
public function IsManager()
{
if($this->role_id =='2')
{
return true;
}
else
{
return false;
}
}
public function IsUser()
{
if($this->role_id =='3')
{
return true;
}
else
{
return false;
}
}
My Kernal:
'IsAdmin' => \App\Http\Middleware\IsAdmin::class,
'IsManager' => \App\Http\Middleware\IsManager::class,
'IsUser' => \App\Http\Middleware\IsUser::class,
My IsAdmin Middlewares:
public function handle($request, Closure $next)
{
$user =Auth::User();
if(!$user->IsAdmin())
{
return redirect('stock');
}
return $next($request);
}
My IsManager
public function handle($request, Closure $next)
{
$user =Auth::User();
if(!$user->IsManager())
{
return redirect('stock');
}
return $next($request);
}
and IsUser
public function handle($request, Closure $next)
{
$user =Auth::User();
if(!$user->IsUser())
{
return redirect('stock');
}
return $next($request);
}
and finally my Route
Route::get('approv',['middleware'=>['IsManager','IsAdmin'],function(){
return view('approv');
}]);
This will not work as you'd expect. All middleware need to pass in order for the request to be processed which means that your user will need to be both a manager and an admin at the same time which based on your setup is impossible.
You can get around this (kind of) by making a different kind of middleware:
Kernel:
'roles' => \App\Http\Middleware\Roles::class,
And the Roles middleware:
class Roles {
private function checkRole($role) {
switch ($role) {
case 'user': return \Auth::user()->IsUser();
case 'manager': return \Auth::user()->IsManager();
case 'admin': return \Auth::user()->IsAdmin();
}
return false;
}
public function handle($request, Closure $next, ...$roles)
{
foreach ($roles as $role) {
if ($this->checkRole($role)) {
//At least one role passes
return $next($request);
}
}
//All checks failed so user does not have any of the required roles
return redirect('stock');
}
}
Then to use this you simply do:
Route::get('approv',['middleware'=>['roles:manager,admin'],function(){
return view('approv');
}]);
This works because Laravel Middleware support parameters. You can pass parameters as a comma separated list of strings where you declare the middleware. In this case this was done as roles:manager,admin
Laravel will then send these parameters as additional parameters in the handle method. These can be accessed using PHPs syntax for variadic arguments. In this particular case it's by using the array spread operator. This is documented as an example in the function arguments section of the PHP manual.
Note that this is actually equivalent to saying :
public function handle($request, Closure $next, $role1=null, $role2=null, $role3=null)
but using the spread operator is much more convenient since ...$roles would be an array which contains only the roles that were passed in the middleware.
I am a newbie with Laravel. I am doing a tutorial and i have issues on restricting access to manager users. I have been able to assign roles (manager and members) to my users at the moment. But my issue lies in the Manager Middleware.
If the user is a manager, it doesn't return the $next($request); but instead it routes to /home after authentication and if user isn't a manager, it routes to /home as well instead of /tickets.
There is a file called RedirectIfAuthenticated, i changed the route in there but the issue still remained the same.
So what am i missing to restrict access to my managers?
Manager middleware
public function handle($request, Closure $next)
{
if(!Auth::check())
{
return redirect('/login');
}
else{
$user = Auth::user();
if($user->hasRole('Manager'))
{
return $next($request);
}
else{
redirect('/tickets');
}
}
return $next($request);
}
Routes
Route::group(array('prefix' => 'admin', 'namespace' => 'Admin', 'middleware' =>'manager'), function () {
Route::get('users', 'UsersController#index');
Route::get('users/{id?}/edit', 'UsersController#edit');
Route::post('users/{id?}/edit','UsersController#update');
Route::get('roles', 'RolesController#index');
Route::get('roles/create', 'RolesController#create');
Route::post('roles/create', 'RolesController#store');
});
Just do the following:
in the else part: instead of redirect('/tickets'); use return redirect('/tickets');
i.e. it will become:
public function handle($request, Closure $next)
{
if(!Auth::check())
{
return redirect('/login');
}
else{
$user = Auth::user();
if($user->hasRole('Manager'))
{
return $next($request);
}
else{
return redirect('/tickets');
}
}
return $next($request);
}
That's it
I have a controller like this:
public function __construct()
{
$check = Auth::id();
if ($check->role == '5') {
// allow to run any other controller
} else {
// return view('home')
}
return $check;
}
public function index()
{
return view('admin.home');
}
What I want to do is whenever, AdminController is triggered, run __construct function and check if role == 5, if it is, proceed with the request, else return view. How can that be done?
Edit
public function handle($request, Closure $next)
{
if ($request->role == 2) {
} else {
return view('index');
}
return $next($request);
}
Kernel:
protected $middlewareGroups = [
'admin' => [
\App\Http\Middleware\CheckAdmin::class,
],
];
Route:
Route::group(['middleware' => ['admin']], function () {
Error::
(1/1) FatalThrowableError Call to a member function setCookie() on
null in VerifyCsrfToken.php (line 156)
view() returns a Illuminate\View\View object, instead of a Illuminate\Http\Response. So instead of sending the view. Redirect the user to index route
Try this
public function handle($request, Closure $next)
{
if ($request->role != 2) {
return return redirect()->route('index');
}
return $next($request);
}
So i'm trying to achieve something, that seems is impossible. I want some routes in my application to use different controller based on user role. This is the approach i'm trying, but it doesn't work well. The user routes work, but admin routes return and Trying to get property on non object error in the VerifyCsrfToken.php file*
Route::group(array('middleware' => 'isAdmin'), function() {
Route::get('/', 'Admin\TestController#getIndex');
});
Route::group(array('middleware' => 'isUser'), function() {
Route::get('/', 'User\TestController#getIndex');
});
My middlewares
public function handle($request, Closure $next)
{
if(Auth::user()->isAdmin()) {
return $next($request);
}
}
public function handle($request, Closure $next)
{
if(Auth::user()->isUser()) {
return $next($request);
}
}
I've seen some handle this kind of situation, by just handling this in the controllers or even checking the use role inside the routes file, but I would rather use middlwares, so my routes file would be cleaner
You can do something like this:
Route::get('/', function () {
if (auth()->check()) {
if (auth()->user()->isAdmin()) {
return redirect()->route('');
} elseif (auth()->user()->isUser()) {
return redirect()->route();
} else {
return view('index');
}
}
return redirect()->to('login');
});
The error message has probably nothing to do with the code your show.
But using multiple controllers on one route is impossible, I asked the same question once.
But you could just use one controller and handle the authorization in that controller.
For example:
public function getIndex()
{
if(Auth::user()->isAdmin()) {
//Admin
return $this->getAdminIndex();
} else {
//No admin
return $this->getUserIndex();
}
}
protected function getAdminIndex()
{
return view('admin.index');
}
protected function getUserIndex()
{
return view('user.index');
}
But the cleanest way to do it is to just have 2 routes.