laravelpolicy

Laravel policy does not authorize action


In my Laravel application, I have several policies working, but one will not work.

Controller

    public function store(Project $project, CreateActionRequest $request)
{
    $this->authorize('store',  $project);

    Action::create([
        'name' => $request->name,
    ]);

    return redirect()->route('projects.show', $project->id)->withSuccess('Massnahme erfolgreich gespeichert');
}

Policy

namespace App\Policies\Project;
use App\Models\Project\Project;
use App\Models\User;
use App\Models\Project\Action;
use Illuminate\Auth\Access\HandlesAuthorization;
class ActionPolicy
{
use HandlesAuthorization;

public function store(User $user, Project $project)
{
    return $user->company_id === $project->company_id;
}
}

AuthServiceProvider

    protected $policies = [
    'App\Models\User' => 'App\Policies\CompanyAdmin\UserPolicy',
    'App\Models\Company' => 'App\Policies\CompanyAdmin\CompanyPolicy',
    'App\Models\Team' => 'App\Policies\CompanyAdmin\TeamPolicy',
    'App\Models\Department' => 'App\Policies\CompanyAdmin\DepartmentPolicy',
    'App\Models\Location' => 'App\Policies\CompanyAdmin\LocationPolicy',
    'App\Models\Division' => 'App\Policies\CompanyAdmin\DivisionPolicy',
    'App\Models\Costcenter' => 'App\Policies\CompanyAdmin\CostcenterPolicy',
    'App\Models\Workplace' => 'App\Policies\CompanyAdmin\WorkplacePolicy',
    'App\Models\Product' => 'App\Policies\CompanyAdmin\ProductPolicy',
    'App\Models\Project\Action' => 'App\Policies\Project\ActionPolicy',
    'App\Models\Project\Project' => 'App\Policies\Project\ProjectPolicy',
];

CreateActionRequest

namespace App\Http\Requests\Project;

use Illuminate\Foundation\Http\FormRequest;

class CreateActionRequest extends FormRequest
{

public function authorize()
{
    return true;
}


public function rules()
{
    return [
        'name' => 'required|min:3',
    ];
}
}

All policies are working except ActionPolicy and ProjectPolicy. I added in the policy a __construct() method to check if the policy is called. But ActionPolicy and ProjectPolicy are not working. How can I search the error? I tried with dd() but I always got the message:

This action is unauthorized


Solution

  • Since you are injecting CreateActionRequest instead of Request that means you are defining your own set of rules to authorize the FormRequest which comes inside of your method. Further it means that you gotta define a few rules which the "FormRequest" has to pass in order to EVEN reach your controller, this is a nice concept that I like about Laravel since the code is not centralized, but rather spread and every layer has it's own responsibility. Now, you don't have to call any method from your CreateActionRequest nor you have to write any code regarding that class in your controller, because Laravel runs authorize method by default before allowing the Request to reach your controller, before running authorizemethod in your CreateActionRequest it runs rules method which verifies that all the given fields pass the expressions you assigned them, so the execution is something like this CreateActionRequest => rules => authorize => IF(authorized) Controller ELSE Not authorized, hope that makes sense. In order to fix your code:

    1.) Remove $this->authorize('store', $project);

    This will allow you to pass not authorized error in case your name passes the truth test inside of rules method inside of your CreateActionRequest. If you wish to utilize your Action Policy you will need to hook up your custom Request(CreateActionRequest) with it and this is how:

    public function authorize()
    {
        $store = $this->route('project');
        //The above line will return Project object if your mapping is correct
        //If it's not it will return the value you passed to your route for {project}
        return $this->user() && $this->user()->can('store', $store);
    }
    

    EDIT:

    Here is the link where you can see how to properly authorize and connect policy with CreateActionRequest