Problem/Motivation

The \Drupal\views\Plugin\views\field\LinkBase::render() method is presuming too much by not rendering a link whose destination page is not accessible by the current user. The actual behaviour could cover most of the cases but there are still business scenarios when a role should be able to list content, including the URL, but still without the ability to access the content page. This is somehow similar to view label entity access introduced in https://www.drupal.org/node/2661092.

Not having access to a content item, doesn't mean automatically that the content's address cannot be read.

Proposed resolution

Add a new option "bypass_access" in \Drupal\views\Plugin\views\field\LinkBase that allows the site builder to bypass the access check when a link is rendered. The new option should default to FALSE, so the behavior of the actual will not be changed.

Remaining tasks

None.

User interface changes

New option as a checkbox the the Views link fields.

API changes

None.

Data model changes

Views config new option in fields.

Issue fork drupal-3008254

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

claudiu.cristea created an issue. See original summary.

claudiu.cristea’s picture

Status: Active » Needs review
StatusFileSize
new10.14 KB

Here's a patch.

dimilias’s picture

That is an initial review. However, I am not 100% familiar with the link base and the usage in Drupal (like the Url class) so it would be nice to have more than one reviews on that.

  1. +++ b/core/modules/views/src/Plugin/views/field/LinkBase.php
    @@ -95,6 +96,12 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    +      '#description' => $this->t('When on, the link will be displayed regardless if the user is allowed to access the link destination page.'),
    

    "When checked" is more appropriate here.

  2. +++ b/core/modules/views/src/Plugin/views/field/LinkBase.php
    @@ -122,6 +129,12 @@ public function query() {
    +    if ($this->options['bypass_access_check']) {
    +      return [
    +        '#markup' => $this->renderLink($row),
    +      ];
    +    }
    +
    

    This can be added in the access check below as

    $access = $this->options['bypass_access_check'] ? AccessResult::allowed() : $this->checkUrlAccess($row);
dhirendra.mishra’s picture

Assigned: Unassigned » dhirendra.mishra
Status: Needs review » Needs work

working on it

claudiu.cristea’s picture

Assigned: dhirendra.mishra » Unassigned
Status: Needs work » Needs review
StatusFileSize
new10.42 KB
new1.74 KB

Fixed requests from #3. I improved more the description message.

dimilias’s picture

Status: Needs review » Reviewed & tested by the community

Patch works fine for me. Setting to rtbc.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 5: 3008254-5.patch, failed testing. View results

dimilias’s picture

dimilias’s picture

Changing this to needs work as the tests failed.

claudiu.cristea’s picture

Status: Needs work » Needs review
claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community

It was the branch that failed. Back to RTBC as the branch test passed and the patch is back to green.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

I'm not entirely sure about the rationale stated in the issue summary. Drupal goes out of its way very often to not render links to things a re user does not have access to. Are we sure this functionality is core-worthy? It'd be great to see a views maintainer or product manager chime in on this issue.

+++ b/core/modules/views/views.post_update.php
@@ -366,3 +367,32 @@ function views_post_update_table_display_cache_max_age(&$sandbox = NULL) {
+function views_post_update_bypass_access_check() {
+  /** @var \Drupal\views\Plugin\ViewsHandlerManager $field_manager */
+  $field_manager = \Drupal::service('plugin.manager.views.field');
+
+  /** @var \Drupal\views\ViewEntityInterface $view */
+  foreach (View::loadMultiple() as $view) {
+    $displays = $view->get('display');
+    $save = FALSE;
+    foreach ($displays as $display_name => &$display) {
+      if (isset($display['display_options']['fields'])) {
+        foreach ($display['display_options']['fields'] as $field_name => &$field) {
+          $field_instance = $field_manager->getHandler($field);
+          // Consider all plugins extending LinkBase.
+          if ($field_instance instanceof LinkBase) {
+            $field['bypass_access_check'] = FALSE;
+            $save = TRUE;
+          }
+        }
+      }
+    }
+    if ($save) {
+      $view->set('display', $displays)->save();
+    }
+  }
+}

Use ConfigEntityUpdateer to do this in a batch. See views_post_update_table_display_cache_max_age() for an example.

claudiu.cristea’s picture

@alexpott, Drupal renders entity labels even the user don't have access to render the entity ('view label' permission).

alexpott’s picture

@claudiu.cristea yeah but that is a bug.

lendude’s picture

Yeah this feels very edge case-y to me. Anything that adds something called 'bypass_access_check' gives me pause.

Is there any reason that when you need this you can't just extend whatever plugin you need to override and hook_field_views_data_alter/hook_views_data_alter to use your plugin for the appropriate fields? I understand that this can be hassle if you want this for all plugins extending LinkBase, but realistically we are only talking about EntityLink right (RevisionLinkRevert anybody?).

Well that's my 2 cents any way.

claudiu.cristea’s picture

@alexpott, @Lendude

Thank you for your feedback.

@claudiu.cristea yeah but that is a bug.

Yes, but it was introduced to satisfy the need of allowing to access entity listings without being able to access the rendered entity or the entity edit form. In the real world the permission to access the content listing may be be different than the access to the content item itself. #2953566: Allow entities to specify a "collection permission" has a good description showing why sometime accessing content lists should be allowed while still not being able to access the full content item.

Also I think the current behavior is wrong. A link that you cannot "see" is, IMO, a link that returns 404. The link doesn't exist because the destination page doesn't exist. A link that returns 403 is a "known" link, just that you'll receive a 403 if you're trying to follow. What now the plugin is doing, is just obscuring a link which you cannot access.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

claudiu.cristea’s picture

StatusFileSize
new10.42 KB

Reroll for 8.8.x.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

pfrenssen made their first commit to this issue’s fork.

pfrenssen’s picture

StatusFileSize
new10.38 KB

Rerolled against 9.4.x and opened a MR for it.

Here is also a patch rolled against the current stable 9.3.x. branch.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

claudiu.cristea’s picture

Status: Needs work » Closed (won't fix)

This doesn't seem to be a very popular solution. Closing.