KEYCLOAK-1534 handle account management update email or username to the already existing value
This commit is contained in:
parent
bddf1adeba
commit
94c0a436b5
3 changed files with 75 additions and 2 deletions
|
@ -109,6 +109,9 @@ invalidPasswordExistingMessage=Invalid existing password.
|
|||
invalidPasswordConfirmMessage=Password confirmation doesn''t match.
|
||||
invalidTotpMessage=Invalid authenticator code.
|
||||
|
||||
usernameExistsMessage=Username already exists.
|
||||
emailExistsMessage=Email already exists.
|
||||
|
||||
readOnlyUserMessage=You can''t update your account as it is read only.
|
||||
readOnlyPasswordMessage=You can''t update your password as your account is read only.
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.keycloak.models.Constants;
|
|||
import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.ModelReadOnlyException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
@ -433,7 +434,14 @@ public class AccountService {
|
|||
|
||||
try {
|
||||
if (realm.isEditUsernameAllowed()) {
|
||||
user.setUsername(formData.getFirst("username"));
|
||||
String username = formData.getFirst("username");
|
||||
|
||||
UserModel existing = session.users().getUserByUsername(username, realm);
|
||||
if (existing != null && !existing.equals(user)) {
|
||||
throw new ModelDuplicateException(Messages.USERNAME_EXISTS);
|
||||
}
|
||||
|
||||
user.setUsername(username);
|
||||
}
|
||||
user.setFirstName(formData.getFirst("firstName"));
|
||||
user.setLastName(formData.getFirst("lastName"));
|
||||
|
@ -441,8 +449,14 @@ public class AccountService {
|
|||
String email = formData.getFirst("email");
|
||||
String oldEmail = user.getEmail();
|
||||
boolean emailChanged = oldEmail != null ? !oldEmail.equals(email) : email != null;
|
||||
if (emailChanged) {
|
||||
UserModel existing = session.users().getUserByEmail(email, realm);
|
||||
if (existing != null && !existing.equals(user)) {
|
||||
throw new ModelDuplicateException(Messages.EMAIL_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
user.setEmail(formData.getFirst("email"));
|
||||
user.setEmail(email);
|
||||
|
||||
AttributeFormDataProcessor.process(formData, realm, user);
|
||||
|
||||
|
@ -457,6 +471,9 @@ public class AccountService {
|
|||
} catch (ModelReadOnlyException roe) {
|
||||
setReferrerOnPage();
|
||||
return account.setError(Messages.READ_ONLY_USER).setProfileFormData(formData).createResponse(AccountPages.ACCOUNT);
|
||||
} catch (ModelDuplicateException mde) {
|
||||
setReferrerOnPage();
|
||||
return account.setError(mde.getMessage()).setProfileFormData(formData).createResponse(AccountPages.ACCOUNT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ public class AccountTest {
|
|||
|
||||
UserModel user2 = manager.getSession().users().addUser(appRealm, "test-user-no-access@localhost");
|
||||
user2.setEnabled(true);
|
||||
user2.setEmail("test-user-no-access@localhost");
|
||||
for (String r : accountApp.getDefaultRoles()) {
|
||||
user2.deleteRoleMapping(accountApp.getRole(r));
|
||||
}
|
||||
|
@ -395,6 +396,10 @@ public class AccountTest {
|
|||
|
||||
events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
|
||||
events.expectAccount(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, "test-user@localhost").detail(Details.UPDATED_EMAIL, "new@email.com").assertEvent();
|
||||
|
||||
// reset user for other tests
|
||||
profilePage.updateProfile("Tom", "Brady", "test-user@localhost");
|
||||
events.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -429,6 +434,17 @@ public class AccountTest {
|
|||
|
||||
events.assertEmpty();
|
||||
|
||||
// Change to the username already occupied by other user
|
||||
profilePage.updateProfile("test-user-no-access@localhost", "New first", "New last", "new@email.com");
|
||||
|
||||
Assert.assertEquals("Username already exists.", profilePage.getError());
|
||||
Assert.assertEquals("test-user-no-access@localhost", profilePage.getUsername());
|
||||
Assert.assertEquals("New first", profilePage.getFirstName());
|
||||
Assert.assertEquals("New last", profilePage.getLastName());
|
||||
Assert.assertEquals("new@email.com", profilePage.getEmail());
|
||||
|
||||
events.assertEmpty();
|
||||
|
||||
profilePage.updateProfile("test-user-new@localhost", "New first", "New last", "new@email.com");
|
||||
|
||||
Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
|
||||
|
@ -452,6 +468,43 @@ public class AccountTest {
|
|||
}
|
||||
}
|
||||
|
||||
// KEYCLOAK-1534
|
||||
@Test
|
||||
public void changeEmailToExisting() {
|
||||
profilePage.open();
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
|
||||
events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
|
||||
|
||||
Assert.assertEquals("test-user@localhost", profilePage.getUsername());
|
||||
Assert.assertEquals("test-user@localhost", profilePage.getEmail());
|
||||
|
||||
// Change to the email, which some other user has
|
||||
profilePage.updateProfile("New first", "New last", "test-user-no-access@localhost");
|
||||
|
||||
profilePage.assertCurrent();
|
||||
Assert.assertEquals("Email already exists.", profilePage.getError());
|
||||
Assert.assertEquals("New first", profilePage.getFirstName());
|
||||
Assert.assertEquals("New last", profilePage.getLastName());
|
||||
Assert.assertEquals("test-user-no-access@localhost", profilePage.getEmail());
|
||||
|
||||
events.assertEmpty();
|
||||
|
||||
// Change some other things, but not email
|
||||
profilePage.updateProfile("New first", "New last", "test-user@localhost");
|
||||
|
||||
Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
|
||||
Assert.assertEquals("New first", profilePage.getFirstName());
|
||||
Assert.assertEquals("New last", profilePage.getLastName());
|
||||
Assert.assertEquals("test-user@localhost", profilePage.getEmail());
|
||||
|
||||
events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
|
||||
|
||||
// Change email and other things to original values
|
||||
profilePage.updateProfile("Tom", "Brady", "test-user@localhost");
|
||||
events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setupTotp() {
|
||||
totpPage.open();
|
||||
|
|
Loading…
Reference in a new issue