All resources fail other than node resource when client is not authenticated as user with 'administer nodes' privilege.

this is because node.module rewrites sql with following function:

function _node_access_join_sql($node_alias = 'n', $node_access_alias = 'na') {
  if (user_access('administer nodes')) {
    return '';
  }

  return 'INNER JOIN {node_access} '. $node_access_alias .' ON '. $node_access_alias .'.nid = '. $node_alias .'.nid';
}

this join will return no results with any sql statement where primary table is not node. breaks comment_resource, file_resource, taxonomy_resource, and user_resource

the proposed solution prefixes all fields in select and where clause. open to alternate solutions. attached is an initial patch.

Comments

emosbaugh’s picture

Status: Active » Needs review
ygerasimov’s picture

Status: Needs review » Needs work

Sorry but I don't understand what exactly calls get broken if user is anonymous? From the patch I can see that broken calls are "index" calls. Is it correct?

Can you write the test for this bug?

emosbaugh’s picture

Status: Needs work » Needs review

Sorry, I tested this and you have to make sure that you have some sort of access module enable that changes the node view grants. As a result node_access_view_all_nodes() needs to return false. I've never written a simpletest. I can try to write one if you still need it. Let me know.

When you call:
$query = services_resource_build_index_query('comments', 'timestamp DESC', 0, '*');
The resulting query ends up looking something like this:
SELECT DISTINCT * FROM {comments} INNER JOIN {node_access} na ON na.nid = n.nid WHERE (na.grant_view >= 1 AND ((na.gid = 0 AND na.realm = 'all'))) ORDER BY timestamp DESC

function _comment_resource_index($page, $fields, $parameters) {
...
  $query = services_resource_build_index_query('comments', 'timestamp DESC', $page, $fields, $parameters);

...

function services_resource_build_index_query($schema, $order, $page, $fields, $parameters = array()) {
...
 // Run through db_rewrite_sql to make sure proper access checks are applied.
  $sql = "SELECT $fields FROM {{$table}} $where ORDER BY $order"; // SELECT * FROM comments WHERE status = 1 ORDER BY timestamp DESC
  $sql = db_rewrite_sql($sql); // SELECT * FROM comments INNER JOIN node_access na ON na.nid = n.nid WHERE status = 1 ORDER BY timestamp DESC

...

// Here the primary_table and primary_field arguments default to the node table
function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid',  $args = array()) {

...

// then node.module rewrites the sql thinking that the primary table is node. it adds a join and where clause
/**
 * Implementation of hook_db_rewrite_sql
 */
function node_db_rewrite_sql($query, $primary_table, $primary_field) {
  if ($primary_field == 'nid' && !node_access_view_all_nodes()) {
    $return['join'] = _node_access_join_sql($primary_table);
    $return['where'] = _node_access_where_sql();
    $return['distinct'] = 1;
    return $return;
  }
}
emosbaugh’s picture

Ok, digging deeper. Enable nodeaccess (http://drupal.org/project/nodeaccess) module and the resulting query when you call services_resource_build_index_query('comments', 'timestamp DESC', 0, '*'), gives an error and looks like the below.

Has nothing to do with whether or not the user is anon. Probably just cant be user 1 or have administer nodes privileged.

SELECT DISTINCT * FROM {comments} INNER JOIN {node_access} na ON na.nid = n.nid WHERE (na.grant_view >= 1 AND ((na.gid = 0 AND na.realm = 'all') OR (na.gid = 1 AND na.realm = 'nodeaccess_rid') OR (na.gid = 0 AND na.realm = 'nodeaccess_uid') OR (na.gid = 0 AND na.realm = 'nodeaccess_author'))) ORDER BY timestamp DESC

ygerasimov’s picture

Status: Needs review » Needs work

Yes, now I understand the problem completely and it is really critical. Thanks for this great catch.

I have ran all tests after applying patch and tests got broken.

@emosbaugh, could you please look what is wrong? I had problems in tests: "Resource Node" and "Resource Comment".

I will try to take a look at them as well in nearest few days.

Meanwhile patch has expressions like:

$where[] = $primary_table .'.'. $field . ' = ' . db_type_placeholder($schema['fields'][$field]['type']);

That should be like:

$where[] = $primary_table . '.' . $field . ' = ' . db_type_placeholder($schema['fields'][$field]['type']);

(style corrections).

emosbaugh’s picture

StatusFileSize
new1.68 KB

I ran tests on both head and patched module. The test results seem to come out exactly the same except for 2 additional "fails" in node resource. See attached file. I will fix these errors and report back.

...
GET http://drupal-services/s775607IK3XufSVRg/node.php returned 200 (817 bytes). Browser ServicesWebTestCase.php 400 ServicesWebTestCase->curlExec()
Successfully received Node info NodeResource: Index ServicesResourceNodeTests.test 63 ServicesResourceNodetests->testNewEndpointResourceNodeIndex()
[01-Jun-2011 09:56:03] SELECT n.* FROM {node} AS n WHERE n.status = %d ORDER BY n.sticky DESC, n.created DESC Fatal error Unknown 0 Unknown
[01-Jun-2011 09:56:03] SELECT n.* FROM {node} AS n WHERE n.status = %d ORDER BY n.sticky DESC, n.created DESC Fatal error Unknown 0 Unknown
Starting run with db_prefix simpletest210148 System ServicesResourceNodeTests.test 35 ServicesResourceNodetests->setUp()
Endpoint successfully created Other ServicesWebTestCase.php 344 ServicesWebTestCase->saveNewEndpoint()
...

emosbaugh’s picture

StatusFileSize
new1.78 KB

forgot to include user

kylebrowning’s picture

emosbaugh, all of the test are not passing pre-patch? Are you on 5.2 or 5.3?

emosbaugh’s picture

PHP Version 5.2.17

emosbaugh’s picture

problem is a lot of tests pass in a 'count' param and the new services 6.3 doesnt take that param. it is hardcoded to 20 results.

see services_resource_build_index_query
line 466:
$result = db_query_range($sql, $parameters, $page * 20, 20);

emosbaugh’s picture

Ok, after a lot of testing I found that the 2 additional error in simpletest were error_log statements that I had inserted for testing purposes :(

So for me the results from the test cases look identical. Please verify.

I have not written a test case as of yet for the addition of node view access restrictions.

emosbaugh’s picture

StatusFileSize
new5.95 KB

Attached is a patch with corrected syntax

marcingy’s picture

Quick comment why do we have defaults for these parameters why not just pass them in for node as well as the function is only used by services and this actually confuses things by having a default that is used once.

emosbaugh’s picture

One more time with a check to see if fields is an empty string. Not sure if this is possible but just in case...

emosbaugh’s picture

emosbaugh’s picture

What is the status of this? What can I do to get this into repo?

emosbaugh’s picture

Status: Needs work » Needs review
kylebrowning’s picture

It looks good, can we get a d7 version (if needed?)

emosbaugh’s picture

I don't believe drupal 7 will have the problem with the new query builder using base_table meta data field rather than alias.

kylebrowning’s picture

Status: Needs review » Fixed
emosbaugh’s picture

Thanks!

kylebrowning’s picture

Status: Fixed » Closed (fixed)