mahmoud mohamed
mahmoud mohamed

Reputation: 25

Laravel 8 Policy Always returns "This action is unauthorized."

I am trying to create a policy for user permissions, so I retrieve user permissions from DB and check his ability to do this action or not, but the policy always return 403:

CategoryController

I have a store method like this

    public function store(Request $request)
{
    $user = auth('sanctum')->user();
    if (!$user) {
        return $this->ApiResponse(401,null,'Can not do this action without login, Login and tray again',);
    }

    $ability = "create-category";
    $this->authorize('can',[$user,Category::class,$ability]);

    $request->validate( [
        'name' => 'required|unique:categories',
        'parent_id' => 'nullable|integer|exists:categories,id',
        ]);

    try {
        $project = Category::create($request->all());
        return $this->ApiResponse(Response::HTTP_CREATED, "category created successfully",null, $project);
    }catch (Exception $e) {
        return $this->ApiResponse(500, 'category can\'t be created try later');
    }
}

CategoryPolicy

I have can method like this

public function can (User $user,Category $category,string $ability)
{
    $role = Role::with('permissions')->find($user->role_id);
    $permissions = $role->permissions;

    for ($i=0; $i<count($permissions); $i++) {
        $userPermissions[$i] = $permissions[$i]['name'];
    }
    if (in_array($ability, $userPermissions)) {
        return true;
    }
    return false;
}

AuthServiceProvider

 protected $policies = [
    Category::class => CategoryPolicy::class,

];

so what is the problem??

Upvotes: 0

Views: 2335

Answers (1)

tanerkay
tanerkay

Reputation: 3930

I think you've just mixed up some parameters

Instead of

$this->authorize('can',[$user,Category::class,$ability]);

You probably want

$this->authorize('create-category', Category::class);

or, if you don't want to specify sanctum as the guard by way of Auth::shouldUse() for example, you can use the following:

$this->authorizeForUser(auth('sanctum')->user(), 'create-category', Category::class);

and in your policy, you can simplify the arguments to:

public function createCategory(User $user, Category $category)

If you need to make any checks against the $ability value, you can use policy filters:


class CategoryPolicy
{
    /**
     * Perform pre-authorization checks.
     *
     * @param  \App\Models\User  $user
     * @param  string  $ability
     * @return void|bool
     */
    public function before(User $user, $ability)
    {
        if ($user->permissions->where('name', $ability)->isEmpty()) {
            return false;
        }
    }

    // ...

Upvotes: 1

Related Questions