Score:2

How to programmatically grant access to view unpublished content with a special query string?

br flag

In my application, I want anonymous users to be able to view an unpublished node but only if they append a special code to the URL. For example:

www.mysite.com/node/123?code=Hx23ufG38

I figure I can do something in a preprocess function to check if the code is appended to the URL and, if so, allow the user to view the unpublished node. (This clearly is not for a use case where the content is sensitive, because anyone visiting the page at the URL with the code appended will be able to see the page.)

How can I programmatically grant the current (anonymous) user permission to view unpublished content, provided the condition is met in the URL?

This is for a Drupal 9 website.

cn flag
Broad strokes you'd probably use `hook_entity_access` (or `hook_ENTITY_TYPE_access`), and add a query string cache context to the `AccessResult` you return from there
br flag
I suspect that is the right answer. I'm experimenting with that hook and it appears to do precisely what I need.
leymannx avatar
ne flag
Little bit similar to this maybe https://drupal.stackexchange.com/a/313783/15055
4uk4 avatar
cn flag
Yes, but then you need to add `->addCacheContexts(['url.query_args:code'])`. Otherwise the first anonymous user with query string will grant access for all other anonymous users following.
leymannx avatar
ne flag
@4uk4 – Ah and in the given answer I actually need to add the user cache context?
4uk4 avatar
cn flag
@leymannx, cachePerUser() is a shortcut for the user context.
leymannx avatar
ne flag
@4uk4 – Ah of course!!
br flag
@4uk4 -- "first anonymous user with query string will grant access for all other anonymous users". I can't reproduce that issue in my application, initially. I have caching turned on at admin/config/development/performance but even with just `return AccessResult::allowed();` and no cache context, access by one anonymous user doesn't clear the way for others.
4uk4 avatar
cn flag
This cache setting is only for the headers sent out to the browser. Drupal has two page cache modules. The anonymous page cache varies by the entire URL including query string, the dynamic page cache varies by route and contexts. As long as the anonymous page cache has cached the correct results all things are fine, but starting with a cleared cache certain combinations of node request should reproduce wrong answers.
No Sssweat avatar
ua flag
Have you considered using the [Access unpublished](https://www.drupal.org/project/access_unpublished) contrib module?
br flag
@NoSssweat Good idea, but that module doesn't allow for anonymous previews of revisions, which is a requirement in my case: https://www.drupal.org/project/access_unpublished/issues/3207620
Score:2
ch flag

You can use https://www.drupal.org/project/access_unpublished or look at its code.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.