How to enable Live Preview for protected content in Statamic
Live Preview is a stellar feature of Statamic, and gives content authors the ability to see real-time content updates without needing to click “Save” first. And for the majority of straight-forward sites, it is there and ready to go out of the box.
But if you’re using a Custom Driver on to protect entries from being public, you may need to update your Protector to let Live Preview users see the content.
If you’re using Statamic’s built-in Protection methods, the test for isLivePreview
is done for you – this just applies for custom drivers.
When using Live Preview, your Protector will still be executed, meaning its logic to either allow or block the user will be run: but the problem with this is that it may require an additional authentication process to correctly run.
Let me explain this:
For a project I’ve been working on, there is an entire Collection of content that requires a user be logged in, and they can only see specific sections of that Collection based on how their user account is configured.
The key here is that the User model being used is not Statamic’s User model – it is a completely separate model – such as when Using an Independent Authentication Guard. This means that there are Statamic CP users who can log in to the CP only, and front end users who can only log in to the front end of the website.
So while the content author is logged in to Statamic’s CP, they may not necessarily always be logged in to the front end of the website. They may not even have a front end account.
The problem here is that the Protector I’ve written for this site will look at the logged in front end user – and if the content author has not manually logged in to the front end (if they can) or does not have an account, the Protector, because it runs on every request including Live Preview requests, will deny access to the Live Preview too.
One approach would be to look at the logged in Statamic user and see if they can access the Collection, blah blah blah, too hard, too manual and too much can go wrong as it relies on the developer doing the right thing and perform the right checks. And yeah, we’re only human so we all know how that goes.
But of course there’s an easy way – just not documented.
Statamic comes with a macro on Laravel’s request named isLivePreview
. Take a guess at what this does.
It’s a test that looks at the request’s token, and returns true if it is a Live Preview request. It is as simple as that.
This should be added to your Protector’s protect
method, and you can then decide how you want to handle it.
If the request is a Live Preview request, you may want to simply return true
– and let the Protection test pass.
1<?php 2 3namespace App\Protectors; 4 5use Illuminate\Support\Facades\Auth; 6use Statamic\Auth\Protect\Protectors\Protector; 7 8class Portal extends Protector 9{10 public function protect(): true11 {12 // if the request is a live preview request, let them in13 if (request()->isLivePreview()) {14 return true;15 }16 17 $user = Auth::guard('web')->user();18 19 // front end protection logic for the web user ($user)20 // do whatever business logic checks are needed, and throw21 // an exception if not allowed22 23 return true;24 }25}
However, there is one more thing though: this is purely looking at the request to make sure it is a Live Preview request – but is not looking at whether a CP user is logged in. Meaning that if a Live Preview request was shared with the correct query parameters, it would be a truly public and valid request for anyone (until the request’s token expires, of course).
We can add one more check to our Protector, and that is to ensure the requesting user is logged in to Statamic.
1<?php 2 3namespace App\Protectors; 4 5use Illuminate\Support\Facades\Auth; 6use Statamic\Auth\Protect\Protectors\Protector; 7 8class Portal extends Protector 9{10 public function protect(): true11 {12 // if the request is a live preview request, and they're a logged in Statamic CP user, let them in13 if (request()->isLivePreview() && Auth::guard('statamic')->user()) {14 return true;15 }16 17 $user = Auth::guard('web')->user();18 19 // front end protection logic for the web user ($user)20 // do whatever business logic checks are needed, and throw21 // an exception if not allowed22 23 return true;24 }25}
You could go further here and test if they have access to the correct Entry/Collection too – but, at least for this site’s use case, is just overkill. Having a user logged in to the Statamic CP is enough for this site.
In these examples, if these tests pass, the protect
method simply returns true, and skips the rest of the logic. But if it is not a Live Preview request and the user is not logged in to the CP, the standard logic runs, and in my instance, shows the app’s public login screen.
With just a simple tweak to your protect
method, you can keep your front end content private, but also enable support for Statamic’s Live Preview.
Comments
Reply on Bluesky to join the conversation.