What is best way to have page access restricted to authentication role / permit? I was thinking using Auth::user()->role for detection which will be put into every route section. So, is there any better way or best practice for doing this in Laravel 4?
Thank you.
You may try something like this (use a filter for role checking)
Route::filter('role', function()
{
return Auth::user()->role;
});
Then in your routes, you can use this (role) filter like
Route::get('protectedPage1', array('before'=>'role', function($role) {
if($role != 'admin') {
return Redirect::to('home');
}
}));
Route::get('protectedPage2', array('before'=>'role', function($role) {
if($role != 'admin') {
return Redirect::to('home');
}
}));
Update:
Route::filter('role', function()
{
if(Auth::user()->role != 'admin') {
return Redirect::to('home');
}
});
Route::get('protectedPage1', array('before'=>'role', function() {
// do your job
}));
Related
I am trying to implement 3 user types in to my application, I am using the default Auth of Laravel.
I created 2 extra middlewares to acheive the to extra user(admin & Districtlogin) conditions along with user approval middleware, and using the default for laravel user
Admin middleware
class Admin
{
tion handle($request, Closure $next)
{
if( Auth::check() && Auth::user()->isAdmin == 1)
{
return $next($request);
}
Auth::logout();
return redirect('login')->with('error','You have not admin access');
}
}
Districtlogin Middleware
class Districtlogin
{
public function handle($request, Closure $next)
{
if (Auth::check() && Auth::user()->isAdmin == 2) {
return $next($request);
}
Auth::logout();
return redirect('login')->with('error', 'You have not admin access');
}
}
One additional middleware to check if the user is approved
class ApproveUser
{
public function handle($request, Closure $next)
{
if( Auth::check() && Auth::user()->row_status == 1)
{
return $next($request);
}
return redirect('/userapprove');
}
I am able to redirect them based on the login
Auth/LoginController
public function redirectPath()
{
if (Auth::user()->isAdmin == 1 && Auth::user()->row_status == 1) {
return '/adminindex';
} elseif (Auth::user()->row_status == 0) {
return '/userapprove';
} elseif (Auth::user()->isAdmin == 2 && Auth::user()->row_status == 1) {
return '/districtindex';
}
return '/engineerdashboard';
}
Here is my
kernel.php
entry
'admin' => \App\Http\Middleware\Admin::class,
'districtlogin' => \App\Http\Middleware\Districtlogin::class,
'userapprove' => \App\Http\Middleware\ApproveUser::class,
I would like to group the admin and Districtlogin middleware.
I am using CRUD, I would like Districtlogin to have access to few controllers - index,store,update
When I try to group the middleware, I am redirected back to the login screen. Neither of the middleware works
Here's what I tried,
1)
Route::middleware(['admin'])->group(function () {
//Admin Dashboard
Route::resource('adminindex', 'AdminindexController')->middleware('districtlogin');
Route::get('adminindex/new', 'AdminindexController#admindashboard');
});
2)
Route::middleware(['admin','districtlogin'])->group(function () {
//Admin Dashboard
Route::resource('adminindex', 'AdminindexController');
Route::get('adminindex/new', 'AdminindexController#admindashboard');
});
3)
Route::middleware(['admin',''])->group(function () {
//Admin Dashboard
Route::resource('adminindex', 'AdminindexController');
Route::get('adminindex/new', 'AdminindexController#admindashboard');
Route::middleware(['districtlogin'])->group(function () {
Route::resource('adminindex', 'AdminindexController');
});
});
But when I use the 'OR' condition, I am able to access the pages
Route::group(['middleware' => ['admin' OR 'districtlogin']], function () {
//Admin Dashboard
Route::resource('adminindex', 'AdminindexController');
Route::get('adminindex/new', 'AdminindexController#admindashboard');
});
The controllers are accessible by both the middlewares. But how do I limit the Crud functions based on the middleware.
I am completely clueless on how to achieve it.
The complete answer is:
The two middlewares are incompatible with each other, they have no common ground. Where one succeeds the other fails and redirects to login page.
So this explains the first part of your question.
The second part is that Route::group(['middleware' => ['admin' OR 'districtlogin']] .. is meaningless as regards to configuring middleware. it is equivalent to Route::group(['middleware' => ['admin']].. since the expression 'admin' OR 'districtlogin' always evaluates to first operand. Plus it is misleading as Laravel does not support having middlewares one or the other it is meaningless expression.
The solution:
Either use one middleware that can support both options, for example:
class AdminOrDistrictlogin
{
public function handle($request, Closure $next)
{
if (Auth::check() && Auth::user()->isAdmin >= 1 ) {
return $next($request);
}
Auth::logout();
return redirect('login')->with('error', 'You have not admin access');
}
}
entry:
'adminOrdistrict' => \App\Http\Middleware\AdminOrDistrictlogin::class,
'userapprove' => \App\Http\Middleware\ApproveUser::class,
routes:
Route::middleware(['adminOrdistrict'])->group(function () {
//Admin or District Dashboard, distignuish later in your code
Route::resource('adminindex', 'AdminindexController');
Route::get('adminindex/new', 'AdminindexController#admindashboard');
});
And in your controllers and views refine further by checking Auth::user()->isAdmin value for distinguishing between simple admins or districts
Or, if the functionality is very different between simple admins and districts, create new and different routes for admin and district and use each middleware in the appropriate route group for each type of user.
For example:
Route::middleware(['admin'])->group(function () {
//Admin Dashboard
Route::resource('adminindex', 'AdminindexController');
Route::get('adminindex/new', 'AdminindexController#admindashboard');
});
Route::middleware(['districtlogin'])->group(function () {
//District Dashboard
Route::resource('districtindex', 'DistrictindexController');
Route::get('districtindex/new', 'DistrictindexController#admindashboard');
});
Choice is yours :)
What I've been trying is to have the middleware do different tasks, based on the user's type.
Here is a Route group.
Route::group(array('prefix' => 'api', 'middleware' => 'admin'), function () {
Route::resource('animal', 'AnimalController');
//Other resources
});
My User model has 2 types, which can be accessed by the following way.
$this->user()->user_type_id;
Following this advice, I was trying this task, and the handle function in App\Http\Middleware\Authenticate looks like this right now.
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ((Auth::user()->user_type_id == 2) {
//If the user is of type 2, this will be triggered
if ($request->ajax()) {
return response('You are type 2.', 401);
}
//Maybe there are other libes here
} else if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('auth/login');
}
}
return $next($request);
}
I thought that this would lead the user of type 2 to get response('You are type 2.', 401), when the user visits a URL prefixed by api/animal, but I saw a message Unauthorized. in the response.
Is it possible to have the authentication middleware work in such a way?
Any advice will be appreciated.
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('auth/login');
}
} else if ($this->user()->user_type_id == 2) {
//If the user is of type 2, this will be triggered
return response('You are type 2.', 401);
}
Try this.
I'm having a problem in accessing the Auth::user() in my route.php. So far here's what i've got:
Route::group(['middleware' => 'auth'], function () {
if(Auth::user()->role == "manager"){
Route::get('/','ManagerController#index');
}
else if(Auth::user()->role == "rater"){
Route::get('/','RaterController#index');
}
});
It gives me this error "Trying to get property of non-object" whenever I try to use the Auth::user()->role
Change your code to:
Route::group(['middleware' => 'auth'], function () {
if (Auth::check()) {
if(Auth::user()->role == "manager"){
Route::get('/','ManagerController#index');
}
else if(Auth::user()->role == "rater"){
Route::get('/','RaterController#index');
}
}
});
Because if the current user has not logged in yet, he will not have a role so Auth::user() will return null and thus accessing role property is not possible. You need to check first if the user is logged in by using if (Auth::check()).
P.S. Checking the authentication inside the routes file is such a bad practice and should be handled inside a controller. Hope this helps.
I am trying to create a filter in Laravel so that only admins are allowed to access some URLs.
What I have done is,
Route::filter('admin', function()
{
if (Auth::user()->permission != -1)
{
if (Request::ajax())
{
return Response::make('Unauthorized', 401);
}
else
{
return Redirect::guest('/');
}
}
});
in the app/filters.php file.
But I am getting an eror like this if I try yo access admin's url-
Users table is like this-
Can anyone help please?
This is because Auth::user() is null. Auth::user() is only available when the user is logged in. You will need to do Auth::check() first before calling anything on the intended user model
Route::filter('admin', function()
{
if (!Auth::check() || Auth::user()->permission != -1)
{
if (Request::ajax())
{
return Response::make('Unauthorized', 401);
}
else
{
return Redirect::guest('/');
}
}
});
how can I secure routes so that user can access only those departments that he belongs to?
my current filter:
Route::filter('department', function ($route, $request) {
// Check to see if the current user belongs to the department:
if (!Request::isMethod('post'))
{
if($request->segment(2) != "create")
{
if (!Auth::user()->canAccessDepartment($request->segment(2))) {
// The user shouldn't be allowed to access the department! Redirect them
return Redirect::to('/')->with( 'notice', 'Error!' );;
}
}
}
});
And this is my method in user model
public function canAccessDepartment($department_id) {
$user = Confide::user();
if ($user->departments()->where('department_id', $department_id)->count() < 1)
{
return false;
}
else{ return true; }
}
In the code you have, the filter is applied to all the routes, and then checks to see if we have a matching method/action. My preference would be to only apply the filter when it's needed. So
[Warning - untested code follows]
Route::resource('department', 'DepartmentController',
array('except' => array('create','store', 'update', 'destroy')));
Route::resource('department','DepartmentController',array('only'=>array('create','store', 'update', 'destroy'),'before'=>'departmentFilter'));
Route::filter('department', function ($route, $request) {
// should this be Confide::user() ?
if (!Auth::user()->canAccessDepartment($request->segment(2))) {
// The user shouldn't be allowed to access the department! Redirect them
return Redirect::to('/')->with( 'notice', 'Error!' );
}
});
I think that this should be done in the database/model level. Since the data that you need to compare is in a database, its better if you do this transaction in a database level.