Problem/Motivation

When an unpublished translation is added to a node, grants are removed from the database. This way no one can access the published original translation

Steps to reproduce

create an entity with translatable status field. No need to do any settings on the PbT side.

1: create a published node
2: save an unpublished translation
3: access is now impossible

This happens because somehow the grant hook is called with the delete flag and the grants to be saved for the node are now an empty array. I think the module doesn't take into account other translations of the node when it is saved?

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

joey-santiago created an issue. See original summary.

jepster_’s picture

Status: Active » Fixed

Thanks for creating this issue here. This issue is resolved in version 3.1.19. See release notes: https://www.drupal.org/project/permissions_by_term/releases/3.1.19

damienmckenna’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

joey-santiago’s picture

Sorry, it doesn't work for me...

What i'm doing is:

  1. Create a pulished node
  2. Check access as anonymous: 200 as expected
  3. Create a French translation for the node and keeping it unpublished
  4. Check access to the translation as anonymous: 403
  5. Check access to the original node as anonymous: 403, WRONG
  6. Save the original node
  7. Check access to the translation as anonymous: 403
  8. Check access to the original node as anonymous: 200 as expected

The problem is every time the unpublished translation is saved, i also lose access to the original node and also the node_access table contents are removed.

Can you please reopen this, or should i create a new issue?

joey-santiago’s picture

Version: 3.1.18 » 3.1.19

Confirm, i find this problem on 3.1.19 as well.

When an unpublished translation is saved, a call to NodeGrantDatabaseStorage::write with the delete flag on is launched, as expected, but the execution stops there, because the module doesn't return any grants i guess?

Now i finally get what happens.

When a published node is saved, the node type is handled by Pbt and the node has no terms associated with it, PbT returns NULL from permissions_by_term_node_access_records, but core has this:

Class NodeAccessControlHandler
/**
   * {@inheritdoc}
   */
  public function acquireGrants(NodeInterface $node) {
    $grants = $this->moduleHandler->invokeAll('node_access_records', [$node]);
    // Let modules alter the grants.
    $this->moduleHandler->alter('node_access_records', $grants, $node);
    // If no grants are set and the node is published, then use the default grant.
    if (empty($grants) && $node->isPublished()) {
      $grants[] = ['realm' => 'all', 'gid' => 0, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0];
    }
    return $grants;
  }

so in this case we're saved by core: PbT doesn't want to do anything with that node and returns NULL, but we should indeed do something with it. When an unpublished translation is saved, then the node is not published and nothing is inserted for us.

joey-santiago’s picture

StatusFileSize
new1.99 KB

This seems to fix the issue for me.

I can share with you the DrupalPod environment where i have the patch if you want to test it. Please, let me know if i can help in any way.

joey-santiago’s picture

StatusFileSize
new1.96 KB

Right. That was not the right way to go. We want to add the default grant instead of the ones checked by PbT.

joey-santiago’s picture

StatusFileSize
new3.1 KB

... And finally, found another case in which instead of returning NULL, we should return the default grants.

joey-santiago’s picture

StatusFileSize
new8.77 KB

Also added some tests for this.

jepster_’s picture

Status: Closed (fixed) » Needs review

Since joey-santiago worked on this issue after it was closed, I am re-opening it and I am asking for review. I will come back to this, when I will have some time for this. Sorry, I am quite busy now.

joey-santiago’s picture

Coming back to this. We noticed that the patch works indeed for that case, but doesn't cover this:

  • node with specific permissions set is created and published
  • unpublished translation is created

in this case the patch only sets the default access, thus opening the node's permissions. Working on a fix.

joey-santiago’s picture

StatusFileSize
new8.98 KB

Reworked the patch and confirmed tests are now passing. I plan on adding a couple tests for the case that we noticed failing, it will come next week.

joey-santiago’s picture

StatusFileSize
new10.26 KB

Here are some more tests. I really think @peter-majmesku some effort should be put into making the module reliable with multilanguage installs.
I had a bit of troubles understanding how the permission_mode should work, but i hope i got it right.

thanks

hkirsman’s picture

What would be needed to test the correct branch? There's only 8.x-1.x available here.

hkirsman’s picture

StatusFileSize
new8.19 KB
new715 bytes

permissions_by_term-3308318-18.patch and permissions_by_term-3308318-19.patch introduced new bug where node is suddenly accessible by anonymous users, permissions_by_term-3308318-10.patch seems to work. I'm new to to this so I thought I'd first start with fixing tests for the permissions_by_term-3308318-10.patch. Does that make sense? If that's ok, then maybe keep it for what was meant to be fixed in permissions_by_term-3308318-19.patch

