How to check if user has permission to access this function in Laravel

22,760

Solution 1

With Laravel you can use a gate for this.

In you App\Providers\AuthServiceProvider file do something like this:

public function boot()
{
    $this->registerPolicies();

    Gate::define('do-everything', function ($user) {
        return $user->hasPermission('do-everything');
    });

    Gate::define('do-one-thing', function ($user) {
        return $user->hasPermission('do-one-thing');
    });
}

And then in your controller:

if (Auth::user()->can('do-everything')) {
    // the user can do everything
}

if (Auth::user()->can('do-one-thing')) {
    // the user can just do one thing
}

or

if (!Auth::user()->can('do-everything')) {
    abort(403);
}
// user has permission to the everything from here on

or in your routes/web.php you could do this:

Route::get('/things', 'ThingController@action')->middleware(['can:do-one-thing']);

or you can group the routes like this:

Route::middleware(['can:do-everything'])->group(function () {
    Route::get('/things', 'ThingController@index');
    Route::get('/other-things', 'OtherThingController@index');
    ...
}

You can also look at https://laravel.com/docs/5.7/authorization for more ideas.

Solution 2

Your helper function returns a new response but it returns it to the controller not as HTTP response, so You can get the returned value like this:

public function index()
    {
        // PERMISSIONS CHECK
        $response = userHasPermission('users show active');


        $getUsers = $this -> users -> getAllActive();
        return Response::json($getUsers);
    }

So what you need is to check the response if it has a value but with this approach you are going to have the same problem as your first one.

To solve it: throw exception from the helper function instead of returning some response.

A better solution is to use FormRequest, check this link to do it, be sure to check "Authorizing Form Requests" section which states the authorize function.

EDIT:

what you have to do is the following:

create new class let's call it "IndexRequest" that inherits from "FormRequest" class, then implement authorize method.

so something like this:

class IndexRequest extends FormRequest
{
      /**
      * Determine if the user is authorized to make this request.
      *
      * @return bool
      */
      public function authorize()
      {
          return Auth::user() -> hasPermissionTo('show all users');
      }

          /**
      * Get the validation rules that apply to the request.
      *
      * @return array
      */
     public function rules()
     {
         return [
         ];
     }
 }

then in your method:

public function index(IndexRequest $request)
{
   $getUsers = $this -> users -> getAllActive();
   return Response::json($getUsers);
}

you don't have to check it manually, Laravel will do it for you using "authorize" function of IndexRequest class.

Share:
22,760

Related videos on Youtube

Ahmed essam
Author by

Ahmed essam

Updated on January 24, 2022

Comments

  • Ahmed essam
    Ahmed essam over 2 years

    I have a function that check if the user has permission or not and it return Boolean.

    Question is

    How I check in each function user has permission or not. For example in users controller I have 2 functions:

    1. index(): show all users
    2. delete($id): delete a single user

    index():

    public function index () {
        if(Auth::user() -> hasPermissionTo('show all users')) {
            // continue for API
        } else {
            // response with error for API
        }
    }
    

    I know that there is a better way to do that because I don't want to repeat this if statement in all my functions.

    What I have tried to do:

    I have tried to create a helper function that check if user has permission and return the response error if the user doesn't have permission. And call it in every function but it didn't work.

    Helper function code:

    if(!function_exists('userHasPermission')) {
        function userHasPermission ($permission) {
            $main_permission = 'do everything';
            if (!Auth::user() -> hasPermissionTo($main_permission) || !Auth::user() -> hasPermissionTo($permission)) {
                $res = trans('api_responses.authorization_failed');
                return Response::json([
                    'message'   =>  $res['message'],
                    'code'      =>  $res['code']
                ], $res['code']);
            }
        }
    }
    

    index function call

    public function index()
        {
            // PERMISSIONS CHECK
            userHasPermission('users show active');
            $getUsers = $this -> users -> getAllActive();
            return Response::json($getUsers);
        }
    

    But it never returns the error response even if the user doesn't have permission and even it entered the if statement in my helper!

    • ceejayoz
      ceejayoz over 5 years
    • Ahmed essam
      Ahmed essam over 5 years
      @ceejayoz Yea I have read it but my problem is that I don't want to check if else in every function in my controllers
  • Ahmed essam
    Ahmed essam over 5 years
    My problem is that I don't want to make this if else statement in every controller that's why I am searching for a better method.
  • Ahmed essam
    Ahmed essam over 5 years
    I already made that and I can use can('do-everything') but I will do the same if statement every controller function
  • Ahmed essam
    Ahmed essam over 5 years
    The problem is that I don't want to make this if statement in each function in each controller
  • Peter
    Peter over 5 years
    @Ahmedessam You can also put this in your routes to keep it out of your controllers. See update in my answer.
  • Ahmed Nour Jamal El-Din
    Ahmed Nour Jamal El-Din over 5 years
    you must check the link I provided in my answer! I think you have to add "FormRequest", please read the documentation!
  • Ahmed essam
    Ahmed essam over 5 years
    Yea Middleware is the best solution for me.. thanks a lot.. please upvote my question it may help others.
  • Ahmed essam
    Ahmed essam over 5 years
    Yea Middleware is the best solution for me.. thanks a lot.. please upvote my question it may help others.