--> AI generate content, reviewed by Greg -->
Problem
farm_multitenant_query_quantity_access_alter() in farm_multitenant.module (~line 315) restricts every access-checked quantity entity query to quantities reachable via log__quantity → log → asset/equipment/location → the organizations of the current user's groups.
Quick forms (farmOS core QuickLogTrait and everything built on it) save their quantity entities first, then create the log that references them. While the log is being validated, its quantity field's ValidReference constraint runs an access-checked selection query on the just-created quantities — which have no log__quantity row yet, so the alter filters them out and validation fails with:
quantity.N.target_id: This entity (quantity: NN) cannot be referenced.The whole submission rolls back. Only administer quantity / administer farm_multitenant bypass the alter, so every quantity-bearing quick form is effectively admin-only on any farm_multitenant site, regardless of which granular quantity permissions the user's role carries (verified: granting the full standard/material quantity permission set changes nothing).
Reproduction
farmOS 4.x + farm_multitenant 2.0.0-beta1 + PostgreSQL 16.
- Create a user with a non-admin role that has full granular quantity permissions (
create standard quantity,view any standard quantity, …) and membership in a farm group. - As that user, submit any quick form that records a quantity (e.g. farmOS core's Planting quick form with a quantity, or any custom quick form using
QuickLogTrait::createLog()with aquantityarray). - Validation fails with
This entity (quantity: NN) cannot be referenced.and the submission rolls back.
Drush-level repro of the underlying query (as that user):
$q = \Drupal::entityTypeManager()->getStorage('quantity')->create(['type' ='standard', 'value' => 1]); $q->save(); // ValidReference-style selection query: $handler = \Drupal::service('plugin.manager.entity_reference_selection')->getInstance(['target_type' => 'quantity', 'handler' => 'default']); var_dump($handler->validateReferenceableEntities([$q->id()])); // [] — own quantity not referenceable.
Proposed fix (MR attached)
OR an own-quantity exemption into the alter's existing orConditionGroup(): the current user's own quantities (quantity.uid = current user) are always referenceable. The quantity entity uses EntityOwnerTrait with the uid owner key, so the base table carries the owner natively.
Rationale: a quantity that no log references yet is only meaningful to its creator (it is invisible everywhere else in the UI), so exempting own quantities closes the validation gap without leaking any other farm's data. The farm-membership chain (log__quantity → log → asset → farm) is kept unchanged for everything else.
Tradeoff to weigh explicitly: the exemption is unconditional on ownership — a user's own quantities stay query-visible to them even after a log ties them to a farm the user has since left. That diverges from the purely membership-based asset/log alters. We think it's defensible (own-authored data; the log and asset context around such a quantity remain membership-scoped), but it is a policy choice the maintainer should make deliberately rather than infer. A stricter alternative — exempting only quantities with no log__quantity row — closes the validation gap too, at the cost of an extra join and of own quantities disappearing from the user's query results the moment their log is saved.
The MR also:
- keeps the deny-all (
1 = 0) behavior for anonymous users without farm memberships (and never adds an empty condition group, which Drupal would silently drop — opening access); - lets a user with no farm memberships still access their own quantities (previously
1 = 0for them, which broke the same validation path for org-less users); - adds a kernel test (
tests/src/Kernel/QuantityQueryAccessTest.php) covering: own not-yet-referenced quantity passes an access-checked entity query and a ValidReference-style selection; another user's quantity in a non-member farm stays filtered out; the farm-membership chain still works; anonymous gets nothing.
Workaround until fixed
Grant administer quantity to affected roles (over-broad — it also bypasses all granular quantity access control), or apply the MR diff via cweagans/composer-patches.
Related
- The same alter unconditionally joins
log__equipment, which breaks installs withoutfarm_equipment(filed separately, see the log_access issue). src/Plugin/views/filter/QuantityAccessFilter.phpduplicates this logic for Views listings; it has the same no-own-quantities property (a user's own not-yet-referenced quantities never show in quantity Views). Not fixed in this MR to keep it reviewable — happy to follow up if wanted.
Environment
- Drupal core 11.3.x
- farmOS 4.x
- farm_multitenant 2.0.0-beta1
- PostgreSQL 16
Issue fork farm_multitenant-3612253
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
gbathree commentedComment #4
gbathree commentedComment #5
peacog commentedComment #6
peacog commentedThanks for the MR @gbathree. I agree that it's acceptable the a user will always see their own quantities, even if the associated asset gets assigned to a farm that the user is no longer a member of.
I'm not sure about the checks for $account->isAuthenticated(). By default all farmOS records are private and can't be accessed by an anonymous user. In theory you could give read permission to the anonymous user, but in that case you would want the permission to dictate whether or not they can access quantities. It would be wrong to deny access based solely on $account->isAuthenticated().
Comment #7
gbathree commentedSo can you clarify your suggestion then? Are you saying that basically it's not necessary to worry about quantities as it relates to multi-farm since we're accepting that a user can see quantities even when the associated log is moved to another farm and the other case of concern (an anonymous user) isn't relevant anyway?
Sorry, just want to make sure I have an understanding and can either finish this or close it out.
Comment #9
peacog commentedYes @gbathree, that's it exactly. I adapted your fix to work with improvements made to the module's hook_query_TAG_alters.
Thank you!