How can I disable a user that should still be visible on the site? It seems that User name on blocked user account not visible in view for anonymous users is basically the same question I'm asking, but it doesn't have an accepted answer or one that works for me.  This is a different take on the question than the one I'm making.

I am migrating a site from another CMS.  I am bringing over staff members, both past and current as users of the site.  As part of the migration, users who are no longer with the organization are being marked as blocked to prevent them from logging into the site.

These users are then associated with nodes on the site via various entity reference fields.  The problem I run into is that for anonymous users, indeed for anyone that doesn't have bypass access controls on their account, these user accounts are not visible.

What is the proper way to keep an account visible, while not allowing users to log-in to it?  For me, the answer will need to be something that will work with the Migrate Module.

Obviously blocking the user seemed like the obvious way to do it for me, but I can't find any permission that will allow access to blocked user info.  Is there another way of doing this, or is there a way of making blocked account info visible?

My Solution

Based on the accepted answer from @kiamlaluno, I created a solution that works for me:

I already have an end_date field for each user (field_user_end_date), so most of the time, that would suffice as a limiting factor for the login, but based on discussions with the stakeholders, I added an additional admin only boolean field named field_user_account_locked.

I implement hook_form_alter to add my validation function to the form:

function mymodule_form_alter(&amp;$form, &amp;$form_state, $form_id)
{
    if ($form_id == 'user_login' || $form_id == 'user_login_block') {
        $form['#validate'][] = 'mymodule_user_login_validate';
    }
}


And here is my validation module:

function mymodule_user_login_validate($form, &amp;$form_state)
{
    if (!empty($form_state['uid'])) {
        // The user trying to login is not limited by flood control;
        // user_login_authenticate_validate() found a user with the username and password entered in the login form.
        $user = user_load($form_state['uid']);
        $end_date = (isset($user-&gt;field_user_end_date[LANGUAGE_NONE][0]['value'])) ? strtotime($user-&gt;field_user_end_date[LANGUAGE_NONE][0]['value']) : time() + 300000;
        if ($end_date &lt; time() || $user-&gt;field_user_account_locked[LANGUAGE_NONE][0]['value'] == 1) {
            form_set_error('name', t('The username %name cannot be used to login.', array('%name' =&gt; $form_state['values']['name'])));
        }
    }
}


I'd love some constructive criticism on it, if you have some.
Using a custom module, you could change the permission to see user profiles. For example, the following code could be used for Drupal 7.

function mymodule_permission() {
  return array(
    'access blocked user profiles' =&gt; array(
      'title' =&gt; t('View user profiles of blocked users'),
    ),
  );
}

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

function mymodule_view_access($account) {
  $uid = is_object($account) ? $account-&gt;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']-&gt;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);
      }
      if (is_object($account)) {
        // If the account is blocked, show the profile to users with the right
        // permission.
        return ($account-&gt;status ? TRUE : user_access('access blocked user profiles'));
      }
    }
  }
  return FALSE;
}


Give the new permission to anonymous users, and they will be able to see the user profile of blocked users.

This is probably easier than changing password and email, and it's easier to revert if you block by mistake a current employee: Just unblock the account.

The code I shown works for a direct access to the user profile, and for modules that only verify the user has the access user profile permission to show the link to a user profile. This is what Drupal does, for example in template_preprocess_username().

  $variables['profile_access'] = user_access('access user profiles');
  $variables['link_attributes'] = array();
  // Populate link path and attributes if appropriate.
  if ($variables['uid'] &amp;&amp; $variables['profile_access']) {
    // We are linking to a local user.
    $variables['link_attributes'] = array('title' =&gt; t('View user profile.'));
    $variables['link_path'] = 'user/' . $variables['uid'];
  }
  elseif (!empty($account-&gt;homepage)) {
    // Like the 'class' attribute, the 'rel' attribute can hold a
    // space-separated set of values, so initialize it as an array to make it
    // easier for other preprocess functions to append to it.
    $variables['link_attributes'] = array('rel' =&gt; array('nofollow'));
    $variables['link_path'] = $account-&gt;homepage;
    $variables['homepage'] = $account-&gt;homepage;
  }


Any module using theme('username') (for which template_preprocess_username is a preprocess function) to show the user name will print the link to the user profile, even if the shown user account is blocked, if the currently logged-in user has the access user profile permission.

If there are modules that check the user account is blocked before showing a link to the user profile, then this method will not work.

In this case, the alternative I would adopt is the following:


Don't block the user accounts for those ex employees
Add a flag to the user accounts that says if an account can be used to log in
Using an extra validation handler for the login form, return an error if one of those accounts is used to log in




function mymodule_form_alter(&amp;$form, &amp;$form_state, $form_id) {
  if ($form_id == 'user_login' || $form_id == 'user_login_block') {
    $form['#validate'][] = 'mymodule_user_login_validate';
  }
  elseif ($form_id == 'user_register_form') {
    $form['account']['can_login'] = array(
      '#type' =&gt; 'checkbox',
      '#title' =&gt; t('The user account can be used to log in'),
      // The form is for registering a new user; there is nothing to load from the database.
      '#default_value' =&gt; TRUE,
      // See user_register_form() which set the following value to TRUE if
      // the currently logged-in user administer users.
      '#access' =&gt; $form['administer_users']['#value'],
    );
    $form['#submit'][] = 'mymodule_register_submit';
  }
  elseif ($form_id == 'user_profile_form') {
    if ($form['#user_category'] == 'account') {
      $form['account']['can_login'] = array(
        '#type' =&gt; 'checkbox',
        '#title' =&gt; t('The user account can be used to log in'),
        '#default_value' =&gt; mymodule_load_flag($form['#user']-&gt;uid),
        '#access' =&gt; user_access('administer users'),
      );
      $form['#submit'][] = 'mymodule_profile_submit';
    }
  }
}

function mymodule_user_login_validate($form, &amp;$form_state) {
  if (!empty($form_state['uid'])) {
    // The user trying to login is not limited by flood control;
    // user_login_authenticate_validate() found a user with the username and password entered in the login form.
    if (!mymodule_load_flag($form_state['uid'])) {
      form_set_error('name', t('The username %name cannot be used to login.', array('%name' =&gt; $form_state['values']['name'])));
    }
  }
}

function mymodule_register_submit($form, &amp;$form_state) {
  if ($form_state['values']['administer_users']) {
    // The user submitting the form can administer users. 
    // user_register_submit() sets $form_state['values']['uid']; save it in
    // a database table the module creates when installed.
    mymodule_save_flag($form_state['values']['uid'], $form_state['values']['can_login']);
  }
}

function mymodule_profile_submit($form, &amp;$form_state) {
  if (user_access('administer users') &amp;&amp; $form['#user_category'] == 'account') {
    // user_profile_submit() sets $form_state['values']['uid']; save it in
    // a database table the module creates when installed.
    mymodule_save_flag($form_state['values']['uid'], $form_state['values']['can_login']);
  }
}