I'm over a site where we need to set visibility to content to be by user's role. Permission by Term was one of the modules that I considered to help accomplish this. When I installed the module, I started to receive feedback from users that they couldn't find a piece of content that they where working on and they couldn't find it after saving a draft version previously. The site uses content moderation, and this content had never been published. After doing some investigation, I found that the PBT module was causing the issue.

The Content Moderation module creates a couple of views that overrides the default content view, and allows users to see the state of the content they are working, amongst other features. When PBT is installed, any user in non-admin role can't see content that isn't published, like in draft, in review, or archived states, for example. I tried modifying the views, and changing permissions, but the only way that they would have able to see the unpublished content is if I left on node's 'bypass content access control' for their role, which isn't an option.

Would it be possible to create a patch so PBT honors node's 'view own unpublished content' and content moderation's 'view any unpublished content' settings so unpublished content will still be visible to non-admin users on sites using content moderation?

Comments

jazzfiction created an issue. See original summary.

eric.guerin@ucsf.edu’s picture

Yes I would also like support for Content Moderation, content moderation is a core module, and shouldn't have issues between Content Moderation and Permissions by Term as one should handle Content workflow really and not the permission of a node.

Maybe Permissions by Term should only take affect after Content is moved from a moderation state of Draft -> to Published, or any moderation state other then Published should not be processed by the module until in the Published state?

bstan’s picture

I am also looking for support with Content Moderation

malaynayak’s picture

StatusFileSize
new598 bytes

Steps to Reproduce

1. Install PBT module.
2. Add some terms and configure user and role based permissions.
3. Add some pages with the taxonomy terms referenced and publish them.
4. Login as a non-admin user e.g user with "Editor" role and go to admin/content. Make sure "View any unpublished content" permission is granted to that role.
5. The editor will be able to see the published pages in the admin/content page.
6. Now create some node without any taxonomy term and keep them unpublished.
7. Visit the admin/content page with same Editor user and the non published contents wont be listed in the page.

Proposed Resolution

The issue was with AccessStorage.php getUnrestrictedNids function.

 
$unrestrictedNids = $this->database->select('taxonomy_index', 't')
     ->fields('t', ['nid'])
      ->condition('t.nid', $restrictedNids, 'NOT IN')
      ->distinct(TRUE)
      ->execute()
      ->fetchCol();

The unrestricted nids are calculated from taxonomy_index, as a result of which the nodes with no taxonomy terms are filtered out and treated as restricted.

The following solution worked for me:

$unrestrictedNids = array_diff($this->getAllNids(), $restrictedNids);

With the above change with disable_node_access_records option set true worked for me.

Submitting the patch to fix the issue. Please review.

malaynayak’s picture

Status: Active » Needs review
simoneb’s picture

StatusFileSize
new1.92 KB

This solution worked for me to show unpublished nodes in views (Permissions by term version Version: 8.x-2.18 )
I had to rebuild permissions after it.

lolcode’s picture

Version: 8.x-2.10 » 8.x-2.25
Status: Needs review » Needs work

I tried both #4 and #6 with no change. Looks like #6 refers to a service not found in the latest D8 version 2.25?

In an attempt to have workflow plus site section permissions I have content moderation and workbench access controlling update and delete with permissions_by_term controlling view. The only remaining issue is viewing unpublished nodes.

pcate’s picture

Ran into this same issue. Tried #6 but like @lolcode it didn't not apply. Looks like some updates with the latest 2.x version caused some line # changes and the patch needs a re-roll.

pcate’s picture

StatusFileSize
new2.24 KB

I re-rolled the patch to work with the latest 2.x dev version.

pcate’s picture

Status: Needs work » Needs review
pcate’s picture

After applying the patch, rebuilding permissions threw the following error:

An AJAX HTTP error occurred.
HTTP Result Code: 500
Debugging information follows.
Path: /batch?id=2962&op=do_nojs&op=do
StatusText: 500 Service unavailable (with message)
ResponseText: The website encountered an unexpected error. Please try again later.Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "permissions_by_term.cache_negotiator". Did you mean one of these: "permissions_by_term.access_storage", "permissions_by_term.cache_invalidator"? in Drupal\Component\DependencyInjection\Container->get() (line 153 of core/lib/Drupal/Component/DependencyInjection/Container.php). Drupal::service('permissions_by_term.cache_negotiator') (Line: 415)
permissions_by_term_node_access_records(Object)
call_user_func_array('permissions_by_term_node_access_records', Array) (Line: 403)
Drupal\Core\Extension\ModuleHandler->invokeAll('node_access_records', Array) (Line: 159)
Drupal\node\NodeAccessControlHandler->acquireGrants(Object) (Line: 1338)
_node_access_rebuild_batch_operation(Array) (Line: 295)
_batch_process() (Line: 137)
_batch_do() (Line: 93)
_batch_page(Object) (Line: 55)
Drupal\system\Controller\BatchController->batchPage(Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 573)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 151)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

