- 🇳🇿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); }