Search code examples
laravelpermissionspolicy

Laravel - Policy custom messages on not authorized not working as expected


So basically I am trying to do a custom deny message when the user is not authorized to do a action like delete/destroy a user. I can't seem to customize the message, I always get the default one saying:

Error
Request failed with status code 403

In my example I have a UserPolicy and the contents of the destroy method here is this:

public function delete(User $user, User $model)
{
    $totalAdmins = User::whereHas('roles', function ($query) {
        $query->where('name', 'administrator');
    })->count();

    // If there is only one administrator, then the user cannot delete it
    if ($totalAdmins === 1 && $model->hasRole('administrator')) {
        return Response::deny('You cannot delete the only administrator.');
    }

    // Admins cannot delete other admins
    if ($user->hasRole('administrator') && $model->hasRole('administrator')) {
        return Response::deny('You cannot delete other administrators.');
    }

    // Only users with the 'delete users' permission can delete users
    if (!$user->hasPermissionTo('delete users')) {
        return Response::deny('You do not have permission to delete users.');
    }

    return Response::allow();
}

I also tried the Gate::inspect(...) way, but I always end up with the same default message.

Don't know if this information is needed, but the alert/notification is done by axios catch method.

this.$axios.delete(url, {
    headers: {
        'Accept': 'application/json',
    },
}).then(response => {
    /* ... */
}).catch(response => {
    this.$swal.fire({
        title: 'Error',
        text: response.message,
        icon: 'error',
        timer: 3000,
        showConfirmButton: false,
        toast: true,
        timerProgressBar: true,
        hideClass: {
            popup: 'animate__animated animate__fadeOutUp',
        },
        showClass: {
            popup: 'animate__animated animate__fadeInDown',
        },
        position: 'top-end'
    });
});

And lastly this is how I do it in the controller to authorize:

$this->authorize('delete', $user);

Am I doing something wrong here or missing something?

Edit: the whole destroy() method from my UserController

public function destroy($user)
{
    # Put users to array
    $users = explode(',', $user);

    foreach($users as $user) {
        # Find each user
        $user = User::findOrFail($user);

        # Authorize
        $this->authorize('delete', $user);

        # Delete user
        $user->delete();
    }

    return response()->json([
        'success' => true,
        'message' => 'User deleted!'
    ]);
}

Solution

  • Fixed it by using error.response.data.message instead of response.message in the axios catch method.