'Laravel authorization policy not working on Show page

I have a laravel app using Policies to assign roles and permissions, i cant seem to access the show page and im not sure what im doing wrong? If i set return true it still shows a 403 error as well, so im unsure where im going wrong here. The index page is accessable but the show page is not?

UserPolicy

public function viewAny(User $user)
{
    if ($user->isSuperAdmin() || $user->hasPermissionTo(44, 'web')) {
        return true;
    }
    return false;
}

public function view(User $user, User $model)
{
    if ($user->isSuperAdmin() || $user->hasPermissionTo(44, 'web')) {
        return true;
    }
    return false;
}

UserController

public function __construct()
{
    $this->authorizeResource(User::class, 'user');

}

public function index()
{
    $page_title = 'Users';
    $page_description = 'User Profiles';
    $users = User::all();

    return view('pages.users.users.index', compact('page_title', 'page_description', 'users'));
}

public function create()
{
    //
}

public function store(Request $request)
{
    //
}

public function show($id)
{
    $user = User::findOrFail($id);
    $user_roles = $user->getRoleNames()->toArray();


    return view('pages.users.users.show', compact('user', 'user_roles'));
}


Solution 1:[1]

Base on Authorize Resource and Resource Controller documentation.

You should run php artisan make:policy UserPolicy --model=User. This allows the policy to navigate within the model.

When you use the authorizeResource() function you should implement your condition in the middleware like:

// For Index
Route::get('/users', [UserController::class, 'index'])->middleware('can:viewAny,user');

// For View
Route::get('/users/{user}', [UserController::class, 'view'])->middleware('can:view,user');

or you can also use one policy for both view and index on your controller.

Solution 2:[2]

I had an issue with authorizeResource function. I stuck on failed auth policy error:

This action is unauthorized.

The problem was that I named controller resource/request param with different name than its model class name.

F. ex. my model class name is Acknowledge , but I named param as timelineAcknowledge

Laravel writes in its documentation that

The authorizeResource method accepts the model's class name as its first argument, and the name of the route / request parameter that will contain the model's ID as its second argument

So the second argument had to be request parameter name.

// Here request param name is timelineAcknowledge
public function show(Acknowledge $timelineAcknowledge)
{
    return $timelineAcknowledge->toArray();
}

// So I used this naming here also
public function __construct()
{
    $this->authorizeResource(Acknowledge::class, 'timelineAcknowledge');
}

Solution was to name request param to the same name as its model class name.

Fixed code example

// I changed param name to the same as its model name
public function show(Acknowledge $acknowledge)
{
    return $acknowledge->toArray();
}

// Changed here also
public function __construct()
{
    $this->authorizeResource(Acknowledge::class, 'acknowledge');
}

I looked over Laravel policy auth code and I saw that the code actually expects the name to be as the model class name, but I couldn't find it anywhere mentioned in Laravel docs.

Of course in most of the cases request param name is the same as model class name, but I had a different case.

Hope it might help for someone.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Doggo
Solution 2 Redas JaruĊĦaitis