2

Is there any way in Drupal to control access to users like it's done in hook_node_access() for nodes? I'm looking for something like hook_user_access() or hook_entity_access().

I have an entity reference field (user reference). I want that users can only select users from their organic group, in the entity reference field.

I wanted to do it by implementing some hook like hook_entity_access(), but this hook doesn't exist.

3

There isn't an equivalent of hook_node_access() for users, or generically for any entity.

To check which user accounts can be selected from the Entity reference autocomplete, you could change the menu callback for the autocomplete.

function mymodule_menu_alter(&$items) {
  if (isset($items['entityreference/autocomplete/single/%/%/%'])) {
    $items['entityreference/autocomplete/single/%/%/%']['page callback'] = 'mymodule_entity_autocomplete';
  }
}

function mymodule_entity_autocomplete($type, $field_name, $entity_type, $bundle_name, $entity_id = '', $string = '') {
  $field = field_info_field($field_name);
  $instance = field_info_instance($entity_type, $field_name, $bundle_name);
  $matches = array();

  if ($type = 'user') {
    // Populate $matches with the matching users the currently logged-in user can select.
    return $matches;
  }

  return entityreference_autocomplete_callback_get_matches($type, $field, $instance, $entity_type, $entity_id, $string);
}

Probably you need to change the access callback of the autocomplete path too, with $items['entityreference/autocomplete/single/%/%/%']['access callback'] = 'mymodule_entity_autocomplete';. The access callback defined from the module is the following one.

function entityreference_autocomplete_access_callback($type, $field_name, $entity_type, $bundle_name) {
  $field = field_info_field($field_name);
  $instance = field_info_instance($entity_type, $field_name, $bundle_name);

  if (!$field || !$instance || $field['type'] != 'entityreference' || !field_access('edit', $field, $entity_type)) {
    return FALSE;
  }
  return TRUE;
}

If then you want to avoid users can view a user account directly using the link to the account, you can change the access callback for user/%user/view.

function mymodule_menu_alter(&$items) {
  if (isset($items['user/%user/view'])) {
    $items['user/%user/view']['access callback'] = 'mymodule_user_view_access';
  }
}

The default access callback is user_view_access(), which contains the following code.

  $uid = is_object($account) ? $account->uid : (int) $account;

  // Never allow access to view the anonymous user account.
  if ($uid) {
    // Admins can view all, users can view own profiles at all times.
    if ($GLOBALS['user']->uid == $uid || user_access('administer users')) {
      return TRUE;
    }
    elseif (user_access('access user profiles')) {
      // At this point, load the complete account object.
      if (!is_object($account)) {
        $account = user_load($uid);
      }
      return (is_object($account) && $account->status);
    }
  }
  return FALSE;

  

Drupal 8 uses hook_entity_access() to control access to any entity (including users) to various operations, hook_ENTITY_TYPE_access() to check the access to specific entities on various operations (for which hook_node_access() is the implementation for nodes), and hook_entity_create_access() to check which users can create an entity.
Drupal 8 code is much simpler than the Drupal 7 code, as as a single hook implementation does the task.

  • thanks, it can help with user page. But it can't help with entity reference field widget. I reviewed code of entityreference. They use entity_load_single() to show entity (user in my case) in autocomplete. – milkovsky Nov 25 '12 at 17:49
  • I apologize: The last time I edited my answer, I didn't complete the edit. I noticed that just now. I had problems with my computer, and forgot about this answer. :| – kiamlaluno Nov 30 '12 at 15:51
  • Thanks, I already resolved my issue using view for the reference field. But your idea with menu callback for the autocomplete is very good. – milkovsky Dec 1 '12 at 13:57
0

Here is one solution.

Entity reference widget can filter values by using view. So in this way there is no need to use any access hook. For other cystom needs we can create custom filter for the view.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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