NodeAccessControlHandler.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. <?php
  2. namespace Drupal\node;
  3. use Drupal\Core\Access\AccessResult;
  4. use Drupal\Core\Entity\EntityHandlerInterface;
  5. use Drupal\Core\Entity\EntityTypeInterface;
  6. use Drupal\Core\Field\FieldDefinitionInterface;
  7. use Drupal\Core\Field\FieldItemListInterface;
  8. use Drupal\Core\Entity\EntityAccessControlHandler;
  9. use Drupal\Core\Entity\EntityInterface;
  10. use Drupal\Core\Session\AccountInterface;
  11. use Symfony\Component\DependencyInjection\ContainerInterface;
  12. /**
  13. * Defines the access control handler for the node entity type.
  14. *
  15. * @see \Drupal\node\Entity\Node
  16. * @ingroup node_access
  17. */
  18. class NodeAccessControlHandler extends EntityAccessControlHandler implements NodeAccessControlHandlerInterface, EntityHandlerInterface {
  19. /**
  20. * The node grant storage.
  21. *
  22. * @var \Drupal\node\NodeGrantDatabaseStorageInterface
  23. */
  24. protected $grantStorage;
  25. /**
  26. * Constructs a NodeAccessControlHandler object.
  27. *
  28. * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
  29. * The entity type definition.
  30. * @param \Drupal\node\NodeGrantDatabaseStorageInterface $grant_storage
  31. * The node grant storage.
  32. */
  33. public function __construct(EntityTypeInterface $entity_type, NodeGrantDatabaseStorageInterface $grant_storage) {
  34. parent::__construct($entity_type);
  35. $this->grantStorage = $grant_storage;
  36. }
  37. /**
  38. * {@inheritdoc}
  39. */
  40. public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
  41. return new static(
  42. $entity_type,
  43. $container->get('node.grant_storage')
  44. );
  45. }
  46. /**
  47. * {@inheritdoc}
  48. */
  49. public function access(EntityInterface $entity, $operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
  50. $account = $this->prepareUser($account);
  51. if ($account->hasPermission('bypass node access')) {
  52. $result = AccessResult::allowed()->cachePerPermissions();
  53. return $return_as_object ? $result : $result->isAllowed();
  54. }
  55. if (!$account->hasPermission('access content')) {
  56. $result = AccessResult::forbidden("The 'access content' permission is required.")->cachePerPermissions();
  57. return $return_as_object ? $result : $result->isAllowed();
  58. }
  59. $result = parent::access($entity, $operation, $account, TRUE)->cachePerPermissions();
  60. return $return_as_object ? $result : $result->isAllowed();
  61. }
  62. /**
  63. * {@inheritdoc}
  64. */
  65. public function createAccess($entity_bundle = NULL, AccountInterface $account = NULL, array $context = [], $return_as_object = FALSE) {
  66. $account = $this->prepareUser($account);
  67. if ($account->hasPermission('bypass node access')) {
  68. $result = AccessResult::allowed()->cachePerPermissions();
  69. return $return_as_object ? $result : $result->isAllowed();
  70. }
  71. if (!$account->hasPermission('access content')) {
  72. $result = AccessResult::forbidden()->cachePerPermissions();
  73. return $return_as_object ? $result : $result->isAllowed();
  74. }
  75. $result = parent::createAccess($entity_bundle, $account, $context, TRUE)->cachePerPermissions();
  76. return $return_as_object ? $result : $result->isAllowed();
  77. }
  78. /**
  79. * {@inheritdoc}
  80. */
  81. protected function checkAccess(EntityInterface $node, $operation, AccountInterface $account) {
  82. /** @var \Drupal\node\NodeInterface $node */
  83. // Fetch information from the node object if possible.
  84. $status = $node->isPublished();
  85. $uid = $node->getOwnerId();
  86. // Check if authors can view their own unpublished nodes.
  87. if ($operation === 'view' && !$status && $account->hasPermission('view own unpublished content') && $account->isAuthenticated() && $account->id() == $uid) {
  88. return AccessResult::allowed()->cachePerPermissions()->cachePerUser()->addCacheableDependency($node);
  89. }
  90. // Evaluate node grants.
  91. return $this->grantStorage->access($node, $operation, $account);
  92. }
  93. /**
  94. * {@inheritdoc}
  95. */
  96. protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
  97. return AccessResult::allowedIf($account->hasPermission('create ' . $entity_bundle . ' content'))->cachePerPermissions();
  98. }
  99. /**
  100. * {@inheritdoc}
  101. */
  102. protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
  103. // Only users with the administer nodes permission can edit administrative
  104. // fields.
  105. $administrative_fields = ['uid', 'status', 'created', 'promote', 'sticky'];
  106. if ($operation == 'edit' && in_array($field_definition->getName(), $administrative_fields, TRUE)) {
  107. return AccessResult::allowedIfHasPermission($account, 'administer nodes');
  108. }
  109. // No user can change read only fields.
  110. $read_only_fields = ['revision_timestamp', 'revision_uid'];
  111. if ($operation == 'edit' && in_array($field_definition->getName(), $read_only_fields, TRUE)) {
  112. return AccessResult::forbidden();
  113. }
  114. // Users have access to the revision_log field either if they have
  115. // administrative permissions or if the new revision option is enabled.
  116. if ($operation == 'edit' && $field_definition->getName() == 'revision_log') {
  117. if ($account->hasPermission('administer nodes')) {
  118. return AccessResult::allowed()->cachePerPermissions();
  119. }
  120. return AccessResult::allowedIf($items->getEntity()->type->entity->isNewRevision())->cachePerPermissions();
  121. }
  122. return parent::checkFieldAccess($operation, $field_definition, $account, $items);
  123. }
  124. /**
  125. * {@inheritdoc}
  126. */
  127. public function acquireGrants(NodeInterface $node) {
  128. $grants = $this->moduleHandler->invokeAll('node_access_records', [$node]);
  129. // Let modules alter the grants.
  130. $this->moduleHandler->alter('node_access_records', $grants, $node);
  131. // If no grants are set and the node is published, then use the default grant.
  132. if (empty($grants) && $node->isPublished()) {
  133. $grants[] = ['realm' => 'all', 'gid' => 0, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0];
  134. }
  135. return $grants;
  136. }
  137. /**
  138. * {@inheritdoc}
  139. */
  140. public function writeGrants(NodeInterface $node, $delete = TRUE) {
  141. $grants = $this->acquireGrants($node);
  142. $this->grantStorage->write($node, $grants, NULL, $delete);
  143. }
  144. /**
  145. * {@inheritdoc}
  146. */
  147. public function writeDefaultGrant() {
  148. $this->grantStorage->writeDefault();
  149. }
  150. /**
  151. * {@inheritdoc}
  152. */
  153. public function deleteGrants() {
  154. $this->grantStorage->delete();
  155. }
  156. /**
  157. * {@inheritdoc}
  158. */
  159. public function countGrants() {
  160. return $this->grantStorage->count();
  161. }
  162. /**
  163. * {@inheritdoc}
  164. */
  165. public function checkAllGrants(AccountInterface $account) {
  166. return $this->grantStorage->checkAll($account);
  167. }
  168. }