I am trying to manage user roles with Laravel 4, but I can't clearly understand how it works, so I am gonna need some explanations.
This is what I want to do:
If user is guest (not logged in), redirect to route /
If logged user role is equal to student, redirect to student/books
If logged user role is equal to admin, relocate to admin/index
What I want is to filter with slug and user role. The user table has the following columns:
first_name | email | password |role
How can I get to this, btw. I'm a newbee in Laravel so I will need a better explanation.
I assume the steps that I need are:
To create a filter in filters.php
To create route groups in routes.php
I assume that you have store user roles inside session Auth::user()->role
filters.php
Route::filter('isAdmin', function()
{
if (Auth::guest() || Auth::user()->role !== "admin")
{
return Redirect::to('/');
}
elseif(Auth::user()->role == "admin"){
}
});
Route::filter('isStudent', function()
{
if (Auth::guest() || Auth::user()->role !== "student")
{
return Redirect::route('adm_index');
} }
elseif(Auth::user()->role == "student"){
return Redirect::route('std_books');
}
});
routes.php
Route::group(array('before' => 'isStudent'), function()
{
Route::get('student/books',array('as'=>'std_books','uses'=>'BookController#method_name'));
});
Route::group(array('before' => 'isAdmin'), function()
{
Route::get('admin/index',array('as'=>'adm_index','uses'=>'AdminController#method_name'));
});
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 :)
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 have this in my database
|username|password|type|
------------------------
|foo |12345 |1 |
|asd |adsdsd |0 |
Here 1 means that the user is an admin, 0 a normal user.
How can I redirect the admin to the admin page and the normal user to normal user page??
if($attempt)
{
$id = User::find($attempt);
$user = $id->type;
if($user === 0)
{
return Redirect::action('LoginUsersController#profile');
}
else
{
return Redirect::to('adminpage');
}
}
I created this in my UsersController page I don’t know if this is the proper way to do this, and my code is not working.
Are you using normal Laravel Authentication?
You will get Object Auth::user(), this will return current user Object.
It should look like this.
Controller (SessionsController#store)
public function store() {
$input = Input::all();
$attempt = Auth::attempt([
'username' => $input['username'],
'password' => $input['password']
]);
if($attempt) {
if(Auth::user()->type == 1) {
return Redirect::admin(); // If admin, redirect to admin
} else {
return Redirect::profile(); // Else, redirect to user profile
}
}
}
Route
Route::resource('sessions', 'SessionsController', ['only' => ['create','store','destroy']]);
Route::get('admin', 'AdminController#dashboard')->before('adminAuth');
Route::get('profile/{id}', 'UsersController#showProfile')->before('auth');
First of all you have to add a new field in your users table to check against, for example 'rank'. If rank for a user is '1' so he is an Admin,
else he is a normal user.
Then define all required routes in your routes file like this:
Route::get('login', 'adminController#login');
Route::post('login', 'adminController#checkuser');
Route::group(array('before' => 'auth'), function() {
Route::resource('admin', 'adminController');
Route::resource('normaluser', 'normaluserController');
} );
Then in your controller you have to define all actions:
public function login()
{
return View::make('loginview');
}
public function checkuser()
{
if (Auth::attempt(array('username'=>Input::get('username'), 'password'=>Input::get('password'))))
{
$user_data = Auth::getUser();
if ($user_data->rank == 1) //if true, so this user is an admin
{return Redirect::to('admin');} //go to adminController index action
else //if not, so he is a normal user
{return Redirect::to('normaluser');} // go to normaluserController index action
}
else
{
//return 'wrong user name or password';
Session::flash('mismatch', "Username and Password mismatch");
return Redirect::to('login'); // go again to login form to relogin
}
}
if any thing is not clear, don't hesitate to ask.
in the if statement use:
if($attempt)
{
$id = User::find($attempt);
$user = $id->type;
if($user === 0)
{
return Redirect::action('LoginUsersController#profile');
header('Location: http://www.example.com/userpahe.php');
}
else
{
return Redirect::to('adminpage');
header('Location: http://www.example.com/admin-page.php');
}
}
I have 2 types of user :
Admin
Not Admin
Admin will get the full-access, where Not Admin will only get the index.
Here are my routes
Route::get('users','UserController#index');
Route::get('users/create', array('as'=>'users.create', 'uses'=>'UserController#create'));
Route::post('users/store','UserController#store');
Route::get('users/{id}', array('before' =>'profile', 'uses'=>'UserController#show'));
Route::get('users/{id}/edit', 'UserController#edit');
Route::put('users/{id}/update', array('as'=>'users.update', 'uses'=>'UserController#update'));
Route::delete('users/{id}/destroy',array('as'=>'users.destroy', 'uses'=>'UserController#destroy'));
How do I make a restriction so that Admin will get the full-access, where Not Admin will only get the access to index.
Add this to your filters.php
Route::filter('admin', function()
{
if (Auth::user()->type == "Admin") // Change this to match your !
{
if (Request::ajax())
{
return Response::make('Unauthorized', 404);
}
}
else return View::make('error'); // Need to have this view !
});
Then try this on your routes.php
Route::group(array('before'=>'admin'),function() {
//Users
Route::get('users','UserController#index');
Route::get('users/create', array('as'=>'users.create', 'uses'=>'UserController#create'));
Route::post('users/store','UserController#store');
Route::get('users/{id}', array('before' =>'profile', 'uses'=>'UserController#show'));
Route::get('users/{id}/edit', 'UserController#edit');
Route::put('users/{id}/update', array('as'=>'users.update', 'uses'=>'UserController#update'));
Route::delete('users/{id}/destroy',array('as'=>'users.destroy', 'uses'=>'UserController#destroy'));
Repeat for if (Auth::user()->type != "Admin")
You would use a route filter that checks their permission level.
To elaborate on #ceejayoz answer with an example:
/*
* Check if user is logged in
*/
Route::filter('auth', function(){
if(!Auth::check()){
return Redirect::to('login')->with('message', 'You must be logged in');
}
});
/*
* Check if the logged in users group name is 'admin'
*/
Route::filter('admin', function(){
if(Auth::user()->group->name != 'admin'){
return Redirect::to('home')->with('message', 'You do not have access to this');
}
});
//Users must be logged in to access these routes
Route::group(array('before'=>'auth'), function(){
Route::get('users','UserController#index');
//Users must be an administrator to access these routes
Route::group(array('before'=>'admin'), function(){
Route::get('users/create', array('as'=>'users.create', 'uses'=>'UserController#create'));
Route::post('users/store','UserController#store');
Route::get('users/{id}', array('before' =>'profile', 'uses'=>'UserController#show'));
Route::get('users/{id}/edit', 'UserController#edit');
Route::put('users/{id}/update', array('as'=>'users.update', 'uses'=>'UserController#update'));
Route::delete('users/{id}/destroy',array('as'=>'users.destroy', 'uses'=>'UserController#destroy'));
});
});
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
}));