? .DS_Store ? 46149_prevent_cancel_uid1_0.patch ? 46149_prevent_cancel_uid1_1.patch ? drushrc.php ? sites/all/modules ? sites/all/themes ? sites/default/files ? sites/default/settings.php Index: modules/user/user.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.admin.inc,v retrieving revision 1.41 diff -u -p -r1.41 user.admin.inc --- modules/user/user.admin.inc 13 Apr 2009 12:14:57 -0000 1.41 +++ modules/user/user.admin.inc 17 Apr 2009 00:16:50 -0000 @@ -193,9 +193,13 @@ function user_admin_account() { $form['last_access'][$account->uid] = array('#markup' => $account->access ? t('@time ago', array('@time' => format_interval(REQUEST_TIME - $account->access))) : t('never')); $form['operations'][$account->uid] = array('#markup' => l(t('edit'), "user/$account->uid/edit", array('query' => $destination))); } + // Remove uid1 from the $accounts array so it can't be accidentally deleted. + if (array_key_exists(1, $accounts)) { + array_pop($accounts); + } $form['accounts'] = array( '#type' => 'checkboxes', - '#options' => $accounts + '#options' => $accounts, ); $form['pager'] = array('#markup' => theme('pager', NULL, 50, 0)); Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.974 diff -u -p -r1.974 user.module --- modules/user/user.module 13 Apr 2009 12:14:57 -0000 1.974 +++ modules/user/user.module 17 Apr 2009 00:16:50 -0000 @@ -2341,6 +2341,10 @@ function user_multiple_cancel_confirm_su if ($form_state['values']['confirm']) { foreach ($form_state['values']['accounts'] as $uid => $value) { + // Prevent uid 1 from being deleted. + if ($uid <= 1) { + continue; + } // Prevent user administrators from deleting themselves without confirmation. if ($uid == $user->uid) { $admin_form_state = $form_state; Index: modules/user/user.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.pages.inc,v retrieving revision 1.33 diff -u -p -r1.33 user.pages.inc --- modules/user/user.pages.inc 13 Apr 2009 12:14:57 -0000 1.33 +++ modules/user/user.pages.inc 17 Apr 2009 00:16:50 -0000 @@ -249,7 +249,7 @@ function user_profile_form($form_state, $form['_category'] = array('#type' => 'value', '#value' => $category); $form['_account'] = array('#type' => 'value', '#value' => $account); $form['submit'] = array('#type' => 'submit', '#value' => t('Save'), '#weight' => 30); - if (($account->uid == $user->uid && user_access('cancel account')) || user_access('administer users')) { + if ((($account->uid == $user->uid && user_access('cancel account')) || user_access('administer users')) && $account->uid > 1) { $form['cancel'] = array( '#type' => 'submit', '#value' => t('Cancel account'), Index: modules/user/user.test =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.test,v retrieving revision 1.33 diff -u -p -r1.33 user.test --- modules/user/user.test 31 Mar 2009 01:49:55 -0000 1.33 +++ modules/user/user.test 17 Apr 2009 00:16:50 -0000 @@ -155,7 +155,7 @@ class UserValidationTestCase extends Dru class UserCancelTestCase extends DrupalWebTestCase { public static function getInfo() { return array( - 'name' => t('Cancel account'), + 'name' => t('Cancel an account'), 'description' => t('Ensure that account cancellation methods work as expected.'), 'group' => t('User'), ); @@ -178,12 +178,12 @@ class UserCancelTestCase extends DrupalW // Attempt to cancel account. $this->drupalGet('user/' . $account->uid . '/edit'); - $this->assertNoRaw(t('Cancel account'), t('No cancel account button displayed.')); + $this->assertNoRaw(t('Cancel account'), t('Cancel account button is hidden if user does not have sufficient permission.')); // Attempt bogus account cancellation request confirmation. $timestamp = $account->login; $this->drupalGet("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login)); - $this->assertResponse(403, t('Bogus cancelling request rejected.')); + $this->assertResponse(403, t('Bogus account cancellation request was rejected.')); $account = user_load($account->uid); $this->assertTrue($account->status == 1, t('User account was not canceled.')); @@ -234,6 +234,24 @@ class UserCancelTestCase extends DrupalW } /** + * Test for protection of user account #1 while logged as uid1. + * This should never be possible, for obvious reasons. + */ + function testUserCancelUser1() { + variable_set('user_cancel_method', 'user_cancel_uid1_prevent'); + // Fetch the uid1 account and and log them in. + $user1 = $this->drupalCreateUser(); + $this->drupalLogin($user1); + $user1 = user_load(1, TRUE); + // Make sure the Cancel Account button does not show up on user/1/edit form. + $this->drupalGet('user/' . $user1->uid . '/edit'); + $this->assertNoRaw(t('Cancel account'), t('Cancel account button is always hidden for user #1.')); + // Make sure the Edit checkbox does not show up on the admin/user page. + $this->drupalGet('admin/user/user'); + $this->assertNoFieldByID('edit-accounts-1', 'unchecked', t('The Update checkbox for uid1 on the admin/user page does not appear.')); + } + + /** * Disable account and keep all content. */ function testUserBlock() { @@ -443,7 +461,7 @@ class UserCancelTestCase extends DrupalW } /** - * Create an administrative user and mass-delete other users. + * Create an administrative user and try to bulk-delete other users. */ function testMassUserCancelByAdmin() { variable_set('user_cancel_method', 'user_cancel_reassign'); @@ -454,25 +472,24 @@ class UserCancelTestCase extends DrupalW $admin_user = $this->drupalCreateUser(array('administer users')); $this->drupalLogin($admin_user); - // Create some users. + // Create three regular users. $users = array(); for ($i = 0; $i < 3; $i++) { $account = $this->drupalCreateUser(array()); $users[$account->uid] = $account; } - - // Cancel user accounts, including own one. + // Attempt to cancel newly created user accounts. $edit = array(); $edit['operation'] = 'cancel'; foreach ($users as $uid => $account) { - $edit['accounts[' . $uid . ']'] = TRUE; + if ($uid > 1) { + $edit['accounts[' . $uid . ']'] = TRUE; + } } - $edit['accounts[' . $admin_user->uid . ']'] = TRUE; $this->drupalPost('admin/user/user', $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.')); $this->assertText(t('Require e-mail confirmation to cancel account.'), t('Allows to send confirmation mail.')); - $this->assertText(t('Notify user when account is canceled.'), t('Allows to send notification mail.')); // Confirm deletion. $this->drupalPost(NULL, NULL, t('Cancel accounts')); @@ -482,11 +499,13 @@ class UserCancelTestCase extends DrupalW $status = $status && !user_load($account->uid, TRUE); } $this->assertTrue($status, t('Users deleted and not found in the database.')); + // $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.')); - // Ensure that admin account was not cancelled. - $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.')); + // Ensure that neither the administrative account nor uid1 was cancelled. $admin_user = user_load($admin_user->uid); - $this->assertTrue($admin_user->status == 1, t('Administrative user is found in the database and enabled.')); + $this->assertTrue($admin_user->status == 1, t('The administrative user still exists and is enabled.')); + $uid1 = user_load(1); + $this->assertTrue($uid1->status == 1, t('User #1 still exists and is enabled.')); } } @@ -763,8 +782,8 @@ class UserPermissionsTestCase extends Dr class UserAdminTestCase extends DrupalWebTestCase { public static function getInfo() { return array( - 'name' => t('User admininstration'), - 'description' => t('Test user admininstration page functionality.'), + 'name' => t('User administration'), + 'description' => t('Test user administration page functionality.'), 'group' => t('User') ); }