Laravel : Setting dynamic routes based on access control list

狂风中的少年 提交于 2019-12-02 20:59:10

The best idea was using middleware parameter create Middleware call CheckPermission then you have to register that middleware into your app/Http/kernel.php file thats only you need check below code

Your kernel.php file

protected $routeMiddleware = [    
        'checkPermission' => \App\Http\Middleware\CheckPermission::class,
    ];

CheckPermission.php

    <?php

    namespace App\Http\Middleware;
    use Closure;
    use DB;

    class CheckPermission
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next,$permission_name)
        {
            //first check that name in your db
            $permission = DB::table('Permission')->where('name',$permission_name)->first()
            if($permission){
              //here you have to get logged in user role
              $role_id = Auth::user()->role;
              ## so now check permission
              $check_permission = DB::table('Permission_role')->where('role_id',$role_id)->where('permission_id',$permission->id)->first();
              if($check_permission){
                 return $next($request);
              }
              //if Permission not assigned for this user role show what you need
            }
            // if Permission name not in table then do what you need 
            ## Ex1 : return 'Permission not in Database';
            ## Ex2 : return redirect()->back();

        }
    }

Your Route file

 Route::group(['middleware' => 'jwt.auth'], function() {
        Route::post('classResult', 'ApiController@getClassResult')->middleware('checkPermission:view-class-result');
        Route::post('studentResult', 'ApiController@studentResult')->middleware('checkPermission:view-student-result');
        Route::post('getStudentExamResult', 'ApiController@downloadSchoolTemplate')->middleware('checkPermission:download-student-result');

   }

So what you can do is make your role name accountants a value to key in the .env file and same for each and every role name.

In case you want to change it in near future you can change it manually in the .env file or you can make changes in the .env file via php code writtern on one of your Laravel function.

While I doubt that this is the best approach to this, but in your way of thinking you could try out this "pseudo code". I hope this expresses the basic idea. What that implies is:

  • A route pattern, not to include all routes explicitely in your routes file. ie. api/studentResult
  • Your controller to dispatch to the proper method that implements your api call via a single action controller (Link to documentation)
  • Your controller to load the correct middleware to take care on authorization

Routes

Route::group(['middleware' => 'jwt.auth'], function() {
    Route::get('user', 'ApiController@getAuthUser');
    Route::get('invalidate', 'ApiController@invalidate');

    // Choose whatever pattern you like...
    Route::post('api/{name}', ApiController::class);
});

Controller

class ApiController {

    public function __construct() {
        $permisions = $this->loadPersionForUser();

        $this->middleware('ability', [$permisions->value1, 'whatever']);
    }

    public function __invoke($method) {
        if (method_exists($this, $method)) {
            return $this->$method();
        }
    }
}

I'm not totally sure if you can load your middleware dynamically like this. If so, this could be a valid approach for this.

In your routes.php

Route::group(['middleware' => 'jwt.auth'], function() {

Route::post('{uri}', 'AccessController@redirectURI');

});

Add this route at the end of all your routes.

Now create a new controller called AccessController and add the below constructor and method to it. Assuming user has a relationship with roles.

public function __construct(Request $request)
{
    $authorised_user = User::where('id', Auth::User()->id)->whereHas('role', function($query) use ($request)
            {
                $query->whereHas('permission', function($query) use ($request)
                {
                    $query->where('routes', $request->route('uri'))
                });
            })->firstOrFail();

            if( $authorised_user )
            {
                $permission = Permission::where('routes', $request->route('uri'))->findOrFail();

                $this->middleware([ 'ability:'.$authorised_user->role()->name.','.$permission->name.',true' ]);
            }
    else
    {
    // user is not authorised. Do what ever you want
    }

}

public function redirectURI($uri)
{
    $permission = Permission::where('routes', $uri)->findOrFail();

    return app('App\\Http\\Controllers\\'. $permission->controller )->$permission->method();
}

Overall it is retrieving the URL and comparing it against available routes in the authenticated user's permissions. If the authenticated user has the permission which the route belongs to, Then adding appropriate middleware.

Finally the redirectURI method is calling the appropriate controller method and returning the response.

Remember to replace the code with appropriate namespace and relations where ever necessary.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!