I need a little help in figuring out how to use hook_apachesolr_modify_query(). I have the annotations.module installed. When I execute a search, apachesolr searches annotations as well. Problem is that it returns nodes which have private annotations to anonymous users.

I need to figure out a way to use hook_apachesolr_modify_query() to reject such nodes that anonymous users should not see.

I've looked at apachesolr_nodeaccess_apachesolr_modify_query(). It appears to use the following format:

    $query->add_subquery($subquery, 'OR');

The $subquery seems to be built like this:

          // From _apachesolr_nodeaccess_build_subquery()
          $node_access_query->add_filter('nodeaccess_' . apachesolr_site_hash() . '_' . $realm, $gid);

But, I don't see a way to say:

If the user does NOT have "view" access to the annotations in this node, then don't display it (even if he has the node access "view" grant).

Could someone please point me to where I can get more info on using this function to filter query results?

Thanks!

Comments

pwolanin’s picture

You can only filter by some property that is in the document int he Solr index.

So - for node access we are indexing the node grants into Solr - you would have to do something similar (using a dynamic field) for your nodes so that for each oneSolr can determine if it has private annotations.

If annontations are simply just public or private, the added property could just be a boolean (or int) field.

somebodysysop’s picture

OK, thanks for the response!

I figure the easiest way would be to create node grants for the annotations so that they would be processed by the apachesolr_nodeaccess.module.

However, when I try and test this using an existing node grant, I'm not getting the anticipated results.

For example, in apachesolr_nodeaccess_apachesolr_update_index, the following dynamic field is added to the index (from node grants):

nodeaccess_a3eb1dd69364_og_public

According to the node_access table, the nodes that are public will have a gid value of "0":

nid: 2968  	 
gid: 0 	 
realm: og_public 	 
grant_view: 1
grant_update: 0 	
grant_delete: 0

So, theoretically, if the node is OG public, I should be able to filter on this dynamic apache solr index field.

Now, in my hook_apachesolr_modify_query() code, I enter the following:

  // If the user is not logged in, then only list "public" group nodes
  if ($user->uid == 0) {
    $key = 'nodeaccess_' . apachesolr_site_hash() . '_og_public';
    $query->add_filter($key, 0);         
  }

The result no nodes appear at all, even though most of my nodes are OG public. I've checked and the $key generated above is the same as that listed in the apache solr query object.

Can anyone tell what I am dong wrong here in my attempt to filter on this dynamic field?

pwolanin’s picture

did you reindex all content?

somebodysysop’s picture

Status: Active » Fixed

OK, I have discovered two thing:

a. The node access realm og_public is NOT indexed in apachesolr. That's why the filter returned no nodes. I tried re-indexing several times, but to no avail. I do not know if this is the result of my specific configuration or is a problem with the indexer. I'll open a new issue for this if I can't resolve it.

b. I could achieve more or less the same thing by using hook_apachesolr_update_index() to add a field, then hook_apachesolr_modify_query() to filter on it:

/**
 * Implementation of apachesolr_update_index
 */
function mymodule_apachesolr_update_index(&$document, $node) {
  static $account;

  // Give the node a value.
  $key = 'nodeaccess_mymodule_public';
  if ($node->og_public == 1) {
    $document->setMultiValue($key, 1);
  } else {
    $document->setMultiValue($key, 0);
  }

}

/**
 * Implementation of hook_apachesolr_modify_query().
 */
function mymodule_apachesolr_modify_query(&$query, &$params) {
  global $user;

  // If the user is not logged in, then only list "public" group nodes
  if ($user->uid == 0) {
    $key = 'nodeaccess_mymodule_public';
    $query->add_filter($key, 1);         
  }
}

So, my larger issue of how to use hook_apachesolr_modify_query() is solved. However, the more specific case is that of limiting access to annotations.

I think I need to close this issue and create another because it's not that I don't want the nodes to be seen in the search (if they contain the search keywords), it's that I don't want the annotations searched and/or displayed if the user doesn't have access to them.

Thanks for the assistance.

Scott Reynolds’s picture

The node access realm og_public is NOT indexed in apachesolr.

So this is true because apachesolr_nodeaccess does a check like this.

 if (!isset($account)) {
    // Load the anonymous user.
    $account = drupal_anonymous_user();
  }

  if (!node_access('view', $node, $account)) {
     // Get the realms here.
  }
  else {
     // Add the generic view grant if we are not using
    // node access or the node is viewable by anonymous users.
  }

Because its viewable by all users it gets the generic nodeaccess_all => 0.

pwolanin’s picture

Right - that's an optimization to avoid needing complex queries for nodes that will end up being shown to the anonymous users.

somebodysysop’s picture

Thanks for the clarification.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.