package org.sonar.server.db.migrations.v51;
-import com.google.common.base.CharMatcher;
+import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.sonar.api.utils.System2;
-import org.sonar.api.utils.text.CsvWriter;
import org.sonar.core.persistence.Database;
import org.sonar.server.db.migrations.BaseDataChange;
import org.sonar.server.db.migrations.Select;
import org.sonar.server.db.migrations.UpsertImpl;
import org.sonar.server.util.ProgressLogger;
-import java.io.StringWriter;
+import javax.annotation.CheckForNull;
+
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
public class CopyScmAccountsFromAuthorsToUsers extends BaseDataChange {
+ private static final char SCM_ACCOUNTS_SEPARATOR = '\n';
+
private final System2 system;
private final AtomicLong counter = new AtomicLong(0L);
final Multimap<Long, String> authorsByPersonId = ArrayListMultimap.create();
context.prepareSelect("SELECT a.person_id, a.login FROM authors a," +
" (SELECT person_id, COUNT(*) AS nb FROM authors GROUP BY person_id HAVING COUNT(*) > 1) group_by_person" +
- " WHERE a.person_id = group_by_person.person_id "
- ).scroll(new Select.RowHandler() {
- @Override
- public void handle(Select.Row row) throws SQLException {
- authorsByPersonId.put(row.getLong(1), row.getString(2));
- }
- });
+ " WHERE a.person_id = group_by_person.person_id "
+ ).scroll(new Select.RowHandler() {
+ @Override
+ public void handle(Select.Row row) throws SQLException {
+ authorsByPersonId.put(row.getLong(1), row.getString(2));
+ }
+ });
Upsert update = context.prepareUpsert("UPDATE users SET scm_accounts = ?, updated_at = ? WHERE id = ?");
for (Long personId : authorsByPersonId.keySet()) {
}
if (!authors.isEmpty()) {
update
- .setString(1, convertScmAccountsToCsv(authors))
+ .setString(1, encodeScmAccounts(authors))
.setLong(2, now)
.setLong(3, user.id)
.addBatch();
return users;
}
- private static String convertScmAccountsToCsv(List<String> scmAccounts) {
- List<String> list = newArrayList(scmAccounts);
- // 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
- list.add(0, "");
- list.add("");
- int size = list.size();
- StringWriter writer = new StringWriter(size);
- CsvWriter csv = CsvWriter.of(writer);
- csv.values(list.toArray(new String[size]));
- csv.close();
- // Remove useless line break added by CsvWriter at this end of the text
- return CharMatcher.JAVA_ISO_CONTROL.removeFrom(writer.toString());
+ @CheckForNull
+ private static String encodeScmAccounts(List<String> scmAccounts) {
+ if (scmAccounts.isEmpty()) {
+ return null;
+ }
+ return SCM_ACCOUNTS_SEPARATOR + Joiner.on(SCM_ACCOUNTS_SEPARATOR).join(scmAccounts) + SCM_ACCOUNTS_SEPARATOR;
}
private static class User {
Long id;
String login;
String email;
- String scmAcounts;
+ String scmAccounts;
- User(Long id, String login, String email, String scmAcounts) {
+ User(Long id, String login, String email, String scmAccounts) {
this.id = id;
this.login = login;
this.email = email;
- this.scmAcounts = scmAcounts;
+ this.scmAccounts = scmAccounts;
}
}
}
package org.sonar.server.user;
-import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.NewUserHandler;
import org.sonar.api.utils.System2;
-import org.sonar.api.utils.text.CsvWriter;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.user.GroupDto;
import org.sonar.core.user.UserDto;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import java.io.StringWriter;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Sets.newLinkedHashSet;
public class UserUpdater implements ServerComponent {
List<String> scmAccounts = sanitizeScmAccounts(newUser.scmAccounts());
if (scmAccounts != null && !scmAccounts.isEmpty()) {
validateScmAccounts(dbSession, scmAccounts, login, email, null, messages);
- userDto.setScmAccounts(convertScmAccountsToCsv(scmAccounts));
+ userDto.setScmAccounts(scmAccounts);
}
if (!messages.isEmpty()) {
List<String> scmAccounts = sanitizeScmAccounts(updateUser.scmAccounts());
if (scmAccounts != null && !scmAccounts.isEmpty()) {
validateScmAccounts(dbSession, scmAccounts, userDto.getLogin(), email != null ? email : userDto.getEmail(), userDto, messages);
- userDto.setScmAccounts(convertScmAccountsToCsv(scmAccounts));
+ userDto.setScmAccounts(scmAccounts);
} else {
- userDto.setScmAccounts(null);
+ userDto.setScmAccounts((String) null);
}
}
userDto.setCryptedPassword(DigestUtils.sha1Hex("--" + saltHex + "--" + password + "--"));
}
- private static String convertScmAccountsToCsv(List<String> scmAccounts) {
- // Use a set to remove duplication, then use a list to add empty characters
- List<String> uniqueScmAccounts = newArrayList(newLinkedHashSet(scmAccounts));
- // 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
- uniqueScmAccounts.add(0, "");
- uniqueScmAccounts.add("");
- int size = uniqueScmAccounts.size();
- StringWriter writer = new StringWriter(size);
- CsvWriter csv = CsvWriter.of(writer);
- csv.values(uniqueScmAccounts.toArray(new String[size]));
- csv.close();
- // Remove useless line break added by CsvWriter at this end of the text
- return CharMatcher.JAVA_ISO_CONTROL.removeFrom(writer.toString());
- }
-
private void notifyNewUser(String login, String name, String email) {
newUserNotifier.onNewUser(NewUserHandler.Context.builder()
.setLogin(login)
}
public List<UserDto> selectNullableByScmAccountOrLoginOrEmail(DbSession session, String scmAccountOrLoginOrEmail) {
- return mapper(session).selectNullableByScmAccountOrLoginOrEmail(scmAccountOrLoginOrEmail);
+ String like = new StringBuilder().append("%").append(UserDto.SCM_ACCOUNTS_SEPARATOR).append(scmAccountOrLoginOrEmail).append(UserDto.SCM_ACCOUNTS_SEPARATOR).append("%").toString();
+ return mapper(session).selectNullableByScmAccountOrLoginOrEmail(scmAccountOrLoginOrEmail, like);
}
protected UserMapper mapper(DbSession session) {
*/
package org.sonar.server.user.index;
-import com.google.common.base.Strings;
import com.google.common.collect.Maps;
-import org.apache.commons.csv.CSVFormat;
-import org.apache.commons.csv.CSVParser;
-import org.apache.commons.csv.CSVRecord;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
+import org.sonar.core.user.UserDto;
import org.sonar.server.db.DbClient;
import org.sonar.server.db.ResultSetIterator;
-import javax.annotation.Nullable;
-
-import java.io.IOException;
-import java.io.StringReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.List;
-
-import static com.google.common.collect.Lists.newArrayList;
/**
* Scrolls over table USERS and reads documents to populate the user index
doc.setName(rs.getString(2));
doc.setEmail(rs.getString(3));
doc.setActive(rs.getBoolean(4));
- doc.setScmAccounts(getScmAccounts(rs.getString(5), login));
+ doc.setScmAccounts(UserDto.decodeScmAccounts(rs.getString(5)));
doc.setCreatedAt(rs.getLong(6));
doc.setUpdatedAt(rs.getLong(7));
return doc;
}
- private List<String> getScmAccounts(@Nullable String csv, String login) {
- List<String> result = newArrayList();
- if (csv == null) {
- return result;
- }
- CSVParser csvParser = null;
- StringReader reader = null;
- try {
- reader = new StringReader(csv);
- csvParser = new CSVParser(reader, CSVFormat.DEFAULT);
- for (CSVRecord csvRecord : csvParser) {
- for (String aCsvRecord : csvRecord) {
- if (!Strings.isNullOrEmpty(aCsvRecord)) {
- result.add(aCsvRecord);
- }
- }
- }
- return result;
- } catch (IOException e) {
- throw new IllegalStateException(String.format("Fail to read scm accounts for user '%s'", login), e);
- } finally {
- IOUtils.closeQuietly(reader);
- IOUtils.closeQuietly(csvParser);
- }
- }
}
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.core.persistence.DbTester;
+import org.sonar.core.user.UserDto;
import org.sonar.server.db.migrations.DatabaseMigration;
import java.util.Map;
migration.execute();
User simon = getUserByLogin("simon");
- assertThat(simon.scmAccounts).isEqualTo(",Simon B,simon@codehaus.org,");
+ assertThat(simon.scmAccounts).isEqualTo(UserDto.SCM_ACCOUNTS_SEPARATOR + "Simon B" + UserDto.SCM_ACCOUNTS_SEPARATOR + "simon@codehaus.org" + UserDto.SCM_ACCOUNTS_SEPARATOR);
assertThat(simon.updatedAt).isEqualTo(updatedDate);
User fabrice = getUserByLogin("fabrice");
- assertThat(fabrice.scmAccounts).isEqualTo(",fab,");
+ assertThat(fabrice.scmAccounts).isEqualTo(UserDto.SCM_ACCOUNTS_SEPARATOR + "fab" + UserDto.SCM_ACCOUNTS_SEPARATOR);
assertThat(fabrice.updatedAt).isEqualTo(updatedDate);
assertThat(getUserByLogin("julien").updatedAt).isEqualTo(oldDate);
assertThat(userDto.getEmail()).isEqualTo("user@mail.com");
assertThat(userDto.getCryptedPassword()).isNotNull();
assertThat(userDto.getSalt()).isNotNull();
- assertThat(userDto.getScmAccounts()).contains(",u1,u_1,");
+ assertThat(userDto.getScmAccountsAsList()).containsOnly("u1", "u_1");
assertThat(userDto.getCreatedAt()).isNotNull();
assertThat(userDto.getUpdatedAt()).isNotNull();
assertThat(dto.getLogin()).isEqualTo("user");
assertThat(dto.getName()).isEqualTo("User");
assertThat(dto.getEmail()).isEqualTo("user@mail.com");
- assertThat(dto.getScmAccounts()).isEqualTo(",u1,u_1,User 1,");
+ assertThat(dto.getScmAccountsAsList()).containsOnly("u1", "u_1", "User 1");
assertThat(dto.isActive()).isTrue();
assertThat(dto.getSalt()).isNotNull();
.setPasswordConfirmation("password")
.setScmAccounts(newArrayList("u1", "", null)));
- assertThat(userDao.selectNullableByLogin(session, "user").getScmAccounts()).isEqualTo(",u1,");
+ assertThat(userDao.selectNullableByLogin(session, "user").getScmAccountsAsList()).containsOnly("u1");
}
@Test
.setPasswordConfirmation("password")
.setScmAccounts(newArrayList("u1", "u1")));
- assertThat(userDao.selectNullableByLogin(session, "user").getScmAccounts()).isEqualTo(",u1,");
+ assertThat(userDao.selectNullableByLogin(session, "user").getScmAccountsAsList()).containsOnly("u1");
}
@Test
assertThat(dto.isActive()).isTrue();
assertThat(dto.getName()).isEqualTo("Marius2");
assertThat(dto.getEmail()).isEqualTo("marius2@mail.com");
- assertThat(dto.getScmAccounts()).isEqualTo(",ma2,");
+ assertThat(dto.getScmAccountsAsList()).containsOnly("ma2");
assertThat(dto.getSalt()).isNotEqualTo("79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365");
assertThat(dto.getCryptedPassword()).isNotEqualTo("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg");
session.clearCache();
UserDto dto = userDao.selectNullableByLogin(session, "marius");
- assertThat(dto.getScmAccounts()).isEqualTo(",ma2,");
+ assertThat(dto.getScmAccountsAsList()).containsOnly("ma2");
}
@Test
// Following fields has not changed
assertThat(dto.getEmail()).isEqualTo("marius@lesbronzes.fr");
- assertThat(dto.getScmAccounts()).isEqualTo(",ma,marius33,");
+ assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33");
assertThat(dto.getSalt()).isEqualTo("79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365");
assertThat(dto.getCryptedPassword()).isEqualTo("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg");
}
// Following fields has not changed
assertThat(dto.getName()).isEqualTo("Marius");
- assertThat(dto.getScmAccounts()).isEqualTo(",ma,marius33,");
+ assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33");
assertThat(dto.getSalt()).isEqualTo("79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365");
assertThat(dto.getCryptedPassword()).isEqualTo("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg");
}
session.clearCache();
UserDto dto = userDao.selectNullableByLogin(session, "marius");
- assertThat(dto.getScmAccounts()).isEqualTo(",ma2,");
+ assertThat(dto.getScmAccountsAsList()).containsOnly("ma2");
// Following fields has not changed
assertThat(dto.getName()).isEqualTo("Marius");
session.clearCache();
UserDto dto = userDao.selectNullableByLogin(session, "marius");
- assertThat(dto.getScmAccounts()).isEqualTo(",ma,marius33,");
+ assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33");
}
@Test
// Following fields has not changed
assertThat(dto.getName()).isEqualTo("Marius");
- assertThat(dto.getScmAccounts()).isEqualTo(",ma,marius33,");
+ assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33");
assertThat(dto.getEmail()).isEqualTo("marius@lesbronzes.fr");
}
assertThat(dto.getName()).isEqualTo("Marius");
assertThat(dto.getEmail()).isEqualTo("marius@lesbronzes.fr");
assertThat(dto.isActive()).isTrue();
- assertThat(dto.getScmAccounts()).isEqualTo(",ma,marius33,");
+ assertThat(dto.getScmAccountsAsList()).containsOnly("ma","marius33");
assertThat(dto.getSalt()).isEqualTo("79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365");
assertThat(dto.getCryptedPassword()).isEqualTo("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg");
assertThat(dto.getCreatedAt()).isEqualTo(1418215735482L);
<dataset>
- <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[true]" scm_accounts="ma,marius33" created_at="1418215735482" updated_at="1418215735485"
+ <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"/>
</dataset>
<dataset>
- <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[false]" scm_accounts="ma,marius33" created_at="1418215735482" updated_at="1418215735485"
+ <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[false]" scm_accounts=" ma marius33 " created_at="1418215735482" updated_at="1418215735485"
salt="79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365" crypted_password="650d2261c98361e2f67f90ce5c65a95e7d8ea2fg"/>
<groups id="1" name="sonar-devs" description="Sonar Devs" created_at="2014-09-08" updated_at="2014-09-08"/>
<dataset>
- <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[true]" scm_accounts="ma,marius33" created_at="1418215735482" updated_at="1418215735485"
+ <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"/>
<groups id="1" name="sonar-devs" description="Sonar Devs" created_at="2014-09-08" updated_at="2014-09-08"/>
<dataset>
- <users id="101" login="john" name="John" email="john@email.com" active="[true]" scm_accounts=",jo," created_at="1418215735482" updated_at="1418215735485"
+ <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>
<dataset>
- <users id="101" login="john" name="John" email="john@email.com" active="[true]" scm_accounts=",jo," created_at="1418215735482" updated_at="1418215735485"
+ <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="technical-account" name="Technical account" email="john@email.com" active="[true]" scm_accounts="[null]" created_at="1418215735482"
<dataset>
- <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[true]" scm_accounts="ma,marius33" created_at="1418215735482" updated_at="1418215735485"
+ <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"/>
</dataset>
<dataset>
- <users id="101" login="john" name="John" email="john@email.com" active="[true]" scm_accounts=",jo," created_at="1418215735482" updated_at="1418215735485"
+ <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"
+ <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>
<dataset>
- <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[true]" scm_accounts="ma,marius33" created_at="1418215735482" updated_at="1418215735485"
+ <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"/>
<groups id="1" name="sonar-users" description="Sonar Users" created_at="2014-09-08" updated_at="2014-09-08"/>
<dataset>
- <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[false]" scm_accounts="ma,marius33" created_at="1418215735482" updated_at="1418215735485"
+ <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[false]" scm_accounts=" ma marius33 " created_at="1418215735482" updated_at="1418215735485"
salt="79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8365" crypted_password="650d2261c98361e2f67f90ce5c65a95e7d8ea2fg"/>
</dataset>
<dataset>
- <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[true]" scm_accounts=",ma,marius33," created_at="1418215735482" updated_at="1418215735485"
+ <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"/>
</dataset>
<dataset>
- <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[true]" scm_accounts=",ma,marius33," created_at="1418215735482" updated_at="1418215735485"
+ <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="marius@lesbronzes.fr" active="[true]" scm_accounts="[null]" created_at="1418215735482" updated_at="1418215735485"
salt="79bd6a8e79fb8c76ac8b121cc7e8e11ad1af8366" crypted_password="650d2261c98361e2f67f90ce5c65a95e7d8ea2fh"/>
<dataset>
- <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[true]" scm_accounts=",ma,marius33," created_at="1418215735482" updated_at="1418215735485"
+ <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"
<dataset>
- <users id="101" login="marius" name="Marius" email="marius@lesbronzes.fr" active="[true]" scm_accounts=",ma,marius33," created_at="1418215735482" updated_at="1418215735485"
+ <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="marius@lesbronzes.fr" active="[true]" scm_accounts="[null]" created_at="1418215735482"
updated_at="1418215735485"
<dataset>
<users id="1" login="user1" name="User1" email="user1@mail.com" active="[true]"
- scm_accounts="user_1,u1"
+ scm_accounts=" user_1 u1 "
created_at="1500000000000"
updated_at="1500000000000"
/>
<dataset>
<users id="1" login="user1" name="User1" email="user1@mail.com" active="[true]"
- scm_accounts=",user_1,u1,"
+ scm_accounts=" user_1 u1 "
created_at="1500000000000"
updated_at="1500000000000"
/>
<!-- scm accounts with comma -->
<users id="2" login="user2" name="User2" email="user2@mail.com" active="[true]"
- scm_accounts=","user,2",user_2,"
+ scm_accounts=" user,2 user_2 "
created_at="1500000000000"
updated_at="1500000000000"
/>
*/
package org.sonar.core.user;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.StringUtils;
+
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* @since 3.2
*/
public class UserDto {
+ public static final char SCM_ACCOUNTS_SEPARATOR = '\n';
+
private Long id;
private String login;
private String name;
return scmAccounts;
}
- public UserDto setScmAccounts(@Nullable String scmAccounts) {
- this.scmAccounts = scmAccounts;
+ public List<String> getScmAccountsAsList() {
+ return decodeScmAccounts(scmAccounts);
+ }
+
+ /**
+ * List of SCM accounts separated by '|'
+ */
+ public UserDto setScmAccounts(@Nullable String s) {
+ this.scmAccounts = s;
return this;
}
+ public UserDto setScmAccounts(@Nullable List list) {
+ this.scmAccounts = encodeScmAccounts(list);
+ return this;
+ }
+
+ @CheckForNull
+ public static String encodeScmAccounts(@Nullable List<String> scmAccounts) {
+ if (scmAccounts != null && !scmAccounts.isEmpty()) {
+ return String.format("%s%s%s", SCM_ACCOUNTS_SEPARATOR, StringUtils.join(scmAccounts, SCM_ACCOUNTS_SEPARATOR), SCM_ACCOUNTS_SEPARATOR);
+ }
+ return null;
+ }
+
+ public static List<String> decodeScmAccounts(@Nullable String dbValue) {
+ if (dbValue == null) {
+ return new ArrayList<>();
+ } else {
+ return Lists.newArrayList(Splitter.on(SCM_ACCOUNTS_SEPARATOR).omitEmptyStrings().split(dbValue));
+ }
+ }
+
public String getCryptedPassword() {
return cryptedPassword;
}
* Can return multiple results if an email is used by many users (For instance, technical account can use the same email as a none technical account)
*/
@CheckForNull
- List<UserDto> selectNullableByScmAccountOrLoginOrEmail(String scmAccountOrLoginOrEmail);
+ List<UserDto> selectNullableByScmAccountOrLoginOrEmail(@Param("scmAccount") String scmAccountOrLoginOrEmail, @Param("likeScmAccount") String likeScmAccount);
@CheckForNull
UserDto selectUser(long userId);
WHERE u.login=#{login}
</select>
- <select id="selectNullableByScmAccountOrLoginOrEmail" parameterType="String" resultType="User">
+ <select id="selectNullableByScmAccountOrLoginOrEmail" parameterType="map" 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>
+ OR u.scm_accounts like #{likeScmAccount}
</select>
<select id="selectUser" parameterType="long" resultType="User">
</delete>
<update id="deactivateUser" parameterType="long">
- UPDATE users SET active=${_false}, updated_at=#{now} WHERE id=#{id}
+ UPDATE users SET active=${_false}, updated_at=#{now,jdbcType=BIGINT} WHERE id=#{id}
</update>
<insert id="insert" parameterType="User" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.user;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class UserDtoTest {
+
+ @Test
+ public void encode_scm_accounts() throws Exception {
+ assertThat(UserDto.encodeScmAccounts(null)).isNull();
+ assertThat(UserDto.encodeScmAccounts(Collections.<String>emptyList())).isNull();
+ assertThat(UserDto.encodeScmAccounts(Arrays.asList("foo"))).isEqualTo("\nfoo\n");
+ assertThat(UserDto.encodeScmAccounts(Arrays.asList("foo", "bar"))).isEqualTo("\nfoo\nbar\n");
+ }
+
+ @Test
+ public void decode_scm_accounts() throws Exception {
+ assertThat(UserDto.decodeScmAccounts(null)).isEmpty();
+ assertThat(UserDto.decodeScmAccounts("\nfoo\n")).containsOnly("foo");
+ assertThat(UserDto.decodeScmAccounts("\nfoo\nbar\n")).containsOnly("foo", "bar");
+ }
+}