pgogy's avatar

Trying to understand policies

Hello, trying to use policies properly and I'm following the guidance (https://laravel.com/docs/12.x/authorization) but it's not working for me. I'm new, and I'm guessing I've missed something big.

So I have a File model, and I want users to be able to see only their own files. I have a FilePolicy in app\Policies so it should auto register. I have seen examples using AuthServiceProvider, but that seems to be laravel 11?

I have the Show function in the File controller

public function show(File $file) { Gate::authorize('view', $file);

if(Request()->user()->can("view", $file)){

I know the above code doesn't need authorize and user->can, but neither seem to call the view function on the policy. They are calling something that returns true (debug at shows one gate)

Any pointers?

1 like
14 replies
Glukinho's avatar

Sorry, I don't understand what is your problem. Can you describe more? What exactly doesn't work as you expect?

1 like
pgogy's avatar

I am expecting if I call user->can(‘view’) that the policy view function would be called for the relevant model

1 like
Glukinho's avatar

Why do you think it is not called? Can you show policy class?

1 like
pgogy's avatar

I have a dd in every policy class function. Will post the class in a second post

1 like
pgogy's avatar

Yes, but it should show the message it is set with?

1 like
pgogy's avatar

And the code keeps going - it gets a true from somewhere else

1 like
pgogy's avatar

I had, but removed that function, and when it was there it would have returned false in this case

(And I put a dd() in there as well)

1 like
Snapey's avatar

make sure you use request() and not Request() and make sure references to File use your model and not a framework class of the same name.

Run composer dump and check there are no warnings.

Posting your policy file would help.

1 like
pgogy's avatar

This is my policy

<?php

namespace App\Policies;

use Illuminate\Auth\Access\Response;
use App\Models\User;
use App\Models\File;
use Illuminate\Auth\Access\HandlesAuthorization;

class FilePolicy
{

    public function create(User $user): bool
    {
        return true;
    }

}

Model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class File extends Model
{
    /** @use HasFactory<\Database\Factories\FileFactory> */
    use HasFactory;

    protected $table = "file";
    protected $guarded = [];

    public function Application() {
        return $this->belongsTo( \App\Models\Application::class );
    }
}

In my controller

dd(request()->user()->can("create", File::class), request()->user()->can("create"));

The above returns true and then false The first request->user->can now shows what is in FilePolicy, but the second does not.

I assume if I fail to pass a parameter referencing the model to user can, it refers to some default policy. So I should pass a second parameter to make sure it calls the correct policy?

1 like
Glukinho's avatar

If you don't have specific model you should use can("create", File::class) (with model class name) to check for policy. Specifying model name is the only way to tell Laravel which policy you need (you can have multiple policies with "create" method, can't you?)

You say it returns true (as it should be, you have return true in your policy), so what is your problem?

Will it change to false if you change your policy to return false;?

1 like
pgogy's avatar

No problem, I just assumed Can knew which policy I wanted to apply and not that I needed to tell it

1 like
Snapey's avatar

how?

and pay attention to standards in php. function names should start with lowercase.

1 like
pgogy's avatar

via some sort of stack trace I guess, anyways, problem solved now

1 like

Please or to participate in this conversation.