We use the Domain Access module to save nodes on several domains. This module also makes sure the Drupal search only returns nodes which are stored on the current domain. Search Config overrules somes settings, because after activating Search Config all nodes are returned. See also #516140: search not working as expected

Is this fixable?

Comments

canen’s picture

This should be fixable but as stated in the module it is one big hack. I can have a look and see if there is a better solution.

xjm’s picture

Tracking.

Exploratus’s picture

subscribe

skizzo’s picture

subscribing

jbomb’s picture

Version: 6.x-1.5 » 6.x-1.x-dev

I've installed both domain access and search_config modules, and then set up two different domains (A and B). I elected to NOT publish new content to all affiliates, I set the domain module to "Search content for the current domain only," and elected to have domain access restrictions enforced for admins. Next I added a new story to domain A. The new story only appears on domain A. I ran cron and searched both domains and received the expected results for each domain.

Was this resolved in #516140: search not working as expected?

jbomb’s picture

Status: Active » Postponed (maintainer needs more info)
BarisW’s picture

Status: Postponed (maintainer needs more info) » Active

@jbomb: #516140: search not working as expected isn't fixed but closed. The problem lies with Search Config and not with Domain Access.
See http://drupal.org/node/516140#comment-1924200

Because hook_db_rewrite_sql is used, the domain filters from Domain Access are overwritten.

BarisW’s picture

By the way, in your setup of #5, try limiting some Content Types in the Search Config settings.
Then you'll see what I mean: all content of all domains will be displayed.

jbomb’s picture

I tried to reproduce this again. Here's the basic setup:

  • Drupal 6.19
  • Domain Access 6.x-2.7
  • Search Config 6.x-1.6

I setup two domains as subdomains:

  • primary.example.com
  • secondary.example.com

Next I created four different nodes, one of each type assigned exclusively to each domain, and configured search_config to filter story nodes from the search results.

Below is a description of the nodes I created:

  • Primary Domain Story (not to be shown in search result)
  • Primary Domain Page
  • Secondary Domain Story (not to be shown in search result)
  • Secondary Domain Page

I will note that at this point some of the nodes were showing up on both domains, but I was able to resolve this by rebuilding permissions at "/admin/content/node-settings."

I then tested the search form on both domain names and received the expected results. Story content did not appear on either search and page content access was restricted to the proper domain. I tested this as an anonymous user, and again as user 1 with Domain Access set to enforce access restrictions for privileged users. I toggled the the domain settings a couple times, and turned search_config on and off, but I received the expected result after each test.

Are you using any other node access modules such as content_access, simple access, module grants or tac? If so, are you using the provided multiple_node_access.patch or domain_adv? I think there is a strong possibility that another module's grant is overriding the Domain Access restriction. If that's the case, it should be discoverable using the devel node access module.

I guess the next step for me is to write up some tests ...

BarisW’s picture

But now try to hide a specific content type in the Search settings. In our case we had a content type Banner. We didn't want these nodes to be found at all, so I selected the content type Banner to be excluded by the Search results. When excluding one or more content types, the domain settings are ingnored.

jbomb’s picture

In the test case presented above the 'story' content type was hidden in the search settings.

BarisW’s picture

Ah apologies, didn't read it carefully.
I'll try it again, my original issue is more than a year old. Maybe the .dev has already been fixed in the meantime.

I might have found a small typo though in the module:

/**
 * Rewrite the search query to exclude selected node types.
 *
 * I feel dirty; This is such a hack.
 * @see http://www.lullabot.com/articles/hiding-content-drupals-search-system
 * @see http://drupal.org/node/111744 if you want to help get something
 * sensible into core.
 */
function search_config_db_rewrite_sql($query, $primary_table, $primary_field, $args) {
  if ($query == '' && $primary_table == 'n' && $primary_field = 'nid' && empty($args)) {
    $excluded_types = array_filter(variable_get('search_config_disable_index_type', array()));
    if (!empty($excluded_types)) {
      $where = " n.type NOT IN ('". join("','", $excluded_types) ."') ";
      return array('where' => $where);
    }
  }
}

Shouldn't $primary_field = 'nid' be $primary_field == 'nid'?
If I remember correctly - the WHERE part of the search query got overwritten by Search Config and therefore bypasses the node access queries.

See http://drupal.org/node/516140#comment-1920416

jbomb’s picture

Shouldn't $primary_field = 'nid' be $primary_field == 'nid'?
If I remember correctly - the WHERE part of the search query got overwritten by Search Config and therefore bypasses the node access queries.

You are correct, the line that you identified does contain a bug. I don't think it's critical because the function will only fire when $query is empty, which I believe is specific to search queries. Nevertheless, this will be addressed shortly.

Drupal core uses the logical operator "AND" to combine the "WHERE" conditions of each hook_db_rewrite_sql() implementation in _db_rewrite_sql(). I am reasonably sure that the implementation in search_config does not circumvent node access controls applied by node_db_rewrite_sql().

jbomb’s picture

Just did some digging around in the hook_search implementation found in node. This implementation invokes _db_rewrite_sql() directly and without any arguments so it is passed with the defaults (including the empty query string). The where condition and join that are passed to do_search() in my implementation is as follows:

// Join:
INNER JOIN {node_access} na ON na.nid = n.nid
// where condition:
(na.grant_view >= 1 AND ((na.gid = 0 AND na.realm = 'all') OR (na.gid = 0 AND na.realm = 'domain_site') OR (na.gid = 0 AND na.realm = 'domain_id'))) AND ( n.type NOT IN ('story') )

The final query executed by the search module is here:
SELECT i.type, i.sid, %d * (8.0039229547058 * SUM(i.score * t.count)) + %d * POW(2, (GREATEST(MAX(n.created), MAX(n.changed), MAX(c.last_comment_timestamp) || 1) - %d) * 6.43e-8) + %d * (2.0 - 2.0 / (1.0 + MAX(c.comment_count) * %f)) AS score FROM {search_index} i INNER JOIN {search_total} t ON i.word = t.word INNER JOIN {node} n ON n.nid = i.sid INNER JOIN {node_access} na ON na.nid = n.nid LEFT JOIN {node_comment_statistics} c ON c.nid = i.sid WHERE n.status = 1 AND (na.grant_view >= 1 AND ((na.gid = 0 AND na.realm = 'all') OR (na.gid = 0 AND na.realm = 'domain_site') OR (na.gid = 0 AND na.realm = 'domain_id'))) AND ( n.type NOT IN ('story') ) AND (i.word = '%s') AND i.type = '%s' GROUP BY i.type, i.sid HAVING COUNT(*) >= %d

Note the inner join on the node_access table.

jbomb’s picture

Status: Active » Closed (cannot reproduce)