Laravel: On-demand authorization
Look mom, no actions!
Dealing with authorization is not always pretty, though. Unless you want to throw exceptions manually, you are forced to register an action into the Gate to be called later. It’s something counterproductive when you think about an authorization that’s is only checked once across all the application.
My most recent pull request into Laravel, which should be ready for version 8.75 any time this week, allows just that.
Quick and not dirty
Let’s say we have a controller where the user can publish an Article. The Article itself must meet only one condition to be published: it has to be approved by an editor beforehand, something that is done elsewhere in the application.
Instead of registering an action and calling the Gate, we can do this authorization in one line.
That’s it. No need to register anything or making and
if statement with an exception. We can just pass a truthy condition and keep going.
We can also do the inverse with
denyIf(). For example, we want to deny publishing the Article if is set as private.
Making authorization relatable
The above code makes sense for the developer, but not for the end user.
Let’s say Jimmy calls his editor to check the Article he wrote, and Mark approves right away. A couple of seconds pass, he retracts and rejects it. Jimmy doesn’t know what happend after the call, so he presses the “Publish” button anyway. The result? A page says that he doesn’t have permission to do that.
To avoid keeping Jimmy into the dark, we can add a message to the authorization exception.
In Laravel, when an authorization exception is thrown, the message will be printed on the error page by default.
Do it simple, or do it complex
There are few scenarios where you will want to make a check over the authenticated user. You don’t need to register an action into the Gate, but instead, you can pass a callback that receives an user instance.
For example, we want to allow publishing if the current user authenticated is an administrator, or the Article is already approved.
We can also use the power of the authorization
Response, and hijack the callback anytime, like a short circuit. Following the same example, let’s add a condition to deny the publishing if the author of the article has been banned.
Any callback will fail automatically if the user is not authenticated, even if the user as parameter is not set in the callback, by returning an
To avoid that, we can allow guests by explicitly setting the
$user variable to
null. For example, we can do that for comments: any guest can comment an Article with a word-count restriction, but a banned user won’t be able to.
Of course the above is only the tip of the iceberg. For package maintainers, this means they can authorize actions without needing to register actions or throw an
For users, one-line authorization is now possible without having to set up the kitchen sink.