EntityReferenceLabelFormatter returns a link even if the user only have "view label" access

Created on 29 June 2022, over 2 years ago
Updated 13 April 2024, 7 months ago

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

🐛 Bug report
Status

Needs work

Version

11.0 🔥

Component
Field 

Last updated about 9 hours ago

Created by

🇭🇺Hungary mxr576 Hungary

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇷🇺Russia Chi

    AuthorFormatter might have save bug.

  • 🇭🇺Hungary mxr576 Hungary

    AuthorFormatter might have same bug.

    It should not ... \Drupal\user\Plugin\Field\FieldFormatter\AuthorFormatter::checkAccess()

  • 🇷🇺Russia lukasss Novoukrainskoe

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

  • 🇷🇺Russia lukasss Novoukrainskoe
  • Pipeline finished with Failed
    15 days ago
    Total: 84s
    #325840
  • Pipeline finished with Failed
    15 days ago
    Total: 86s
    #325897
  • Pipeline finished with Failed
    15 days ago
    Total: 3386s
    #325907
  • First commit to issue fork.
  • Pipeline finished with Success
    15 days ago
    Total: 4147s
    #326119
  • 🇷🇺Russia lukasss Novoukrainskoe
  • 🇷🇺Russia lukasss Novoukrainskoe
  • 🇷🇺Russia Chi

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

  • 🇷🇺Russia lukasss Novoukrainskoe

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

  • 🇷🇺Russia lukasss Novoukrainskoe

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

  • 🇷🇺Russia lukasss Novoukrainskoe

    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...

  • 🇺🇸United States smustgrave

    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.

  • 🇷🇺Russia Chi

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

  • 🇷🇺Russia lukasss Novoukrainskoe

    @chi yes, that's right

  • 🇮🇳India KumudB Ahmedabad

    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.
  • 🇮🇳India KumudB Ahmedabad

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

  • Pipeline finished with Failed
    3 days ago
    Total: 203s
    #337144
  • Pipeline finished with Failed
    3 days ago
    Total: 159s
    #337146
Production build 0.71.5 2024