Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom message on Laravel policy authorization

In my Laravel 5.8 project I am implementing a reputation system similar to Stack Exchange's one: for example, users can reply to a discussion only if they have "Level 3" reputation.

I wanted to use Laravel's policies system to build the permissions logic like so in my DiscussionPolicy file:

public function reply(User $user)
{
    $result = true;
    if ($user->current_level < 3) {
        $result = false;
        //I want to inject a custom error message here
    }
    return $result;
}

Everything works, but users get a 403 page without any explanation, and I wanted to find an elegant way to tell them that they cannot perform that action because they don't have Level 3.

Can you please suggest a way to inject somehow this message, to show it in my custom 403.blade.php page? I've been able to do this by flashing a variable in the session, but I don't think it's elegant, I would like to use something like a MessageBag (Illuminate\Support\MessageBag).

LARAVEL 8.x : check this answer.

like image 210
Marco Cazzaro Avatar asked Jun 06 '19 08:06

Marco Cazzaro


2 Answers

Answer was given in comments, put here for reference:

Laravel provides this functionality through the deny() function in the HandlesAuthorization trait. The deny() function throws an UnauthorizedException but allows you to specify a message instead of throwing a plain exception.

Replace the return false with it and you can send custom messages to render in the exception handler.

Example:

public function reply(User $user)
{
    if ($user->current_level < 3) {
        $this->deny('Sorry, your level is not high enough to do that!');
        // Laravel 6+ requires you to return the deny(), see following line
        // return $this->deny('Sorry, your level is not high enough to do that!');
    }
    return true;
}
like image 177
Loek Avatar answered Nov 09 '22 09:11

Loek


I thought I'd add this answer as I arrived here searching for how to return messages from policy methods as the code I'm maintaining only returns false when an action is not allowed.

The current documentation says to return an Illuminate\Auth\Access\Response instance from your policy method:

...
use Illuminate\Auth\Access\Response;

public function update(User $user, Post $post)
{
    return $user->id === $post->user_id
                ? Response::allow()
                : Response::deny('You do not own this post.');
}
like image 5
Tony Avatar answered Nov 09 '22 08:11

Tony