Problem/Motivation

I have a Vocabulary 'Resort' that use permissions_by_term to restrict access.
When I create a New node in english (default language) with taxonomy 'Resort' field I only have access to the Resort I should have access.
But when I try to create it from another language url like this one: /fr/node/add/activity_card I have access to all the Resorts for this field.

I have 2 languages installed 'en' & 'fr'. 'en' being the default one.
The restriction is done by user and by role.
The user I use do not have the allowed role but is listed as a valid user for 1 term and 1 term only.
In the end The user can create the Node for another Resort but he cannot access it once created.

So:
/node/add/activity_card is OK
/fr/node/add/activity_card is KO

I tried to rebuild permissions (/admin/reports/status/rebuild), it doesn't solve the issue.

Comments

GPZ created an issue. See original summary.

jepster_’s picture

Are you using the Content Translation module for translating your nodes? Do the nodes have different node ids? Does each node id have different taxonomy terms?

languages

jepster_’s picture

Status: Active » Postponed (maintainer needs more info)

Are your terms in the same language as the nodes? Please make sure, that your node is in the same language as your related taxonomy term. Otherwise the permission handling does not apply.

jepster_’s picture

Status: Postponed (maintainer needs more info) » Closed (works as designed)

Content language must match the term language. This is a feature and not a bug.

gpz’s picture

StatusFileSize
new58.38 KB
new43.52 KB
new63.32 KB
new142.06 KB

Thank you for your reply and sorry for my late reply.

- Yes I use the Content Translation module.
- I use the translation tab to translate a node.
- Nodes have the same Id across languages but I was talking about the node/ADD, so the node id is not revealant here. But I have the same issue with the edit.
- Terms are translated the same way (I have 4 of them, all of them are translated, and the user used for the screenshot should only have access to one of them 'Marrakech')

