Verifique se o usuário tem acesso a uma determinada página

23

Como posso determinar se um usuário tem permissão para acessar uma determinada página?

farzan
fonte
Você não especificou qual versão do Drupal você usa. Mais detalhes sobre seu objetivo também seriam úteis; nos casos mais comuns, o Drupal manipula o acesso ao menu automaticamente.
Dylan Tack

Respostas:

25

Se você deseja verificar se o usuário conectado no momento tem acesso a uma página, use o seguinte código:

if ($router_item = menu_get_item($path)) {
  if ($router_item['access']) {
    // The user has access to the page in $path.
  }
}

$path é o caminho da página que você deseja verificar (por exemplo, nó / 1, admin / usuário / usuário).

O código funciona no Drupal 6 e versões superiores, e é o código usado em menu_execute_active_handler () .

O motivo pelo qual não estou sugerindo chamar diretamente o retorno de chamada de acesso é porque os argumentos que precisam ser passados ​​para essa função.

O código usado por _menu_check_access () é o seguinte (Drupal 7):

$arguments = menu_unserialize($item['access_arguments'], $map);
// As call_user_func_array is quite slow and user_access is a very common
// callback, it is worth making a special case for it.
if ($callback == 'user_access') {
  $item['access'] = (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
}
elseif (function_exists($callback)) {
  $item['access'] = call_user_func_array($callback, $arguments);
}

O código, que precisa ser o mais genérico possível, não lida diretamente com um objeto de usuário. Isso significa que não é possível substituir o objeto de usuário do usuário atualmente conectado por outro objeto de usuário.
O código deve ser genérico o suficiente para manipular definições de menu, como as seguintes:

$items['node/add/' . $type_url_str] = array(
  'title' => $type->name, 
  'title callback' => 'check_plain', 
  'page callback' => 'node_add', 
  'page arguments' => array($type->type), 
  'access callback' => 'node_access', 
  'access arguments' => array('create', $type->type), 
  'description' => $type->description, 
  'file' => 'node.pages.inc',
);

$items['node/%node'] = array(
  'title callback' => 'node_page_title', 
  'title arguments' => array(1),
  // The page callback also invokes drupal_set_title() in case
  // the menu router's title is overridden by a menu link. 
  'page callback' => 'node_page_view', 
  'page arguments' => array(1), 
  'access callback' => 'node_access', 
  'access arguments' => array('view', 1),
);

Nas duas definições, os argumentos de acesso não incluem um objeto de usuário e, neste caso , node_access () usa o objeto de usuário para o usuário conectado no momento. No segundo caso, um dos argumentos é o objeto de nó obtido da URL; por exemplo, se a URL for example.com/node/1, o segundo argumento passado para o retorno de chamada de acesso é o objeto do nó com o ID do nó igual a 1.
Escrever código que também lida com esses casos significaria duplicar o código já existe no Drupal. Mesmo se você duplicou esse código, ainda haveria o problema dos retornos de chamada de acesso que estão verificando o acesso no usuário conectado no momento.

Se você deseja verificar se um usuário que não é o usuário conectado no momento pode acessar um menu, altere primeiro o valor da variável global $user, use o código que relatei no início da minha resposta e, em seguida, restaure o valor de $user. Para saber como alterar o valor global $user, você pode ver Representando programaticamente outro usuário sem fazer com que o usuário conectado no momento efetue logout . A diferença é que, em vez de usar o valor retornado de drupal_anonymous_user () , você usa o valor retornado de user_load () .

kiamlaluno
fonte
Posso saber em qual gancho esse código deve ser escrito.
Gladiator
14

Tente drupal_valid_path () .

A função retorna TRUEé o caminho passado conforme o argumento existe e o usuário atual tem acesso a ele. Portanto, se você estiver trabalhando no Drupal 7 e precisar verificar o acesso do usuário atualmente conectado, é o caminho mais fácil:

if (drupal_valid_path('my/path')) {
  // Your code here...
}
peterpoe
fonte
1
No D7, drupal_valid_pathfaz o trabalho perfeitamente e é feito para atender exatamente a essa necessidade. Ele usa menu_get_item e verifica o acesso também.
Weboide
Isso é verdade, mas funciona apenas para o usuário conectado no momento. Se você quiser saber se algum outro usuário pode acessar o caminho, drupal_valid_pathnão o ajudará.
Andrew Schulman
@AndrewSchulman Eu não acho que exista uma API para isso, mas você pode mudar temporariamente os usuários.
Peterpoe 03/03
No Drupal 8, isso foi movido para \Drupal::service('path.validator')->isValid($path);- veja a documentação
Gogowitsch
3

Ligue para o access callbackespecificado na entrada do menu responsável pela página. Essa entrada de menu geralmente é criada pelo Drupal chamando a implementação hook_menue é armazenada em algum lugar do banco de dados. Cuidado para que os dados retornados por hook_menupossam ser alterados por uma implementação de módulo hook_menu_alter.

Observe que alguns módulos podem não passar o usuário como um argumento separado (conforme especificado pela access argumentschave da entrada do menu), mas, em vez disso, podem usar o $userobjeto global . Você precisará verificar isso para cada módulo que você usa.

Oswald
fonte
Este método pode ser usado para descobrir se algum outro usuário que não seja o usuário ativo tem permissão para acessar a página.
Oswald
1
Chamar o retorno de chamada de acesso não é tão fácil quanto chamar qualquer outra função, pois o retorno de chamada de acesso precisa de argumentos específicos; consulte _menu_check_access () , que é a função que verifica se o usuário conectado no momento tem acesso a um menu.
Kiamlaluno
2

Confira a user_access()função. Consulte o link para os parâmetros especificados para cada versão do Drupal. Na página de documentação do Drupal 7-8:

Parâmetros

$ string A permissão, como "administrar nós", está sendo verificada.

$ account (opcional) A conta a ser verificada, se não for dada, use o usuário conectado no momento.

Valor de retorno

Booleano TRUE se o usuário atual tiver a permissão solicitada.

Todas as verificações de permissão no Drupal devem passar por essa função. Dessa forma, garantimos um comportamento consistente e garantimos que o superusuário possa executar todas as ações.

Laxman13
fonte
user_access () é para verificar se o usuário tem um certo "tipo" de permissões. O que é necessário é se o usuário pode acessar um determinado "caminho"; por exemplo, se o usuário puder acessar 'node / 12'?
Farzan
Bem, como você está determinando quando um usuário tem permissão ou não? Eu diria que há uma opção na página de permissões que você quer ter verificado ou não dar certos papéis a permissão
Laxman13
user_access()nem sempre é o retorno de chamada de acesso usado por um menu; mesmo assim, você deve conhecer os argumentos de acesso aos quais precisa passar user_access().
kiamlaluno
Eu sei que nem sempre é user_access(), apenas imaginei que o OP tinha uma permissão em mente para verificar se o usuário deveria ter acesso. Não era uma pergunta muito descritivo
Laxman13
Mesmo que o user_access não possa verificar o acesso a um caminho específico, acho que usar o user_access sempre que possível é a melhor maneira de verificar o acesso. Boa resposta @ Laxman13 +1.
precisa saber é o seguinte
2

Se você precisar saber se um usuário pode acessar um nó específico e está usando um módulo de acesso ao nó, use node_access () . (sem um módulo de acesso ao nó, eles apenas precisam da permissão "acessar conteúdo".)

Se você deseja descobrir se um usuário pode acessar um caminho arbitrário definido por uma implementação hook_menu (), pode ser necessário recuperar a entrada de menu do banco de dados e avaliar seu parâmetro 'access callback'.

gapple
fonte
2
    $node = node_load(123);

    $account = user_load(456);

    if (node_access("update", $node, $account) === TRUE) 
   {

         print "access";    
    }
Mahipal Purohit
fonte