How can I disable a user that should still be visible on the site?
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']);
  }
}