diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index e29f49a..82388d8 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -1021,18 +1021,3 @@ function template_preprocess_comment_wrapper(&$variables) { function comment_ranking() { return \Drupal::service('comment.statistics')->getRankingInfo(); } - -/** - * Implements hook_file_download_access(). - */ -function comment_file_download_access($field, EntityInterface $entity, FileInterface $file) { - if ($entity instanceof CommentInterface) { - $current_user = \Drupal::currentUser(); - if ($current_user->hasPermission('access comments') && $entity->isPublished() || $current_user->hasPermission('administer comments')) { - $commented_entity = $entity->getCommentedEntity(); - // Check access to parent entity. - return $commented_entity->access('view'); - } - return FALSE; - } -} diff --git a/core/modules/comment/src/CommentAccessController.php b/core/modules/comment/src/CommentAccessController.php index 81b426e..5f169f3 100644 --- a/core/modules/comment/src/CommentAccessController.php +++ b/core/modules/comment/src/CommentAccessController.php @@ -25,11 +25,13 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A /** @var \Drupal\Core\Entity\EntityInterface|\Drupal\user\EntityOwnerInterface $entity */ switch ($operation) { case 'view': - return $account->hasPermission('access comments'); + if ($account->hasPermission('access comments') && $entity->isPublished() || $account->hasPermission('administer comments')) { + return $entity->getCommentedEntity()->access($operation); + } break; case 'update': - return ($account->id() && $account->id() == $entity->getOwnerId() && $entity->status->value == CommentInterface::PUBLISHED && $account->hasPermission('edit own comments')) || $account->hasPermission('administer comments'); + return ($account->id() && $account->id() == $entity->getOwnerId() && $entity->isPublished() && $account->hasPermission('edit own comments')) || $account->hasPermission('administer comments'); break; case 'delete': diff --git a/core/modules/file/file.api.php b/core/modules/file/file.api.php index 6ec14c5..23a0291 100644 --- a/core/modules/file/file.api.php +++ b/core/modules/file/file.api.php @@ -78,60 +78,5 @@ function hook_file_move(Drupal\file\FileInterface $file, Drupal\file\FileInterfa } /** - * Control download access to files. - * - * The hook is typically implemented to limit access based on the entity that - * references the file; for example, only users with access to a node should be - * allowed to download files attached to that node. - * - * @param $field - * The field to which the file belongs. - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity which references the file. - * @param \Drupal\file\FileInterface $file - * The file entity that is being requested. - * - * @return - * TRUE is access should be allowed by this entity or FALSE if denied. Note - * that denial may be overridden by another entity controller, making this - * grant permissive rather than restrictive. - * - * @see hook_entity_field_access(). - */ -function hook_file_download_access($field, Drupal\Core\Entity\EntityInterface $entity, Drupal\file\FileInterface $file) { - if ($entity->getEntityTypeId() == 'node') { - return $entity->access('view'); - } -} - -/** - * Alter the access rules applied to a file download. - * - * Entities that implement file management set the access rules for their - * individual files. Module may use this hook to create custom access rules - * for file downloads. - * - * @see hook_file_download_access(). - * - * @param $grants - * An array of grants gathered by hook_file_download_access(). The array is - * keyed by the module that defines the entity type's access control; the - * values are Boolean grant responses for each module. - * @param array $context - * An associative array containing the following key-value pairs: - * - field: The field to which the file belongs. - * - entity: The entity which references the file. - * - file: The file entity that is being requested. - * - * @see hook_file_download_access(). - */ -function hook_file_download_access_alter(&$grants, $context) { - // For our example module, we always enforce the rules set by node module. - if (isset($grants['node'])) { - $grants = array('node' => $grants['node']); - } -} - -/** * @} End of "addtogroup hooks". */ diff --git a/core/modules/file/file.module b/core/modules/file/file.module index ce63484..c4215cd 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -604,13 +604,8 @@ function file_theme() { /** * Implements hook_file_download(). - * - * This function takes an extra parameter $field_type so that it may - * be re-used by other File-like modules, such as Image. */ -function file_file_download($uri, $field_type = 'file') { - $user = \Drupal::currentUser(); - +function file_file_download($uri) { // Get the file record based on the URI. If not in the database just return. /** @var \Drupal\file\FileInterface[] $files */ $files = entity_load_multiple_by_properties('file', array('uri' => $uri)); @@ -629,69 +624,18 @@ function file_file_download($uri, $field_type = 'file') { } // Find out which (if any) fields of this type contain the file. - $references = file_get_file_references($file, NULL, EntityStorageInterface::FIELD_LOAD_CURRENT, $field_type); + $references = file_get_file_references($file, NULL, EntityStorageInterface::FIELD_LOAD_CURRENT, NULL); // Stop processing if there are no references in order to avoid returning // headers for files controlled by other modules. Make an exception for // temporary files where the host entity has not yet been saved (for example, // an image preview on a node/add form) in which case, allow download by the // file's owner. - if (empty($references) && ($file->isPermanent() || $file->getOwnerId() != $user->id())) { + if (empty($references) && ($file->isPermanent() || $file->getOwnerId() != \Drupal::currentUser()->id())) { return; } - // Default to allow access. - $denied = FALSE; - // Loop through all references of this file. If a reference explicitly allows - // access to the field to which this file belongs, no further checks are done - // and download access is granted. If a reference denies access, eventually - // existing additional references are checked. If all references were checked - // and no reference denied access, access is granted as well. If at least one - // reference denied access, access is denied. - foreach ($references as $field_name => $field_references) { - foreach ($field_references as $entity_type => $entities) { - $field_storage_definitions = \Drupal::entityManager()->getFieldStorageDefinitions($entity_type); - $field_storage = $field_storage_definitions[$field_name]; - foreach ($entities as $entity) { - // Check if access to this field is not disallowed. - if (!$entity->get($field_name)->access('view')) { - $denied = TRUE; - continue; - } - - // Invoke hook and collect grants/denies for download access. - // Default to FALSE and let entities overrule this ruling. - $grants = array('system' => FALSE); - foreach (\Drupal::moduleHandler()->getImplementations('file_download_access') as $module) { - $grants = array_merge($grants, array($module => \Drupal::moduleHandler()->invoke($module, 'file_download_access', array($field_storage, $entity, $file)))); - } - // Allow other modules to alter the returned grants/denies. - $context = array( - 'entity' => $entity, - 'field' => $field_storage, - 'file' => $file, - ); - \Drupal::moduleHandler()->alter('file_download_access', $grants, $context); - - if (in_array(TRUE, $grants)) { - // If TRUE is returned, access is granted and no further checks are - // necessary. - $denied = FALSE; - break 3; - } - - if (in_array(FALSE, $grants)) { - // If an implementation returns FALSE, access to this entity is denied - // but the file could belong to another entity to which the user might - // have access. Continue with these. - $denied = TRUE; - } - } - } - } - - // Access specifically denied. - if ($denied) { + if (!$file->access('view')) { return -1; } diff --git a/core/modules/file/src/Entity/File.php b/core/modules/file/src/Entity/File.php index cf8848b..59a5421 100644 --- a/core/modules/file/src/Entity/File.php +++ b/core/modules/file/src/Entity/File.php @@ -23,6 +23,7 @@ * label = @Translation("File"), * controllers = { * "storage" = "Drupal\file\FileStorage", + * "access" = "Drupal\file\FileAccessController", * "view_builder" = "Drupal\Core\Entity\EntityViewBuilder" * }, * base_table = "file_managed", diff --git a/core/modules/file/src/FileAccessController.php b/core/modules/file/src/FileAccessController.php new file mode 100644 index 0000000..377d079 --- /dev/null +++ b/core/modules/file/src/FileAccessController.php @@ -0,0 +1,55 @@ +getFileReferences($entity) as $field_name => $entity_map) { + foreach ($entity_map as $referencing_entity_type => $referencing_entities) { + /** @var \Drupal\Core\Entity\EntityInterface $referencing_entity */ + foreach ($referencing_entities as $referencing_entity) { + if ($referencing_entity->access($operation, $account) && $referencing_entity->$field_name->access($operation, $account)) { + return TRUE; + } + } + } + } + + return FALSE; + } + + /** + * Wrapper for file_get_file_references(). + * + * @param \Drupal\file\FileInterface $file + * The file object for which to get references. + * + * @return array + * A multidimensional array. The keys are field_name, entity_type, + * entity_id and the value is an entity referencing this file. + * + * @see file_get_file_references() + */ + protected function getFileReferences(FileInterface $file) { + return file_get_file_references($file, NULL, EntityStorageInterface::FIELD_LOAD_REVISION, NULL); + } + +} diff --git a/core/modules/file/tests/file_module_test/file_module_test.module b/core/modules/file/tests/file_module_test/file_module_test.module deleted file mode 100644 index d84eddc..0000000 --- a/core/modules/file/tests/file_module_test/file_module_test.module +++ /dev/null @@ -1,21 +0,0 @@ -getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle()); - // Allow the file to be downloaded only if the given arguments are correct. - if (empty($field_definitions[$field_storage->getName()])) { - return FALSE; - } -} diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 86c878f..ba8c979 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -205,17 +205,6 @@ function image_file_download($uri) { } return -1; } - - // Private file access for the original files. Note that we only - // check access for non-temporary images, since file.module will - // grant access for all temporary files. - $files = entity_load_multiple_by_properties('file', array('uri' => $uri)); - if (count($files)) { - $file = reset($files); - if ($file->status) { - return file_file_download($uri, 'image'); - } - } } /** diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 262e07b..1a27d14 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -1600,15 +1600,6 @@ function node_modules_uninstalled($modules) { } /** - * Implements hook_file_download_access(). - */ -function node_file_download_access($field, EntityInterface $entity, File $file) { - if ($entity->getEntityTypeId() == 'node') { - return $entity->access('view'); - } -} - -/** * Implements hook_ENTITY_TYPE_delete() for 'language_entity'. */ function node_language_entity_delete(LanguageEntity $language) { diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module index 56ec514..62e0397 100644 --- a/core/modules/taxonomy/taxonomy.module +++ b/core/modules/taxonomy/taxonomy.module @@ -665,15 +665,6 @@ function taxonomy_term_load($tid) { } /** - * Implements hook_file_download_access(). - */ -function taxonomy_file_download_access($field, EntityInterface $entity, FileInterface $file) { - if ($entity->getEntityTypeId() == 'taxonomy_term') { - return $entity->access('view'); - } -} - -/** * Implodes a list of tags of a certain vocabulary into a string. * * @see \Drupal\Component\Utility\Tags::explode() diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 9209a39..f992ed5 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -1490,15 +1490,6 @@ function user_cookie_delete($cookie_name) { } /** - * Implements hook_file_download_access(). - */ -function user_file_download_access($field, EntityInterface $entity, File $file) { - if ($entity->getEntityTypeId() == 'user') { - return $entity->access('view'); - } -} - -/** * Implements hook_toolbar(). */ function user_toolbar() {