diff --git a/core/modules/user/lib/Drupal/user/Tests/UserEditTest.php b/core/modules/user/lib/Drupal/user/Tests/UserEditTest.php index 6bf60bc..0a5fcd5 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserEditTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserEditTest.php @@ -99,4 +99,30 @@ class UserEditTest extends WebTestBase { $this->drupalPost("user/$user1->uid/edit", array('mail' => ''), t('Save')); $this->assertRaw(t("The changes have been saved.")); } + + /** + * Check that existing users whose username matches another user's email + * address or vice versa are not forced to update their username or email + * address. + */ + function testUserEditWithConflicts() { + $user_with_email = $this->drupalCreateUser(); + $user_with_name = $this->drupalCreateUser(); + + // Change the second user's username to the same value as the first user's + // email address. + $user_with_name->name = $user_with_email->mail; + $user_with_name->save(); + + // Test that the first user can save their account with no errors. + $this->drupalLogin($user_with_email); + $this->drupalPost("user/$user_with_email->uid/edit", array(), t('Save')); + $this->assertText(t("The changes have been saved."), "The user does not need to change their username if it matches another user's email address."); + $this->drupalLogout(); + + // Test that the second user can save their account with no errors. + $this->drupalLogin($user_with_name); + $this->drupalPost("user/$user_with_name->uid/edit", array(), t('Save')); + $this->assertText(t("The changes have been saved."), "The user does not need to change their email address if it matches another user's username."); + } } diff --git a/core/modules/user/lib/Drupal/user/Tests/UserPasswordResetTest.php b/core/modules/user/lib/Drupal/user/Tests/UserPasswordResetTest.php index 00c947f..85a95ef 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserPasswordResetTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserPasswordResetTest.php @@ -33,26 +33,14 @@ class UserPasswordResetTest extends WebTestBase { // Don't require admin approval for new accounts. variable_set('user_register', USER_REGISTER_VISITORS); - // Create a user to be duplicated. + // Create two users. $user_with_email = $this->drupalCreateUser(); + $user_with_name = $this->drupalCreateUser(); - // Create a new user with the email from the above as the user's name. - $edit = array(); - $edit['name'] = $user_with_email->mail; - $edit['mail'] = $this->randomName() . "@example.com"; - $edit['pass[pass1]'] = $new_pass = $this->randomName(); - $edit['pass[pass2]'] = $new_pass; - $this->drupalPost('user/register', $edit, t('Create new account')); - // For backward compatibility, registration with a username that conflicts - // with an email address of another account should be allowed. - $this->assertText(t('Registration successful. You are now logged in.'), t('Users are logged in after registering.')); - // The above logs in the user. Log out to test password reset. - $this->drupalLogout(); - - // Get the duplicate user. - $users = user_load_multiple(array(), array('name' => $edit['name'], 'status' => '1')); - $user_with_name = reset($users); - + // Change the second user's username to the same value as the first user's + // email address. + $user_with_name->name = $user_with_email->mail; + $user_with_name->save(); // Try and reset based on the duplicated email. $edit = array(); @@ -76,7 +64,6 @@ class UserPasswordResetTest extends WebTestBase { // If the user is logged in, they should not have to choose an account to // reset their password. - $user_with_name->pass_raw = $new_pass; $this->drupalLogin($user_with_name); $this->drupalGet('user/password'); // There should not be a form element for name. diff --git a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php index 56ad9a0..b51d941 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php @@ -137,6 +137,43 @@ class UserRegistrationTest extends WebTestBase { $this->assertText(t('The e-mail address @email is already registered.', array('@email' => $duplicate_user->mail)), t('Supplying a duplicate email address with added whitespace displays an error message')); } + /** + * Ensure that a new account cannot be created when the username matches an + * existing user's email address, or when the email address matches an + * existing user's username. + */ + function testRegistrationConflicts() { + // Don't require e-mail verification. + variable_set('user_email_verification', FALSE); + + // Allow registration by site visitors without administrator approval. + variable_set('user_register', USER_REGISTER_VISITORS); + + // Set up a user to check for duplicates. + $duplicate_user = $this->drupalCreateUser(); + + $edit = array(); + $edit['name'] = $duplicate_user->mail; + $edit['mail'] = $this->randomName() . '@example.com'; + + // Attempt to create a new account using a username that matches an + // existing email. + $this->drupalPost('user/register', $edit, t('Create new account')); + $this->assertText(t('The name @name is already taken.', array('@name' => $edit['name'])), "A user cannot be created when their username matches an existing user's email address."); + + // Change the username to an email address. + $duplicate_user->name = $name = $this->randomName() . '@example.com'; + $duplicate_user->save(); + + $edit['name'] = $this->randomName(); + $edit['mail'] = $name; + + // Attempt to create a new account using an email that matches an existing + // username. + $this->drupalPost('user/register', $edit, t('Create new account')); + $this->assertText(t('The e-mail address @email is already registered.', array('@email' => $edit['mail'])), "A user cannot be created when their email address matches an existing username."); + } + function testRegistrationDefaultValues() { // Allow registration by site visitors without administrator approval. variable_set('user_register', USER_REGISTER_VISITORS); diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 519500e..e34f1a2 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -966,6 +966,9 @@ function user_validate_current_pass(&$form, &$form_state) { */ function user_account_form_validate($form, &$form_state) { $account = $form['#user']; + $name_taken = FALSE; + $mail_taken = FALSE; + // Validate new or changing username. if (isset($form_state['values']['name'])) { if ($error = user_validate_name($form_state['values']['name'])) { @@ -982,7 +985,18 @@ function user_account_form_validate($form, &$form_state) { ->execute() ->fetchField(); - if ($name_taken) { + // For new registrations, make sure the username does not conflict with an + // existing user's email address. + if (empty($account->uid)) { + $mail_taken = (bool) db_select('users') + ->fields('users', array('uid')) + ->condition('mail', db_like($form_state['values']['name']), 'LIKE') + ->range(0, 1) + ->execute() + ->fetchField(); + } + + if ($name_taken || $mail_taken) { form_set_error('name', t('The name %name is already taken.', array('%name' => $form_state['values']['name']))); } } @@ -999,7 +1013,18 @@ function user_account_form_validate($form, &$form_state) { ->execute() ->fetchField(); - if ($mail_taken) { + // For new registrations, make sure the email address does not conflict with + // an existing user's username. + if (empty($account->uid)) { + $name_taken = (bool) db_select('users') + ->fields('users', array('uid')) + ->condition('name', db_like($mail), 'LIKE') + ->range(0, 1) + ->execute() + ->fetchField(); + } + + if ($mail_taken || $name_taken) { // Format error message dependent on whether the user is logged in or not. if ($GLOBALS['user']->uid) { form_set_error('mail', t('The e-mail address %email is already taken.', array('%email' => $mail)));