Problem/Motivation

EntityReferenceLabelFormatter properly checks if a user has "view label" entity access (only and not "view" access) but then it still renders a link to the entity's canonical page even if the user only has "view label" access (but not "view" access). When a user clicks on the link it gets a 403 page as they should.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Issue fork drupal-3293287

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

mxr576 created an issue. See original summary.

mxr576’s picture

Status: Active » Needs review
mxr576’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

Probably \Drupal\Tests\field\Kernel\EntityReference\EntityReferenceFormatterTest::testLabelFormatter() should be extended.

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.

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

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

chi’s picture

AuthorFormatter might have same bug.

mxr576’s picture

AuthorFormatter might have same bug.

It should not ... it is indirectly protected by \template_preprocess_username() --> $variables['profile_access'] = $account->access('view');

lukasss changed the visibility of the branch 3293287-entityreferencelabelformatter-returns-a to hidden.

lukasss’s picture

Assigned: Unassigned » lukasss

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

lukasss’s picture

Assigned: lukasss » Unassigned
Status: Needs work » Needs review
lukasss’s picture

Issue tags: -Needs tests
chi’s picture

I wonder if $entity->toUrl()->access() is more appropriate here than $entity->access('view').

lukasss changed the visibility of the branch 3293287- to hidden.

lukasss changed the visibility of the branch 11.x to hidden.

lukasss’s picture

If an entity type doesn't have any link templates.
We get: Cannot generate default URL because no link template 'canonical' or 'edit-form' was found for the 'entity_test_label' entity type

There is a test that checks this.
https://git.drupalcode.org/project/drupal/-/blob/11.x/core/modules/field...

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative, +Needs issue summary update

Have not yet review but issue summary appears to be incomplete. Bugs should contain steps to reproduce and proposed solution. If other sections don't apply N/A is fine.

chi’s picture

Re #18. It happens without this MR as well. Right?

lukasss’s picture

@chi yes, that's right

kumudb’s picture

There is conflict on MR so I have implement code here, please update this on MR , below error is displaying on MR
Conflict: This file was modified in both the source and target branches. Ask someone with write access to resolve it.

To resolve the issue where the EntityReferenceLabelFormatter improperly renders links to entities when the user has "view label" access but not "view" access, we need to add an additional access check within the viewElements() function. Specifically, we should ensure that the link is rendered only if the user has both "view label" and "view" access to the entity.

/**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];
    $output_as_link = $this->getSetting('link');

    foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {
      $label = $entity->label();
      // Check if the user has "view label" access.
        if ($entity->access('view label')) {
            $uri = NULL;
      // If the link is to be displayed, ensure "view" access as well.
      if ($output_as_link && !$entity->isNew() && $entity->access('view')) {
                try {
                    $uri = $entity->toUrl();
                }
        catch (UndefinedLinkTemplateException $e) {
          // This exception is thrown by \Drupal\Core\Entity\Entity::urlInfo()
          // and it means that the entity type doesn't have a link template nor
          // a valid "uri_callback", so don't bother trying to output a link for
          // the rest of the referenced entities.
          $output_as_link = FALSE;
        }
      }

      if ($output_as_link && isset($uri) && !$entity->isNew()) {
        $elements[$delta] = [
          '#type' => 'link',
          '#title' => $label,
          '#url' => $uri,
          '#options' => $uri->getOptions(),
        ];

        if (!empty($items[$delta]->_attributes)) {
          $elements[$delta]['#options'] += ['attributes' => []];
          $elements[$delta]['#options']['attributes'] += $items[$delta]->_attributes;
          // Unset field item attributes since they have been included in the
          // formatter output and shouldn't be rendered in the field template.
          unset($items[$delta]->_attributes);
        }
      }
      else {
        $elements[$delta] = ['#plain_text' => $label];
      }
      $elements[$delta]['#entity'] = $entity;
      $elements[$delta]['#cache']['tags'] = $entity->getCacheTags();
    }

    return $elements;
  }

Key Changes Made

1. Added view label Access Check:

  • Before rendering anything, ensure the user has at least "view label" access to the entity.
    if ($entity->access('view label')) { ... }
    

2. Added view Access Check for Links:

  • Ensure that links are rendered only if the user has both "view label" and "view" access to the entity.
if ($output_as_link && !$entity->isNew() && $entity->access('view')) { ... }

Testing the Changes

Scenario 1: User with Both "view label" and "view" Access

  • Expect the label to render as a clickable link to the entity's canonical page.

Scenario 2: User with Only "view label" Access

  • Expect the label to render as plain text, with no clickable link.

Scenario 3: User with No Access

  • Expect no label to be rendered for entities the user lacks access to.

kumudb changed the visibility of the branch 3293287-entityreferencelabelformatter-doesnt-have-view-entity-access to hidden.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.