phpuint Illuminate\Auth\Access\AuthorizationException: This action is unauthorized

1k Views Asked by At

I have index method in controller like this

 public function index()
{
     $this->authorize('index', Contact::class);
  ....
}

and index method in ContactPolicy

public function index()
{
    return Auth::user()->can('view_Contact');
}

and test method like this

/** @test */
public function a_user_without_permission_can_not_see_contacts()
{
    $this->login(['no_permission']);
    $this->get('/contacts')
        ->assertStatus(403);
}

When I run my test show me this error

1) Tests\Feature\AccountTest::a_user_without_permission_can_not_see_contacts Illuminate\Auth\Access\AuthorizationException: This action is unauthorized.

Note1: When I change My controller to this it work correctly and show me green

public function index()
{
    if(Auth::user()->can('view_Contact')){
      ........
    }else
    return response()->view('403',['msg' => 'you_not_have_not_permission'])->setStatusCode(403) ;

Note2:
In login method in test class I send user permissions parameters and it work correctly.

1

There are 1 best solutions below

0
On

the authorize method throws an exception if the user is not authorized. you need to use @expectesException or similar methods to signal your test to expect an exception.

Or, you can add a condition to your Handler class to catch this kind of exception and return a 403 response


edit: more explanation

when you call authorize method and the user does not have permission, the program throws an exception. when a user is calling the api, the exception is translated to a response with 403 status and shown to the user, but when you are calling the api from within the program itself, the exception is thrown and the program halts, hence there would be no JSON response whatsoever. To handle this situation, you have two options:

1- if you decide not to change your program, then instead of expecting a response with a specific status, you should tell your test to expect an AuthorizationException thrown. you can read how to do this hear

2- you can change your code so that instead of delegating the task of handling the exception to Laravel, you do it yourself in the Handler class and prepare a JSON response with 403 status and then your test should be run correctly.