From 96405d5fbeddecffbf6723a99bd7cf3fae43739e Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Mon, 7 Dec 2015 09:44:16 +0100 Subject: [PATCH] SONAR-7036 Allow update password of technical user When using an external authentication (like LDAP), it's now possible to update the password of technical accounts --- .../org/sonar/server/user/UserUpdater.java | 10 +- .../sonar/server/user/UserUpdaterTest.java | 130 ++++++++++-------- .../UserUpdaterTest/update_technical_user.xml | 7 + 3 files changed, 86 insertions(+), 61 deletions(-) create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/update_technical_user.xml diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/UserUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/user/UserUpdater.java index 39dc813d935..5b9f0d2c98a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/UserUpdater.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/UserUpdater.java @@ -51,6 +51,8 @@ import org.sonar.server.user.index.UserIndexer; import org.sonar.server.util.Validation; import static com.google.common.collect.Lists.newArrayList; +import static java.util.Arrays.asList; +import static org.sonar.api.CoreProperties.CORE_AUTHENTICATOR_LOCAL_USERS; @ServerSide public class UserUpdater { @@ -72,6 +74,7 @@ public class UserUpdater { private final UserIndexer userIndexer; private final System2 system2; private final SecurityRealmFactory realmFactory; + private final List technicalUsers; public UserUpdater(NewUserNotifier newUserNotifier, Settings settings, DbClient dbClient, UserIndexer userIndexer, System2 system2, SecurityRealmFactory realmFactory) { this.newUserNotifier = newUserNotifier; @@ -80,6 +83,7 @@ public class UserUpdater { this.userIndexer = userIndexer; this.system2 = system2; this.realmFactory = realmFactory; + this.technicalUsers = asList(settings.getStringArray(CORE_AUTHENTICATOR_LOCAL_USERS)); } /** @@ -214,7 +218,7 @@ public class UserUpdater { String password = updateUser.password(); String passwordConfirmation = updateUser.passwordConfirmation(); if (updateUser.isPasswordChanged()) { - checkPasswordChangeAllowed(messages); + checkPasswordChangeAllowed(updateUser.login(), messages); validatePasswords(password, passwordConfirmation, messages); setEncryptedPassWord(password, userDto); } @@ -266,8 +270,8 @@ public class UserUpdater { } } - private void checkPasswordChangeAllowed(List messages) { - if (realmFactory.hasExternalAuthentication()) { + private void checkPasswordChangeAllowed(String login, List messages) { + if (realmFactory.hasExternalAuthentication() && !technicalUsers.contains(login)) { messages.add(Message.of("user.password_cant_be_changed_on_external_auth")); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterTest.java index 70fc04756c9..1bc82b39ea5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/UserUpdaterTest.java @@ -29,7 +29,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.mockito.ArgumentCaptor; -import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.platform.NewUserHandler; import org.sonar.api.utils.System2; @@ -60,16 +59,18 @@ import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.sonar.api.CoreProperties.CORE_AUTHENTICATOR_LOCAL_USERS; +import static org.sonar.api.CoreProperties.CORE_DEFAULT_GROUP; @Category(DbTests.class) public class UserUpdaterTest { - @Rule - public DbTester db = DbTester.create(System2.INSTANCE); - + static final String DEFAULT_LOGIN = "marius"; + static final String TECHNICAL_USER = "tech_user"; @ClassRule public static EsTester es = new EsTester().addDefinitions(new UserIndexDefinition(new Settings())); - + @Rule + public DbTester db = DbTester.create(System2.INSTANCE); System2 system2 = mock(System2.class); NewUserNotifier newUserNotifier = mock(NewUserNotifier.class); @@ -87,11 +88,11 @@ public class UserUpdaterTest { UserUpdater userUpdater; - @Before public void setUp() { es.truncateIndices(); settings = new Settings(); + settings.setProperty(CORE_AUTHENTICATOR_LOCAL_USERS, TECHNICAL_USER); session = db.getSession(); userDao = new UserDao(db.myBatis(), system2); groupDao = new GroupDao(system2); @@ -270,7 +271,7 @@ public class UserUpdaterTest { public void fail_to_create_user_with_missing_name() { try { userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName(null) .setEmail("marius@mail.com") .setPassword("password") @@ -285,7 +286,7 @@ public class UserUpdaterTest { public void fail_to_create_user_with_too_long_name() { try { userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName(Strings.repeat("m", 201)) .setEmail("marius@mail.com") .setPassword("password") @@ -300,7 +301,7 @@ public class UserUpdaterTest { public void fail_to_create_user_with_too_long_email() { try { userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName("Marius") .setEmail(Strings.repeat("m", 101)) .setPassword("password") @@ -315,7 +316,7 @@ public class UserUpdaterTest { public void fail_to_create_user_with_missing_password() { try { userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName("Marius") .setEmail("marius@mail.com") .setPassword(null) @@ -330,7 +331,7 @@ public class UserUpdaterTest { public void fail_to_create_user_with_missing_password_confirmation() { try { userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName("Marius") .setEmail("marius@mail.com") .setPassword("password") @@ -345,7 +346,7 @@ public class UserUpdaterTest { public void fail_to_create_user_with_password_not_matching_password_confirmation() { try { userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName("Marius") .setEmail("marius@mail.com") .setPassword("password") @@ -377,7 +378,7 @@ public class UserUpdaterTest { try { userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName("Marius") .setEmail("marius@mail.com") .setPassword("password") @@ -395,7 +396,7 @@ public class UserUpdaterTest { try { userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName("Marius") .setEmail("marius@mail.com") .setPassword("password") @@ -411,12 +412,12 @@ public class UserUpdaterTest { public void fail_to_create_user_when_scm_account_is_user_login() { try { userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName("Marius2") .setEmail("marius2@mail.com") .setPassword("password2") .setPasswordConfirmation("password2") - .setScmAccounts(newArrayList("marius"))); + .setScmAccounts(newArrayList(DEFAULT_LOGIN))); fail(); } catch (BadRequestException e) { assertThat(e.errors().messages()).containsOnly(Message.of("user.login_or_email_used_as_scm_account")); @@ -427,7 +428,7 @@ public class UserUpdaterTest { public void fail_to_create_user_when_scm_account_is_user_email() { try { userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName("Marius2") .setEmail("marius2@mail.com") .setPassword("password2") @@ -477,7 +478,7 @@ public class UserUpdaterTest { @Test public void fail_to_associate_default_group_to_user_if_no_default_group() { - settings.setProperty(CoreProperties.CORE_DEFAULT_GROUP, (String) null); + settings.setProperty(CORE_DEFAULT_GROUP, (String) null); try { userUpdater.create(NewUser.create() @@ -494,7 +495,7 @@ public class UserUpdaterTest { @Test public void fail_to_associate_default_group_when_default_group_does_not_exist() { - settings.setProperty(CoreProperties.CORE_DEFAULT_GROUP, "polop"); + settings.setProperty(CORE_DEFAULT_GROUP, "polop"); try { userUpdater.create(NewUser.create() @@ -517,14 +518,14 @@ public class UserUpdaterTest { createDefaultGroup(); boolean result = userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName("Marius2") .setEmail("marius2@mail.com") .setPassword("password2") .setPasswordConfirmation("password2")); session.commit(); - UserDto dto = userDao.selectByLogin(session, "marius"); + UserDto dto = userDao.selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.isActive()).isTrue(); assertThat(dto.getName()).isEqualTo("Marius2"); assertThat(dto.getEmail()).isEqualTo("marius2@mail.com"); @@ -545,7 +546,7 @@ public class UserUpdaterTest { try { userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName("Marius2") .setEmail("marius2@mail.com") .setPassword("password2") @@ -562,14 +563,14 @@ public class UserUpdaterTest { createDefaultGroup(); userUpdater.create(NewUser.create() - .setLogin("marius") + .setLogin(DEFAULT_LOGIN) .setName("Marius2") .setEmail("marius2@mail.com") .setPassword("password2") .setPasswordConfirmation("password2")); session.commit(); - GroupMembershipFinder.Membership membership = groupMembershipFinder.find(GroupMembershipQuery.builder().login("marius").groupSearch("sonar-users").build()); + GroupMembershipFinder.Membership membership = groupMembershipFinder.find(GroupMembershipQuery.builder().login(DEFAULT_LOGIN).groupSearch("sonar-users").build()); assertThat(membership.groups()).hasSize(1); assertThat(membership.groups().get(0).name()).isEqualTo("sonar-users"); assertThat(membership.groups().get(0).isMember()).isTrue(); @@ -581,7 +582,7 @@ public class UserUpdaterTest { when(system2.now()).thenReturn(1418215735486L); createDefaultGroup(); - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setName("Marius2") .setEmail("marius2@mail.com") .setPassword("password2") @@ -590,7 +591,7 @@ public class UserUpdaterTest { session.commit(); session.clearCache(); - UserDto dto = userDao.selectByLogin(session, "marius"); + UserDto dto = userDao.selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.isActive()).isTrue(); assertThat(dto.getName()).isEqualTo("Marius2"); assertThat(dto.getEmail()).isEqualTo("marius2@mail.com"); @@ -605,7 +606,7 @@ public class UserUpdaterTest { assertThat(indexUsers).hasSize(1); assertThat(indexUsers.get(0).getSource()) .contains( - entry("login", "marius"), + entry("login", DEFAULT_LOGIN), entry("name", "Marius2"), entry("email", "marius2@mail.com")); } @@ -616,7 +617,7 @@ public class UserUpdaterTest { when(system2.now()).thenReturn(1418215735486L); createDefaultGroup(); - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setName("Marius2") .setEmail("marius2@mail.com") .setPassword("password2") @@ -625,7 +626,7 @@ public class UserUpdaterTest { session.commit(); session.clearCache(); - UserDto dto = userDao.selectByLogin(session, "marius"); + UserDto dto = userDao.selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.isActive()).isTrue(); assertThat(dto.getName()).isEqualTo("Marius2"); assertThat(dto.getEmail()).isEqualTo("marius2@mail.com"); @@ -640,7 +641,7 @@ public class UserUpdaterTest { assertThat(indexUsers).hasSize(1); assertThat(indexUsers.get(0).getSource()) .contains( - entry("login", "marius"), + entry("login", DEFAULT_LOGIN), entry("name", "Marius2"), entry("email", "marius2@mail.com")); } @@ -650,7 +651,7 @@ public class UserUpdaterTest { db.prepareDbUnit(getClass(), "update_user.xml"); createDefaultGroup(); - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setName("Marius2") .setEmail("marius2@mail.com") .setPassword("password2") @@ -659,7 +660,7 @@ public class UserUpdaterTest { session.commit(); session.clearCache(); - UserDto dto = userDao.selectByLogin(session, "marius"); + UserDto dto = userDao.selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.getScmAccountsAsList()).containsOnly("ma2"); } @@ -668,12 +669,12 @@ public class UserUpdaterTest { db.prepareDbUnit(getClass(), "update_user.xml"); createDefaultGroup(); - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setName("Marius2")); session.commit(); session.clearCache(); - UserDto dto = userDao.selectByLogin(session, "marius"); + UserDto dto = userDao.selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.getName()).isEqualTo("Marius2"); // Following fields has not changed @@ -688,12 +689,12 @@ public class UserUpdaterTest { db.prepareDbUnit(getClass(), "update_user.xml"); createDefaultGroup(); - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setEmail("marius2@mail.com")); session.commit(); session.clearCache(); - UserDto dto = userDao.selectByLogin(session, "marius"); + UserDto dto = userDao.selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.getEmail()).isEqualTo("marius2@mail.com"); // Following fields has not changed @@ -708,12 +709,12 @@ public class UserUpdaterTest { db.prepareDbUnit(getClass(), "update_user.xml"); createDefaultGroup(); - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setScmAccounts(newArrayList("ma2"))); session.commit(); session.clearCache(); - UserDto dto = userDao.selectByLogin(session, "marius"); + UserDto dto = userDao.selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.getScmAccountsAsList()).containsOnly("ma2"); // Following fields has not changed @@ -728,12 +729,12 @@ public class UserUpdaterTest { db.prepareDbUnit(getClass(), "update_user.xml"); createDefaultGroup(); - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setScmAccounts(newArrayList("ma", "marius33"))); session.commit(); session.clearCache(); - UserDto dto = userDao.selectByLogin(session, "marius"); + UserDto dto = userDao.selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33"); } @@ -742,12 +743,12 @@ public class UserUpdaterTest { db.prepareDbUnit(getClass(), "update_user.xml"); createDefaultGroup(); - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setScmAccounts(null)); session.commit(); session.clearCache(); - UserDto dto = userDao.selectByLogin(session, "marius"); + UserDto dto = userDao.selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.getScmAccounts()).isNull(); } @@ -756,13 +757,13 @@ public class UserUpdaterTest { db.prepareDbUnit(getClass(), "update_user.xml"); createDefaultGroup(); - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setPassword("password2") .setPasswordConfirmation("password2")); session.commit(); session.clearCache(); - UserDto dto = userDao.selectByLogin(session, "marius"); + UserDto dto = userDao.selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.getSalt()).isNotEqualTo("79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365"); assertThat(dto.getCryptedPassword()).isNotEqualTo("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg"); @@ -776,11 +777,10 @@ public class UserUpdaterTest { public void fail_to_update_password_when_external_auth_is_used() { db.prepareDbUnit(getClass(), "update_user.xml"); createDefaultGroup(); - when(realmFactory.hasExternalAuthentication()).thenReturn(true); try { - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setPassword("password2") .setPasswordConfirmation("password2")); } catch (BadRequestException e) { @@ -788,13 +788,27 @@ public class UserUpdaterTest { } } + @Test + public void update_password_of_technical_user_when_external_auth_is_used() { + db.prepareDbUnit(getClass(), "update_technical_user.xml"); + createDefaultGroup(); + when(realmFactory.hasExternalAuthentication()).thenReturn(true); + + userUpdater.update(UpdateUser.create(TECHNICAL_USER) + .setPassword("password2") + .setPasswordConfirmation("password2")); + + UserDto dto = userDao.selectByLogin(session, TECHNICAL_USER); + assertThat(dto.getSalt()).isNotEqualTo("79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365"); + } + @Test public void not_associate_default_group_when_updating_user() { db.prepareDbUnit(getClass(), "associate_default_groups_when_updating_user.xml"); createDefaultGroup(); // Existing user, he has no group, and should not be associated to the default one - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setName("Marius2") .setEmail("marius2@mail.com") .setPassword("password2") @@ -802,7 +816,7 @@ public class UserUpdaterTest { .setScmAccounts(newArrayList("ma2"))); session.commit(); - GroupMembershipFinder.Membership membership = groupMembershipFinder.find(GroupMembershipQuery.builder().login("marius").groupSearch("sonar-users").build()); + GroupMembershipFinder.Membership membership = groupMembershipFinder.find(GroupMembershipQuery.builder().login(DEFAULT_LOGIN).groupSearch("sonar-users").build()); assertThat(membership.groups()).hasSize(1); assertThat(membership.groups().get(0).name()).isEqualTo("sonar-users"); assertThat(membership.groups().get(0).isMember()).isFalse(); @@ -811,16 +825,16 @@ public class UserUpdaterTest { @Test public void not_associate_default_group_when_updating_user_if_already_existing() { db.prepareDbUnit(getClass(), "not_associate_default_group_when_updating_user_if_already_existing.xml"); - settings.setProperty(CoreProperties.CORE_DEFAULT_GROUP, "sonar-users"); + settings.setProperty(CORE_DEFAULT_GROUP, "sonar-users"); session.commit(); // User is already associate to the default group - GroupMembershipFinder.Membership membership = groupMembershipFinder.find(GroupMembershipQuery.builder().login("marius").groupSearch("sonar-users").build()); + GroupMembershipFinder.Membership membership = groupMembershipFinder.find(GroupMembershipQuery.builder().login(DEFAULT_LOGIN).groupSearch("sonar-users").build()); assertThat(membership.groups()).hasSize(1); assertThat(membership.groups().get(0).name()).isEqualTo("sonar-users"); assertThat(membership.groups().get(0).isMember()).isTrue(); - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setName("Marius2") .setEmail("marius2@mail.com") .setPassword("password2") @@ -829,7 +843,7 @@ public class UserUpdaterTest { session.commit(); // Nothing as changed - membership = groupMembershipFinder.find(GroupMembershipQuery.builder().login("marius").groupSearch("sonar-users").build()); + membership = groupMembershipFinder.find(GroupMembershipQuery.builder().login(DEFAULT_LOGIN).groupSearch("sonar-users").build()); assertThat(membership.groups()).hasSize(1); assertThat(membership.groups().get(0).name()).isEqualTo("sonar-users"); assertThat(membership.groups().get(0).isMember()).isTrue(); @@ -841,7 +855,7 @@ public class UserUpdaterTest { createDefaultGroup(); try { - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setName("Marius2") .setEmail("marius2@mail.com") .setPassword("password2") @@ -859,8 +873,8 @@ public class UserUpdaterTest { createDefaultGroup(); try { - userUpdater.update(UpdateUser.create("marius") - .setScmAccounts(newArrayList("marius"))); + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) + .setScmAccounts(newArrayList(DEFAULT_LOGIN))); fail(); } catch (BadRequestException e) { assertThat(e.errors().messages()).containsOnly(Message.of("user.login_or_email_used_as_scm_account")); @@ -873,7 +887,7 @@ public class UserUpdaterTest { createDefaultGroup(); try { - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setScmAccounts(newArrayList("marius@lesbronzes.fr"))); fail(); } catch (BadRequestException e) { @@ -887,7 +901,7 @@ public class UserUpdaterTest { createDefaultGroup(); try { - userUpdater.update(UpdateUser.create("marius") + userUpdater.update(UpdateUser.create(DEFAULT_LOGIN) .setEmail("marius@newmail.com") .setScmAccounts(newArrayList("marius@newmail.com"))); fail(); @@ -897,7 +911,7 @@ public class UserUpdaterTest { } private void createDefaultGroup() { - settings.setProperty(CoreProperties.CORE_DEFAULT_GROUP, "sonar-users"); + settings.setProperty(CORE_DEFAULT_GROUP, "sonar-users"); groupDao.insert(session, new GroupDto().setName("sonar-users").setDescription("Sonar Users")); session.commit(); } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/update_technical_user.xml b/server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/update_technical_user.xml new file mode 100644 index 00000000000..6b824d7cf25 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/update_technical_user.xml @@ -0,0 +1,7 @@ + + + + + -- 2.39.5