Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.1089
diff -u -p -r1.1089 user.module
--- modules/user/user.module 7 Dec 2009 03:45:16 -0000 1.1089
+++ modules/user/user.module 10 Dec 2009 22:54:27 -0000
@@ -2703,10 +2703,29 @@ function user_multiple_cancel_confirm($f
$edit = $form_state['input'];
$form['accounts'] = array('#prefix' => '
', '#tree' => TRUE);
- // array_filter() returns only elements with TRUE values.
- foreach (array_filter($edit['accounts']) as $uid => $value) {
- $user = db_query('SELECT name FROM {users} WHERE uid = :uid', array(':uid' => $uid))->fetchField();
- $form['accounts'][$uid] = array('#type' => 'hidden', '#value' => $uid, '#prefix' => '', '#suffix' => check_plain($user) . "\n");
+ $accounts = user_load_multiple(array_keys(array_filter($edit['accounts'])));
+ foreach ($accounts as $uid => $account) {
+ // Prevent user 1 from being canceled.
+ if ($uid <= 1) {
+ continue;
+ }
+ $form['accounts'][$uid] = array(
+ '#type' => 'hidden',
+ '#value' => $uid,
+ '#prefix' => '',
+ '#suffix' => check_plain($account->name) . "\n",
+ );
+ }
+
+ // Output a notice that user 1 cannot be canceled.
+ if (isset($accounts[1])) {
+ $redirect = (count($accounts) == 1);
+ $message = t('The user account %name cannot be cancelled.', array('%name' => $accounts[1]->name));
+ drupal_set_message($message, $redirect ? 'error' : 'warning');
+ // If only user 1 was selected, redirect to the overview.
+ if ($redirect) {
+ drupal_goto('admin/people');
+ }
}
$form['operation'] = array('#type' => 'hidden', '#value' => 'cancel');
@@ -2755,6 +2774,10 @@ function user_multiple_cancel_confirm_su
if ($form_state['values']['confirm']) {
foreach ($form_state['values']['accounts'] as $uid => $value) {
+ // Prevent programmatic form submissions from cancelling user 1.
+ if ($uid <= 1) {
+ continue;
+ }
// Prevent user administrators from deleting themselves without confirmation.
if ($uid == $user->uid) {
$admin_form_state = $form_state;
@@ -2768,7 +2791,6 @@ function user_multiple_cancel_confirm_su
}
}
$form_state['redirect'] = 'admin/people';
- return;
}
/**
Index: modules/user/user.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.pages.inc,v
retrieving revision 1.62
diff -u -p -r1.62 user.pages.inc
--- modules/user/user.pages.inc 1 Dec 2009 16:03:35 -0000 1.62
+++ modules/user/user.pages.inc 10 Dec 2009 22:33:12 -0000
@@ -244,7 +244,7 @@ function user_profile_form($form, &$form
'#value' => t('Cancel account'),
'#weight' => 31,
'#submit' => array('user_edit_cancel_submit'),
- '#access' => ($account->uid == $user->uid && user_access('cancel account')) || user_access('administer users'),
+ '#access' => $account->uid > 1 && (($account->uid == $user->uid && user_access('cancel account')) || user_access('administer users')),
);
}
Index: modules/user/user.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.test,v
retrieving revision 1.71
diff -u -p -r1.71 user.test
--- modules/user/user.test 10 Dec 2009 15:39:43 -0000 1.71
+++ modules/user/user.test 10 Dec 2009 22:33:12 -0000
@@ -343,6 +343,44 @@ class UserCancelTestCase extends DrupalW
}
/**
+ * Tests that user account for uid 1 cannot be cancelled.
+ *
+ * This should never be possible, or the site owner would become unable to
+ * administer the site.
+ */
+ function testUserCancelUid1() {
+ // Update uid 1's name and password to we know it.
+ $password = user_password();
+ require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
+ $account = array(
+ 'name' => 'user1',
+ 'pass' => user_hash_password(trim($password)),
+ );
+ // We cannot use user_save() here or the password would be hashed again.
+ db_update('users')
+ ->fields($account)
+ ->condition('uid', 1)
+ ->execute();
+
+ // Reload and log in uid 1.
+ $user1 = user_load(1, TRUE);
+ $user1->pass_raw = $password;
+
+ // Try to cancel uid 1's account with a different user.
+ $this->admin_user = $this->drupalCreateUser(array('administer users'));
+ $this->drupalLogin($this->admin_user);
+ $edit = array(
+ 'operation' => 'cancel',
+ 'accounts[1]' => TRUE,
+ );
+ $this->drupalPost('admin/people', $edit, t('Update'));
+
+ // Verify that uid 1's account was not cancelled.
+ $user1 = user_load(1, TRUE);
+ $this->assertEqual($user1->status, 1, t('User #1 still exists and is not blocked.'));
+ }
+
+ /**
* Attempt invalid account cancellations.
*/
function testUserCancelInvalid() {
@@ -619,6 +657,8 @@ class UserCancelTestCase extends DrupalW
$edit['accounts[' . $uid . ']'] = TRUE;
}
$edit['accounts[' . $admin_user->uid . ']'] = TRUE;
+ // Also try to cancel uid 1.
+ $edit['accounts[1]'] = TRUE;
$this->drupalPost('admin/people', $edit, t('Update'));
$this->assertText(t('Are you sure you want to cancel these user accounts?'), t('Confirmation form to cancel accounts displayed.'));
$this->assertText(t('When cancelling these accounts'), t('Allows to select account cancellation method.'));
@@ -638,6 +678,10 @@ class UserCancelTestCase extends DrupalW
$this->assertText(t('A confirmation request to cancel your account has been sent to your e-mail address.'), t('Account cancellation request mailed message displayed.'));
$admin_user = user_load($admin_user->uid);
$this->assertTrue($admin_user->status == 1, t('Administrative user is found in the database and enabled.'));
+
+ // Verify that uid 1's account was not cancelled.
+ $user1 = user_load(1, TRUE);
+ $this->assertEqual($user1->status, 1, t('User #1 still exists and is not blocked.'));
}
}