Quantcast
Channel: Issues for Drupal core
Viewing all articles
Browse latest Browse all 295852

node_access filters out accessible nodes when node is left joined

$
0
0

Problem/Motivation

If you are looking for a D7 version of this, see #3176634: [D7] node_access filters out accessible nodes when node is left joined.

Currently, when a node table is left joined into a query, adding a node_access tag to the query filters out accessible rows from the base table (effectively acting more like an inner join). In particular, rows containing null values are incorrectly filtered out by node_access (i.e., if the base table has null entries for the node ID, node_access denies access to all users based on those null values, even though they should have no relevance to node_access checks). The most common example is a view where rows disappear from the table after adding an optional relationship to the view.

See the tests in patch #326 to reproduce, or manually:
1. enable Views,
2. Create a field referencing nodes
3. Create a node having the entity reference field empty,
4. Create a View with a relationship using the entity reference field. Do NOT select "Require this relationship".
5. Expected result is that regular users can see the node in the View. Current result is that regular users cannot see the node.

Proposed resolution

The problems can be fixed by altering how the node_access conditions are added into the query whenever the node table is a joined table. Currently the conditions are added to the overall query conditions; the proposal is to instead add the node_access conditions into the join conditions.

This approach maintains the integrity of the node_access checks: all nodes to which the current user is denied access are removed from the query results. However, it makes as few additional changes as possible to the query results.

The primary effect is that rows containing optional, empty (null node ID) entries are no longer removed. Furthermore, if rows contain optional (left-joined) content from an access-denied node, only the content of the denied node is removed from the results. In the context of a view, this means that any individual cells of a table containing restricted content will be blanked, but non-restricted content in the rest of the row is still visible to the user.

Things discussed

  1. Recent questions include:
    1. Is the current patch, which avoids an API change, preferable (see #321)? => Yes
    2. Is it appropriate for a bug-fix patch to incorporate code for a requested feature (see #319)? => No
  2. Write tests. (Patch #326 contains comprehensive tests, including nested joins and all combinations of accessible and restricted content.) This needs tests for #480-3 which Spokje replied to in #489.
  3. In Postgres with 3 node tables and a count query, placeholders are getting inserted in the wrong sequence.(This was an issue for patch #149 but was reported as fixed by a subsequent patch. The current D8 patch doesn't edit the placeholders, and has been tested successfully using PostgreSQL.)
  4. Address issue of node access with a type of "entity" -- no known cases where this bug is triggered, recommend creating new issue.(The entity-specific query alterations have been removed in D8, making the issue no longer relevant.

User interface changes

None

API changes

None

Data model changes

None

Detailed example

As an example, a site has 'page' nodes containing a field that is a reference to a related 'article' node. A view is created to list the page nodes: the page title is shown in the first column; the related article's title is shown in the second column (using an optional relationship). The following is the view as seen by an admin. Any node with 'public' in the title is visible to everyone; any node with 'private' in the title should not be visible to regular users.

Case A: admin view
Page titleArticle title
Public-page-1Public-article-a
Public-page-2[none]
Public-page-3Private-article-b
Private-page-4Private-article-c


With current code, the table shown to non-admins incorrectly removes some rows containing public pages:

Case B: public view, unpatched
Page titleArticle title
Public-page-1Public-article-a


With patch #326, regular users will see:

Case C: public view, patched
Page titleArticle title
Public-page-1Public-article-a
Public-page-2[none]
Public-page-3[none]

All private pages and private articles have been filtered out. Public-page-3 is still displayed because it is public content; the reference to private-article-b is in an optional column, implying that unavailable content should result in a blank cell instead of removing the entire row.

Some users may prefer to construct a view where the entire row is removed if it contains a reference to an inaccessible article. In many cases, such views will simply want to change the article column into a required column. If, however, it is necessary to keep rows with missing articles, and only filter rows with inaccessible articles, users can add the appropriate filter into the view, for example, "where article_title is null AND article_reference is not null". This would produce:

Case D: public view, alternate
Page titleArticle title
Public-page-1Public-article-a
Public-page-2[none]

Different approaches were tried to address all the identified scenario's and the current approach ticks all the boxes.

Original report by [username]

I'm loving the Entity Reference module, but I've come across some weird behavior. It's probably just something I've missed setting.

I have a content type called Album. I've got another content type called Review which has an entity reference to Album.

I've created a View which lists Albums. I wanted to include some fields from my Review content type, but I still want to list each Album, even if a review referencing the album has not been created yet.

In my view, under Relationships, I add an "Entity Reference: Referencing entity" relationship. I make sure "Require this relationship" is NOT checked.

When I'm logged in as an administrator, all Albums are returned, as expected. But when I'm not logged in, or I'm logged in as a regular user, only albums that are referenced by a review are displayed. I'm really puzzled as to why I get different results depending on my user role.

I get the same results regardless of if I add fields from the Review content type or not. I've tried clearing the cache multiple times, and I've tried checking and unchecking the "Require this relationship" box. I've deleted the relationship and tried adding it again, but I always get the same results.

Release notes snippet

Queries with the node_access tag now get the access information joined to the correct table. This means that when joining the node table this data will be added to the correct join. Previously it would get joined on the base table which could cause results that should be visible to disappear. It also means that for queries with multiple joins to the node table there will be additional joins which might lead to longer query run times.


Viewing all articles
Browse latest Browse all 295852

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>