diff --git a/modules/field/field.module b/modules/field/field.module index dedf847..4e39a03 100644 --- a/modules/field/field.module +++ b/modules/field/field.module @@ -972,6 +972,10 @@ function field_has_data($field) { ->fieldCondition($field) ->range(0, 1) ->count() + // Neutralize the 'entity_field_access' query tag added by + // field_sql_storage_field_storage_query(). The result cannot depend on the + // access grants of the current user. + ->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT') ->execute(); } diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.module b/modules/field/modules/field_sql_storage/field_sql_storage.module index 2ed7835..a756194 100644 --- a/modules/field/modules/field_sql_storage/field_sql_storage.module +++ b/modules/field/modules/field_sql_storage/field_sql_storage.module @@ -512,7 +512,12 @@ function field_sql_storage_field_storage_query(EntityFieldQuery $query) { } else { $select_query = db_select($tablename, $table_alias); - $select_query->addTag('entity_field_access'); + // Allow queries internal to the Field API to opt out of the access + // check, for situations where the query's results should not depend on + // the access grants for the current user. + if (!isset($query->tags['DANGEROUS_ACCESS_CHECK_OPT_OUT'])) { + $select_query->addTag('entity_field_access'); + } $select_query->addMetaData('base_table', $tablename); $select_query->fields($table_alias, array('entity_type', 'entity_id', 'revision_id', 'bundle')); $field_base_table = $table_alias; diff --git a/modules/node/node.test b/modules/node/node.test index f46d2a1..6e458bb 100644 --- a/modules/node/node.test +++ b/modules/node/node.test @@ -6,6 +6,26 @@ */ /** + * Defines a base class for testing the Node module. + */ +class NodeWebTestCase extends DrupalWebTestCase { + function setUp() { + $modules = func_get_args(); + if (isset($modules[0]) && is_array($modules[0])) { + $modules = $modules[0]; + } + $modules[] = 'node'; + parent::setUp($modules); + + // Create Basic page and Article node types. + if ($this->profile != 'standard') { + $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); + $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); + } + } +} + +/** * Test the node_load_multiple() function. */ class NodeLoadMultipleTestCase extends DrupalWebTestCase { @@ -2493,3 +2513,78 @@ class NodeAccessPagerTestCase extends DrupalWebTestCase { $this->assertNoRaw('page=2', t('No third page exists.')); } } + + +/** + * Tests the interaction of the node access system with fields. + */ +class NodeAccessFieldTestCase extends NodeWebTestCase { + + public static function getInfo() { + return array( + 'name' => 'Node access and fields', + 'description' => 'Tests the interaction of the node access system with fields.', + 'group' => 'Node', + ); + } + + public function setUp() { + parent::setUp('node_access_test', 'field_ui'); + node_access_rebuild(); + + // Create some users. + $this->admin_user = $this->drupalCreateUser(array('access content', 'bypass node access')); + $this->content_admin_user = $this->drupalCreateUser(array('access content', 'administer content types')); + + // Add a custom field to the page content type. + $this->field_name = drupal_strtolower($this->randomName() . '_field_name'); + $this->field = field_create_field(array('field_name' => $this->field_name, 'type' => 'text')); + $this->instance = field_create_instance(array( + 'field_name' => $this->field_name, + 'entity_type' => 'node', + 'bundle' => 'page', + )); + } + + /** + * Tests administering fields when node access is restricted. + */ + function testNodeAccessAdministerField() { + // Create a page node. + $langcode = LANGUAGE_NONE; + $field_data = array(); + $value = $field_data[$langcode][0]['value'] = $this->randomName(); + $node = $this->drupalCreateNode(array($this->field_name => $field_data)); + + // Log in as the administrator and confirm that the field value is present. + $this->drupalLogin($this->admin_user); + $this->drupalGet("node/{$node->nid}"); + $this->assertText($value, 'The saved field value is visible to an administrator.'); + + // Log in as the content admin and try to view the node. + $this->drupalLogin($this->content_admin_user); + $this->drupalGet("node/{$node->nid}"); + $this->assertText('Access denied', 'Access is denied for the content admin.'); + + // Modify the field default as the content admin. + $edit = array(); + $default = 'Sometimes words have two meanings'; + $edit["{$this->field_name}[$langcode][0][value]"] = $default; + $this->drupalPost( + "admin/structure/types/manage/page/fields/{$this->field_name}", + $edit, + t('Save settings') + ); + + // Log in as the administrator. + $this->drupalLogin($this->admin_user); + + // Confirm that the existing node still has the correct field value. + $this->drupalGet("node/{$node->nid}"); + $this->assertText($value, 'The original field value is visible to an administrator.'); + + // Confirm that the new default value appears when creating a new node. + $this->drupalGet('node/add/page'); + $this->assertRaw($default, 'The updated default value is displayed when creating a new node.'); + } +}