Last active
September 28, 2024 10:42
-
-
Save adamfranco/5814eba660cbda3c93b5253b28b325ab to your computer and use it in GitHub Desktop.
Extending the Drupal Group module with an AccessControl decorator for a node visibility field
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
services: | |
group.relation_handler_decorator.access_control.visibility_field: | |
class: 'Drupal\middlebury_course_hub\Plugin\Group\RelationHandler\VisibilityFieldAccessControl' | |
decorates: 'group.relation_handler.access_control' | |
decoration_priority: 500 | |
arguments: ['@group.relation_handler_decorator.access_control.visibility_field.inner'] | |
shared: false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Drupal\middlebury_course_hub\Plugin\Group\RelationHandler; | |
use Drupal\Core\Access\AccessResult; | |
use Drupal\Core\Entity\EntityInterface; | |
use Drupal\Core\Session\AccountInterface; | |
use Drupal\group\Plugin\Group\RelationHandler\AccessControlTrait; | |
use Drupal\group\Plugin\Group\RelationHandler\AccessControlInterface; | |
/** | |
* An access control handler that grants view access based on visibility field. | |
* | |
* In the Course Hub instructors can set a "visibility" field to make syllabus | |
* and resources visibile to just the "class" (group members), "institution" | |
* (all authenticated users), or "public" (anonymous) visitors. | |
* | |
* This Access Control handler looks at that field and opens up access if | |
* needed. | |
*/ | |
class VisibilityFieldAccessControl implements AccessControlInterface { | |
use AccessControlTrait; | |
/** | |
* Constructs a new VisibilityFieldAccessControl. | |
* | |
* @param \Drupal\group\Plugin\Group\RelationHandler\AccessControlInterface $parent | |
* The parent access control handler. | |
*/ | |
public function __construct(AccessControlInterface $parent) { | |
$this->parent = $parent; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function supportsOperation($operation, $target) { | |
// We know how to check view on entities. | |
if ($operation == 'view' && $target == 'entity') { | |
return TRUE; | |
} | |
// Yield to the handler we are decorating. Other access control checks will | |
// be passed through the chain of decorators for this handler. | |
return $this->parent->supportsOperation($operation, $target); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function entityAccess(EntityInterface $entity, $operation, AccountInterface $account, $return_as_object = FALSE) { | |
// For entities that have our CourseHub-specific visibility field, allow | |
// view access to syllabi and resources when the instructor choses | |
// "All Middlebury People" or "Public / Anyone in the world" as the value. | |
if ($operation == 'view' && $entity->hasField('field_visibility')) { | |
// If the visibility is set to public, allow all to view. | |
if ($entity->field_visibility->value == 'public') { | |
$result = AccessResult::allowed(); | |
} | |
// Allow authenticated users view-access when 'institution' is chosen. | |
// Note: This may be worth refactoring into a role check. | |
elseif ($entity->field_visibility->value == 'institution' && $account->isAuthenticated()) { | |
$result = AccessResult::allowed(); | |
} | |
// Otherwise, get the result from the handler we are decorating. | |
// Unless another decorator takes precedence, the Group module will check | |
// group membership and role permissions to provide a view access result. | |
else { | |
$result = $this->parent->entityAccess($entity, $operation, $account, TRUE); | |
} | |
// We need to add the entity as a dependency because its visibility | |
// field's value might change. | |
$result->addCacheableDependency($entity); | |
return $return_as_object ? $result : $result->isAllowed(); | |
} | |
// For other operations and entities without our visibility field, yield to | |
// the handler we are decorating and let it provide the result. | |
return $this->parent->entityAccess($entity, $operation, $account, $return_as_object); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This was helpful, i have some doubts though,
Can we use this method of access control to views as well where in the data in the view is shown based on the access rules set here in the above code. Cause whats happening now is if i have a view that show all the content of the group to the members of the groups and filters the content for a non member of the group, what i want is irrespective of the user is a member or not a member of the group he should be able to see content attached to the group.