You are here

masquerade_drush.drush.inc in Masquerade Extras 6.2

Same filename and directory in other branches
  1. 7.2 masquerade_drush/masquerade_drush.drush.inc

Provides some drush commands for masquerade.

File

masquerade_drush/masquerade_drush.drush.inc
View source
<?php

/**
 * @file
 * Provides some drush commands for masquerade.
 */

/**
 * Implements hook_drush_command().
 *
 * Specifies our custom commands.
 *
 * @see hook_drush_command()
 */
function masquerade_drush_drush_command() {
  $items = array();
  $items['masquerade'] = array(
    'description' => 'Manipulates masquerades.',
    'arguments' => array(
      'command' => 'The masquerade command to execute.',
      'account' => 'The user account to execute as.',
      'target' => 'The user account to pretend to be.',
    ),
    'options' => array(),
    'aliases' => array(
      'msq',
    ),
    'examples' => array(
      'drush masquerade [list|show]' => 'Lists the active masquerades in the site.',
      'drush masquerade [terminate|end|stop|term] <source:username>' => 'Terminates any active masquerades for username|user ID|email address',
      'drush masquerade [start|begin] <source:username> <target:username>' => 'Initializes a masquerade for <username|user ID|email address>.' . "\n" . 'On the next page, they will become the "target" account.',
    ),
    'bootstrap' => DRUSH_BOOTSTRAP_SITE,
  );
  $items['sessions'] = array(
    'description' => 'Manipulates user sessions.',
    'arguments' => array(
      'command' => 'The command to execute.',
      'account' => 'The user account to manipulate.',
    ),
    'examples' => array(
      'drush sessions [list]' => 'Lists all users logged in to the site.',
      'drush sessions <user>' => 'Lists any sessions belonging to <user>.',
      'drush sessions terminate <user>' => 'Ends the session for <user>.',
    ),
    'aliases' => array(
      'sess',
    ),
    'bootstrap' => DRUSH_BOOTSTRAP_SITE,
  );
  return $items;
}

/**
 * Implements hook_drush_help().
 *
 * @see hook_drush_help()
 */
function masquerade_drush_drush_help($section) {
  switch ($section) {

    // drush masquerade
    case 'drush:masquerade':
      return dt('Allows you to initialize, terminate, and list masquerades in the current site.');
    case 'meta:masquerade:title':
      return dt('Masquerade Commands');
    case 'meta:masquerade:summary':
      return dt('Manipulates masquerades within a Drupal site.');

    // drush sessions
    case 'drush:sessions':
      return dt('Allows you to view and terminate active user sessions in the site.');
    case 'meta:sessions:title':
      return dt('User Sesssions');
    case 'meta:sessions:summary':
      return dt('Manipulates user sessions in your Drupal site.');
  }
}

/**
 * Implements drush_HOOK_COMMAND().
 *
 * @param string $command
 *  Command to execute.
 * @param string $param1
 *  A property to pass in.
 *
 * @see drush_invoke()
 * @see drush_HOOK_COMMAND()
 */
function drush_masquerade_drush_sessions($command = NULL, $param1 = NULL) {
  switch ($command) {

    // Terminates a user's session.
    case 'terminate':
    case 'end':
    case 'stop':
    case 'term':
      return _masquerade_drush_sessions_terminate($param1);

    // Lists active masquerades.
    case 'list':
    case 'show':
      return _masquerade_drush_sessions($param1);

    // If no command was specified, we can shortcut this.
    default:
      return _masquerade_drush_sessions($command);
  }
}

/**
 * Implements drush_HOOK_COMMAND().
 *
 * @param string $command
 *  The command to execute.
 * @param string $param1
 *  A property to pass in.
 * @param string $param2
 *  An additional property to pass in.
 *
 * @see drush_invoke()
 * @see drush_HOOK_COMMAND()
 */
function drush_masquerade_drush_masquerade($command = NULL, $param1 = NULL, $param2 = NULL) {
  switch ($command) {

    // Terminates a masquerade from the source account.
    case 'terminate':
    case 'end':
    case 'stop':
    case 'term':
      return _masquerade_drush_terminate_masquerade($param1);

    // Starts a masquerade.
    case 'start':
    case 'begin':
      return _masquerade_drush_start_masquerade($param1, $param2);

    // Lists active masquerades.
    case 'list':
    case 'show':
      return _masquerade_drush_list($param1);

    // A shortcut to list masquerades from the active user
    // if no 'list|show' is provided.
    default:
      return _masquerade_drush_list($command);
  }
}

/**
 * Retrieves a user account.
 * @param string $account
 *  The user ID, email address, or account name we want to load.
 * @return
 *  Loads the base user.
 * @retval stdClass
 */