So looks like the patch needs much more significant work and possibly a different approach.

pcate’s picture

Status: Needs review » Needs work
jepster_’s picture

Assigned: Unassigned » jepster_
Status: Needs work » Postponed (maintainer needs more info)
jepster_’s picture

Status: Postponed (maintainer needs more info) » Needs review
StatusFileSize
new15.08 KB

Would it be possible to create a patch so PBT honors node's 'view own unpublished content' and content moderation's 'view any unpublished content' settings so unpublished content will still be visible to non-admin users on sites using content moderation?

Yes, it is possible easily. The important part is located in AccessCheck::canUserAccessByNode():

Before there was this check:

    if ($user instanceof User && $user->hasPermission('bypass node access')) {
      return TRUE;
    }

Now I have added the checks for the two other permissions:

    if ($user instanceof User && $user->hasPermission('view own unpublished content') &&
      (int) $node->getOwnerId() === (int) $uid &&
      !$node->isPublished()
    ) {
      return TRUE;
    }

    if ($user instanceof User && $user->hasPermission('view any unpublished content') &&
      !$node->isPublished()
    ) {
      return TRUE;
    }

Here is my patch. Please re-view the patch and test. If you have no further notices, I will commit these changes and create new releases for the Drupal 8 and 9 version.

jepster_’s picture

Assigned: jepster_ » Unassigned
pcate’s picture

@PeterMajmesku I apply the #14 patch but am getting the following error on almost every page.

The website encountered an unexpected error. Please try again later.
TypeError: Argument 1 passed to Drupal\permissions_by_term\Service\AccessCheck::canUserAccessByNode() must be an instance of Drupal\node\Entity\Node, string given, called in /var/www/hrnih/docroot/modules/contrib/permissions_by_term/src/Listener/KernelEventListener.php on line 171 in Drupal\permissions_by_term\Service\AccessCheck->canUserAccessByNode() (line 41 of modules/contrib/permissions_by_term/src/Service/AccessCheck.php).
Drupal\permissions_by_term\Service\AccessCheck->canUserAccessByNode('1616', , 'en') (Line: 171)
Drupal\permissions_by_term\Listener\KernelEventListener->handleAccessToNodePages(Object) (Line: 83)
Drupal\permissions_by_term\Listener\KernelEventListener->onKernelRequest(Object, 'kernel.request', Object)
call_user_func(Array, Object, 'kernel.request', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.request', Object) (Line: 127)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
pcate’s picture

Status: Needs review » Needs work
jepster_’s picture

Status: Needs work » Needs review
StatusFileSize
new15.34 KB

Here is an updated version. Fixed the method signature error. Please test.

pcate’s picture

@PeterMajmesku #18 fixed the #16 error message.

Unfortunately it does not appear to have fixed the general error of this issue. When going to the /admin/content view with a user that can view unpublished draft content, the unpublished content still does not appear.

I made sure to rebuild access permissions and create caches before testing.

pcate’s picture

Status: Needs review » Needs work
jepster_’s picture

Status: Needs work » Needs review
StatusFileSize
new17.84 KB

@PCate: Thanks for the manual testing. You are right. I did the manual testing now by myself and it did work. Here is an new patch version. Please re-check.

pcate’s picture

@PeterMajmesku #21 works!

For anyone, I had rebuild permissions and clear cache after applying the patch.

pcate’s picture

Status: Needs review » Reviewed & tested by the community
jepster_’s picture

Status: Reviewed & tested by the community » Fixed

Commited into 8.x-2.26 for Drupal 8 and 3.1.2 for Drupal 9.

jepster_’s picture

Status: Fixed » Closed (fixed)
gargsuchi’s picture

I am on Permissions by term 2.28. And I see this problem.
A non-admin user is able to see the unpublished content in admin/content. But when I enable this module, they are not able to see the unpublished content.

jepster_’s picture

Have you rebuilt your node access records after update? Have you checked the settings (e.g. permission mode)? Do you have term permissions for these unpublished nodes?

gargsuchi’s picture

Hi Peter

* Yes, I have rebuilt access records.
* Permission mode - This is unchecked in my install
* It does not matter if the node has a restricted term or not. No unpublished nodes show up in the view listing.

gargsuchi’s picture

StatusFileSize
new867 bytes

Here is a patch that fixes this for me.