Controlling/selling node access by node reference? I have been using Drupal for many years now (starting with Drupal 6) and only recently - in the context of a big project - made the switch to D8. So far, working with D8 has been a very pleasant experience, to say the least. I was prepared, however, that there would be a few rocks on the road. And I would like to ask for help removing a big one (for me)...
In a nutshell, the situation is this: I am creating a kind of learning management system (LMS), with lessons, courses and classes. Each lesson belongs to exactly one course, but each courses may or may not belong to zero, one or more classes. I was thinking of using simple node references to structure this:

a field in the content type lesson that references the course that this lesson belongs to
and an entity reference field in the content type class that references all courses in this class (so, this is referenced the other way round)

Now, I'd like to sell access to each of these content types and my problem is this: If a user buys access to one of the classes, she should also be able to access all of the courses (and lessons) that are referenced by this class. So, when checking the access permissions for a single course, the system will not only have to check, if the user has bought this course, but also, if the user has access to a class that contains this course.
I was first thinking of solving this with the module Node access node reference, but this seems to work the other way round (and doesn't have a D8 version). Same for Access by Reference. (In general, most of the access control modules I looked at, don't seem to be ready for D8 yet.) But what about rule-based access control? Or groups?
Can anybody suggest a way forword?
Any help would be much appreciated.
Thanks in advance.
Why not go custom access the main thing is relating your "Class" or Item to the product the person buys aka on the product you could create a entity reference to the node or class or whatever  ...

you can do some thing like the following 

use Drupal\Core\Access\AccessResult;
/**
* Implements hook_node_access().
*/
function mymodule_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Session\AccountInterface $account){
// Note thes checks do not work on admin (user 1). and clear cache each time.
$type = $node-&gt;bundle();
if ($type === 'your_content_type') {
  if ($account-&gt;id() !== 0) {
    $user = $account-&gt;getAccount();
    $uid = $user-&gt;id();
    // Ok we know is trying to access and the node type.
    $storage = \Drupal::entityTypeManager()-&gt;getStorage('commerce_order');
    $orders = $storage-&gt;loadByProperties(['uid' =&gt; $uid]);
    if (count($orders) != 0) {
      $has_bought = FALSE;

      // CUSTOM FIND Your Corse .
      $corse_type = $node-&gt;field_corse_type-&gt;value;
      foreach ($orders as $order) {
        $order_items = $order-&gt;order_items-&gt;referencedEntities();
        foreach ($order_items as $item) {
          // Do better than this lol ...
          // dump($item);
          if ($item-&gt;title-&gt;value == 'SOME Course' &amp;&amp; $corse_type == 'SOMETHING RELATED TO PRODUCT') {
            $has_bought = TRUE;
        }
      }
    }
    // final check.
    if ($has_bought === TRUE) {
      return AccessResult::isAllowed();
    }
    else{
      // Kick them. as not bought.
      return AccessResult::forbidden();
    }
  }
  else {
    // Kick them. as not paid.
    return AccessResult::forbidden();
  }

  }
  else {
  // kick them.
  return AccessResult::forbidden();
  }
 }
 else {
  return AccessResult::neutral();
  }
}