Entity API and RESTful Web Services: keeping field-level access consistent between Views and JSON:API output
0 reputation · 18 Jul 2025, 15:10 UTC
0 reputation · 18 Jul 2025, 15:10 UTC
I am designing a Drupal 10 site where a custom entity type (defined via the Entity API, with two bundles and several fielded sub-resources) must be exposed through both a Views "Entity list" display for site visitors and a JSON:API endpoint provided by the RESTful Web Services module for an external client application.
The integration concern is access control. Field-level restrictions are implemented with hook_entity_access() plus field access logic, and I need both output channels to honor the same rules. My uncertainty is whether the Views entity display plugin and the JSON:API serializer evaluate field access through the same code path, or whether each applies its own filtering, which could cause a field to be hidden in the rendered View but still present in the JSON response (or the reverse).
Access results are also cacheable, so I am unsure which cache contexts and tags must bubble up correctly when the same entity is rendered through two different pipelines.
31775 reputation · 18 Jul 2025, 17:06 UTC
1. Do Views and JSON:API use the same access layer?
Yes. Both pipelines call field_access() (which in turn invokes hook_entity_access() and the field‑access API) to decide whether a field should be rendered. The Views entity display uses entity_view(), and the JSON:API serializer calls the same routine for every exposed field. Therefore, if your field‑visibility logic lives in hook_entity_access() or the field‑access API, it will automatically apply to both Views and JSON:API without duplication.
2. Which cache metadata is required?
user.permissions – changes when the user’s permissions change.user.roles – changes when the user’s roles change.entity_field_access – added by the Entity API to invalidate when a field’s access settings change.url – optional if you expose different views per URL (e.g., Views exposed filters).entity_field_access – invalidated when any field’s access configuration changes.entity:entity_type – invalidated when the entity type definition changes.entity:entity_type:bundle – invalidated when a bundle’s field configuration changes.entity:entity_type:entity_id – ensures that updates to a specific entity instance clear the cache for that instance.Both Views and JSON:API automatically add most of these contexts and tags. If you add custom field‑visibility logic (e.g., hook_entity_view_alter() that hides fields), remember to attach entity_field_access yourself.
3. How to verify parity programmatically?
$config['entity']['debug'] = TRUE) and look at the hook logs for a request to the Views page and a JSON:API request. The decisions logged should match.entity_view() and records the fields that appear in the render array.data.attributes array.These steps give you a repeatable, automated way to confirm that Views and JSON:API honour the same field‑level permissions.
We assume your custom entity type implements CacheBackendInterface and registers the entity_field_access tag; if not, the tag will not be propagated and field‑level changes will not invalidate the cache. If you use a custom JSON:API serializer or a Views plugin that alters field visibility, you must ensure those components also attach the same cache contexts and tags.
Do you have any custom field‑visibility logic outside of hook_entity_access() (e.g., hook_entity_view_alter(), a custom serializer, or a Views plugin that hides fields)? That detail could affect whether the two pipelines stay in sync.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.