I have following requirements:
- Users have (among others) role "tier1", "tier2" or "tier3". Higher value means more permissions and anonymous users are considered "tier0".
- Users from tier2 and tier3 can create certain node type - MyNode. And only these users can update and delete them.
- The node type MyNode contains (my custom) field for restricting access - it's a simple integer. 0 means all users can access it, 1 means users of tier 1-3 can access it, etc.
What's the proper way to implement the node restriction?
What I tried & longer description of the problem
After Googling and reading documentation, I found hook_entity_access. I simply iterated all fields and if I found my access field type, read the value and handle it. It was working pretty nicely for viewing, editing and deleting. But not for views - they completely ignored that.
After some more googling, I found that hook_entity_access/hook_node_access are ignored in views as explained on Node access rights. This page also explains that this problem should be solved by using hook_query_TAG_alter, however I can't understand how it should be used. It seems to me I'm missing some bigger picture and failed to google it. But I found another solution - to use hook_node_access_records with hook_node_grants. I implemented this solution (with a tutorial help).
So each instance of MyNode provide grant based on field value, e.g. gid 2 means tier 2-3 can access the node. Each user is given grants based on their tier role, e.g. user with tier1 receive grants with gid 1, 2 and 3. This fixed view problem, but caused another one - if I set access of a node to 3, then users of tier 0-2 cannot view it (that's correct), but user of tier 2 can edit it (that's problem).
After some testing, it seems like permissions are handled differently for view and update/delete. View grant permissions are AND-ed with basic permission system (/admin/people/permissions), but update/delete permissions are OR-ed. I used the basic permission system to determine which roles can generally create, update and delete MyNode nodes.
So my current solution is merge of both approaches - grant system for views and hook_node_access for working with nodes directly. However, it seems to me quite hacky, dirty solution - I practically implemented same thing twice in different systems, because each system can handle only subset of all operations. And so, my question is - what's the proper implementation? What is correct Drupal-way?
Note: of course, I looked at modules to solve this. I rejected most of them, because they're still in alpha/beta/rc phase, while lifetime of D8 is ending. How much time I would have to wait for D9 implementation? Others were imho too bloated for "simple" "compare numeric value with role and accept/reject".
My system: Drupal version: 8.8.3