alaa abbad’s picture

StatusFileSize
new8.19 KB

Reroll the patch to ensure compatibility with the most recent version.

hkirsman’s picture

StatusFileSize
new132.56 KB

Status check. So there's merge request and patches in this issue. The new defaultGrants() method in MR and in permissions_by_term-3308318-10.patch is exactly the same. Patch permissions_by_term-3308318-18.patch already has more logic in it. Latest patches from @joey-santiago were
permissions_by_term-3308318-18.patch and permissions_by_term-3308318-19.patch
Interdiff between them is:

diff -u b/tests/src/Kernel/NodeAccessRecordsTest.php b/tests/src/Kernel/NodeAccessRecordsTest.php
--- b/tests/src/Kernel/NodeAccessRecordsTest.php
+++ b/tests/src/Kernel/NodeAccessRecordsTest.php
@@ -98,25 +98,14 @@
     $node->save();
     self::assertTrue($this->isNodeAccessRecordCreatedInPBTRealm($node->id()));
 
-    \Drupal::configFactory()->getEditable('permissions_by_term.settings')->set('permission_mode', TRUE)->save(TRUE);
-    $term = Term::create([
-      'name' => 'term2',
-      'vid'  => 'test',
-    ]);
-    $term->save();
-
-    $node = Node::create([
-      'type' => 'page',
-      'title' => 'test_title',
-      'field_tags' => [
-        [
-          'target_id' => $term->id()
-        ]
-      ],
-      'language' => 'en',
-    ]);
-    $node->save();
+    $translation = $node->addTranslation('fr');
+    $translation->title->value = $this->randomString();
+    $translation->status->value = 0;
+    $translation->save();
     self::assertTrue($this->isNodeAccessRecordCreatedInPBTRealm($node->id()));
+    self::assertFalse($this->isNodeAccessRecordCreatedInDefaultRealm($node->id(), 'en'));
+    self::assertFalse($this->isNodeAccessRecordCreatedInDefaultRealm($node->id(), 'fr'));
+
   }
 
   public function testCreateIfTermHasNoPermissionButPermissionModeIsOn(): void {
@@ -139,6 +128,15 @@
     ]);
     $node->save();
     self::assertTrue($this->isNodeAccessRecordCreatedInPBTRealm($node->id()));
+    self::assertFalse($this->isNodeAccessRecordCreatedInDefaultRealm($node->id(), 'en'));
+
+    $translation = $node->addTranslation('fr');
+    $translation->title->value = $this->randomString();
+    $translation->status->value = 0;
+    $translation->save();
+    self::assertTrue($this->isNodeAccessRecordCreatedInPBTRealm($node->id()));
+    self::assertFalse($this->isNodeAccessRecordCreatedInDefaultRealm($node->id(), 'en'));
+    self::assertFalse($this->isNodeAccessRecordCreatedInDefaultRealm($node->id(), 'fr'));
   }
 
   private function isNodeAccessRecordCreatedInPBTRealm(string $nid): bool {

So more tests were added as was said in https://www.drupal.org/project/permissions_by_term/issues/3308318#commen...

I'm a afraid my comment and patch in #21 might have been kind of incorrect as this is also related to https://www.drupal.org/project/drupal/issues/962664
I would say permissions_by_term-3308318-19.patch is the last correct patch for PbT 3.1.19 and Drupal core 9.

Problem is that the patch still fails. I would assume it was working in some env but what am I missing...

fail

hkirsman’s picture

Ok, I think I get it now. The patch was only tested with the test that was updated, but not whole permissions_by_term test set. tests/src/Kernel/NodeAccessRecordsTest.php works just fine. There's still this but it's minor code change where roles are created to add human readable label:

Role label is expected to be a string.

hkirsman’s picture

StatusFileSize
new134.19 KB
new14.31 KB
new3.62 KB

Got tests working on Permissions by Term version 3.1.19, Drupal core 9.3.22 (could have been probably 9.5.x). Next up is to update againast latest version of PbT and maybe Drupal 10.2

Tests working

hkirsman’s picture

StatusFileSize
new12.54 KB

I could not create interdiff for some reason, but it the new patch should be correct. I've tested this on permissions_by_term 3.1.33 and core 10.2.7

hkirsman’s picture

Version: 3.1.19 » 3.1.33
hkirsman’s picture

StatusFileSize
new44.72 KB

This is also issue for testing:
Can't run tests