How to apply multiple filters on route group in La

2019-02-21 04:25发布

Goal: I want to make route filter in Laravel 4 using Route::group and Route::filter


Description

I have 2 types of user :

  1. Internal
  2. Distributor

For, Internal, I have 2 groups:

  • admin
  • regular

For Distributor, I have 4 groups:

  • gold
  • silver
  • bronze
  • oem

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 ?

2条回答
劫难
2楼-- · 2019-02-21 04:59

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.

查看更多
手持菜刀,她持情操
3楼-- · 2019-02-21 05:16

According to your situation ...

I suggest:

  1. check your Auth::user()->type right in your routes.php
  2. Don't forget to check Auth::check() before checking the user type condition
  3. 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
}
查看更多
登录 后发表回答