function _masquerade_drush_get_user($account) {

  // Don't trust user input, even on the command line.
  $account_name = db_escape_string($account);

  // Start writing a query to find the user.
  $query_user = sprintf("SELECT uid\n       FROM {users} AS u\n      WHERE u.name='%s'\n         OR u.mail='%s'", $account_name, $account_name);

  // If the account passed to us was a user id...
  if (is_int($account)) {
    $query_user .= sprintf("OR u.uid='%d'", $account);
  }

  // Finally, we get to execute the query.
  $query_user = db_query($query_user);
  $user = db_fetch_object($query_user);

  // If the user requested wasn't found, return FALSE.
  if (empty($user->uid)) {
    return FALSE;
  }

  // Finally, get the user requested!
  return user_load($user->uid);
}

/**
 * Deletes active masquerades from the database.
 * This is exceptionally useful when an active masquerade is causing
 * a development problem and the user can't end the masquerade.
 * @param string $account
 *  The source account name whose masquerade(s) need to be stopped.
 */
function _masquerade_drush_terminate_masquerade($account) {

  // Find the requested user account.
  $account = _masquerade_drush_get_user($account);

  // Make sure the user provided exists.
  if (empty($account)) {
    return drush_print(dt('You must specify a valid user account. You can provide an email address, user ID, or username.'));
  }

  // Lookup the masquerades the current user has active.
  $query_active_masquerades = db_query("SELECT `sid`, `uid_as`, `uid_from`\n       FROM {masquerade}\n      WHERE uid_from = %d", $account->uid);

  // Loop over each masquerade the user currently has active.
  while (FALSE !== ($masquerade = db_fetch_object($query_active_masquerades))) {

    // Restore the session owner to its originator.
    $upd = db_query("UPDATE {sessions}\n          SET `uid` = %d\n        WHERE `sid` = '%s'\n        LIMIT 1;", $masquerade->uid_from, $masquerade->sid);
  }

  // Terminate all masquerades in the masquerade table from this user.
  $query_num_ended = db_query("DELETE FROM {masquerade}\n       WHERE `uid_from` = %d", $account->uid);

  // Alert the user to any # of masquerades we terminated.
  if (db_affected_rows($query_num_ended)) {
    return drush_log(dt('Ended @count masquerades from account @user', array(
      '@count' => $num_ended,
      '@user' => $account->name,
    )), 'success');
  }
  return drush_log(dt('No active masquerades for "@user"', array(
    '@user' => $account->name,
  )), 'warning');
}

/**
 * Initializes a masquerade on the user's behalf.
 * This is useful when developing and you want the user to start masquerading
 * as soon as they login to the site.
 * @param string $account
 *  The (source) username.
 * @param string $target
 *  The (target) username.
 */
