2

We deal with nodes representing humans with two important properties: mother and father.

Your parents as well as your aunts and uncles should get extra permissions, like to see you in a certain view mode, or to see your private images.

Where should I place this complex access control in a way that I can easily call it in several controllers and hooks?

Is there a name for the kind of feature I'm going to program?

If there's no better idea, I would go with a validation. We could put the access control in a validator that we use like this:

$errors = $family_access_validator->validate($node);
if (count($errors) > 0) {
    throw new AccessDeniedHttpException();
}

However, I'm not sure whether this is the correct approach. When we use validation, we are always interested in the message why the data is rejected. Here, we are only interested in OK or not OK.

2

2 Answers 2

5

For access control on routes, you can write a service which implements AccessInterface. At its simplest, this is just a class placed in a module's src/Access folder with a single method public function access(AccountInterface $account), returning a flavour of AccessResult. Then you simply register your class in the module's services.yml, annotate the route to use that access checker and Drupal will do the rest. Relevant documentation

The documentation suggests that if the route being access-checked has an upcasted parameter like {node}, then you can add $node to function's arguments - i.e. public function access(AccountInterface $account, Node $node) and it will be automatically supplied. I haven't actually tried that part myself though. Assuming it works, you can then access the node's fields as normal in order to compare the entity ids of the mother/father fields with the user to which the $account belongs.

I'm not sure if there are similar ways to automatically invoke this same access check for displaying entities with different view modes, but at the end of the day it is just a service like any other, so you could always request it from the container or inject it into whatever other controllers / services / hooks you need. In these contexts you will of course have to 'manually' supply the current user $account and relevant $node to check.

4

Where should I place this complex access control in a way that I can easily call it in several controllers and hooks?

Is there a name for the kind of feature I'm going to program?

The term/concept you're looking for is a Service:

Drupal 8 introduces the concept of services to decouple reusable functionality and makes these services pluggable and replaceable by registering them with a service container. As a developer, it is best practice to access any of the services provided by Drupal via the service container to ensure the decoupled nature of these systems is respected.

The above link describes in detail how to create services, and how to access them via the service container, both statically and via dependency injection.

Once you know these methods, you'll be able to easily re-use your functionality in controllers, hooks, plugins, other services, and beyond.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.