Hiding nodes based on geographical location I am setting up a ecommerce site for a client using drupal and ubercart. They have a number of products on the site that are not available in certain countries. We have discussed solutions using subdomains, but ideally they want to be able to control whether or not a product visible in any giving country.

So my question. Is there a module that allows a person to block the visibility of a node based on the user's geographical location? Ideally, this would block everything including any views the node might appear in. Any ideas?
I'm going to assume that you wouldn't mind writing a custom module for this. Lets call it say, my_mod. The use-case you have mentioned is perfectly suited to take advantage of the Drupal Node Access system.

A few assumptions:


You have a vocabulary, Locations that houses a growing list of locations with which either a user or a piece of content on your site can be tagged with.
Attach a Taxonomy Term Reference field field_location with this vocabulary to both products and users.
Say for a given user, based on his access, you "guess" his location from his IP and set/append this field for him.


Then all you need to do is let Drupal know that users can only see products that have been tagged with the locations that they are a part of using the Node Access hooks as shown below.

/**
 * Access realm that defines access control to content by user location
 */
 define('USER_GEOGRAPHY_REALM', 'user_geography');
 /**
  * Taxonomy term reference field. Allows tagging a user/node with a 
  * a given term from the "Locations" vocabulary.
  */
 define('LOCATION_FIELD', 'field_location');

/**
 * Implements hook_node_access_records().
 */
function my_mod_node_access_records($node) {
  $grants = array();
  $items = field_get_items('node', $node, LOCATION_FIELD);
  // In the USER_GEOGRAPHY_REALM access realm, we say that a user
  // who has the grant ID equivalent to the {taxonomy_term_data}.tid of
  // a term with which the node was tagged is allowed to see it.
  foreach ($items as $item) {
    $grants[] = array(
      'realm' =&gt; USER_GEOGRAPHY_REALM,
      'gid' =&gt; $item['tid'],
      'grant_view' =&gt; 1,
      'grant_update' =&gt; 0,
      'grant_delete' =&gt; 0
    );
  }
  return $grants;
}

/**
 * Implements hook_node_grants().
 */
function my_mod_node_grants($account, $op) {
  if ($op == 'view') {
    // Reload to make sure fields have been attached.
    $account = user_load($account-&gt;uid);
    $gids = array(USER_GEOGRAPHY_REALM =&gt; array());
    $items = field_get_items('user', $account, LOCATION_FIELD);
    // In the USER_GEOGRAPHY_REALM, a user's grants are the different
    // locations that he is a part of.
    foreach ($items as $item) {
      $gids[USER_GEOGRAPHY_REALM][] = $item['gid']
    }
    return $gids;
  }
}


You are free to extend the logic to include per-location limits for a user if you'd like.

You may have to remember to disallow the user from editing his own Location field and can use hook_field_access() for this purpose.