aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2017-03-21 18:02:22 +0100
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2017-03-24 17:38:53 +0100
commit4d444b9e946325b8e3f7e4a91fe3fb21cf0272ff (patch)
tree7cadf9092bb50b0f5da469f5b6e8cdbdb75cc8ac /server
parent515da3680100ab023c69a99faf2028f12cbd4492 (diff)
downloadsonarqube-4d444b9e946325b8e3f7e4a91fe3fb21cf0272ff.tar.gz
sonarqube-4d444b9e946325b8e3f7e4a91fe3fb21cf0272ff.zip
SONAR-8980 Index organizations when indexing a user
Diffstat (limited to 'server')
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDao.java20
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberMapper.java5
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMemberMapper.xml16
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/organization/OrganizationMemberDaoTest.java36
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/ws/RemoveMemberAction.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/ws/SearchMembersAction.java9
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/index/UserDoc.java11
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndex.java11
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexDefinition.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexer.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/index/UserQuery.java36
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/index/UserResultSetIterator.java23
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/organization/ws/SearchMembersActionTest.java43
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexDefinitionTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexTest.java48
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexerTest.java16
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/index/UserResultSetIteratorTest.java56
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/user/index/UserResultSetIteratorTest/shared.xml35
18 files changed, 234 insertions, 140 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDao.java
index 6a10a129ab4..e19d186c323 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDao.java
@@ -23,9 +23,12 @@ package org.sonar.db.organization;
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import java.util.function.BiConsumer;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
+import static org.sonar.db.DatabaseUtils.executeLargeInputsWithoutOutput;
+
public class OrganizationMemberDao implements Dao {
private static OrganizationMemberMapper mapper(DbSession dbSession) {
return dbSession.getMapper(OrganizationMemberMapper.class);
@@ -55,4 +58,21 @@ public class OrganizationMemberDao implements Dao {
return mapper(dbSession).selectOrganizationUuidsByUser(userId);
}
+ /**
+ *
+ * @param loginOrganizationConsumer {@link BiConsumer}<String,String> (login, organization uuid)
+ */
+ public void selectForUserIndexing(DbSession dbSession, List<String> logins, BiConsumer<String, String> loginOrganizationConsumer) {
+ executeLargeInputsWithoutOutput(logins, list -> mapper(dbSession).selectForIndexing(list)
+ .forEach(row -> loginOrganizationConsumer.accept(row.get("login"), row.get("organizationUuid"))));
+ }
+
+ /**
+ *
+ * @param loginOrganizationConsumer {@link BiConsumer}<String,String> (login, organization uuid)
+ */
+ public void selectAllForUserIndexing(DbSession dbSession, BiConsumer<String, String> loginOrganizationConsumer) {
+ mapper(dbSession).selectAllForIndexing()
+ .forEach(row -> loginOrganizationConsumer.accept(row.get("login"), row.get("organizationUuid")));
+ }
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberMapper.java
index 80237b276d1..5491715a43a 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberMapper.java
@@ -21,6 +21,7 @@
package org.sonar.db.organization;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.apache.ibatis.annotations.Param;
@@ -31,6 +32,10 @@ public interface OrganizationMemberMapper {
List<String> selectLogins(String organizationUuid);
+ List<Map<String, String>> selectForIndexing(@Param("logins") List<String> logins);
+
+ List<Map<String, String>> selectAllForIndexing();
+
void insert(OrganizationMemberDto organizationMember);
void delete(@Param("organizationUuid") String organizationUuid, @Param("userId") Integer userId);
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMemberMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMemberMapper.xml
index 2a63ade892f..951929079ea 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMemberMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMemberMapper.xml
@@ -30,6 +30,22 @@
where om.user_id = #{userId, jdbcType=INTEGER}
</select>
+ <select id="selectForIndexing" resultType="hashmap">
+ select u.login as "login", om.organization_uuid as "organizationUuid"
+ from organization_members om
+ inner join users u on om.user_id=u.id
+ where u.login in
+ <foreach collection="logins" open="(" close=")" item="login" separator=",">
+ #{login, jdbcType=VARCHAR}
+ </foreach>
+ </select>
+
+ <select id="selectAllForIndexing" resultType="hashmap">
+ select u.login as "login", om.organization_uuid as "organizationUuid"
+ from organization_members om
+ inner join users u on om.user_id=u.id
+ </select>
+
<insert id="insert" parameterType="OrganizationMember" useGeneratedKeys="false">
insert into organization_members
(
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/organization/OrganizationMemberDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/organization/OrganizationMemberDaoTest.java
index a586f1be28b..1bd9fc6afcb 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/organization/OrganizationMemberDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/organization/OrganizationMemberDaoTest.java
@@ -20,10 +20,13 @@
package org.sonar.db.organization;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.ibatis.exceptions.PersistenceException;
+import org.assertj.core.groups.Tuple;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -34,6 +37,7 @@ import org.sonar.db.user.UserDto;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
+import static org.assertj.core.api.Assertions.tuple;
public class OrganizationMemberDaoTest {
@Rule
@@ -88,6 +92,38 @@ public class OrganizationMemberDaoTest {
}
@Test
+ public void select_for_indexing() {
+ OrganizationDto org1 = db.organizations().insert(o -> o.setUuid("ORG_1"));
+ OrganizationDto org2 = db.organizations().insert(o -> o.setUuid("ORG_2"));
+ UserDto user1 = db.users().insertUser("L_1");
+ UserDto user2 = db.users().insertUser("L_2");
+ db.organizations().addMember(org1, user1);
+ db.organizations().addMember(org1, user2);
+ db.organizations().addMember(org2, user1);
+ List<Tuple> result = new ArrayList<>();
+
+ underTest.selectForUserIndexing(dbSession, Arrays.asList("L_1", "L_2"), (login, org) -> result.add(tuple(login, org)));
+
+ assertThat(result).containsOnly(tuple("L_1", "ORG_1"), tuple("L_1", "ORG_2"), tuple("L_2", "ORG_1"));
+ }
+
+ @Test
+ public void select_all_for_indexing() {
+ OrganizationDto org1 = db.organizations().insert(o -> o.setUuid("ORG_1"));
+ OrganizationDto org2 = db.organizations().insert(o -> o.setUuid("ORG_2"));
+ UserDto user1 = db.users().insertUser("L_1");
+ UserDto user2 = db.users().insertUser("L_2");
+ db.organizations().addMember(org1, user1);
+ db.organizations().addMember(org1, user2);
+ db.organizations().addMember(org2, user1);
+ List<Tuple> result = new ArrayList<>();
+
+ underTest.selectAllForUserIndexing(dbSession, (login, org) -> result.add(tuple(login, org)));
+
+ assertThat(result).containsOnly(tuple("L_1", "ORG_1"), tuple("L_1", "ORG_2"), tuple("L_2", "ORG_1"));
+ }
+
+ @Test
public void insert() {
underTest.insert(dbSession, create("O_1", 256));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/RemoveMemberAction.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/RemoveMemberAction.java
index 1c31b25fd60..1fcc099a4db 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/RemoveMemberAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/RemoveMemberAction.java
@@ -108,5 +108,4 @@ public class RemoveMemberAction implements OrganizationsWsAction {
organizationDto.getUuid(), ADMINISTER.getKey(), user.getId());
checkRequest(remainingAdmins > 0, "The last administrator member cannot be removed");
}
-
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/SearchMembersAction.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/SearchMembersAction.java
index 77208d0f7a2..1dffd2a3e11 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/SearchMembersAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/SearchMembersAction.java
@@ -98,9 +98,8 @@ public class SearchMembersAction implements OrganizationsWsAction {
public void handle(Request request, Response response) throws Exception {
try (DbSession dbSession = dbClient.openSession(false)) {
OrganizationDto organization = getOrganization(dbSession, request.param("organization"));
- List<String> memberLogins = dbClient.organizationMemberDao().selectLoginsByOrganizationUuid(dbSession, organization.getUuid());
- UserQuery.Builder userQuery = buildUserQuery(request, memberLogins);
+ UserQuery.Builder userQuery = buildUserQuery(request, organization);
SearchOptions searchOptions = buildSearchOptions(request);
SearchResult<UserDoc> searchResults = userIndex.search(userQuery.build(), searchOptions);
@@ -143,7 +142,7 @@ public class SearchMembersAction implements OrganizationsWsAction {
return response.build();
}
- private static UserQuery.Builder buildUserQuery(Request request, List<String> memberLogins) {
+ private static UserQuery.Builder buildUserQuery(Request request, OrganizationDto organization) {
UserQuery.Builder userQuery = UserQuery.builder();
String textQuery = request.param(Param.TEXT_QUERY);
checkArgument(textQuery == null || textQuery.length() >= 2, "Query length must be greater than or equal to 2");
@@ -151,9 +150,9 @@ public class SearchMembersAction implements OrganizationsWsAction {
SelectionMode selectionMode = SelectionMode.fromParam(request.mandatoryParam(Param.SELECTED));
if (SelectionMode.DESELECTED.equals(selectionMode)) {
- userQuery.setExcludedLogins(memberLogins);
+ userQuery.setExcludedOrganizationUuid(organization.getUuid());
} else {
- userQuery.setLogins(memberLogins);
+ userQuery.setOrganizationUuid(organization.getUuid());
}
return userQuery;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserDoc.java b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserDoc.java
index c1ad19d6322..1b7591d0f55 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserDoc.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserDoc.java
@@ -27,6 +27,8 @@ import javax.annotation.Nullable;
import org.sonar.api.user.User;
import org.sonar.server.es.BaseDoc;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_ORGANIZATION_UUIDS;
+
public class UserDoc extends BaseDoc implements User {
public UserDoc(Map<String, Object> fields) {
@@ -77,6 +79,10 @@ public class UserDoc extends BaseDoc implements User {
return getField(UserIndexDefinition.FIELD_SCM_ACCOUNTS);
}
+ public List<String> organizationUuids() {
+ return getField(FIELD_ORGANIZATION_UUIDS);
+ }
+
public long createdAt() {
return getFieldAsDate(UserIndexDefinition.FIELD_CREATED_AT).getTime();
}
@@ -110,6 +116,11 @@ public class UserDoc extends BaseDoc implements User {
return this;
}
+ public UserDoc setOrganizationUuids(@Nullable List<String> organizationUuids) {
+ setField(FIELD_ORGANIZATION_UUIDS, organizationUuids);
+ return this;
+ }
+
public UserDoc setCreatedAt(long l) {
setField(UserIndexDefinition.FIELD_CREATED_AT, new Date(l));
return this;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndex.java b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndex.java
index a3a17feb13d..6961dfffabf 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndex.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndex.java
@@ -57,6 +57,7 @@ import static org.sonar.server.user.index.UserIndexDefinition.FIELD_ACTIVE;
import static org.sonar.server.user.index.UserIndexDefinition.FIELD_EMAIL;
import static org.sonar.server.user.index.UserIndexDefinition.FIELD_LOGIN;
import static org.sonar.server.user.index.UserIndexDefinition.FIELD_NAME;
+import static org.sonar.server.user.index.UserIndexDefinition.FIELD_ORGANIZATION_UUIDS;
import static org.sonar.server.user.index.UserIndexDefinition.FIELD_SCM_ACCOUNTS;
@ServerSide
@@ -140,12 +141,10 @@ public class UserIndex {
.addSort(FIELD_NAME, SortOrder.ASC);
BoolQueryBuilder filter = boolQuery().must(termQuery(FIELD_ACTIVE, true));
-
- userQuery.getLogins().ifPresent(
- logins -> filter.must(termsQuery(FIELD_LOGIN, userQuery.getLogins().get())));
-
- userQuery.getExcludedLogins().ifPresent(
- excludedLogins -> filter.mustNot(termsQuery(FIELD_LOGIN, userQuery.getExcludedLogins().get())));
+ userQuery.getOrganizationUuid()
+ .ifPresent(o -> filter.must(termQuery(FIELD_ORGANIZATION_UUIDS, o)));
+ userQuery.getExcludedOrganizationUuid()
+ .ifPresent(o -> filter.mustNot(termQuery(FIELD_ORGANIZATION_UUIDS, o)));
QueryBuilder esQuery = matchAllQuery();
Optional<String> textQuery = userQuery.getTextQuery();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexDefinition.java b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexDefinition.java
index 68777d84338..ace94fdfac9 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexDefinition.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexDefinition.java
@@ -40,6 +40,7 @@ public class UserIndexDefinition implements IndexDefinition {
public static final String FIELD_UPDATED_AT = "updatedAt";
public static final String FIELD_ACTIVE = "active";
public static final String FIELD_SCM_ACCOUNTS = "scmAccounts";
+ public static final String FIELD_ORGANIZATION_UUIDS = "organizationUuids";
private final Settings settings;
@@ -62,5 +63,6 @@ public class UserIndexDefinition implements IndexDefinition {
mapping.createDateTimeField(FIELD_UPDATED_AT);
mapping.createBooleanField(FIELD_ACTIVE);
mapping.stringFieldBuilder(FIELD_SCM_ACCOUNTS).disableNorms().build();
+ mapping.stringFieldBuilder(FIELD_ORGANIZATION_UUIDS).disableNorms().build();
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexer.java
index edac71f8fdc..34c906db284 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexer.java
@@ -52,12 +52,12 @@ public class UserIndexer implements StartupIndexer {
@Override
public void indexOnStartup(Set<IndexType> emptyIndexTypes) {
- doIndex(null, Size.REGULAR);
+ doIndex(null, Size.LARGE);
}
public void index(String login) {
requireNonNull(login);
- doIndex(login, Size.LARGE);
+ doIndex(login, Size.REGULAR);
}
private void doIndex(@Nullable String login, Size bulkSize) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserQuery.java b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserQuery.java
index 9ff05e694ce..5b5ebda4dc9 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserQuery.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserQuery.java
@@ -20,8 +20,6 @@
package org.sonar.server.user.index;
-import com.google.common.collect.ImmutableList;
-import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@@ -31,25 +29,25 @@ import static org.apache.commons.lang.StringUtils.isBlank;
@Immutable
public class UserQuery {
private final String textQuery;
- private final List<String> logins;
- private final List<String> excludedLogins;
+ private final String organizationUuid;
+ private final String excludedOrganizationUuid;
private UserQuery(Builder builder) {
this.textQuery = builder.textQuery;
- this.logins = builder.logins == null ? null : ImmutableList.copyOf(builder.logins);
- this.excludedLogins = builder.excludedLogins == null ? null : ImmutableList.copyOf(builder.excludedLogins);
+ this.organizationUuid = builder.organizationUuid;
+ this.excludedOrganizationUuid = builder.excludedOrganizationUuid;
}
public Optional<String> getTextQuery() {
return Optional.ofNullable(textQuery);
}
- public Optional<List<String>> getLogins() {
- return Optional.ofNullable(logins);
+ public Optional<String> getOrganizationUuid() {
+ return Optional.ofNullable(organizationUuid);
}
- public Optional<List<String>> getExcludedLogins() {
- return Optional.ofNullable(excludedLogins);
+ public Optional<String> getExcludedOrganizationUuid() {
+ return Optional.ofNullable(excludedOrganizationUuid);
}
public static Builder builder() {
@@ -58,8 +56,8 @@ public class UserQuery {
public static class Builder {
private String textQuery;
- private List<String> logins;
- private List<String> excludedLogins;
+ private String organizationUuid;
+ private String excludedOrganizationUuid;
private Builder() {
// enforce factory method
@@ -74,13 +72,19 @@ public class UserQuery {
return this;
}
- public Builder setLogins(@Nullable List<String> logins) {
- this.logins = logins;
+ /**
+ * Include only users that are members of the organizationUuid
+ */
+ public Builder setOrganizationUuid(@Nullable String organizationUuid) {
+ this.organizationUuid = organizationUuid;
return this;
}
- public Builder setExcludedLogins(@Nullable List<String> excludedLogins) {
- this.excludedLogins = excludedLogins;
+ /**
+ * Include only users that are not members of the excludedOrganizationUuid
+ */
+ public Builder setExcludedOrganizationUuid(@Nullable String excludedOrganizationUuid) {
+ this.excludedOrganizationUuid = excludedOrganizationUuid;
return this;
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserResultSetIterator.java b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserResultSetIterator.java
index 48a0177b867..f2876942d74 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/user/index/UserResultSetIterator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/user/index/UserResultSetIterator.java
@@ -19,6 +19,8 @@
*/
package org.sonar.server.user.index;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -30,6 +32,8 @@ import org.sonar.db.DbSession;
import org.sonar.db.ResultSetIterator;
import org.sonar.db.user.UserDto;
+import static java.util.Collections.singletonList;
+
/**
* Scrolls over table USERS and reads documents to populate the user index
*/
@@ -47,11 +51,13 @@ class UserResultSetIterator extends ResultSetIterator<UserDoc> {
};
private static final String SQL_ALL = "select " + StringUtils.join(FIELDS, ",") + " from users u ";
-
private static final String LOGIN_FILTER = " WHERE u.login=?";
- private UserResultSetIterator(PreparedStatement stmt) throws SQLException {
+ private final ListMultimap<String, String> organizationUuidsByLogins;
+
+ private UserResultSetIterator(PreparedStatement stmt, ListMultimap<String, String> organizationUuidsByLogins) throws SQLException {
super(stmt);
+ this.organizationUuidsByLogins = organizationUuidsByLogins;
}
static UserResultSetIterator create(DbClient dbClient, DbSession session, @Nullable String login) {
@@ -59,7 +65,15 @@ class UserResultSetIterator extends ResultSetIterator<UserDoc> {
String sql = createSql(login);
PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(session, sql);
setParameter(stmt, login);
- return new UserResultSetIterator(stmt);
+
+ ListMultimap<String, String> organizationUuidsByLogin = ArrayListMultimap.create();
+ if (login == null) {
+ dbClient.organizationMemberDao().selectAllForUserIndexing(session, organizationUuidsByLogin::put);
+ } else {
+ dbClient.organizationMemberDao().selectForUserIndexing(session, singletonList(login), organizationUuidsByLogin::put);
+ }
+
+ return new UserResultSetIterator(stmt, organizationUuidsByLogin);
} catch (SQLException e) {
throw new IllegalStateException("Fail to prepare SQL request to select all users", e);
}
@@ -79,7 +93,7 @@ class UserResultSetIterator extends ResultSetIterator<UserDoc> {
@Override
protected UserDoc read(ResultSet rs) throws SQLException {
- UserDoc doc = new UserDoc(Maps.<String, Object>newHashMapWithExpectedSize(7));
+ UserDoc doc = new UserDoc(Maps.newHashMapWithExpectedSize(8));
String login = rs.getString(1);
@@ -91,6 +105,7 @@ class UserResultSetIterator extends ResultSetIterator<UserDoc> {
doc.setScmAccounts(UserDto.decodeScmAccounts(rs.getString(5)));
doc.setCreatedAt(rs.getLong(6));
doc.setUpdatedAt(rs.getLong(7));
+ doc.setOrganizationUuids(organizationUuidsByLogins.get(login));
return doc;
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/SearchMembersActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/SearchMembersActionTest.java
index 1e61a2718a8..1c99f943686 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/SearchMembersActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/SearchMembersActionTest.java
@@ -90,12 +90,13 @@ public class SearchMembersActionTest {
public void search_members_of_default_organization() {
OrganizationDto defaultOrganization = db.getDefaultOrganization();
OrganizationDto anotherOrganization = db.organizations().insert();
- UserDto user = insertUser();
- UserDto anotherUser = insertUser();
- UserDto userInAnotherOrganization = insertUser();
+ UserDto user = db.users().insertUser();
+ UserDto anotherUser = db.users().insertUser();
+ UserDto userInAnotherOrganization = db.users().insertUser();
db.organizations().addMember(defaultOrganization, user);
db.organizations().addMember(defaultOrganization, anotherUser);
db.organizations().addMember(anotherOrganization, userInAnotherOrganization);
+ indexAllUsers();
SearchMembersWsResponse result = call();
@@ -110,12 +111,13 @@ public class SearchMembersActionTest {
public void search_members_of_specified_organization() {
OrganizationDto organization = db.organizations().insert();
OrganizationDto anotherOrganization = db.organizations().insert();
- UserDto user = insertUser();
- UserDto anotherUser = insertUser();
- UserDto userInAnotherOrganization = insertUser();
+ UserDto user = db.users().insertUser();
+ UserDto anotherUser = db.users().insertUser();
+ UserDto userInAnotherOrganization = db.users().insertUser();
db.organizations().addMember(organization, user);
db.organizations().addMember(organization, anotherUser);
db.organizations().addMember(anotherOrganization, userInAnotherOrganization);
+ indexAllUsers();
request.setOrganization(organization.getKey());
SearchMembersWsResponse result = call();
@@ -130,8 +132,8 @@ public class SearchMembersActionTest {
@Test
public void return_avatar() {
UserDto user = db.users().insertUser(u -> u.setEmail("email@domain.com"));
- indexer.index(user.getLogin());
db.organizations().addMember(db.getDefaultOrganization(), user);
+ indexer.index(user.getLogin());
SearchMembersWsResponse result = call();
@@ -140,10 +142,11 @@ public class SearchMembersActionTest {
@Test
public void do_not_return_group_count_if_no_admin_permission() {
- UserDto user = insertUser();
+ UserDto user = db.users().insertUser();
GroupDto group = db.users().insertGroup();
db.users().insertMember(group, user);
db.organizations().addMember(db.getDefaultOrganization(), user);
+ indexAllUsers();
SearchMembersWsResponse result = call();
@@ -153,8 +156,8 @@ public class SearchMembersActionTest {
@Test
public void return_group_counts_if_org_admin() {
userSession.addPermission(OrganizationPermission.ADMINISTER, db.getDefaultOrganization());
- UserDto user = insertUser();
- UserDto anotherUser = insertUser();
+ UserDto user = db.users().insertUser();
+ UserDto anotherUser = db.users().insertUser();
IntStream.range(0, 10)
.mapToObj(i -> db.users().insertGroup())
.forEach(g -> db.users().insertMembers(g, user));
@@ -164,6 +167,7 @@ public class SearchMembersActionTest {
db.organizations().addMember(db.getDefaultOrganization(), user);
db.organizations().addMember(db.getDefaultOrganization(), anotherUser);
db.organizations().addMember(anotherOrganization, user);
+ indexAllUsers();
SearchMembersWsResponse result = call();
@@ -176,12 +180,13 @@ public class SearchMembersActionTest {
public void search_non_members() {
OrganizationDto defaultOrganization = db.getDefaultOrganization();
OrganizationDto anotherOrganization = db.organizations().insert();
- UserDto user = insertUser();
- UserDto anotherUser = insertUser();
- UserDto userInAnotherOrganization = insertUser();
+ UserDto user = db.users().insertUser();
+ UserDto anotherUser = db.users().insertUser();
+ UserDto userInAnotherOrganization = db.users().insertUser();
db.organizations().addMember(anotherOrganization, user);
db.organizations().addMember(anotherOrganization, anotherUser);
db.organizations().addMember(defaultOrganization, userInAnotherOrganization);
+ indexAllUsers();
request.setSelected(WebService.SelectionMode.DESELECTED.value());
SearchMembersWsResponse result = call();
@@ -200,6 +205,7 @@ public class SearchMembersActionTest {
db.organizations().addMember(db.getDefaultOrganization(), userDto);
indexer.index(userDto.getLogin());
});
+ indexAllUsers();
request.setPage(2).setPageSize(3);
SearchMembersWsResponse result = call();
@@ -218,6 +224,7 @@ public class SearchMembersActionTest {
db.organizations().addMember(db.getDefaultOrganization(), userDto);
indexer.index(userDto.getLogin());
});
+ indexAllUsers();
request.setQuery("_9");
SearchMembersWsResponse result = call();
@@ -232,6 +239,7 @@ public class SearchMembersActionTest {
db.organizations().addMember(db.getDefaultOrganization(), userDto);
indexer.index(userDto.getLogin());
});
+ indexAllUsers();
request.setQuery("_9");
SearchMembersWsResponse result = call();
@@ -248,6 +256,7 @@ public class SearchMembersActionTest {
db.organizations().addMember(db.getDefaultOrganization(), userDto);
indexer.index(userDto.getLogin());
});
+ indexAllUsers();
request.setQuery("_9");
SearchMembersWsResponse result = call();
@@ -263,6 +272,7 @@ public class SearchMembersActionTest {
indexer.index(grace.getLogin());
db.organizations().addMember(db.getDefaultOrganization(), ada);
db.organizations().addMember(db.getDefaultOrganization(), grace);
+ indexAllUsers();
String result = ws.newRequest().execute().getInput();
@@ -318,11 +328,8 @@ public class SearchMembersActionTest {
assertThat(selected.defaultValue()).isEqualTo("selected");
}
- private UserDto insertUser() {
- UserDto userDto = db.users().insertUser();
- indexer.index(userDto.getLogin());
-
- return userDto;
+ private void indexAllUsers() {
+ indexer.indexOnStartup(indexer.getIndexTypes());
}
private SearchMembersWsResponse call() {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexDefinitionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexDefinitionTest.java
index 0687a43c4e6..f6e7776b053 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexDefinitionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexDefinitionTest.java
@@ -28,7 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class UserIndexDefinitionTest {
- IndexDefinition.IndexDefinitionContext underTest = new IndexDefinition.IndexDefinitionContext();
+ private IndexDefinition.IndexDefinitionContext underTest = new IndexDefinition.IndexDefinitionContext();
@Test
public void define() {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexTest.java
index b3a257f6cac..1159085b851 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexTest.java
@@ -28,11 +28,10 @@ import org.junit.Test;
import org.sonar.api.config.MapSettings;
import org.sonar.server.es.EsTester;
import org.sonar.server.es.SearchOptions;
-import org.sonar.server.es.SearchResult;
+import static com.google.common.collect.Lists.newArrayList;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.user.index.UserIndexDefinition.INDEX_TYPE_USER;
@@ -144,36 +143,27 @@ public class UserIndexTest {
}
@Test
- public void search_users_filter_logins() throws Exception {
- esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser(USER1_LOGIN, asList("user_1", "u1")).setEmail("email1"));
- esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser(USER2_LOGIN, emptyList()).setEmail("email2"));
- esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser("user3", emptyList()).setEmail("email2"));
-
- SearchResult<UserDoc> result = underTest.search(userQuery.setLogins(asList(USER1_LOGIN, USER2_LOGIN)).build(), new SearchOptions());
- assertThat(result.getDocs()).hasSize(2)
- .extracting(UserDoc::login)
- .containsOnly(USER1_LOGIN, USER2_LOGIN);
- }
-
- @Test
- public void search_users_filter_logins_that_match_exactly() {
- esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser("USER_1", asList("user_1", "u1")).setEmail("email1"));
- esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser("UsEr_1", emptyList()).setEmail("email2"));
-
- assertThat(underTest.search(userQuery.setLogins(singletonList("USER_1")).build(), new SearchOptions()).getDocs()).hasSize(1);
- assertThat(underTest.search(userQuery.setLogins(singletonList("USER_")).build(), new SearchOptions()).getDocs()).isEmpty();
- assertThat(underTest.search(userQuery.setLogins(emptyList()).build(), new SearchOptions()).getDocs()).isEmpty();
+ public void search_users_filter_by_organization_uuid() {
+ esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser(USER1_LOGIN, asList("user_1", "u1")).setEmail("email1")
+ .setOrganizationUuids(newArrayList("O1", "O2")));
+ esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser(USER2_LOGIN, emptyList()).setEmail("email2")
+ .setOrganizationUuids(newArrayList("O2")));
+
+ assertThat(underTest.search(userQuery.setOrganizationUuid("O42").build(), new SearchOptions()).getDocs()).isEmpty();
+ assertThat(underTest.search(userQuery.setOrganizationUuid("O2").build(), new SearchOptions()).getDocs()).hasSize(2);
+ assertThat(underTest.search(userQuery.setOrganizationUuid("O1").build(), new SearchOptions()).getDocs()).hasSize(1);
}
@Test
- public void search_users_exclude_logins() throws Exception {
- esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser(USER1_LOGIN, asList("user_1", "u1")).setEmail("email1"));
- esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser(USER2_LOGIN, emptyList()).setEmail("email2"));
- esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser("user3", emptyList()).setEmail("email2"));
-
- assertThat(underTest.search(userQuery.setExcludedLogins(emptyList()).build(), new SearchOptions()).getDocs()).hasSize(3);
- assertThat(underTest.search(userQuery.setExcludedLogins(asList(USER1_LOGIN, USER2_LOGIN, "user3")).build(), new SearchOptions()).getDocs()).isEmpty();
- assertThat(underTest.search(userQuery.setExcludedLogins(asList(USER1_LOGIN, USER2_LOGIN)).build(), new SearchOptions()).getDocs()).hasSize(1);
+ public void search_users_filter_by_excluded_organization_uuid() {
+ esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser(USER1_LOGIN, asList("user_1", "u1")).setEmail("email1")
+ .setOrganizationUuids(newArrayList("O1", "O2")));
+ esTester.putDocuments(INDEX_TYPE_USER.getIndex(), INDEX_TYPE_USER.getType(), newUser(USER2_LOGIN, emptyList()).setEmail("email2")
+ .setOrganizationUuids(newArrayList("O2")));
+
+ assertThat(underTest.search(userQuery.setExcludedOrganizationUuid("O42").build(), new SearchOptions()).getDocs()).hasSize(2);
+ assertThat(underTest.search(userQuery.setExcludedOrganizationUuid("O2").build(), new SearchOptions()).getDocs()).isEmpty();
+ assertThat(underTest.search(userQuery.setExcludedOrganizationUuid("O1").build(), new SearchOptions()).getDocs()).hasSize(1);
}
private static UserDoc newUser(String login, List<String> scmAccounts) {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexerTest.java
index a293caee01d..8f9230c55ee 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexerTest.java
@@ -35,26 +35,26 @@ public class UserIndexerTest {
private System2 system2 = System2.INSTANCE;
@Rule
- public DbTester dbTester = DbTester.create(system2);
+ public DbTester db = DbTester.create(system2);
@Rule
- public EsTester esTester = new EsTester(new UserIndexDefinition(new MapSettings()));
+ public EsTester es = new EsTester(new UserIndexDefinition(new MapSettings()));
@Test
public void index_nothing() {
UserIndexer indexer = createIndexer();
indexer.indexOnStartup(null);
- assertThat(esTester.countDocuments(UserIndexDefinition.INDEX_TYPE_USER)).isEqualTo(0L);
+ assertThat(es.countDocuments(UserIndexDefinition.INDEX_TYPE_USER)).isEqualTo(0L);
}
@Test
public void index_everything() {
- dbTester.prepareDbUnit(getClass(), "index.xml");
+ db.prepareDbUnit(getClass(), "index.xml");
UserIndexer indexer = createIndexer();
indexer.indexOnStartup(null);
- List<UserDoc> docs = esTester.getDocuments(UserIndexDefinition.INDEX_TYPE_USER, UserDoc.class);
+ List<UserDoc> docs = es.getDocuments(UserIndexDefinition.INDEX_TYPE_USER, UserDoc.class);
assertThat(docs).hasSize(1);
UserDoc doc = docs.get(0);
assertThat(doc.login()).isEqualTo("user1");
@@ -68,17 +68,17 @@ public class UserIndexerTest {
@Test
public void index_single_user() {
- UserDto user = dbTester.users().insertUser();
+ UserDto user = db.users().insertUser();
UserIndexer indexer = createIndexer();
indexer.indexOnStartup(null);
- List<UserDoc> docs = esTester.getDocuments(UserIndexDefinition.INDEX_TYPE_USER, UserDoc.class);
+ List<UserDoc> docs = es.getDocuments(UserIndexDefinition.INDEX_TYPE_USER, UserDoc.class);
assertThat(docs).hasSize(1);
assertThat(docs).extracting(UserDoc::login).containsExactly(user.getLogin());
}
private UserIndexer createIndexer() {
- return new UserIndexer(dbTester.getDbClient(), esTester.client());
+ return new UserIndexer(db.getDbClient(), es.client());
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/index/UserResultSetIteratorTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/index/UserResultSetIteratorTest.java
index 10171f211ea..c2271a768ca 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/user/index/UserResultSetIteratorTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/user/index/UserResultSetIteratorTest.java
@@ -19,31 +19,54 @@
*/
package org.sonar.server.user.index;
-import com.google.common.base.Function;
import com.google.common.collect.Maps;
+import java.util.Arrays;
import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
-import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.user.UserDto;
import static org.assertj.core.api.Assertions.assertThat;
public class UserResultSetIteratorTest {
@Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
+ public DbTester db = DbTester.create();
@Test
public void iterator_over_users() {
- dbTester.prepareDbUnit(getClass(), "shared.xml");
- UserResultSetIterator it = UserResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), null);
- Map<String, UserDoc> usersByLogin = Maps.uniqueIndex(it, new Function<UserDoc, String>() {
- @Override
- public String apply(UserDoc user) {
- return user.login();
- }
- });
+ UserDto userDto1 = db.users().insertUser(u -> u
+ .setName("User1")
+ .setLogin("user1")
+ .setEmail("user1@mail.com")
+ .setScmAccounts(Arrays.asList("user_1", "u1"))
+ .setCreatedAt(1_500_000_000_000L)
+ .setUpdatedAt(1_500_000_000_000L));
+ UserDto userDto2 = db.users().insertUser(u -> u
+ .setName("User2")
+ .setLogin("user2")
+ .setEmail("user2@mail.com")
+ .setScmAccounts(Arrays.asList("user,2", "user_2"))
+ .setCreatedAt(1_500_000_000_000L)
+ .setUpdatedAt(1_500_000_000_000L));
+ UserDto userDto3 = db.users().insertUser(u -> u
+ .setName("User3")
+ .setLogin("user3")
+ .setEmail(null)
+ .setActive(false)
+ .setScmAccounts((String) null)
+ .setCreatedAt(1_500_000_000_000L)
+ .setUpdatedAt(1_550_000_000_000L));
+ OrganizationDto org1 = db.organizations().insertForUuid("ORG_1");
+ OrganizationDto org2 = db.organizations().insertForUuid("ORG_2");
+ db.organizations().addMember(org1, userDto1);
+ db.organizations().addMember(org1, userDto2);
+ db.organizations().addMember(org2, userDto1);
+
+ UserResultSetIterator it = UserResultSetIterator.create(db.getDbClient(), db.getSession(), null);
+ Map<String, UserDoc> usersByLogin = Maps.uniqueIndex(it, UserDoc::login);
it.close();
assertThat(usersByLogin).hasSize(3);
@@ -53,16 +76,18 @@ public class UserResultSetIteratorTest {
assertThat(user1.email()).isEqualTo("user1@mail.com");
assertThat(user1.active()).isTrue();
assertThat(user1.scmAccounts()).containsOnly("user_1", "u1");
- assertThat(user1.createdAt()).isEqualTo(1500000000000L);
- assertThat(user1.updatedAt()).isEqualTo(1500000000000L);
+ assertThat(user1.createdAt()).isEqualTo(1_500_000_000_000L);
+ assertThat(user1.updatedAt()).isEqualTo(1_500_000_000_000L);
+ assertThat(user1.organizationUuids()).containsOnly("ORG_1", "ORG_2");
UserDoc user2 = usersByLogin.get("user2");
assertThat(user2.name()).isEqualTo("User2");
assertThat(user2.email()).isEqualTo("user2@mail.com");
assertThat(user2.active()).isTrue();
assertThat(user2.scmAccounts()).containsOnly("user,2", "user_2");
- assertThat(user2.createdAt()).isEqualTo(1500000000000L);
- assertThat(user2.updatedAt()).isEqualTo(1500000000000L);
+ assertThat(user2.createdAt()).isEqualTo(1_500_000_000_000L);
+ assertThat(user2.updatedAt()).isEqualTo(1_500_000_000_000L);
+ assertThat(user2.organizationUuids()).containsOnly("ORG_1");
UserDoc user3 = usersByLogin.get("user3");
assertThat(user3.name()).isEqualTo("User3");
@@ -71,5 +96,6 @@ public class UserResultSetIteratorTest {
assertThat(user3.scmAccounts()).isEmpty();
assertThat(user3.createdAt()).isEqualTo(1500000000000L);
assertThat(user3.updatedAt()).isEqualTo(1550000000000L);
+ assertThat(user3.organizationUuids()).isEmpty();
}
}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/index/UserResultSetIteratorTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/user/index/UserResultSetIteratorTest/shared.xml
deleted file mode 100644
index 6af8bdfcb84..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/user/index/UserResultSetIteratorTest/shared.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<dataset>
-
- <users id="1"
- login="user1"
- name="User1"
- email="user1@mail.com"
- active="[true]"
- scm_accounts="&#10;user_1&#10;u1&#10;"
- created_at="1500000000000"
- updated_at="1500000000000"
- is_root="[false]"/>
-
- <!-- scm accounts with comma -->
- <users id="2"
- login="user2"
- name="User2"
- email="user2@mail.com"
- active="[true]"
- scm_accounts="&#10;user,2&#10;user_2&#10;"
- created_at="1500000000000"
- updated_at="1500000000000"
- is_root="[false]"/>
-
- <!--no scm account, no email -->
- <users id="3"
- login="user3"
- name="User3"
- email="[null]"
- active="[false]"
- scm_accounts="[null]"
- created_at="1500000000000"
- updated_at="1550000000000"
- is_root="[false]"/>
-
-</dataset>