Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.946 diff -u -p -r1.946 user.module --- modules/user/user.module 16 Dec 2008 23:57:33 -0000 1.946 +++ modules/user/user.module 17 Dec 2008 01:15:28 -0000 @@ -1597,10 +1597,17 @@ function _user_edit_submit($uid, &$edit) /** * Delete a user. * + * @note User #1 cannot be deleted * @param $edit An array of submitted form values. * @param $uid The user ID of the user to delete. */ function user_delete($edit, $uid) { + // Don't allow deletion of user #1 + if ($uid == 1) { + drupal_set_message(t('Failed to delete user 1: This user is the superuser or root administrator, and cannot be deleted.'), 'error'); + return; + } + $account = user_load(array('uid' => $uid)); drupal_session_destroy_uid($uid); _user_mail_notify('status_deleted', $account); Index: modules/user/user.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.pages.inc,v retrieving revision 1.24 diff -u -p -r1.24 user.pages.inc --- modules/user/user.pages.inc 24 Nov 2008 00:40:45 -0000 1.24 +++ modules/user/user.pages.inc 17 Dec 2008 01:15:28 -0000 @@ -238,7 +238,8 @@ 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 (user_access('administer users')) { + // User 1 cannot be deleted so we don't display the delete button. + if (user_access('administer users') && $account->uid != 1) { $form['delete'] = array( '#type' => 'submit', '#value' => t('Delete'), Index: modules/user/user.test =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.test,v retrieving revision 1.23 diff -u -p -r1.23 user.test --- modules/user/user.test 16 Dec 2008 23:57:33 -0000 1.23 +++ modules/user/user.test 17 Dec 2008 01:15:29 -0000 @@ -193,6 +193,104 @@ class UserDeleteTestCase extends DrupalW } } +class UserRootAdminNoDeleteTestCase extends DrupalWebTestCase { + function getInfo() { + return array( + 'name' => t('Deny user #1 deletion'), + 'description' => t('Tries to delete user #1, only to be disallowed'), + 'group' => t('User') + ); + } + + /** + * Don't allow the root administrator to delete itself. + */ + function testDeleteRootAdminSelf() { + // login as the root administrator + $this->drupalLogin($this->rootAdminLoad()); + + // Check the edit user page for the delete button. + $this->drupalGet('user/1/edit'); + $this->assertNoRaw('value="' . t('Delete') . '"', t('No delete button on user/1/edit for root administrator')); + + // Check error while trying to delete the root administrator + $this->drupalPost('user/1/delete', NULL, t('Delete')); + $this->assertText(t('Failed to delete user 1: This user is the superuser or root administrator, and cannot be deleted.'), t("Deny deletion of user #1 by root administrator")); + + // Sort the list, so that the root administrator is in the list + $edit = array('sort' => 'desc', 'order' => 'Member+for'); + $this->drupalGet('admin/user/user', $edit); + + // Select the root administrator for deletion + $edit = array('operation' => 'delete', 'accounts[1]' => '1'); + $this->drupalPost(NULL, $edit, t('Update')); + + // Confirm the selection. + $this->drupalPost(NULL, NULL, t('Delete all')); + $this->assertText(t('Failed to delete user 1: This user is the superuser or root administrator, and cannot be deleted.'), t("Deny deletion of the root administrator by itself trough the mass deletion form")); + } + + /** + * Don't allow deletion of the root administrator by another administrator + */ + function testDeleteRootAdminOther() { + // login as another administrator. + $this->drupalLogin($this->drupalCreateUser(array('administer users'))); + + // Check the edit user page for the delete button. + $this->drupalGet('user/1/edit'); + $this->assertNoRaw('value="' . t('Delete') . '"', t('No delete button on /user/1/edit')); + + // Check error while trying to delete the root administrator + $this->drupalPost('user/1/delete', NULL, t('Delete')); + $this->assertText(t('Failed to delete user 1: This user is the superuser or root administrator, and cannot be deleted.'), t("Deny deletion of user #1")); + + // Sort the list, so that the root administrator is in the list + $edit = array('sort' => 'desc', 'order' => 'Member+for'); + $this->drupalGet('admin/user/user', $edit); + + // Select the root administrator for deletion + $edit = array('operation' => 'delete', 'accounts[1]' => '1'); + $this->drupalPost(NULL, $edit, t('Update')); + + // Confirm the selection. + $this->drupalPost(NULL, NULL, t('Delete all')); + $this->assertText(t('Failed to delete user 1: This user is the superuser or root administrator, and cannot be deleted.'), t("Deny deletion of the root administrator trough the mass deletion form")); + } + + /** + * Small unit-test to check the user_delete() function. + */ + function testDeleteRootAdminPHP() { + user_delete(NULL, 1); + $this->assertTrue(user_load(1), t("Deny deletion of the root administrator trough user_delete()")); + } + + /** + * Pepare the root administrator for login + */ + function rootAdminLoad() { + // generate a username and password for the root administrator + $password = user_password(); + $username = $this->randomName(); + + // add the username and the hashed password to the database. + require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc'); + db_update('users') + ->fields(array('name' => $username, 'pass' => user_hash_password($password))) + ->condition('uid', 1) + ->execute(); + + // load the complete user from the database. + $root_admin = user_load(1); + + // Add the raw password so that we can log in as this user. + $root_admin->pass_raw = $password; + + return $root_admin; + } +} + class UserPictureTestCase extends DrupalWebTestCase { protected $user; protected $_directory_test;