function _masquerade_drush_start_masquerade($account, $target) {
  session_start();
  $account = _masquerade_drush_get_user($account);
  $target = _masquerade_drush_get_user($target);

  // Ensure the user specified the account they want to begin the masquerade with.
  if (empty($account)) {
    return drush_log(dt("You must specify the source user. You can provide an email address, user ID, or username."), 'error');
  }

  // Ensure the user specified the account they want to masquerade as.
  if (empty($target)) {
    return drush_log(dt("You must specify the target user. You can provide an email address, user ID, or username."), 'error');
  }

  // Lookup the requested account's session.
  $query_session = db_query('SELECT `sid`, `uid`
       FROM {sessions} AS s
      WHERE s.`uid` = %d', $account->uid);
  $session = db_fetch_object($query_session);

  // If the requested user doesn't have a session, this won't work...just exit.
  if (empty($session)) {
    return drush_log(dt("The requested masquerader is not currently logged into the site."), 'error');
  }

  // Take over our own session with the session ID of the real user.
  session_id($session->sid);

  // Change ownership of the session to the target user.
  $query_session_update = db_query("UPDATE {sessions}\n        SET `uid` = %d,\n        `session` = '%s',\n          `cache` = %d\n      WHERE `uid` = %d\n      LIMIT  1", $target->uid, serialize($_SESSION), 0, $account->uid);

  // If no update was performed, there's something amiss.
  if (0 == db_affected_rows($query_session_update)) {
    return drush_log(dt('There was a problem initializing a masquerade for: "@name".', array(
      '@name' => $account->name,
    )), 'error');
  }

  // Update the masquerade table.
  $query_new_masquerader = db_query("INSERT INTO {masquerade}\n      (uid_from, uid_as, sid)\n     VALUES (%d, %d, '%s');", $account->uid, $target->uid, $session->sid);

  // Inform the user the masquerade has begun.
  if (0 < db_affected_rows($query_new_masquerader)) {
    return drush_log(dt('Initialized masquerade for "@user" as "@target"', array(
      '@user' => $account->name,
      '@target' => $target->name,
    )), 'success');
  }

  // There was a problem initializing the masquerade.
  return drush_log(dt('There was a problem initalizing the masquerade.'), 'error');
}

/**
 * Displays a table of active masquerades in the site.
 * @param string $account
 *  An optional username, user ID, or email address to filter
 *  the list down to.
 */
function _masquerade_drush_list($account = NULL) {
  $query_masqueraders = "SELECT m.sid AS sid, \n       u2.uid AS u2_uid, \n       u2.name AS u2_name,\n       u.uid AS uid,\n       u.name AS name\n       FROM {masquerade} AS m\n     LEFT JOIN {users} AS u2\n         ON u2.uid = m.uid_as\n     LEFT JOIN {users} AS u\n         ON u.uid = m.uid_from";

  // If a user account was provided, we can whittle down
  // the list to just masquerades with this account.
  if (FALSE !== ($account = _masquerade_drush_get_user($account))) {
    $query .= sprintf("WHERE m.uid_from = %d", $account->uid);
  }
  $query_list = db_query($query_masqueraders);

  // Fill in the rows.
  $rows = array();
  $rows[] = array(
    'Source User',
    'UserId',
    'Posing As',
    'UserId',
  );

  // Just a helpful display trick.
  $rows[] = array(
    '-------------------------',
    '----------',
    '-------------------------',
    '----------',
  );
  $found = 0;

  // Loop through the active masquerades and turn them into rows.
  while (FALSE !== ($m = db_fetch_object($query_list))) {
    $rows[] = array(
      $m->name,
      $m->uid,
      $m->u2_name,
      $m->u2_uid,
    );
    $found++;
  }
  if ($found < 1) {
    return drush_log(dt('No one is masquerading at this time.'), 'ok');
  }

  // Display the list.
  drush_print_table($rows, TRUE);
}

/**
 * Utility command to dump the active sessions table from the site.
 * @param string $account
 *  An account name, user ID, or email address to search for.
 */
function _masquerade_drush_sessions($account = NULL) {

  // Grab all the sessions
  $query_sessions = "\n     SELECT s.`uid`, s.`sid`, u.`name`, s.`timestamp`, s.`hostname`\n       FROM {sessions} AS s\n     LEFT JOIN {users} AS u\n         ON u.`uid` = s.`uid`";

  // If the account was found, limit the results to just that account.
  if (!empty($account)) {

    // If an account was provided, load it.
    $user = _masquerade_drush_get_user($account);

    // Make sure we found the user.
    if (!$user) {
      return drush_log(dt('The account "@name" could not be found.', array(
        '@name' => $account,
      )), 'error');
    }

    // This is the closest and safest way to affect the query in oen shot.
    $query_sessions .= sprintf(" AND s.uid = %d", $user->uid);
  }
  $query_sessions = db_query($query_sessions);
  if (!empty($user) && empty($sessions)) {
    return drush_log(dt('The user "@name" is not logged in right now.', array(
      '@name' => $user->name,
    )), 'ok');
  }

  // Dump a list of headers so the table actually makes sense.
  $list = array(
    array(
      'uid',
      'username',
      'hostname',
      'timestamp',
    ),
    array(
      '----------',
      '-----------',
      '---------------',
      '-----------',
    ),
  );
  while (FALSE !== ($s = db_fetch_object($query_sessions))) {
    $list[] = array(
      $s->uid,
      $s->name,
      $s->hostname,
      $s->timestamp,
    );
  }
  drush_print_table($list, TRUE);
}

/**
 * Ends a user's session.
 * @param string $param1
 *  The account name, user id, or email address to lookup.
 */
function _masquerade_drush_sessions_terminate($param1 = NULL) {
  if (empty($param1)) {
    return drush_log(dt('Please specify an account.'), 'error');
  }

  // Try to lookup the user account.
  $account = _masquerade_drush_get_user($param1);

  // Make sure we found the account we wanted.
  if (empty($account)) {
    return drush_log(dt('The account "@name" could not be found.', array(
      '@name' => $param1,
    )), 'error');
  }

  // Check which command we wanted to execute.
  $response = drush_prompt(dt('Are you sure you want to terminate "@name"\'s session? (y/n)', array(
    '@name' => $account->name,
  )), NULL);
  $response = strtoupper(trim($response));
  if (!in_array($response, array(
    'Y',
    'YES',
  ))) {
    return drush_log(dt('Cancelled action.'), 'ok');
  }
  $query_terminated = db_query("DELETE FROM {sessions}\n           WHERE `uid` = %d", $account->uid);
  return drush_log(dt('Terminated @count sessions for "@name".', array(
    '@count' => db_affected_rows($query_terminated),
    '@name' => $account->name,
  )), 'ok');
}

Functions

Namesort descending Description
drush_masquerade_drush_masquerade Implements drush_HOOK_COMMAND().
drush_masquerade_drush_sessions Implements drush_HOOK_COMMAND().
masquerade_drush_drush_command Implements hook_drush_command().
masquerade_drush_drush_help Implements hook_drush_help().
_masquerade_drush_get_user Retrieves a user account.
_masquerade_drush_list Displays a table of active masquerades in the site.
_masquerade_drush_sessions Utility command to dump the active sessions table from the site.
_masquerade_drush_sessions_terminate Ends a user's session.
_masquerade_drush_start_masquerade Initializes a masquerade on the user's behalf. This is useful when developing and you want the user to start masquerading as soon as they login to the site.
_masquerade_drush_terminate_masquerade Deletes active masquerades from the database. This is exceptionally useful when an active masquerade is causing a development problem and the user can't end the masquerade.