- The field on the node with the taxonomy reference was not a translatable field (I don't want that the english point to a term and another language to another term). But I've tried to make this field translatable and it doesn't change the issue.

I have uploaded some images to show what I have in English and what I have in French and an extract of the DB.

I might do something wrong but I don't know what.

gpz’s picture

It seems to work now with the 1.58 version

jepster_’s picture

Perhaps your issue was related to #2911842: Restricted node appears in view.

gpz’s picture

Well, I was too quick to shout victory.
I might be doing something wrong.
I created an example here to reproduce the problem: https://dfz3x.ply.st

Admin
username: admin
password: admin

User with problem
username: USER2
password: USER2

When editing with USER2 this following node, we can see in the select every terms:
https://dfz3x.ply.st/fr/node/7/edit

The english one is OK:
https://dfz3x.ply.st/node/7/edit

I have rendered the taxo field as a rendered entity to show that languages match:
https://dfz3x.ply.st/node/7
https://dfz3x.ply.st/fr/node/7

gpz’s picture

I think that part of the problem is due to primary keys.
tid + uid is not enough.
I cannot add multiple languages for the same tid and uid in the table permissions_by_term_user (the problem will be the same with permissions_by_term_role)

I tried to also add langcode as primary key and manually insert a tid/uid/langcode and it seems to work (need more test). Unfortunately when you save a Term from the translated version, the table is not updated to add the a line with the langcode. If you change the user, it will then replace the line with the new user and the current langcode but we'll miss the one for the original langcode.

jepster_’s picture

Status: Closed (works as designed) » Needs work

Yes, you cannot add multiple languages with the same tid. I have checked it right now. That's an issue. The db schema must be updated. Thanks for reporting!

jepster_’s picture

Status: Needs work » Postponed (maintainer needs more info)
StatusFileSize
new453 bytes

@GPZ: Could you please check the attached patch for checking if it's solving the issue for you? I have removed the "tid" field in "permissions_by_term_role" and "permissions_by_term_user" as primary field in the DB schema.

gpz’s picture

Thank you for the patch.
Unfortunately no, it doesn't solve the problem, it is even worst now.
I now cannot add the same role to multiple Term or a user to multiple Term.
I think it either need an unrelated unique primary key or add to primary keys the langcode.

But it won't be enough.
When adding a translation to a Term, and saving it, it doesn't save the new langcode in the permissions_by_term_user.
I think in AccessStorage::saveTermPermissions, getUserTermPermissionsByTid should use the langcode ? otherwise it find a result (but from the english version). It is probably the same for the getRoleTermPermissionsByTid.

jepster_’s picture

@GPZ: Thanks for testing. I have modified the patch according to the mentioned methods. I have also written an automated test for that. The old Unit and Behat tests do run successfully: https://bitbucket.org/peter_majmesku/permissions_by_term/addon/pipelines....

Please test the updated patch (remove the changes from the old one and apply anew): https://www.drupal.org/files/issues/2018-08-11/2982955-saving-term-with-...

gpz’s picture

It looks promising but I still have few problems. Thank you.

- I noticed that there is a missing argument in permissions_by_term_submit (.module) line 89. saveTermPermissions should take a langcode

- I also have warnings when adding a translation to a node (from english to french):

Warning: Missing argument 2 for Drupal\permissions_by_term\Service\AccessStorage::getUserTermPermissionsByTid(), called in /var/www/html/docroot/modules/contrib/permissions_by_term/src/Service/AccessStorage.php on line 160 and defined in Drupal\permissions_by_term\Service\AccessStorage->getUserTermPermissionsByTid() (line 116 of modules/contrib/permissions_by_term/src/Service/AccessStorage.php).
Drupal\permissions_by_term\Service\AccessStorage->getUserTermPermissionsByTid('114') (Line: 160)
Drupal\permissions_by_term\Service\AccessStorage->getUserTermPermissionsByTids(Array) (Line: 69)
Drupal\permissions_by_term\Service\NodeEntityBundleInfo->renderNodeDetails('modules/contrib/permissions_by_term/src/View/node-details.html.twig', '4289') (Line: 237)
permissions_by_term_form_alter(Array, Object, 'node_editorial_form') (Line: 539)
Drupal\Core\Extension\ModuleHandler->alter('form', Array, Object, 'node_editorial_form') (Line: 834)
Drupal\Core\Form\FormBuilder->prepareForm('node_editorial_form', Array, Object) (Line: 276)
Drupal\Core\Form\FormBuilder->buildForm('node_editorial_form', Object) (Line: 48)
Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'default', Array) (Line: 399)
Drupal\content_translation\Controller\ContentTranslationController->add(Object, Object, Object, 'node')
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 582)
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: 67)
Drupal\simple_oauth\HttpMiddleware\BasicAuthSwap->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: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 51)
Drupal\jsonapi\StackMiddleware\FormatSetter->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: 666)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
Notice: Undefined variable: langcode in Drupal\permissions_by_term\Service\AccessStorage->getUserTermPermissionsByTid() (line 119 of modules/contrib/permissions_by_term/src/Service/AccessStorage.php).
Drupal\permissions_by_term\Service\AccessStorage->getUserTermPermissionsByTid('114') (Line: 160)
Drupal\permissions_by_term\Service\AccessStorage->getUserTermPermissionsByTids(Array) (Line: 69)
Drupal\permissions_by_term\Service\NodeEntityBundleInfo->renderNodeDetails('modules/contrib/permissions_by_term/src/View/node-details.html.twig', '4289') (Line: 237)
permissions_by_term_form_alter(Array, Object, 'node_editorial_form') (Line: 539)
Drupal\Core\Extension\ModuleHandler->alter('form', Array, Object, 'node_editorial_form') (Line: 834)
Drupal\Core\Form\FormBuilder->prepareForm('node_editorial_form', Array, Object) (Line: 276)
Drupal\Core\Form\FormBuilder->buildForm('node_editorial_form', Object) (Line: 48)
Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'default', Array) (Line: 399)
Drupal\content_translation\Controller\ContentTranslationController->add(Object, Object, Object, 'node')
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 582)
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: 67)
Drupal\simple_oauth\HttpMiddleware\BasicAuthSwap->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: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 51)
Drupal\jsonapi\StackMiddleware\FormatSetter->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: 666)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
Warning: Missing argument 2 for Drupal\permissions_by_term\Service\AccessStorage::getRoleTermPermissionsByTid(), called in /var/www/html/docroot/modules/contrib/permissions_by_term/src/Service/AccessStorage.php on line 194 and defined in Drupal\permissions_by_term\Service\AccessStorage->getRoleTermPermissionsByTid() (line 176 of modules/contrib/permissions_by_term/src/Service/AccessStorage.php).
Drupal\permissions_by_term\Service\AccessStorage->getRoleTermPermissionsByTid('114') (Line: 194)
Drupal\permissions_by_term\Service\AccessStorage->getRoleTermPermissionsByTids(Array) (Line: 70)
Drupal\permissions_by_term\Service\NodeEntityBundleInfo->renderNodeDetails('modules/contrib/permissions_by_term/src/View/node-details.html.twig', '4289') (Line: 237)
permissions_by_term_form_alter(Array, Object, 'node_editorial_form') (Line: 539)
Drupal\Core\Extension\ModuleHandler->alter('form', Array, Object, 'node_editorial_form') (Line: 834)
Drupal\Core\Form\FormBuilder->prepareForm('node_editorial_form', Array, Object) (Line: 276)
Drupal\Core\Form\FormBuilder->buildForm('node_editorial_form', Object) (Line: 48)
Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'default', Array) (Line: 399)
Drupal\content_translation\Controller\ContentTranslationController->add(Object, Object, Object, 'node')
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 582)
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: 67)
Drupal\simple_oauth\HttpMiddleware\BasicAuthSwap->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: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 51)
Drupal\jsonapi\StackMiddleware\FormatSetter->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: 666)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
Notice: Undefined variable: langcode in Drupal\permissions_by_term\Service\AccessStorage->getRoleTermPermissionsByTid() (line 179 of modules/contrib/permissions_by_term/src/Service/AccessStorage.php).
Drupal\permissions_by_term\Service\AccessStorage->getRoleTermPermissionsByTid('114') (Line: 194)
Drupal\permissions_by_term\Service\AccessStorage->getRoleTermPermissionsByTids(Array) (Line: 70)
Drupal\permissions_by_term\Service\NodeEntityBundleInfo->renderNodeDetails('modules/contrib/permissions_by_term/src/View/node-details.html.twig', '4289') (Line: 237)
permissions_by_term_form_alter(Array, Object, 'node_editorial_form') (Line: 539)
Drupal\Core\Extension\ModuleHandler->alter('form', Array, Object, 'node_editorial_form') (Line: 834)
Drupal\Core\Form\FormBuilder->prepareForm('node_editorial_form', Array, Object) (Line: 276)
Drupal\Core\Form\FormBuilder->buildForm('node_editorial_form', Object) (Line: 48)
Drupal\Core\Entity\EntityFormBuilder->getForm(Object, 'default', Array) (Line: 399)
Drupal\content_translation\Controller\ContentTranslationController->add(Object, Object, Object, 'node')
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 582)
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: 67)
Drupal\simple_oauth\HttpMiddleware\BasicAuthSwap->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: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 51)
Drupal\jsonapi\StackMiddleware\FormatSetter->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: 666)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
gpz’s picture

