Drupal - How to grant edit access for specific nodes to 1 or more selected users?

The Group module is what you should be looking at ... It's not °overkill° (as in your question), instead it's the only stable contributed D8 module available today that will also address your needs.

For this specific question, you'd enable the gnode submodule, and for each group type you would define the appropriate permissions (view, edit, delete, etc) for the various Content Types. Refer to my answer to "How to configure access to courses for teachers and students?" for a sample configuration.

Note:

Let me address (part of) your additional comment below this answer also, which is like so:

I will need to have quite a few Groups in my case - one for each course taught by more than 1 teacher.

If I was to configure the Group module for your case, I would use an approach like so:

  • Create a Group type = Courses.
  • Create Group roles = Teacher and Student.
  • Create exactly 1 Group for each possible Course, labeled (say) C1, C2, C3, ....
  • Only grant the Group Permission to "edit" a node of content type "Course" to users who have been granted the "Group role" Teacher. And as per your "I want all nodes to still be publicly viewable by anyone (even anonymous users)", you want to grant "View" access to "Outsiders" and "Anonymous", and probably also to "Students".
  • If only teacher (user) T1 is teaching Course C1, then only T1 is granted the Group role "Teacher" for (group) C1.
  • If teachers (users) T2 and T3 are teaching Course C2, then only T2 and T3 are granted the Group role "Teacher" for (group) C2.
  • When creating nodes of type "Course", assign them to 1 (and only one) Group (so either C1, C2, or C3, or ...). And decide about which teacher(s) (user(s)) Tx the newly created Course will be granted the Group role "Teacher".

Done ...

Resources

  • Community documentation for the Group module.
  • Video tutorial "How to use the Group module in Drupal 8 to manage editorial access control to different areas of a web site".

If you have a content type course with an entity reference field field_teachers you can enable edit for multiple users like this:

mymodule.module:

use Drupal\node\NodeInterface;
use Drupal\Core\Access\AccessResult;

/**
 * Implements hook_node_access().
 */
function mymodule_node_access(NodeInterface $node, $op, $account) {
  $type = $node->bundle();

  if ($type != 'course' || $op != 'update') {
    return AccessResult::neutral();
  }

  $uids = array_column($node->field_teachers->getValue(), 'target_id');

  return AccessResult::allowedIf(in_array($account->id(), $uids))->cachePerUser()->addCacheableDependency($node);
}

If field_teachers is not referencing users but another content type, then the uid of the teacher is probably stored in the referenced content type and you have to fetch the uid of each teacher from there. In this case add all nodes involved as cacheable dependencies, so that when a teacher's node is modified with a different uid the access result is invalidated.


You can look into the Workbench Access module. This allows you to restrict editing rights to nodes based on menu structure or a taxonomy.

You can create a taxonomy vocabulary for the different editor groups. Example terms may be 4th Grade Math, 5th grade Science, etc, or even just Math, Science, etc. Add a taxonomy reference field to your Courses node, this is used to assign your content to your Groups. Then you can assign your users (teachers) to the correct Group (which are just based on your taxonomy vocabulary) and all teachers in the group can edit the node.

You could implement a situation where each course creates a corresponding taxonomy term automagically when a course node is created. You can do this with hook_ENTITY_TYPE_insert.

Something like the following:

function hook_node_insert($node) {
  if ($node->bundle() == 'course') {
    // Check if a term with the $node->title() already exists. (See below [1])
    // Or create a term (See below [2])

    // Then set your taxonomy term reference field with the new tid, or existing tid
    $node->field_my_tax_group_field[] = ['target_id' => $the_tid];

    // Then save the node.
    $node->save();
  } 
}

If you use this technique, the only thing you'll need to do manually after creating a Course node is assign the correct users to the Group to allow them to edit it.

[1] Check if a term exists.

[2] Create a new taxonomy term

Tags:

Nodes

Users

8