Question

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?

Was it helpful?

Solution

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');
}

OTHER TIPS

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!

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") {
      unset($data['tabs'][0]['output'][$key]);
    }
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with drupal.stackexchange
scroll top