From 1c94124a5a037eead548aef2e2b3cbb512303db6 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Thu, 8 Jan 2015 10:36:12 +0000 Subject: [PATCH] Issue #2344151 by larowlan: Comment field access doesn't work if $items isn't present --- .../src/CommentAccessControlHandler.php | 22 +- .../src/Tests/Views/CommentRestExportTest.php | 68 +++ .../src/Tests/Views/CommentTestBase.php | 3 +- .../views.view.test_comment_rest.yml | 388 ++++++++++++++++++ 4 files changed, 474 insertions(+), 7 deletions(-) create mode 100644 core/modules/comment/src/Tests/Views/CommentRestExportTest.php create mode 100644 core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml diff --git a/core/modules/comment/src/CommentAccessControlHandler.php b/core/modules/comment/src/CommentAccessControlHandler.php index 0bc58ce77b38..7d6504c9e51a 100644 --- a/core/modules/comment/src/CommentAccessControlHandler.php +++ b/core/modules/comment/src/CommentAccessControlHandler.php @@ -57,8 +57,6 @@ protected function checkCreateAccess(AccountInterface $account, array $context, * {@inheritdoc} */ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) { - /** @var \Drupal\comment\CommentInterface $entity */ - $entity = $items->getEntity(); if ($operation == 'edit') { // Only users with the "administer comments" permission can edit // administrative fields. @@ -87,13 +85,22 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_ if (in_array($field_definition->getName(), $read_only_fields, TRUE)) { return AccessResult::forbidden(); } - $commented_entity = $entity->getCommentedEntity(); - $anonymous_contact = $commented_entity->get($entity->getFieldName())->getFieldDefinition()->getSetting('anonymous_contact'); // If the field is configured to accept anonymous contact details - admins // can edit name, homepage and mail. Anonymous users can also fill in the // fields on comment creation. if (in_array($field_definition->getName(), ['name', 'mail', 'homepage'], TRUE)) { + if (!$items) { + // We cannot make a decision about access to edit these fields if we + // don't have any items and therefore cannot determine the Comment + // entity. In this case we err on the side of caution and prevent edit + // access. + return AccessResult::forbidden(); + } + /** @var \Drupal\comment\CommentInterface $entity */ + $entity = $items->getEntity(); + $commented_entity = $entity->getCommentedEntity(); + $anonymous_contact = $commented_entity->get($entity->getFieldName())->getFieldDefinition()->getSetting('anonymous_contact'); $admin_access = AccessResult::allowedIfHasPermission($account, 'administer comments'); $anonymous_access = AccessResult::allowedIf($entity->isNew() && $account->isAnonymous() && $anonymous_contact != COMMENT_ANONYMOUS_MAYNOT_CONTACT && $account->hasPermission('post comments')) ->cachePerRole() @@ -105,14 +112,17 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_ } if ($operation == 'view') { + $entity = $items ? $items->getEntity() : NULL; // Admins can view any fields except hostname, other users need both the // "access comments" permission and for the comment to be published. The // mail field is hidden from non-admins. $admin_access = AccessResult::allowedIf($account->hasPermission('administer comments') && $field_definition->getName() != 'hostname') ->cachePerRole(); - $anonymous_access = AccessResult::allowedIf($account->hasPermission('access comments') && $entity->isPublished() && !in_array($field_definition->getName(), array('mail', 'hostname'), TRUE)) - ->cacheUntilEntityChanges($entity) + $anonymous_access = AccessResult::allowedIf($account->hasPermission('access comments') && (!$entity || $entity->isPublished()) && !in_array($field_definition->getName(), array('mail', 'hostname'), TRUE)) ->cachePerRole(); + if ($entity) { + $anonymous_access->cacheUntilEntityChanges($entity); + } return $admin_access->orIf($anonymous_access); } return parent::checkFieldAccess($operation, $field_definition, $account, $items); diff --git a/core/modules/comment/src/Tests/Views/CommentRestExportTest.php b/core/modules/comment/src/Tests/Views/CommentRestExportTest.php new file mode 100644 index 000000000000..8cc432d1f191 --- /dev/null +++ b/core/modules/comment/src/Tests/Views/CommentRestExportTest.php @@ -0,0 +1,68 @@ +<?php + +/** + * @file + * Contains \Drupal\comment\Tests\Views\CommentRestExportTest. + */ + +namespace Drupal\comment\Tests\Views; + +use Drupal\Component\Serialization\Json; + +/** + * Tests a comment rest export view. + * + * @group comment + */ +class CommentRestExportTest extends CommentTestBase { + + /** + * Views used by this test. + * + * @var array + */ + public static $testViews = ['test_comment_rest']; + + /** + * {@inheritdoc} + */ + public static $modules = ['node', 'comment', 'comment_test_views', 'rest', 'hal']; + + protected function setUp() { + parent::setUp(); + // Add another anonymous comment. + $comment = array( + 'uid' => 0, + 'entity_id' => $this->nodeUserCommented->id(), + 'entity_type' => 'node', + 'field_name' => 'comment', + 'subject' => 'A lot, apparently', + 'cid' => '', + 'pid' => $this->comment->id(), + 'mail' => 'someone@example.com', + 'name' => 'bobby tables', + 'hostname' => 'public.example.com', + ); + $this->comment = entity_create('comment', $comment); + $this->comment->save(); + } + + + /** + * Test comment row. + */ + public function testCommentRestExport() { + $this->drupalGet(sprintf('node/%d/comments', $this->nodeUserCommented->id()), [], ['Accept' => 'application/hal+json']); + $this->assertResponse(200); + $contents = Json::decode($this->getRawContent()); + $this->assertEqual($contents[0]['subject'], 'How much wood would a woodchuck chuck'); + $this->assertEqual($contents[1]['subject'], 'A lot, apparently'); + $this->assertEqual(count($contents), 2); + + // Ensure field-level access is respected - user shouldn't be able to see + // mail or hostname fields. + $this->assertNoText('someone@example.com'); + $this->assertNoText('public.example.com'); + } + +} diff --git a/core/modules/comment/src/Tests/Views/CommentTestBase.php b/core/modules/comment/src/Tests/Views/CommentTestBase.php index 306ab24746f3..7d4705f32fe6 100644 --- a/core/modules/comment/src/Tests/Views/CommentTestBase.php +++ b/core/modules/comment/src/Tests/Views/CommentTestBase.php @@ -79,9 +79,10 @@ protected function setUp() { 'entity_id' => $this->nodeUserCommented->id(), 'entity_type' => 'node', 'field_name' => 'comment', + 'subject' => 'How much wood would a woodchuck chuck', 'cid' => '', 'pid' => '', - 'node_type' => '', + 'mail' => 'someone@example.com', ); $this->comment = entity_create('comment', $comment); $this->comment->save(); diff --git a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml new file mode 100644 index 000000000000..bd04a83c59c3 --- /dev/null +++ b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_rest.yml @@ -0,0 +1,388 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.comment.comment_body + module: + - comment + - node + - rest + - text + - user +id: test_comment_rest +label: 'Comments by node' +module: views +description: '' +tag: '' +base_table: comment +base_field: cid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'access content' + cache: + type: none + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: false + query_tags: { } + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + pager: + type: full + options: + items_per_page: 10 + offset: 0 + id: 0 + total_pages: null + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + tags: + previous: '‹ previous' + next: 'next ›' + first: '« first' + last: 'last »' + quantity: 9 + style: + type: serializer + row: + type: fields + options: + inline: { } + separator: '' + hide_empty: false + default_field_elements: true + relationships: + node: + id: node + table: comment_field_data + field: node + required: true + plugin_id: standard + relationship: none + group_type: group + admin_label: Content + fields: + subject: + id: subject + table: comment_field_data + field: subject + relationship: none + group_type: group + entity_type: comment + entity_field: subject + admin_label: '' + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: '' + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + link_to_comment: true + link_to_entity: false + plugin_id: comment + name: + id: name + table: comment_field_data + field: name + entity_type: comment + entity_field: name + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: '' + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + link_to_user: false + plugin_id: comment_username + created: + id: created + table: comment_field_data + field: created + entity_type: comment + entity_field: created + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: '' + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + date_format: long + custom_date_format: '' + timezone: '' + plugin_id: date + comment_body: + id: comment_body + table: comment__comment_body + field: comment_body + relationship: none + entity_type: comment + entity_field: comment_body + group_type: group + admin_label: '' + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: '' + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: text_default + settings: { } + group_column: value + group_columns: { } + group_rows: true + delta_limit: all + delta_offset: '0' + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + plugin_id: field + filters: { } + sorts: { } + header: { } + footer: { } + empty: { } + arguments: + nid: + id: nid + table: node + field: nid + relationship: node + group_type: group + admin_label: '' + default_action: default + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: node + default_argument_skip_url: false + summary_options: + base_path: '' + count: true + items_per_page: 25 + override: false + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: false + validate: + type: none + fail: 'not found' + validate_options: { } + break_phrase: false + not: false + plugin_id: numeric + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + display_extenders: { } + rest_export_1: + display_plugin: rest_export + id: rest_export_1 + display_title: 'REST export' + position: 1 + display_options: + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + path: node/%node/comments + pager: + type: some + options: + items_per_page: 10 + offset: 0 + style: + type: serializer + options: + uses_fields: false + formats: + json: json + row: + type: data_field + options: + field_options: + subject: + alias: '' + raw_output: true + name: + alias: '' + raw_output: true + display_extenders: { } -- GitLab