Anonymous user see all

Created on 14 April 2020, over 4 years ago
Updated 11 July 2023, over 1 year ago

I Have a View of "Products - Books"

Product contains Authors and Illustrators fields (reference entity - separate node Autor)

I wanted to list related books on the author or illustrator node (contextual filter author_filed OR Illustrator field).
It works independently (only Author_field or only Illustrator_field). If I enable the OR module to have it in one view, the Administrator sees it correctly, but the anonymous user sees all the products (as if there was no contextual filter).

🐛 Bug report
Status

Active

Version

1.1

Component

Code

Created by

🇨🇿Czech Republic mandus.cz

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

Comments & Activities

Not all content is available!

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

  • 🇳🇿New Zealand john pitcairn

    I'm seeing this problem with a view of Profile entities, using the "OR" condition on two contextual profile_id arguments. Any user who does not have "administer profiles" permission sees all profiles on the system.

    Stepping through it with a debugger, the condition group this module adds looks correct when it is added. But I think something later in the rewrite/access chain is messing it up for users without administer permission for the base table entity. That's why "Disable SQL rewriting" fixes this, but it's a potentially dangerous fix.

  • john pitcairn has a good start. After some digging, the issue appears to be with how Drupal adds additional entity access conditions for the `status` field. In our example, I have a view that displays a list of practitioner profiles and the contextual filter is using the OR module extension, by listing profiles where the primary address OR secondary address are within a set distance.

    Here's a very simplified query pseudo code. In the WHERE clause Drupal adds a condition for profile status to the Contextual filters AND View Filters. Normally, if this an "AND" that's not a problem. When the access control is run, the condition `profile.status == 1` is removed if you are a member of "administer profiles".

    SELECT first_name, last_name, title 
    FROM profile
    WHERE ((primary distance < 40 OR secondary distance < 40 OR profile.status == 1) AND (profile.publish == 1 AND profile.status == 1))

    Contextual Filter Group: (primary distance < 40 OR secondary distance < 40 OR profile.status == 1)
    View Filter Group: (profile.publish == 1 AND profile.status == 1)
    This condition is removed if you have "administer profile" access: profile.status == 1

    Either the OR extension module should be updated to somehow manage this issue or Drupal 10 needs to come up with a different method for appending `status` fields, which I'm guessing is used by most entities. The solution is maybe the altering the query to look something like this when using OR for contextual filters.

    SELECT first_name, last_name, title 
    FROM profile
    WHERE (
        # contextual filter grouping
        (
            (primary distance < 40 AND profile.status == 1) OR 
            (secondary distance < 40 AND profile.status == 1) 
        ) 
        AND
       # view filter grouping 
       (profile.publish == 1 AND profile.status == 1)
    )

    Here's where the profile.status condition is added.

    web/modules/contrib/entity/src/QueryAccess/ViewsQueryAlter.php Line #133 $query->addWhere(0, $sql_conditions);

    
    /** @var \Drupal\entity\QueryAccess\QueryAccessHandlerInterface $query_access */
        $query_access = $this->entityTypeManager->getHandler($entity_type_id, 'query_access');
        $conditions = $query_access->getConditions('view');
        if ($conditions->isAlwaysFalse()) {
          $query->addWhereExpression(0, '1 = 0');
        }
        elseif (count($conditions)) {
          // Store the data table, in case mapConditions() needs to join it in.
          $base_table['data_table'] = $entity_type->getDataTable();
          $field_storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($entity_type_id);
          /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
          $table_mapping = $storage->getTableMapping();
          $sql_conditions = $this->mapConditions($conditions, $query, $base_table, $field_storage_definitions, $table_mapping);
          $query->addWhere(0, $sql_conditions);
        }
    
    
Production build 0.71.5 2024