You are here

userone.module in User One 6

Same filename and directory in other branches
  1. 8 userone.module
  2. 7 userone.module

User One module.

Allows first user to log in with a login name different from username.

File

userone.module
View source
<?php

/**
 * @file
 * User One module.
 *
 * Allows first user to log in with a login name different from username.
 */

/**
 * Implementation of hook_help().
 */
function userone_help($path, $arg) {
  switch ($path) {
    case 'admin/help#userone':
      return t('Allows first user to log in with a login name different from user name.');
  }
}

/**
 * Implementation of hook_menu_alter().
 */
function userone_menu_alter(&$items) {

  // Since there is no "pre-delete" action for hook_user(), modify access callback.
  $items['user/%user/delete']['access callback'] = 'userone_delete_access';
}
function userone_delete_access($perm) {

  // No one, not even user one, should have delete permission for user one.
  if (arg(1) == 1) {
    return FALSE;
  }
  else {
    return user_access($perm);
  }
}

/**
 * @param $mode
 *   string: 'view' or 'edit'
 */
function userone_access_raw($mode) {
  static $cached, $roles;
  if (!$cached[$mode]) {
    $cached[$mode] = TRUE;
    $roles[$mode] = array();
    if ($mode == 'view') {
      $result = db_query("SELECT rid FROM {permission} WHERE perm LIKE '%%access user profiles,%%' OR perm LIKE '%%access user profiles'");
    }
    else {
      if ($mode == 'edit') {
        $result = db_query("SELECT rid FROM {permission} WHERE perm LIKE '%%administer users,%%' OR perm LIKE '%%administer users'");
      }
      else {
        return FALSE;
      }
    }
    while ($row = db_fetch_object($result)) {
      $roles[$mode][] = $row->rid;
    }
  }
  return $roles[$mode];
}

/**
 * Implementation of hook_user().
 */
function userone_user($op, &$edit, &$account, $category = NULL) {
  global $user;

  // Access control to edit of user one account.
  if ($op == 'form') {
    if ($account->uid == 1 and $user->uid != 1) {

      // Make sure access allowed roles are pulled from ones with 'administer users' permission.
      $roles_access = userone_access_raw('edit');
      $roles_access = array_intersect($roles_access, variable_get('userone_edit_access', userone_access_raw('edit')));
      if (!(user_edit_access($account) and (bool) array_intersect($roles_access, array_keys($user->roles)))) {
        drupal_goto('user');
      }
    }
  }
  else {
    if ($op == 'view') {
      if ($account->uid == 1 and $user->uid != 1) {

        // Make sure access allowed roles are pulled from ones with 'access user profiles' permission.
        $roles_access = userone_access_raw('view');
        $roles_access = array_intersect($roles_access, variable_get('userone_view_access', userone_access_raw('view')));
        if (!(user_view_access($account) and (bool) array_intersect($roles_access, array_keys($user->roles)))) {
          drupal_goto('user');
        }
      }
    }
  }
}

/**
 * Implementation of hook_form_alter().
 */
function userone_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'user_login' || $form_id == 'user_login_block') {

    // Replace the core validator with useone's.
    foreach ($form['#validate'] as $key => $validator) {
      if ($validator == 'user_login_authenticate_validate') {
        $form['#validate'][$key] = 'userone_login_authenticate_validate';
        break;
      }
    }
  }
  else {
    if ($form_id == 'user_admin_account') {
      $keys = array(
        'name',
        'status',
        'roles',
        'member_for',
        'last_access',
        'operations',
      );
      foreach ($keys as $key) {
        unset($form[$key][1]);
      }
      unset($form['accounts']['#options'][1]);
    }
  }
}

/**
 * Replace core's user_login_authenticate_validate()
 */
function userone_login_authenticate_validate($form, &$form_state) {
  if (!userone_authenticate($form_state['values'])) {
    user_authenticate($form_state['values']);
  }
}

/**
 * @return
 *   True if User One handled authentication whether it was successful or not so it is not handled again by user_authenticate().
 */
