Goal: I want to make route filter in Laravel 4 using Route::group
and Route::filter
Description
I have 2 types of user :
- Internal
- Distributor
For, Internal
, I have 2 groups:
For Distributor
, I have 4 groups:
Eligible Route
OEM Distributor are eligible for only 5 routes.
Route::get('distributors/{id}', array('before' =>'profile', 'uses'=>'DistributorController@show'));
Route::get('distributors/{id}/edit', 'DistributorController@edit');
Route::put('distributors/{id}/update', array('as'=>'distributors.update', 'uses'=>'DistributorController@update'));
Route::get('catalog_downloads','CatalogDownloadController@index');
Route::get('catalog_downloads/{id}/download','CatalogDownloadController@file_download');
Regular Distributor are eligible for 8 routes.
Route::get('distributors/{id}', array('before' =>'profile', 'uses'=>'DistributorController@show'));
Route::get('distributors/{id}/edit', 'DistributorController@edit');
Route::put('distributors/{id}/update', array('as'=>'distributors.update', 'uses'=>'DistributorController@update'));
Route::get('catalog_downloads','CatalogDownloadController@index');
Route::get('catalog_downloads/{id}/download','CatalogDownloadController@file_download');
Route::get('marketing_materials','MarketingMaterialController@index');
Route::get('marketing_materials/{id}/download/thumb_path','MarketingMaterialController@thumb_download');
Route::get('marketing_materials/{id}/download/media_path','MarketingMaterialController@media_download');
Code
Questions
- Can someone please help me or at least direct me to the right direction ?
According to your situation ...
I suggest:
- check your
Auth::user()->type
right in your routes.php
- Don't forget to check Auth::check() before checking the user type condition
- Do it for OEM and repeat the same logic for non OEM.
Here is the code - please modify to fit your exact needs.
<?
// OEM Routes
if(Auth::check()){
if ( (Auth::user()->type == "Distributor") AND (Auth::user()->distributor()->first()->type == 'OEM') ){
Route::group(array('before'=>'auth'),function() {
Route::group(array('before'=>'csrf'), function(){
// Other important routes like sign-out, dashboard, or change password should also listed here
Route::get('/account/sign-out',array('as'=>'account-sign-out','uses'=>'AccountController@getSignOut' ));
Route::get('/dashboard', array('as' =>'dashboard','uses'=>'HomeController@dashboard'));
// Allow routes
Route::get('distributors/{id}', array('uses'=>'DistributorController@show'));
Route::get('distributors/{id}/edit', 'DistributorController@edit');
Route::put('distributors/{id}/update', array('as'=>'distributors.update', 'uses'=>'DistributorController@update'));
Route::get('catalog_downloads','CatalogDownloadController@index');
Route::get('catalog_downloads/{id}/download','CatalogDownloadController@file_download');
});
}
}else{
return Redirect::route('home'); // I assume you have this declare somewhere
}
// Not OEM Routes
if(Auth::check()){
if ( (Auth::user()->type == "Distributor") AND (Auth::user()->distributor()->first()->type !== 'OEM') ){
Route::group(array('before'=>'auth'),function() {
Route::group(array('before'=>'csrf'), function(){
// Other important routes like sign-out, dashboard, or change password should also listed here
Route::get('/account/sign-out',array('as'=>'account-sign-out','uses'=>'AccountController@getSignOut' ));
Route::get('/dashboard', array('as' =>'dashboard','uses'=>'HomeController@dashboard'));
// Allow routes
Route::get('marketing_materials','MarketingMaterialController@index');
Route::get('marketing_materials/{id}/download/thumb_path','MarketingMaterialController@thumb_download');
Route::get('marketing_materials/{id}/download/media_path','MarketingMaterialController@media_download');
Route::get('distributors/{id}', array('uses'=>'DistributorController@show'));
Route::get('distributors/{id}/edit', 'DistributorController@edit');
Route::put('distributors/{id}/update', array('as'=>'distributors.update', 'uses'=>'DistributorController@update'));
Route::get('catalog_downloads','CatalogDownloadController@index');
Route::get('catalog_downloads/{id}/download','CatalogDownloadController@file_download');
});
}
}else{
return Redirect::route('home'); // I assume you have this declare somewhere
}
As you ask, I show you another aproach to the problem. I think it's more flexible and maintainable.
My final target it's get that kind of routes:
Route::group(['before' => 'acl.permitted'], function() {
Route::get('/something', ['as' => 'some_route_alias', 'uses' => 'SomeController@someMethod']);
Route::get('/something_else', ['as' => 'another_route_alias', 'uses' => 'AnotherController@anotherMethod']);
...
});
So that you acl.permitted
filter checks if the user is allowed to access to some route. Let's take a look to the filter.
class AclPermissionFilter {
public function filter ($route, $request) {
$user = Auth::user();
if ($user){
// Maybe add a superuser break
$user->load('groups', 'groups.permissions');
$permission = AclPermissions::where('route_alias', $route->getName())->get()->first();
foreach ($user->groups as $group) {
$pass = $group->permissions->contains($permission);
if ($pass) break;
}
} else {
// Maybe check for public scopes
}
return $pass;
}
}
Now we can declare the filter. For example in the filter file:
Route::filter('acl.permitted', 'AclPermittedFilter');
Then we need the User->Group->Permission hierarchy.
Class User {
...
public function groups() {
return $this-->belongstoMany('AclGroup','acl_user_groups','user_id','group_id');
}
}
Class AclGroups {
...
// Add here the attributes that you want. i.e: name, description,...
...
public function users() {
return $this->belongsToMany('User', 'acl_user_groups');
}
public function permissions() {
return $this->belongsToMany('AclPermission', 'acl_group_permissions');
}
}
Class AclPermissions {
...
// Add here the attributes that you want. i.e: route_alias, description,...
...
public function groups() {
return $this->belongsToMany('AclGroup', 'acl_group_permissions');
}
public function getKey() {
return $this->attributes['route_alias'];
}
}
Then you can seed the permissions table with all the route alias with that.
class AclTableSeeder extends Seeder {
public function run(){
foreach (Route::getRoutes() as $route){
$action = $route->getAction();
if (isset($action['as'])){
AclPermissions::create(['route_alias' => $action['as']]);
}
}
}
}
Finally you need to create your groups ('Internal' and 'Distributor' in your case) and atach them to the appropiate permissions. If you don't want to create the users-group-permissions maintenance then you can do it in a seed file.
The main advantaje of this solution is that you don't have to harcoded the permission's logic, and it's a more global solution. On the other hand you'd probably need to create the group-permissions maintenance admin page sometime in the future.
I hope it may help you.