* Return true if the user has been reactivated
*/
public boolean create(NewUser newUser) {
- UserDto userDto = createNewUserDto(newUser);
boolean isUserReactivated = false;
DbSession dbSession = dbClient.openSession(false);
try {
+ UserDto userDto = createNewUserDto(dbSession, newUser);
String login = userDto.getLogin();
UserDto existingUser = dbClient.userDao().selectNullableByLogin(dbSession, login);
if (existingUser == null) {
.setScmAccounts(newUser.scmAccounts())
.setPassword(newUser.password())
.setPasswordConfirmation(newUser.passwordConfirmation());
- updateUserDto(updateUser, existingUser);
+ updateUserDto(dbSession, updateUser, existingUser);
updateUser(dbSession, existingUser);
isUserReactivated = true;
}
try {
UserDto user = dbClient.userDao().selectNullableByLogin(dbSession, updateUser.login());
if (user != null) {
- updateUserDto(updateUser, user);
+ updateUserDto(dbSession, updateUser, user);
updateUser(dbSession, user);
} else {
throw new NotFoundException(String.format("User '%s' does not exists", updateUser.login()));
}
}
- private static UserDto createNewUserDto(NewUser newUser) {
+ private UserDto createNewUserDto(DbSession dbSession, NewUser newUser) {
UserDto userDto = new UserDto();
List<Message> messages = newArrayList();
validatePasswords(password, passwordConfirmation, messages);
setEncryptedPassWord(password, userDto);
- userDto.setScmAccounts(convertScmAccountsToCsv(newUser.scmAccounts()));
+ List<String> scmAccounts = sanitizeScmAccounts(newUser.scmAccounts());
+ validateScmAccounts(dbSession, scmAccounts, login, email, messages);
+ userDto.setScmAccounts(convertScmAccountsToCsv(scmAccounts));
if (!messages.isEmpty()) {
throw new BadRequestException(messages);
return userDto;
}
- private static void updateUserDto(UpdateUser updateUser, UserDto userDto) {
+ private void updateUserDto(DbSession dbSession, UpdateUser updateUser, UserDto userDto) {
List<Message> messages = newArrayList();
String name = updateUser.name();
}
if (updateUser.isScmAccountsChanged()) {
- userDto.setScmAccounts(convertScmAccountsToCsv(updateUser.scmAccounts()));
+ List<String> scmAccounts = sanitizeScmAccounts(updateUser.scmAccounts());
+ validateScmAccounts(dbSession, scmAccounts, userDto.getLogin(), email != null ? email : userDto.getEmail(), messages);
+ userDto.setScmAccounts(convertScmAccountsToCsv(scmAccounts));
}
if (!messages.isEmpty()) {
}
}
+ private void validateScmAccounts(DbSession dbSession, @Nullable List<String> scmAccounts, @Nullable String login, @Nullable String email, List<Message> messages) {
+ if (scmAccounts != null) {
+ for (String scmAccount : scmAccounts) {
+ if (scmAccount.equals(login) || scmAccount.equals(email)) {
+ messages.add(Message.of("user.login_or_email_used_as_scm_account"));
+ } else {
+ UserDto matchingUser = dbClient.userDao().selectNullableByScmAccountOrLoginOrName(dbSession, scmAccount);
+ if (matchingUser != null) {
+ messages.add(Message.of("user.scm_account_already_used", scmAccount, matchingUser.getName(), matchingUser.getLogin()));
+ }
+ }
+ }
+ }
+ }
+
+ @CheckForNull
+ private static List<String> sanitizeScmAccounts(@Nullable List<String> scmAccounts) {
+ if (scmAccounts != null) {
+ scmAccounts.removeAll(Arrays.asList(null, ""));
+ return scmAccounts;
+ }
+ return null;
+ }
+
private void saveUser(DbSession dbSession, UserDto userDto) {
long now = system2.now();
userDto.setActive(true).setCreatedAt(now).setUpdatedAt(now);
@CheckForNull
private static String convertScmAccountsToCsv(@Nullable List<String> scmAccounts) {
if (scmAccounts != null) {
- // Remove empty characters
- scmAccounts.removeAll(Arrays.asList(null, ""));
// Add one empty character at the begin and at the end of the list to be able to generate a coma at the begin and at the end of the
// text
scmAccounts.add(0, "");
return user;
}
+ @CheckForNull
+ public UserDto selectNullableByScmAccountOrLoginOrName(DbSession session, String scmAccount) {
+ return mapper(session).selectNullableByScmAccountOrLoginOrName(scmAccount);
+ }
+
protected UserMapper mapper(DbSession session) {
return session.getMapper(UserMapper.class);
}
}
}
+ @Test
+ public void fail_to_create_user_when_scm_account_is_already_used() throws Exception {
+ db.prepareDbUnit(getClass(), "fail_to_create_user_when_scm_account_is_already_used.xml");
+
+ try {
+ userUpdater.create(NewUser.create()
+ .setLogin("marius")
+ .setName("Marius2")
+ .setEmail("marius2@mail.com")
+ .setPassword("password2")
+ .setPasswordConfirmation("password2")
+ .setScmAccounts(newArrayList("jo")));
+ fail();
+ } catch (BadRequestException e) {
+ assertThat(e.errors().messages()).containsOnly(Message.of("user.scm_account_already_used", "jo", "John", "john"));
+ }
+ }
+
+ @Test
+ public void fail_to_create_user_when_scm_account_is_user_login() throws Exception {
+ try {
+ userUpdater.create(NewUser.create()
+ .setLogin("marius")
+ .setName("Marius2")
+ .setEmail("marius2@mail.com")
+ .setPassword("password2")
+ .setPasswordConfirmation("password2")
+ .setScmAccounts(newArrayList("marius")));
+ fail();
+ } catch (BadRequestException e) {
+ assertThat(e.errors().messages()).containsOnly(Message.of("user.login_or_email_used_as_scm_account"));
+ }
+ }
+
+ @Test
+ public void fail_to_create_user_when_scm_account_is_user_email() throws Exception {
+ try {
+ userUpdater.create(NewUser.create()
+ .setLogin("marius")
+ .setName("Marius2")
+ .setEmail("marius2@mail.com")
+ .setPassword("password2")
+ .setPasswordConfirmation("password2")
+ .setScmAccounts(newArrayList("marius2@mail.com")));
+ fail();
+ } catch (BadRequestException e) {
+ assertThat(e.errors().messages()).containsOnly(Message.of("user.login_or_email_used_as_scm_account"));
+ }
+ }
+
@Test
public void notify_new_user() throws Exception {
createDefaultGroup();
assertThat(dto.getUpdatedAt()).isEqualTo(1418215735486L);
}
+ @Test
+ public void update_user_with_scm_accounts_containing_blank_entry() throws Exception {
+ db.prepareDbUnit(getClass(), "update_user.xml");
+ createDefaultGroup();
+
+ userUpdater.update(UpdateUser.create("marius")
+ .setName("Marius2")
+ .setEmail("marius2@mail.com")
+ .setPassword("password2")
+ .setPasswordConfirmation("password2")
+ .setScmAccounts(newArrayList("ma2", "", null)));
+ session.commit();
+ session.clearCache();
+
+ UserDto dto = userDao.selectNullableByLogin(session, "marius");
+ assertThat(dto.getScmAccounts()).isEqualTo(",ma2,");
+ }
+
@Test
public void update_only_user_name() throws Exception {
db.prepareDbUnit(getClass(), "update_user.xml");
}
}
+ @Test
+ public void fail_to_update_user_when_scm_account_is_already_used() throws Exception {
+ db.prepareDbUnit(getClass(), "fail_to_update_user_when_scm_account_is_already_used.xml");
+ createDefaultGroup();
+
+ try {
+ userUpdater.update(UpdateUser.create("marius")
+ .setName("Marius2")
+ .setEmail("marius2@mail.com")
+ .setPassword("password2")
+ .setPasswordConfirmation("password2")
+ .setScmAccounts(newArrayList("jo")));
+ fail();
+ } catch (BadRequestException e) {
+ assertThat(e.errors().messages()).containsOnly(Message.of("user.scm_account_already_used", "jo", "John", "john"));
+ }
+ }
+
+ @Test
+ public void fail_to_update_user_when_scm_account_is_user_login() throws Exception {
+ db.prepareDbUnit(getClass(), "update_user.xml");
+ createDefaultGroup();
+
+ try {
+ userUpdater.update(UpdateUser.create("marius")
+ .setScmAccounts(newArrayList("marius")));
+ fail();
+ } catch (BadRequestException e) {
+ assertThat(e.errors().messages()).containsOnly(Message.of("user.login_or_email_used_as_scm_account"));
+ }
+ }
+
+ @Test
+ public void fail_to_update_user_when_scm_account_is_existing_user_email() throws Exception {
+ db.prepareDbUnit(getClass(), "update_user.xml");
+ createDefaultGroup();
+
+ try {
+ userUpdater.update(UpdateUser.create("marius")
+ .setScmAccounts(newArrayList("marius@lesbronzes.fr")));
+ fail();
+ } catch (BadRequestException e) {
+ assertThat(e.errors().messages()).containsOnly(Message.of("user.login_or_email_used_as_scm_account"));
+ }
+ }
+
+ @Test
+ public void fail_to_update_user_when_scm_account_is_new_user_email() throws Exception {
+ db.prepareDbUnit(getClass(), "update_user.xml");
+ createDefaultGroup();
+
+ try {
+ userUpdater.update(UpdateUser.create("marius")
+ .setEmail("marius@newmail.com")
+ .setScmAccounts(newArrayList("marius@newmail.com")));
+ fail();
+ } catch (BadRequestException e) {
+ assertThat(e.errors().messages()).containsOnly(Message.of("user.login_or_email_used_as_scm_account"));
+ }
+ }
+
private void createDefaultGroup() {
settings.setProperty(CoreProperties.CORE_DEFAULT_GROUP, "sonar-users");
groupDao.insert(session, new GroupDto().setName("sonar-users").setDescription("Sonar Users"));
assertThat(dto.getUpdatedAt()).isEqualTo(1418215735485L);
}
+ @Test
+ public void select_nullable_by_scm_account() {
+ db.prepareDbUnit(getClass(), "select_nullable_by_scm_account.xml");
+
+ assertThat(dao.selectNullableByScmAccountOrLoginOrName(session, "ma").getLogin()).isEqualTo("marius");
+ assertThat(dao.selectNullableByScmAccountOrLoginOrName(session, "marius").getLogin()).isEqualTo("marius");
+ assertThat(dao.selectNullableByScmAccountOrLoginOrName(session, "marius@lesbronzes.fr").getLogin()).isEqualTo("marius");
+
+ assertThat(dao.selectNullableByScmAccountOrLoginOrName(session, "m")).isNull();
+ assertThat(dao.selectNullableByScmAccountOrLoginOrName(session, "unknown")).isNull();
+ }
+
@Test
public void select_by_login_with_unknown_login() {
try {
--- /dev/null
+<dataset>
+
+ <users id="101" login="john" name="John" email="john@email.com" active="[true]" scm_accounts=",jo," created_at="1418215735482" updated_at="1418215735485"
+ salt="79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365" crypted_password="650d2261c98361e2f67f90ce5c65a95e7d8ea2fg"/>
+
+</dataset>
<users id="101" login="john" name="John" email="john@email.com" active="[true]" scm_accounts=",jo," created_at="1418215735482" updated_at="1418215735485"
salt="79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365" crypted_password="650d2261c98361e2f67f90ce5c65a95e7d8ea2fg"/>
+ <users id="102" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[true]" scm_accounts="ma,marius33" created_at="1418215735482" updated_at="1418215735485"
+ salt="79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365" crypted_password="650d2261c98361e2f67f90ce5c65a95e7d8ea2fg"/>
</dataset>
--- /dev/null
+<dataset>
+
+ <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[true]" scm_accounts=",ma,marius33," created_at="1418215735482" updated_at="1418215735485"
+ salt="79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365" crypted_password="650d2261c98361e2f67f90ce5c65a95e7d8ea2fg"/>
+ <users id="102" login="sbrandhof" name="Simon Brandhof" email="sbrandhof@lesbronzes.fr" active="[true]" scm_accounts="[null]" created_at="1418215735482"
+ updated_at="1418215735485"
+ salt="79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8366" crypted_password="650d2261c98361e2f67f90ce5c65a95e7d8ea2fh"/>
+
+</dataset>
@CheckForNull
UserDto selectByLogin(String login);
+ @CheckForNull
+ UserDto selectNullableByScmAccountOrLoginOrName(String scmAccount);
+
@CheckForNull
UserDto selectUser(long userId);
<select id="selectByLogin" parameterType="String" resultType="User">
SELECT
<include refid="userColumns"/>
- FROM users u WHERE u.login=#{login}
+ FROM users u
+ WHERE u.login=#{login}
+ </select>
+
+ <select id="selectNullableByScmAccountOrLoginOrName" parameterType="String" resultType="User">
+ SELECT
+ <include refid="userColumns"/>
+ FROM users u
+ WHERE
+ u.login=#{scmAccount}
+ OR u.email=#{scmAccount}
+ OR
+ <choose>
+ <when test="_databaseId == 'mssql'">
+ u.scm_accounts LIKE '%,' + #{scmAccount} + ',%'
+ </when>
+ <when test="_databaseId == 'mysql'">
+ u.scm_accounts LIKE concat('%,', #{scmAccount}, ',%')
+ </when>
+ <otherwise>
+ u.scm_accounts LIKE '%,' || #{scmAccount} || ',%'
+ </otherwise>
+ </choose>
</select>
<select id="selectUser" parameterType="long" resultType="User">
SELECT
<include refid="userColumns"/>
- FROM users u WHERE u.id=#{id}
+ FROM users u
+ WHERE u.id=#{id}
</select>
<select id="selectUserByLogin" parameterType="string" resultType="User">
SELECT
<include refid="userColumns"/>
- FROM users u WHERE u.login=#{id} AND u.active=${_true}
+ FROM users u
+ WHERE u.login=#{id} AND u.active=${_true}
</select>
<select id="selectUsersByLogins" parameterType="map" resultType="User">
user.password_doesnt_match_confirmation=Password doesn't match confirmation.
user.reactivated=The user '{0}' has been reactivated.
user.add_scm_account=Add SCM account
+user.scm_account_already_used=The scm account '{0}' is already used by user '{1} ({2})'
+user.login_or_email_used_as_scm_account=Login and email are automatically considered as SCM accounts
#------------------------------------------------------------------------------