Search code examples
phplaravellaravel-authorization

Why policy always return 403 error with renamed controllers method. Laravel 10


I have a "Meta" model created for this classes - "MetaPolicy" and "MetaController". The policy have registered with the "AuthServiceProvider". I don't use standard naming of controller resource methods. In the controller constructor.

I prescribed the method $this->authorizeResource(Meta::class); and redefined the method under the names of my controller methods, but it didn't help. Policy and still returns error 403.

Model

class Meta extends Model
{
    use HasFactory;

    /**
     * Use timestamps
     *
     * @var bool
     */
    public $timestamps = false;

    /**
     * Name of current table
     *
     * @var string
     */
    protected $table = 'metas';

    /**
     * Primary key
     *
     * @var string
     */
    protected $primaryKey = 'id';
}

Policy code

class MetaPolicy
{

    /**
     * Determine whether the user can view any models.
     */
    public function viewAny(User $user): bool
    {
        return true;
    }

    /**
     * Determine whether the user can view the model.
     */
    public function view(User $user, Meta $meta): bool
    {
        return true;
    }

    /**
     * Determine whether the user can create models.
     */
    public function create(User $user): bool
    {
        return true;
    }

    /**
     * Determine whether the user can update the model.
     */
    public function update(User $user, Meta $meta): bool
    {
        return true;
    }

    /**
     * Determine whether the user can delete the model.
     */
    public function delete(User $user, Meta $meta): bool
    {
        return true;
    }
}

Controller code

class MetaController extends Controller
{
    /**
     * Get the map of resource methods to ability names.
     *
     * @return array
     */
    protected function resourceAbilityMap()
    {
        return [
            'showList' => 'viewAny',
            'showViewForm' => 'view',
            'showCreateForm' => 'create',
            'create' => 'create',
            'showEditForm' => 'update',
            'edit' => 'update',
            'delete' => 'delete',
        ];
    }

    public function __construct()
    {
        $this->authorizeResource(Meta::class);
    }

    public function showList()
    {
        $list = Meta::paginate(5)->withQueryString();

        return view('admin.meta.list', compact('list'));
    }

    public function showCreateForm()
    {
        return view('admin.meta.form');
    }

    public function showEditForm(Request $request, $id)
    {
        $content = Meta::where('id', $id)->first();

        return view('admin.meta.form', compact('content'));
    }

    public function showViewForm(Request $request, $id)
    {
        $content = Meta::where('id', $id)->first();

        return view('admin.meta.view', compact('content'));
    }
}

Solution

  • The solution that helped me was to redefine the method resourceMethodsWithoutModels() of trait Illuminate\Foundation\Auth\Access\AuthorizesRequests. I just added a method with the method names I need to the MetaController.

    protected function resourceMethodsWithoutModels()
    {
      return ['showList', 'showCreateForm', 'create'];
    }
    

    As I understand it, it depends on the naming features of middleware for policy methods that do not accept the model object at the input.