diff options
author | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2017-03-21 18:02:22 +0100 |
---|---|---|
committer | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2017-03-24 17:38:53 +0100 |
commit | 4d444b9e946325b8e3f7e4a91fe3fb21cf0272ff (patch) | |
tree | 7cadf9092bb50b0f5da469f5b6e8cdbdb75cc8ac /server | |
parent | 515da3680100ab023c69a99faf2028f12cbd4492 (diff) | |
download | sonarqube-4d444b9e946325b8e3f7e4a91fe3fb21cf0272ff.tar.gz sonarqube-4d444b9e946325b8e3f7e4a91fe3fb21cf0272ff.zip |
SONAR-8980 Index organizations when indexing a user
Diffstat (limited to 'server')
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=" user_1 u1 " - 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=" user,2 user_2 " - 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> |