I realize this is quite a specific Drupal commerce question, but perhaps I can get some insights as I am stuck here.
I need to control access to commerce orders on a per-order basis based on an entity reference field. So users will not have access to view commerce orders, except if they are related to them.
My custom access check requires an operation, and entity and a user.
Looking at all the hooks Drupal commerce executes in order to determine access:
commerce_order_access()
calls the generic access helper,commerce_entity_access()
for view operations, this constructs an access query based on the entity, which relies on Database API invoking hook_query_TAG_alter(). For orders, this ishook_query_commerce_order_access_alter()
.commerce order's implementation of this hook,
commerce_order_query_commerce_order_access_alter
(), calls a generic implementation back in commerce module,commerce_entity_access_query_alter()
.commerce_entity_access_query_alter()
checks entity type and user access permissions for the entity and builds an OR conditions array that you can alter for Orders usinghook_commerce_entity_access_condition_commerce_order_alter()
.
All these functions however never get a specific entity to operate on and always check 'global' permissions with user_access()
.
The committed patch Pass entity to Commerce entity access check contexts changes this so the entity is added to the query metadata in commerce_entity_access()
and as such can also be used in hook_commerce_entity_access_condition_commerce_order_alter()
.
So far so good, this works and I can check access to my order in hook_commerce_entity_access_condition_commerce_order_alter()
.
The real problem
The problem I run into occurs when loading the orders through Views;
Views does not load the entity but just adds it to the select query and then performs the above access checks, starting with commerce_order_query_commerce_order_access_alter()
(hook_query_TAG_alter()
). This way the entity is not set (commerce_entity_access()
is never called) and thus not available for access checking and all there is for me to alter is the query.
The thing I came up with
Actually the only thing I could think of was to load all commerce order entities, run them all through my access check and save the id's of the allowed orders. Then in hook_commerce_entity_access_condition_commerce_order_alter()
add all these id's to the query in a condition.
I am however afraid this will be a huge performance drop once there have been made some orders
So is there a way I can fetch entities from a Views select query? Or id's? Or do I need to implement my check elsewhere?