I’m creating a policy for model todo to authorize the user role and then set custom access for model functions like create()
, update()
, etc. As written in Laravel Documentation, we can create a policy for the todo model with php artisan make:policy todoPolicy --model=todo
.
When we use modelname + Policy for our policy name that is located in AppPolicies folder, Laravel automatically register them for the model, as we used todoPolicy for todo Model.
Also, to check if this Policy works or not, I had set return true;
for the create()
function in the todoPolicy file, and I’m calling $this->authorize('create,' todo::class);
in add function of component for testing it.
But it always returns 403, not an authorized page. What’s the problem with my code?
Component / Controller
namespace AppLivewireElementsTodolist;
use LivewireComponent;
use AppModelstodo;
class Todolist extends Component
{
public $description;
public function done($id) {
sleep(0.5);
todo::where('id',$id)->first()->update([
'is_done' => true,
]);
}
public function restore($id) {
sleep(0.5);
todo::where('id',$id)->first()->update([
'is_done' => false,
]);
}
public function delete($id) {
sleep(0.5);
todo::where('id',$id)->first()->delete();
}
public function add(todo $todo) {
$this->authorize('create',$todo);
$this->validate([
'description' => ['required','max:128'],
]);
sleep(0.5);
todo::create([
'user_id' => session('user_id'),
'description' => $this->description,
]);
$this->reset();
}
public function render()
{
return view('livewire.elements.todolist.todolist',[
'todos' => todo::orderBy('is_done','ASC')->orderBy('created_at','DESC')->get(),
]);
}
}
TodoPolicy
namespace AppPolicies;
use AppModelsUser;
use AppModelstodo;
use IlluminateAuthAccessResponse;
class todoPolicy
{
/**
* Determine whether the user can view any models.
*/
public function viewAny(User $user): bool
{
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, todo $todo): bool
{
}
/**
* 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, todo $todo): bool
{
//
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, todo $todo): bool
{
//
}
/**
* Determine whether the user can restore the model.
*/
public function restore(User $user, todo $todo): bool
{
//
}
/**
* Determine whether the user can permanently delete the model.
*/
public function forceDelete(User $user, todo $todo): bool
{
//
}
}
I have tried registering policies manually, but it didn’t change anything.
2
Answers
The problem was that when we want to
return true;
a policy function without passing models to it, we should make the model optional like this:It's so Important specially when you don't use Laravel Authentication System.
It took me a while to find it but after diging in the laravael pacakge I found out that policies must be inside the models folder.
So the namespace for your policy class should be
namespace AppModelsPolicies;