diff --git a/sites/all/modules/masquerade/masquerade.module b/sites/all/modules/masquerade/masquerade.module
index 252b4bd..2a95dce 100644
--- a/sites/all/modules/masquerade/masquerade.module
+++ b/sites/all/modules/masquerade/masquerade.module
@@ -23,15 +23,21 @@ function masquerade_help($path, $arg) {
* @return array
*/
function masquerade_permission() {
- return array(
- 'masquerade as user' => array(
- 'title' => t('Masquerade as user'),
- 'description' => t('Masquerade as another user.'),
- ),
- 'masquerade as admin' => array(
- 'title' => t('Masquerade as admin'),
- 'description' => t('Masquerade as the site admin (UID 1).'),
- ),
+ $roles = array();
+ // Load and build permissions for all roles in our site
+ foreach (user_roles() as $rid => $role) {
+ $title = 'masquerade as '. $role;
+ $description = t('Masquerade as a member of the @role role.', array('@role' => $role));
+ if ($rid == DRUPAL_AUTHENTICATED_RID) {
+ $description = t('Grant this permission with caution. Any user signed in is given this role.');
+ }
+ $roles[$title] = array(
+ 'title' => t($title),
+ 'description' => $description,
+ );
+ }
+
+ return $roles + array(
'administer masquerade' => array(
'title' => t('Administer Masquerade'),
'description' => t('Perform administration tasks and configure the Masquerade module.'),
@@ -188,7 +194,7 @@ function masquerade_translated_menu_link_alter(&$item, $map) {
function masquerade_user_operations() {
return array(
'masquerade' => array(
- 'label' => t('Masquerade as user'),
+ 'label' => t('Masquerade as this user'),
'callback' => 'masquerade_user_operations_masquerade',
),
);
@@ -223,7 +229,7 @@ function masquerade_menu_access($type, $uid = NULL) {
case 'unswitch':
return isset($_SESSION['masquerading']) || arg(2) == 'menu-customize' || arg(2) == 'menu';
case 'autocomplete':
- return isset($_SESSION['masquerading']) || (user_access('masquerade as user') || user_access('masquerade as admin'));
+ return isset($_SESSION['masquerading']) || masquerade_has_any_masquerade_permission();
break;
case 'user':
global $user;
@@ -232,18 +238,20 @@ function masquerade_menu_access($type, $uid = NULL) {
case 'switch':
$switch_to_account = FALSE;
global $user;
- if ($uid) {
- if (!is_numeric($uid)) {
+ if (!is_numeric($uid)) {
+ return FALSE;
+ }
+ if ($account = user_load($uid)) {
+ $switch_to_account = db_query("SELECT 1 FROM {masquerade_users} WHERE uid_from = :uid_from AND uid_to = :uid_to", array(
+ ':uid_from' => $user->uid,
+ ':uid_to' => $account->uid
+ ))->fetchField();
+ // Ensure the user we want to switch to has only roles we're permitted to access.
+ if (!masquerade_check_user_roles($account)) {
return FALSE;
}
- if ($account = user_load($uid)) {
- $switch_to_account = db_query("SELECT 1 FROM {masquerade_users} WHERE uid_from = :uid_from AND uid_to = :uid_to", array(
- ':uid_from' => $user->uid,
- ':uid_to' => $account->uid
- ))->fetchField();
- }
}
- return !isset($_SESSION['masquerading']) && (user_access('masquerade as user') || user_access('masquerade as admin') || $switch_to_account);
+ return !isset($_SESSION['masquerading']) || $switch_to_account;
break;
}
}
@@ -252,26 +260,6 @@ function masquerade_menu_access($type, $uid = NULL) {
* Admin settings form.
*/
function masquerade_admin_settings() {
- // create a list of roles; all selected roles are considered administrative.
- $roles = user_roles();
- $form['masquerade_admin_roles'] = array(
- '#type' => 'checkboxes',
- '#title' => t('Roles that are considered "administrators" for masquerading'),
- '#options' => $roles,
- '#default_value' => variable_get('masquerade_admin_roles', array()),
- );
-
- $test_name = _masquerade_user_load(variable_get('masquerade_test_user', ''));
-
- $form['masquerade_test_user'] = array(
- '#type' => 'textfield',
- '#title' => t('Menu Quick Switch user'),
- '#autocomplete_path' => 'masquerade/autocomplete',
- '#default_value' => isset($test_name->name) ? check_plain($test_name->name) : '',
- '#description' => t('Enter the username of an account you wish to switch easily between via a menu item.'),
- '#maxlength' => NULL,
- );
-
$quick_switch = user_load_multiple(variable_get('masquerade_quick_switches', array()));
$quick_switch_users = array();
foreach ($quick_switch as $uid => $account) {
@@ -297,15 +285,6 @@ function masquerade_admin_settings() {
}
function masquerade_admin_settings_validate($form, &$form_state) {
- if (!empty($form_state['values']['masquerade_test_user'])) {
- $test_user = _masquerade_user_load($form_state['values']['masquerade_test_user']);
- if (!$test_user) {
- form_set_error('masquerade_test_user', t('%user does not exist. Please enter a valid username.', array('%user' => $form_state['values']['masquerade_test_user'])));
- }
- }
- // Needs to rebuild menu in masquerade_admin_settings_submit().
- $form_state['masquerade_rebuild_menu'] = (variable_get('masquerade_test_user', '') != $form_state['values']['masquerade_test_user']);
-
// A comma-separated list of users.
$masquerade_switches = drupal_explode_tags($form_state['values']['masquerade_quick_switches']);
// Change user names to user ID's for system_settings_form_submit() to save.
@@ -374,15 +353,17 @@ function masquerade_user_logout($account) {
* Implements hook_user_view().
*/
function masquerade_user_view($account, $view_mode, $langcode) {
- // check if user qualifies as admin
- $roles = array_keys(array_filter(variable_get('masquerade_admin_roles', array())));
- $perm = $account->uid == 1 || array_intersect(array_keys((array)$account->roles), $roles) ?
- 'masquerade as admin' :
- 'masquerade as user';
-
global $user;
+ // Make sure the account viewed isn't our own and that we have adequate
+ // permissions to masquerade as it
+ if ($user->uid == $account->uid || !masquerade_check_user_roles($account)) {
+ return;
+ }
- if (user_access($perm) && empty($account->masquerading) && $user->uid != $account->uid) {
+ // Ensure we have access to: the user page, that we are not presently masquerading,
+ // that the current account isn't our own, and that the user we're looking at
+ // only has roles we can become.
+ if (empty($account->masquerading)) {
$account->content['masquerade'] = array(
'#markup' => l(t('Masquerade as !user', array('!user' => $account->name)),
'masquerade/switch/' . $account->uid,
@@ -444,6 +425,9 @@ function masquerade_user_validate(&$form, $form_state) {
if (!_masquerade_user_load($username)) {
form_set_error('masquerade_users', t('%user is not a valid user name.', array('%user' => $username)));
}
+ if (!masquerade_check_user_roles($username)) {
+ form_set_error('masquerade_users', t('This account has been assigned roles you are not permitted to access.'));
+ }
}
}
}
@@ -532,7 +516,7 @@ function masquerade_block_view($delta = '') {
$block = array();
switch ($delta) {
case 'masquerade':
- if (isset($_SESSION['masquerading']) || (user_access('masquerade as user') || user_access('masquerade as admin'))) {
+ if (isset($_SESSION['masquerading']) || masquerade_has_any_masquerade_permission()) {
$block['subject'] = t('Masquerade');
$block['content'] = drupal_get_form('masquerade_block_1');
}
@@ -568,6 +552,10 @@ function masquerade_block_1() {
if (!isset($_SESSION['user']->uid) || $switch_user != $_SESSION['user']->uid) {
$account = user_load($switch_user);
if (isset($account->uid)) {
+ // Make sure the users in the quick switch list only have roles we're allowed to become.
+ if (!masquerade_check_user_roles($account)) {
+ continue;
+ }
$switch_link = 'masquerade/switch/' . $account->uid;
if ($account->uid) {
$quick_switch_links[] = l($account->name, $switch_link, array('query' => array('token' => drupal_get_token($switch_link))));
@@ -631,6 +619,9 @@ function masquerade_block_1_validate($form, &$form_state) {
if (!$masq_user) {
form_set_error('masquerade_user_field', t('User %masq_as does not exist. Please enter a valid username.', array('%masq_as' => $form_state['values']['masquerade_user_field'])));
}
+ elseif (!masquerade_check_user_roles($masq_user)) {
+ form_set_error('masquerade_user_field', t('You cannot masquerade as %masq_as because this person has roles you are not permitted to switch to.', array('%masq_as' => $form_state['values']['masquerade_user_field'])));
+ }
elseif ($masq_user->uid == $user->uid) {
form_set_error('masquerade_user_field', t('You cannot masquerade as yourself. Please choose a different user to masquerade as.'));
}
@@ -667,10 +658,19 @@ function masquerade_autocomplete($string) {
$matches[$anonymous] = $anonymous;
}
// Other suggestions.
- $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER(:string)", 0, 10, array(
- ':string' => $string . '%',
- ));
- foreach ($result as $user) {
+ $query = db_select('users', 'u')
+ ->fields('u', array('name'))
+ ->condition('name', db_like($string) . '%', 'LIKE')
+ ->orderBy('name', 'ASC')
+ ->range(0, 10);
+
+ $rids = masquerade_get_allowed_roles();
+ if (!in_array(DRUPAL_AUTHENTICATED_RID, $rids)) {
+ $query->join('users_roles', 'ur', 'u.uid = ur.uid');
+ $query->condition('rid', $rids);
+ }
+
+ foreach ($query->execute() as $user) {
$matches[$user->name] = check_plain($user->name);
}
if (module_exists('devel')) {
@@ -705,10 +705,19 @@ function masquerade_autocomplete_multiple($string, $add_anonymous = TRUE) {
}
}
// Other suggestions.
- $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE :string", 0, 10, array(
- ':string' => $last_string . '%',
- ));
- foreach ($result as $user) {
+ $query = db_select('users', 'u')
+ ->fields('u', array('name'))
+ ->condition('name', db_like($string) . '%', 'LIKE')
+ ->orderBy('name', 'ASC')
+ ->range(0, 10);
+
+ $rids = masquerade_get_allowed_roles();
+ if (!in_array(DRUPAL_AUTHENTICATED_RID, $rids)) {
+ $query->join('users_roles', 'ur', 'u.uid = ur.uid');
+ $query->condition('rid', $rids);
+ }
+
+ foreach ($query->execute() as $user) {
$matches[$prefix . $user->name] = check_plain($user->name);
}
@@ -762,23 +771,15 @@ function masquerade_switch_user($uid) {
$new_user = user_load($uid);
- $roles = array_keys(array_filter(variable_get('masquerade_admin_roles', array())));
- $perm = $uid == 1 || array_intersect(array_keys($new_user->roles), $roles) ?
- 'masquerade as admin' :
- 'masquerade as user';
-
- // Check to see if we need admin permission.
- $results = db_query_range('SELECT 1 FROM {masquerade_users} WHERE uid_from = :uid_from AND uid_to = :uid_to', 0, 1, array(
- ':uid_from' => $user->uid,
- ':uid_to' => $new_user->uid,
- ));
- if (!user_access($perm) && !isset($_SESSION['masquerading']) && !$results->fetchField()) {
- watchdog('masquerade', 'This user requires administrative permissions to switch to the user %user.', array('%user' => $new_user->name), WATCHDOG_ERROR);
+ if ($user->uid == $uid || isset($user->masquerading)) {
+ watchdog('masquerade', 'This user is already %user.', array('%user' => $new_user->name), WATCHDOG_ERROR);
return FALSE;
}
- if ($user->uid == $uid || isset($user->masquerading)) {
- watchdog('masquerade', 'This user is already %user.', array('%user' => $new_user->name), WATCHDOG_ERROR);
+ // Ensure the account we're switching to isn't our own and that we have
+ // permission to masquerade with these roles
+ if ($user->uid !== $new_user->uid && !masquerade_check_user_roles($new_user)) {
+ watchdog('masquerade', 'The user %user has roles %user2 does not have permission to obtain.', array('%user' => $new_user->name, '%user2' => $user->name), WATCHDOG_ERROR);
return FALSE;
}
@@ -798,7 +799,6 @@ function masquerade_switch_user($uid) {
'sid' => session_id(),
));
$query->execute();
- // switch user
watchdog('masquerade', 'User %user now masquerading as %masq_as.', array('%user' => $user->name, '%masq_as' => $new_user->name ? $new_user->name : variable_get('anonymous', t('Anonymous'))), WATCHDOG_INFO);
drupal_set_message(t('You are now masquerading as !masq_as.', array('!masq_as' => theme('username', array('account' => $new_user)))));
@@ -859,3 +859,91 @@ function masquerade_switch_back() {
watchdog('masquerade', 'User %user no longer masquerading as %masq_as.', array('%user' => $user->name, '%masq_as' => $oldname), WATCHDOG_INFO);
}
+
+/**
+ * Checks if the user has access to masquerade as a specific role.
+ * @param string $role
+ * The name of the role to check. Also accepts a machine name permission.
+ * @return bool
+ * Whether or not the current user is allowed to masquerade as someone with this role.
+ */
+function masquerade_check_role_permission($role) {
+ $permission = stripos($role, 'masquerade as') ? $role : 'masquerade as ' . $role;
+ return user_access($permission);
+}
+
+/**
+ * Checks an array of roles to see if we have access to them.
+ *
+ * @param $roles
+ * An array of roles to check
+ * @return bool
+ * Return FALSE if any role exists that the current user isn't permitted to become.
+ * Return TRUE otherwise.
+ */
+function masquerade_check_roles($roles = array()) {
+ foreach ($roles as $rid => $role) {
+ if ($rid == DRUPAL_AUTHENTICATED_RID) {
+ continue;
+ }
+ if (!masquerade_check_role_permission($role)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Checks all roles of the user we're trying to become.
+ *
+ * @param mixed
+ * The user object to check roles. Also accepts uids and user names.
+ * @return bool
+ * Return FALSE if any role exists that the current user isn't permitted to become.
+ * Return TRUE otherwise.
+ */
+function masquerade_check_user_roles($user) {
+ if (is_numeric($user)) {
+ $user = user_load($user);
+ }
+ elseif (is_string($user)) {
+ $user = user_load_by_name($user);
+ }
+ elseif (!is_object($user) || !isset($user->roles)) {
+ return FALSE;
+ }
+ return masquerade_check_roles($user->roles);
+}
+
+/**
+ * Check if the current user has ANY masquerade permission.
+ *
+ * @return bool
+ * Return TRUE if user has access to masquerade at all.
+ * Return FALSE if user can't masquerade.
+ */
+function masquerade_has_any_masquerade_permission() {
+ $return = FALSE;
+ foreach(user_roles() as $rid => $role) {
+ if (masquerade_check_role_permission($role)) {
+ $return = TRUE;
+ }
+ }
+ return $return;
+}
+
+/**
+ * Get roles the current user is allowed to masquerade to.
+ *
+ * @return void
+ **/
+function masquerade_get_allowed_roles() {
+ $rids = array();
+ foreach (user_roles() as $rid => $role) {
+ if (masquerade_check_role_permission($role)) {
+ $rids[$rid] = $rid;
+ }
+ }
+
+ return $rids;
+}
\ No newline at end of file