Regra de acesso em Node no Drupal via programação

Por padrão no Drupal, caso um node esteja publicado, ele será visualizado por qualquer usuário que tenha a permissão de visualizar um conteúdo publicado.
Porém, em alguns casos, existe a necessidade de publicar um node restrito específico.

Para simular tal necessidade, vamos criar um campo do tipo checkout no "Tipo de Conteúdo", que informa se o node é privado ou não.
A primeira regra de visualização será feita utilizando o hook_node_access()

/**
 * Implements hook_node_access().
 */
function mymodule_node_access($node, $op, $account) {

  //Caso o campo esteja checado, o Node é privado
  if (isset($node->field_private[LANGUAGE_NONE][0]) 
     && $node->field_private[LANGUAGE_NONE][0]['value'] == 1) {

  	return NODE_ACCESS_DENY;
  }
}

A desvantagem de utilizar o hook_node_access() é que serve apenas para a visualização da página do node, não restringindo em Views, Menus, Query, etc.
Para a regra funcionar em geral, vamos ignorar a implementação feita no hook_node_access() e utilizar os seguintes hooks: 

hook_node_access_records($node) 
hook_node_grants($account, $op)

O hook_node_access_records() é chamado no momento de salvar um node, atribuindo uma regra à sua exibição.
O hook_node_grants() é chamado quando executada uma ação no node (View, Update ou Delete), e verifica se o usuário corrente possui ou não acesso a essas ações.

No exemplo abaixo, a regra será a de exibir apenas os conteúdos privados para usuários logados que tenham a permissão de "Access private content".  

/**
 * Implementation of hook_node_access_records().
 */
function mymodule_node_access_records($node) {

  //Verifica se o node é privado ou não
  if (isset($node->field_private[LANGUAGE_NONE][0]) && $node->field_private[LANGUAGE_NONE][0]['value'] == '1') {
     $private = TRUE;
  } else {
     $private = FALSE;
  }

  //Caso seja privado, o node é salvo com a gid 1
  if ($private) {
    $grants[] = array(
       'realm' => 'mymodule',
       'gid' => 1,
       'grant_view' => 1,
       'grant_update' => 0,
       'grant_delete' => 0,
       'priority' => 0,
    );
  }
  else {
    //Caso não seja privado, o node é salvo com a gid 0
    $grants[] = array(
       'realm' => 'mymodule',
       'gid' => 0,
       'grant_view' => 1,
       'grant_update' => 0,
       'grant_delete' => 0,
       'priority' => 0,
    );
  } 

  return $grants;
}

/**
 * Implementation of hook_node_grants().
 */
function mymodule_node_grants($account, $op) {

  if ($op == 'view') {
    if (array_key_exists(DRUPAL_AUTHENTICATED_RID, $account->roles)) {

    	/**
	    * Se o usuário que estiver logado tiver a permissão de "Access private content"
	    * poderá visualizar os nodes de gid 0 (públicos) ou 1 (privados). Caso contrario,
	    * irá visualizar apenas os nodes públicos. 
	    */
    	if((in_array("Access private content", $account->roles)){
	       $grants['mymodule'] = array(0,1);
    	} else {
    	   $grants['mymodule'] = array(0);
    	}
    }
    else {
       //Caso seja anonimo, visualiza apenas nodes de gid 0 (públicos).
       $grants['mymodule'] = array(0);
    }

    return isset($grants) ? $grants : array();
  }
}

IMPORTANTE: Para que a implementação funcione, remova o seguinte registro da tabela "node_access":

 nid | gid | realm | grant_view | grant_update | grant_delete 

 -----+-----+-------+------------+--------------+--------------

    0 |   0 | all   |          1 |            0 |            0 

 

O registro acima é o padrão do Drupal, dando acesso a todos os nodes publicados. 

Deletado o registro acima e implementado os hooks, edite e salve seus nodes informando sua regra de acesso.
Após salvar os nodes, veja que novos registros foram adicionados na tabela "node_access".

nid | gid |  realm   | grant_view | grant_update | grant_delete 

 -----+-----+----------+------------+--------------+--------------

    1 |   0 | mymodule |          1 |            0 |            0

    2 |   1 | mymodule |          1 |            0 |            0

 

Para mais detalhes, consulte as seguintes documentações: 
hook_node_access_records, hook_node_grantsfonte.