Sorry, for the first problem, it's my bad, the warning was not a missing argument but an unhandle exception (permissions_by_term.mode line 89 - patch applied)

For the second problem I just added $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId(); in functions getUserTermPermissionsByTids and getRoleTermPermissionsByTids in AccessStorage.php. It's not perfect as you could edit the english translation from the french but I'm not sure how I can get the information from those functions.

Otherwise it seems to work well. Thank you.

gpz’s picture

Is it normal it does "Rebuilding content access permissions" each time I add a user to "Allowed users" in the permission Details ?

  • Peter Majmesku committed 24672a3 on 8.x-1.x
    Issue #2982955 by GPZ: Multilingual and taxonomy term field permission...
gpz’s picture

I saw you did a new version with the patch. Great!

But you didn't changed the call to getUserTermPermissionsByTid inside getUserTermPermissionsByTids (same for Role).
I join the patch I applied myself to v1.58
I saw someone else did a patch to v1.59 by adding a default value to getRoleTermPermissionsByTid.
https://www.drupal.org/project/permissions_by_term/issues/2992782

Moreover I think you should warn other users in the Release note that your service API changed from 1.58 to 1.59.
I, for example use your service AccessStorage to filter the Content View and to add/Remove user to a term from the user form.
The following methods have a new parameter:
- getUserTermPermissionsByTid
- getRoleTermPermissionsByTid
- getAllowedUserIds
- deleteTermPermissionsByUserIds
- deleteTermPermissionsByRoleIds
even
- getSubmittedUserIds (I think the parameter is not used in this one)

jepster_’s picture

Status: Postponed (maintainer needs more info) » Fixed
jepster_’s picture

Status: Fixed » Closed (fixed)