If you refer to any entity with an entity reference field right now, access to that entity is not enforced when the entity is displayed through the formatter.

The attached patch adds an access check by invoking entity_access() in entityreference_field_formatter_prepare_view(), since that is where the entities are loaded, and non-existing entities are removed there as well. This was an easy fix, but you might want to handle this in the handler instead?

Comments

amitaibu’s picture

> This was an easy fix, but you might want to handle this in the handler instead?

Indeed, I think maybe we should use $valid_ids = entityreference_get_selection_handler($field, $instance)->validateReferencableEntities(array_keys($ids));, instead of just entity_acces() (For example once we get this, OG will not need to declare its own formatter, which sounds great).

fabsor’s picture

StatusFileSize
new1.18 KB

Alright, here is a version that uses the handler instead. Another upside of this is that there already are tests for this.

amitaibu’s picture

Status: Needs review » Needs work
+++ b/entityreference.moduleundefined
@@ -602,9 +602,10 @@ function entityreference_field_formatter_prepare_view($entity_type, $entities, $
+    $valid_ids = entityreference_get_handler($field)->validateReferencableEntities($target_ids);

If there are no valid-ids, maybe we can return early.

fabsor’s picture

Status: Needs work » Needs review

We still need to loop through the items array and unset inapplicable items even if we didn't get any results, the formatter_view expects to be able to render each row in items, so it will try to render them and it will result in warnings. We could go through the items array if we don't have any results and unset them in our own loop and then return, but that seems like doing double work since we have the proper logic in place anyway.

amitaibu’s picture

After testing the patch, and thinking some more I think that maybe entity_access() (i.e. the first path) is the correct approach. As a user might be able to select limited nodes but they are still allowed to view other nodes, so validateReferencableEntities will be too strict.

Status: Needs review » Needs work

The last submitted patch, no-access-check-1412572-2.patch, failed testing.

amitaibu’s picture

@fabsor, can you re-roll please?

fabsor’s picture

Status: Needs work » Needs review
StatusFileSize
new1.11 KB

Here is a reroll of the entity access patch, since that's the one that was most interesting.

amitaibu’s picture

Status: Needs review » Fixed

Committed, thanks.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

firebird’s picture

Status: Closed (fixed) » Active

This patch is causing a slight problem for me.

For referred entities that do not define an access callback, the entityreference field is not shown. This is because entity_access() returns NULL, which gets evaluated as FALSE in:

if (isset($target_entities[$item['target_id']]) && entity_access('view', $field['settings']['target_type'], $target_entities[$item['target_id']])) {

Elsewhere, for example in hook_node_access, a returned NULL value means "I don't care", whereas a FALSE means "No access".

Shouldn't the if-clause here do a strict comparison to FALSE, instead of evaluating NULL as FALSE?

firebird’s picture

Alumei’s picture

I have also noticed, that when using entity-reference to link a user, the value is only show, if the viewing user has the 'View user profiles' permission.
This result is resonable from the point, that entity_access obviously should check for that permission.
But in my usecase i want to reference a user account so that only users with the 'View user profiles' get a link to the profile page and all other users simply get the referenced account name shown.

joachim’s picture

Priority: Normal » Critical

This patch also has a serious problem in that it *removes data* from the entity.

For example, suppose I have node A that has a reference field to node B, and node B is unpublished.

In the node template, I would expect the $node object to be the same in all circumstances: it's the loaded, raw data from the database.

However, this patch has changed that: the $node object in the template has its field value *unset* when a user who does not have access to node B looks at node A.

amitaibu’s picture

> This patch also has a serious problem in that it *removes data* from the entity.

I see, so you are actually recommending to move this to the formatter itself?

joachim’s picture

Yes, definitely. Entity objects should not have their data removed.

amitaibu’s picture

@joachim, any chance for a patch :) ?

amitaibu’s picture

Issue tags: +Release blocker

Adding tags

joachim’s picture

Status: Active » Needs review
StatusFileSize
new2.55 KB

Here's a patch on RC5 which is currently identical to HEAD :)

I'm keeping the access check in entityreference_field_formatter_prepare_view(). There would be no performance change in moving it to entityreference_field_formatter_view(), but the code we'd repeat would be more complex to read, so that's one reason to keep it where it is. Also, I figure the earlier the access data gets in, the better for any alter hooks or theme preprocessing.

amitaibu’s picture

We should add tests for it. joachim, got time for this?

twardnw’s picture

Patch in #19 applies clean and access to entities is working correctly for me. My test was that an anon user cannot see unpublished node from reference on a published node.

amitaibu’s picture

Status: Needs review » Fixed

I've edited a bit the patch, and committed. thanks.
This code is already in the 8.x patch.

Automatically closed -- issue fixed for 2 weeks with no activity.