diff --git a/masquerade.module b/masquerade.module
--- a/masquerade.module Wed May 04 08:58:40 2011
+++ b/masquerade.module Sun Jun 26 23:39:35 2011
@@ -23,15 +23,22 @@
* @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;
+ $key = drupal_strtolower($title);
+ $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_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 @@
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,7 +238,6 @@
case 'switch':
$switch_to_account = FALSE;
global $user;
- if ($uid) {
if (!is_numeric($uid)) {
return FALSE;
}
@@ -241,8 +246,11 @@
':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;
}
- 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;
}
}
@@ -251,26 +259,6 @@
* 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) {
@@ -296,15 +284,6 @@
}
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.
@@ -373,15 +352,15 @@
* 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,
@@ -439,6 +418,9 @@
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.'));
+ }
}
}
}
@@ -527,8 +509,10 @@
$block = array();
switch ($delta) {
case 'masquerade':
+ if (isset($_SESSION['masquerading']) || masquerade_has_any_masquerade_permission()) {
$block['subject'] = t('Masquerade');
$block['content'] = drupal_get_form('masquerade_block_1');
+ }
break;
}
return $block;
@@ -560,6 +544,10 @@
foreach ($masquerade_switches as $switch_user) {
if (!isset($_SESSION['user']->uid) || $switch_user != $_SESSION['user']->uid) {
$user_name = user_load($switch_user);
+ // Make sure the users in the quick switch list only have roles we're allowed to become.
+ if (!masquerade_check_user_roles($user_name)) {
+ continue;
+ }
$switch_link = 'masquerade/switch/' . $user_name->uid;
if ($user_name->uid) {
$quick_switch_links[] = l($user_name->name, $switch_link, array('query' => array('token' => drupal_get_token($switch_link))));
@@ -625,6 +613,9 @@
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.'));
}
@@ -757,23 +748,14 @@
$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('SELECT TRUE FROM {masquerade_users} WHERE uid_from = :uid_from AND uid_to = :uid_to', 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;
}
@@ -789,7 +771,6 @@
'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)))));
@@ -836,4 +817,71 @@
$oldname = ($user->uid == 0 ? variable_get('anonymous', t('Anonymous')) : $user->name);
$user = user_load($uid);
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.
+ * @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.
+ * @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 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;
}