function userone_authenticate($form_values) {
  global $user;
  if ($userone_name = variable_get('userone_name', '')) {
    $userone = user_load(1);
    if ($form_values['name'] == $userone_name) {
      if (md5($form_values['pass']) == $userone->pass) {
        if (userone_check_ip()) {
          $user = $userone;
          user_authenticate_finalize($form_values);
          watchdog('userone', 'Session opened for user one account.');
        }
        else {
          watchdog('userone', 'Login attempt failed for user one due to unmatching IP address.');
        }
      }
      else {
        watchdog('userone', 'Login attempt failed for user one with User One login (%user).', array(
          '%user' => $form_values['name'],
        ));
      }
      return TRUE;
    }
    elseif ($form_values['name'] == $userone->name) {
      if (md5($form_values['pass']) == $userone->pass) {
        watchdog('userone', 'Login attempt failed for user one with Drupal username (%user) and correct password.', array(
          '%user' => $form_values['name'],
        ));
      }
      else {
        watchdog('userone', 'Login attempt failed for user one with Drupal username (%user) and wrong password.', array(
          '%user' => $form_values['name'],
        ));
      }
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Check if remote ip address is in the allowed list.
 */
function userone_check_ip() {
  if ($ips = variable_get('userone_ip', '')) {
    $ips = explode("\n", str_replace("\r", '', $ips));
    foreach ($ips as $ip) {
      if (strpos($_SERVER['REMOTE_ADDR'] . '.', "{$ip}.") === 0) {
        return TRUE;
      }
    }
    return FALSE;
  }
  return TRUE;
}

/**
 * Implementation of hook_menu().
 */
function userone_menu() {
  global $user;
  $items = array();
  $items['admin/settings/userone'] = array(
    'title' => 'User One',
    'description' => 'Configure User One.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'userone_admin_settings',
    ),
    'access callback' => 'userone_admin_access',
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}
function userone_admin_access() {
  return $GLOBALS['user']->uid == 1 ? TRUE : FALSE;
}
function userone_admin_settings() {
  $form['info'] = array(
    '#value' => '<p>' . t('User One authenticates the admin account (user 1) using login name in place of username. The module may conflict with  other 3rd party authentication modules.') . '</p>',
  );
  $form['userone_name'] = array(
    '#type' => 'textfield',
    '#title' => t('User One Login Name'),
    '#description' => t('In order to ensure uniqueness of the login name, you are <strong>strongly encouraged to use illegal characters</strong> for regular user name such as !@#$%&*.'),
    '#default_value' => variable_get('userone_name', ''),
  );
  $form['userone_ip'] = array(
    '#type' => 'textarea',
    '#title' => t('Allowed IP addresses'),
    '#description' => t('List one IP per line which admin account should login from. Missing trailing numbers will be interpreted as wildcard. (i.e., 123.45 will allow all IPs like 123.45.*.*). If empty, there will be no restriction.'),
    '#default_value' => variable_get('userone_ip', ''),
  );
  $roles = user_roles(TRUE, 'administer users');
  if ($roles) {
    $form['userone_edit_access'] = array(
      '#type' => 'checkboxes',
      '#title' => t('Allow editing user one account'),
      '#default_value' => variable_get('userone_edit_access', array()),
      '#options' => $roles,
      '#description' => t("User One blocks all roles with 'administer users' permission from editing user one account. Check roles for which you want to allow editing user one account, which is not recommended. Additionally, delete access to user one is blocked for everyone including user one itself."),
    );
  }
  else {
    $form['userone_edit_access_info'] = array(
      '#type' => 'item',
      '#title' => t('Access to user one edit blocked'),
      '#description' => t('No account except user one account can edit user one account regardless of roles and permissions.'),
    );
  }
  $roles = user_roles(FALSE, 'access user profiles');
  if ($roles) {
    $form['userone_view_access'] = array(
      '#type' => 'checkboxes',
      '#title' => t('Allow viewing user one account'),
      '#default_value' => variable_get('userone_view_access', userone_access_raw('view')),
      '#options' => $roles,
      '#description' => t("Uncheck roles for which you want to disallow viewing user one account even if they have 'access user profiles' permission."),
    );
  }
  else {
    $form['userone_view_access_info'] = array(
      '#type' => 'item',
      '#title' => t('Access to user one profile blocked'),
      '#description' => t('No account except user one account can view user one account.'),
    );
  }
  return system_settings_form($form);
}
function userone_admin_settings_validate($form, &$form_state) {
  $userone = user_load(1);
  if ($form_state['values']['userone_name'] == $userone->name) {
    form_set_error('userone_name', t('Login name may not be same as username, %name.', array(
      '%name' => $userone->name,
    )));
  }
}

/**
 * Implementation of hook_block().
 *
 * Code is identical to user_block() except it hides user one in "What's new" and "Who's online" blocks.
 */
function userone_block($op = 'list', $delta = 0, $edit = array()) {
  global $user;
  if ($op == 'list') {
    $blocks[2]['info'] = t('Who\'s new (userone)');

    // Too dynamic to cache.
    $blocks[3]['info'] = t('Who\'s online (userone)');
    $blocks[3]['cache'] = BLOCK_NO_CACHE;
    return $blocks;
  }
  else {
    if ($op == 'configure' && $delta == 2) {
      $form['user_block_whois_new_count'] = array(
        '#type' => 'select',
        '#title' => t('Number of users to display'),
        '#default_value' => variable_get('user_block_whois_new_count', 5),
        '#options' => drupal_map_assoc(array(
          1,
          2,
          3,
          4,
          5,
          6,
          7,
          8,
          9,
          10,
        )),
      );
      return $form;
    }
    else {
      if ($op == 'configure' && $delta == 3) {
        $period = drupal_map_assoc(array(
          30,
          60,
          120,
          180,
          300,
          600,
          900,
          1800,
          2700,
          3600,
          5400,
          7200,
          10800,
          21600,
          43200,
          86400,
        ), 'format_interval');
        $form['user_block_seconds_online'] = array(
          '#type' => 'select',
          '#title' => t('User activity'),
          '#default_value' => variable_get('user_block_seconds_online', 900),
          '#options' => $period,
          '#description' => t('A user is considered online for this long after they have last viewed a page.'),
        );
        $form['user_block_max_list_count'] = array(
          '#type' => 'select',
          '#title' => t('User list length'),
          '#default_value' => variable_get('user_block_max_list_count', 10),
          '#options' => drupal_map_assoc(array(
            0,
            5,
            10,
            15,
            20,
            25,
            30,
            40,
            50,
            75,
            100,
          )),
          '#description' => t('Maximum number of currently online users to display.'),
        );
        return $form;
      }
      else {
        if ($op == 'save' && $delta == 2) {
          variable_set('user_block_whois_new_count', $edit['user_block_whois_new_count']);
        }
        else {
          if ($op == 'save' && $delta == 3) {
            variable_set('user_block_seconds_online', $edit['user_block_seconds_online']);
            variable_set('user_block_max_list_count', $edit['user_block_max_list_count']);
          }
          else {
            if ($op == 'view') {
              $block = array();
              switch ($delta) {
                case 2:
                  if (user_access('access content')) {

                    // Retrieve a list of new users who have subsequently accessed the site successfully.
                    $result = db_query_range('SELECT uid, name FROM {users} WHERE uid > 1 AND status != 0 AND access != 0 ORDER BY created DESC', 0, variable_get('user_block_whois_new_count', 5));
                    while ($account = db_fetch_object($result)) {
                      $items[] = $account;
                    }
                    $output = theme('user_list', $items);
                    $block['subject'] = t('Who\'s new');
                    $block['content'] = $output;
                  }
                  return $block;
                case 3:
                  if (user_access('access content')) {

                    // Count users active within the defined period.
                    $interval = time() - variable_get('user_block_seconds_online', 900);

                    // Perform database queries to gather online user lists.  We use s.timestamp
                    // rather than u.access because it is much faster.
                    $anonymous_count = sess_count($interval);
                    $authenticated_users = db_query('SELECT DISTINCT u.uid, u.name, s.timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE u.uid > 1 AND s.timestamp >= %d AND s.uid > 0 ORDER BY s.timestamp DESC', $interval);
                    $authenticated_count = 0;
                    $max_users = variable_get('user_block_max_list_count', 10);
                    $items = array();
                    while ($account = db_fetch_object($authenticated_users)) {
                      if ($max_users > 0) {
                        $items[] = $account;
                        $max_users--;
                      }
                      $authenticated_count++;
                    }

                    // Format the output with proper grammar.
                    if ($anonymous_count == 1 && $authenticated_count == 1) {
                      $output = t('There is currently %members and %visitors online.', array(
                        '%members' => format_plural($authenticated_count, '1 user', '@count users'),
                        '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests'),
                      ));
                    }
                    else {
                      $output = t('There are currently %members and %visitors online.', array(
                        '%members' => format_plural($authenticated_count, '1 user', '@count users'),
                        '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests'),
                      ));
                    }

                    // Display a list of currently online users.
                    $max_users = variable_get('user_block_max_list_count', 10);
                    if ($authenticated_count && $max_users) {
                      $output .= theme('user_list', $items, t('Online users'));
                    }
                    $block['subject'] = t('Who\'s online');
                    $block['content'] = $output;
                  }
                  return $block;
              }
            }
          }
        }
      }
    }
  }
}