Access denied on entities referenced by the one being access checked by PbE

Created on 8 December 2024, 11 days ago

Problem/Motivation

Using PbE, entities referenced by the one being checked have access denied if "Require all terms granted"
In my case, PbE used for Media (directly accessed by url), the file attached to the media is hidden, even for User 1, if the Media has some terms associated with permission.

Actually, the File is getting access denied during the iteration over fields with referenced entities by the entity being checked, without verifying that those entities are PbT accessControlled. Depending on PbT settings, they may default to access denied if they are not PbE accessControlled

Proposed resolution

Check if referenced entities are AccessControlled before the "recursive call to check if the user is allowed to access this entity".

🐛 Bug report
Status

Active

Version

3.1

Component

Code

Created by

🇧🇪Belgium f2boot

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @f2boot
  • 🇩🇪Germany Peter Majmesku 🇩🇪Düsseldorf

    Does this error also occur with version 3.1.35? Please check.

  • 🇧🇪Belgium f2boot

    Yes, it also occurs with version 3.1.35. (and is still solved by the patch)

    As far is I can see, the isAccessAllowed function from AccessChecker service in PbE iterates recursively over the entities referenced by the entity being checked. In the case of a Media, the File entity that is referenced is treated.
    If setting "Require all terms granted", isAccessAllowed defaults access_allowed to FALSE. Since the File entity has no reference to taxonomy term, nor further entity reference (except uid), it is not changing the default and ends up with access denied while it was actually not meant to be AccessControlled by PbE.

    By checking the referenced entity isAccessControlled (false), it is not treated and therefore not access denied.

    A question subsists: should we clear the cache of isAccessDenied. I thought no, so iIset the parameter passed to the function accordingly.

    Thanks

  • 🇩🇪Germany Peter Majmesku 🇩🇪Düsseldorf

    Unfortunately I am not able to reproduce it.

    * Installed a new D11 site with PbE installed.
    * Set "Require all terms granted" setting
    * Referenced two terms to this media: admin role only, editor role only
    * Referenced the media to a node
    * Afterwards I was able to view the node and the related media as admin user

  • 🇧🇪Belgium f2boot

    Thanks for checking, sorry for not being clear enough earlier.

    In my case, I am accessing the Media directly (that needs setting "autonomous URL for media" in /admin/config/media/media-settings) and the File attached to the Media got access denied.

    In your case, you access the Node and the Media is checked for access, which is fine since, indeed, it has isAccessControlled TRUE and it probably does not go to the final "return access_allowed" = FALSE (as described above) in isAccessAllowed (because one of the terms is returning access_allowed = true by the part of the function cheking taxonomy_term)

  • 🇩🇪Germany Peter Majmesku 🇩🇪Düsseldorf

    Hi f2boot, I followed your description and tried to reproduce your issue.

    However, it works on my end.

    * I activate the "Require all terms granted" setting
    * I do relate a media entity with terms
    * I do set permissions for that terms
    * I do access the file, which is related to my media, directly
    * I try the access as guest user and admin user
    * I do experience the expected result

    Please notice, that files must be stored in the private filesystem to get secured. Also you must write your own hook_file_download() implementation.

    E.g:

    /**
     * Implements hook_file_download().
     */
    function fancy_module_media_document_file_download(string $uri) {
      $files = \Drupal::entityTypeManager()
        ->getStorage('file')
        ->loadByProperties(['uri' => $uri]);
    
      foreach ($files as $file) {
        $multipleMedia = \Drupal::entityTypeManager()
          ->getStorage('media')
          ->loadByProperties(['field_media_file.target_id' => $file->id()]);
    
        $oneMedia = reset($multipleMedia);
    
        if ($oneMedia instanceof \Drupal\media\MediaInterface) {
          /** @var \Drupal\permissions_by_entity\AccessChecker $accessChecker */
          $accessChecker = \Drupal::service('permissions_by_entity.access_checker');
          $isAllowed = $accessChecker->isAccessAllowed($oneMedia);
    
          if (!$isAllowed) {
            throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
          }
        }
      }
    
    }
    

    You can find more detailed description about securing documents in your filesystem by PbT in the documentation: https://www.drupal.org/docs/extending-drupal/contributed-modules/contrib...

Production build 0.71.5 2024