I want to avoid access to user/%user/view, so only admins can see profiles. At first I tried with changing the permission user_view_access without any luck.

I tried to use the hook hook_menu_alter:

53 function mymenu_menu_alter(&$items) {
54   $items['user'] = array(
55     'access callback' => 'user_access',                                                                                                                                                                                                  
56     'access arguments' => array('access administration pages'),                                                                                                                                                                         
57     'type' => MENU_NORMAL_ITEM,
58   );
59   $items['user/%user_uid_optional'] = array(
60     'access callback' => 'user_access',
61     'access arguments' => array('access administration pages'),
62      'type' => MENU_NORMAL_ITEM,
63   );
64   $items['user/%user/view'] = array(
65     'access callback' => 'user_edit_access',
66     'access arguments' => array('access administration pages'),
67     'type' => MENU_NORMAL_ITEM,
68   );

It doesn't work neither. Do you have any hint?

  • 3
    The easiest way to do this is to simply remove the permission 'access user profiles' from those roles that should not see user profiles. No custom code required that way.
    – jhedstrom
    Commented Apr 19, 2011 at 16:01
  • The problem with that is that it seems that I can see the usernames.
    – penyaskito
    Commented Apr 19, 2011 at 16:41
  • 3
    That's correct, you'll still be able to see those. In order to selectively hide the usernames, you'll need to override theme_username (api.drupal.org/api/drupal/includes--theme.inc/function/…).
    – jhedstrom
    Commented Apr 19, 2011 at 17:54

5 Answers 5


There are four problems with the code you reported:

  • The code is changing the menu type, when it should not do so.
  • The code is changing values that it should not touch, if the purpose is to only change who can access the user profiles.
  • user_edit_access() and user_access() expect the argument they receive to be a user object, not a string. It is wrong to set "access arguments" to array('access administration pages'), as you are doing.
  • Even if you would set "access arguments" to array(1), user_edit_access() allows the users to see their own user profile; if you want to avoid to show to the users their own user profile, then that function is not the function I would use as access callback.
  • As said by jhedstrom, it is not necessary to use code in this case, when it is enough to don't give the permission to access user profiles to those roles you don't want to be able to see any user profile. The answer I am going to give takes the assumption you don't want the users to see any user profile, including their own; in this case, removing the permission to access user profiles doesn't help, as Drupal still allows the users to see their own user profile.
function mymenu_menu_alter(&$items) {
  $items['user/%user/view']['access callback'] = FALSE;

function mymenu_user_view_access($account) {
  return $account && $account->uid && user_access('administer users');
  • * About changing the menu type, is because I want to hide the link. Is there a better way of doing that?
    – penyaskito
    Commented Apr 20, 2011 at 6:55
  • The link is not shown, if the user doesn't have the permission to see the linked page.
    – apaderno
    Commented May 15, 2012 at 11:30
  • I am getting Notice: Trying to get property of non-object in mymenu_user_access()
    – rfegade
    Commented Feb 11, 2016 at 11:55

Finally I achieved what I wanted with:

  function mymenu_menu_alter(&$items) {
   $items['user/%user_uid_optional'] = array(
      'page callback' => '_mymenu_profile_view',
      'page arguments' => array(1),
      'type' => MENU_LOCAL_TASK,

  function _mymenu_profile_view($account) {
    global $user;
    if (user_access('administer users')) {
      include_once(drupal_get_path('module', 'user').'/user.pages.inc');
      return user_view($account);
    } else {
      return drupal_not_found();

Thanks for your suggestions!

  • 2
    It's not the page callback that should decide who can access the page; that should be done from the access callback.
    – apaderno
    Commented May 15, 2012 at 11:31
  • I wouldn't even have gone to all this bother. I'd have used Path Access and had all the legwork taken out for me. If only I'd noticed this question sooner.
    – Chapabu
    Commented May 15, 2012 at 13:00
  • 1
    @Chapabu You can always add your answer. I think there are users for which your solution could be interesting.
    – apaderno
    Commented Nov 20, 2012 at 17:19
  • @kiamlaluno Done - expanded also :)
    – Chapabu
    Commented Nov 21, 2012 at 9:02

This is coming a bit late, but I'll leave this here just in case anyone else has the same problem :)

There's Path Access:

Although a lot of the Drupal modules provide some degree of access control permissions it never covers all possible requirements users have. Path_access provides the means to restrict pages based on their path alias - meaning you can lock out certain user role groups from whole sections of a site using wildcards.

But the best option, and a module that is now at the top of my master .make file is Rabbit Hole - which supports custom redirects for nodes, users and taxonomy terms.

Rabbit Hole is a module that adds the ability to control what should happen when en entity is being viewed at its own page.

Perhaps you have a content type that never should be displayed on its own page, like an image content type that's displayed in a carousel. Rabbit Hole can prevent this node from being accessible on its own page, through node/xxx.


For this trick I have used chain_menu_access module. Code below.

 * Implements hook_menu_alter().
function mymodule_menu_alter(&$items) {
  chain_menu_access_chain($items, 'user/%user', '_mymodule_check_permission');

function _mymodule_check_permission() {
  global $user;

  $own_profile = $user->uid == arg(1);
  $has_access = user_access('administer users');

  return (!$has_access && !$own_profile) ? FALSE : TRUE;

If you want a user to be able to edit their own profile but not view it:

If already using Panels module you can simply create a second variant in the user view override if (in the selection rules) a user lacks the permission needed to view the usual panel (such as User:Permission => Logged in user has "View user profiles"). You choose a HTTP Response Code and select a 301 redirect to user/%user:uid/edit.

You can then hide the view button with CSS or implement the code mentioned above:

function mymodule_menu_alter(&$items) {
  $items['user/%user/view']['access callback'] = '_mymodule_user_view_access';
  $items['user/%user/view']['access arguments'] = array(1);

function _mymodule_user_view_access($account) {
  return $account && $account->uid && user_access('administer users');

or use several methods to remove tabs. I suppose the following should work in Drupal 7 but maybe it's not the right way to do it or it has side effects.

function mymodule_menu_local_tasks_alter(&$data) {
  foreach ($data['tabs'][0]['output'] as $key => $value) {
    if ($value['#link']['path'] == "user/%/view") {

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.