import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
private static final String FIELD_NAME = "name";
private static final String FIELD_EMAIL = "email";
private static final String FIELD_SCM_ACCOUNTS = "scmAccounts";
- private static final String FIELD_GROUPS_COUNT = "groupsCount";
- private static final Set<String> FIELDS = ImmutableSet.of(FIELD_LOGIN, FIELD_NAME, FIELD_EMAIL, FIELD_SCM_ACCOUNTS, FIELD_GROUPS_COUNT);
+ private static final String FIELD_GROUPS = "groups";
+ private static final Set<String> FIELDS = ImmutableSet.of(FIELD_LOGIN, FIELD_NAME, FIELD_EMAIL, FIELD_SCM_ACCOUNTS, FIELD_GROUPS);
private final UserIndex userIndex;
private final DbClient dbClient;
List<String> fields = request.paramAsStrings(Param.FIELDS);
SearchResult<UserDoc> result = userIndex.search(request.param(Param.TEXT_QUERY), options);
- Map<String, Integer> groupsByLogin = Maps.newHashMap();
+ Multimap<String, String> groupsByLogin = Multimaps.forMap(Maps.<String, String>newHashMap());
DbSession session = dbClient.openSession(false);
try {
Collection<String> logins = Collections2.transform(result.getDocs(), new Function<UserDoc, String>() {
return input.login();
}
});
- groupsByLogin = dbClient.groupMembershipDao().countGroupsByLogins(session, logins);
+ groupsByLogin = dbClient.groupMembershipDao().selectGroupsByLogins(session, logins);
} finally {
session.close();
}
json.endObject().close();
}
- private void writeUsers(JsonWriter json, SearchResult<UserDoc> result, @Nullable List<String> fields, Map<String, Integer> groupsByLogin) {
+ private void writeUsers(JsonWriter json, SearchResult<UserDoc> result, @Nullable List<String> fields, Multimap<String, String> groupsByLogin) {
json.name("users").beginArray();
for (UserDoc user : result.getDocs()) {
writeIfNeeded(json, user.login(), FIELD_LOGIN, fields);
writeIfNeeded(json, user.name(), FIELD_NAME, fields);
writeIfNeeded(json, user.email(), FIELD_EMAIL, fields);
- writeIfNeeded(json, groupsByLogin.get(user.login()), FIELD_GROUPS_COUNT, fields);
+ writeGroupsIfNeeded(json, groupsByLogin.get(user.login()), fields);
if (fieldIsWanted(FIELD_SCM_ACCOUNTS, fields)) {
json.name(FIELD_SCM_ACCOUNTS)
.beginArray()
}
}
- private void writeIfNeeded(JsonWriter json, Integer value, String field, @Nullable List<String> fields) {
- if (fieldIsWanted(field, fields)) {
- json.prop(field, value);
+ private void writeGroupsIfNeeded(JsonWriter json, Collection<String> groups, @Nullable List<String> fields) {
+ if (fieldIsWanted(FIELD_GROUPS, fields)) {
+ json.name(FIELD_GROUPS).beginArray();
+ for (String groupName : groups) {
+ json.value(groupName);
+ }
+ json.endArray();
}
}
"login": "fmallet",
"name": "Freddy Mallet",
"active": true,
- "email": "f@m.com"
+ "email": "f@m.com",
+ "scmAccounts": [],
+ "groups": ["sonar-users", "sonar-administrators"]
},
{
"login": "sbrandhof",
"name": "Simon",
"active": true,
- "scmAccounts": ["simon.brandhof", "s.brandhof@company.tld"]
+ "email": "s.brandhof@company.tld",
+ "scmAccounts": ["simon.brandhof", "s.brandhof@company.tld"],
+ "groups": ["sonar-users"]
}
]
}
.contains("name")
.contains("email")
.contains("scmAccounts")
- .contains("groupsCount");
+ .contains("groups");
assertThat(tester.newGetRequest("api/users", "search").setParam("f", "").execute().outputAsString())
.contains("login")
.contains("name")
.contains("email")
.contains("scmAccounts")
- .contains("groupsCount");
+ .contains("groups");
assertThat(tester.newGetRequest("api/users", "search").setParam("f", "login").execute().outputAsString())
.contains("login")
.doesNotContain("name")
.doesNotContain("email")
.doesNotContain("scmAccounts")
- .doesNotContain("groupsCount");
+ .doesNotContain("groups");
assertThat(tester.newGetRequest("api/users", "search").setParam("f", "scmAccounts").execute().outputAsString())
.doesNotContain("login")
.doesNotContain("name")
.doesNotContain("email")
.contains("scmAccounts")
- .doesNotContain("groupsCount");
+ .doesNotContain("groups");
- assertThat(tester.newGetRequest("api/users", "search").setParam("f", "groupsCount").execute().outputAsString())
+ assertThat(tester.newGetRequest("api/users", "search").setParam("f", "groups").execute().outputAsString())
.doesNotContain("login")
.doesNotContain("name")
.doesNotContain("email")
.doesNotContain("scmAccounts")
- .contains("groupsCount");
+ .contains("groups");
}
@Test
"scmAccounts": [
"user-0"
],
- "groupsCount": 0
+ "groups": []
},
{
"login": "user-1",
"scmAccounts": [
"user-1"
],
- "groupsCount": 0
+ "groups": []
},
{
"login": "user-2",
"scmAccounts": [
"user-2"
],
- "groupsCount": 0
+ "groups": []
},
{
"login": "user-3",
"scmAccounts": [
"user-3"
],
- "groupsCount": 0
+ "groups": []
},
{
"login": "user-4",
"scmAccounts": [
"user-4"
],
- "groupsCount": 0
+ "groups": []
}
]
}
"scmAccounts": [
"user-0"
],
- "groupsCount": 2
+ "groups": ["sonar-admins", "sonar-users"]
}
]
}
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
+import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.List;
import java.util.Map;
return result;
}
- public Map<String, Integer> countGroupsByLogins(final DbSession session, Collection<String> logins) {
- final Map<String, Integer> result = Maps.newHashMap();
- DaoUtils.executeLargeInputs(logins, new NonNullInputFunction<List<String>, List<UserGroupCount>>() {
+ public Multimap<String, String> selectGroupsByLogins(final DbSession session, Collection<String> logins) {
+ final Multimap<String, String> result = ArrayListMultimap.create();
+ DaoUtils.executeLargeInputs(logins, new NonNullInputFunction<List<String>, List<LoginGroup>>() {
@Override
- protected List<UserGroupCount> doApply(List<String> input) {
- List<UserGroupCount> groupCounts = mapper(session).countGroupsByLogins(input);
- for (UserGroupCount count : groupCounts) {
- result.put(count.login(), count.groupCount());
+ protected List<LoginGroup> doApply(List<String> input) {
+ List<LoginGroup> groupMemberships = mapper(session).selectGroupsByLogins(input);
+ for (LoginGroup membership : groupMemberships) {
+ result.put(membership.login(), membership.groupName());
}
- return groupCounts;
+ return groupMemberships;
}
});
List<GroupUserCount> countUsersByGroup(@Param("groupIds") List<Long> groupIds);
- List<UserGroupCount> countGroupsByLogins(@Param("logins") List<String> logins);
+ List<LoginGroup> selectGroupsByLogins(@Param("logins") List<String> logins);
}
--- /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;
+
+public class LoginGroup {
+
+ private String login;
+ private String groupName;
+
+ public String login() {
+ return login;
+ }
+
+ public String groupName() {
+ return groupName;
+ }
+}
+++ /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;
-
-public class UserGroupCount {
-
- private String login;
- private int groupCount;
-
- public String login() {
- return login;
- }
-
- public int groupCount() {
- return groupCount;
- }
-}
\ No newline at end of file
GROUP BY g.name
</select>
- <select id="countGroupsByLogins" parameterType="string" resultType="org.sonar.core.user.UserGroupCount">
- SELECT u.login as login, count(gu.user_id) as groupCount
+ <select id="selectGroupsByLogins" parameterType="string" resultType="org.sonar.core.user.LoginGroup">
+ SELECT u.login as login, g.name as groupName
FROM users u
LEFT JOIN groups_users gu ON gu.user_id=u.id
+ INNER JOIN groups g ON gu.group_id=g.id
<where>
u.login in
<foreach collection="logins" open="(" close=")" item="login" separator=",">
#{login}
</foreach>
</where>
- GROUP BY u.login
</select>
</mapper>
package org.sonar.core.user;
+import com.google.common.collect.Multimap;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
DbSession session = dbTester.myBatis().openSession(false);
try {
- assertThat(dao.countGroupsByLogins(session, Arrays.<String>asList())).isEmpty();
- assertThat(dao.countGroupsByLogins(session, Arrays.asList("two-hundred")))
- .containsExactly(entry("two-hundred", 3));
- assertThat(dao.countGroupsByLogins(session, Arrays.asList("two-hundred", "two-hundred-one")))
- .containsOnly(entry("two-hundred", 3), entry("two-hundred-one", 1));
- assertThat(dao.countGroupsByLogins(session, Arrays.asList("two-hundred", "two-hundred-one", "two-hundred-two")))
- .containsOnly(entry("two-hundred", 3), entry("two-hundred-one", 1), entry("two-hundred-two", 0));
- assertThat(dao.countGroupsByLogins(session, Arrays.asList("two-hundred-two")))
- .containsOnly(entry("two-hundred-two", 0));
+ assertThat(dao.selectGroupsByLogins(session, Arrays.<String>asList()).keys()).isEmpty();
+ Multimap<String, String> groupsByLogin = dao.selectGroupsByLogins(session, Arrays.asList("two-hundred", "two-hundred-one", "two-hundred-two"));
+ assertThat(groupsByLogin.get("two-hundred")).containsOnly("sonar-administrators", "sonar-users", "sonar-reviewers");
+ assertThat(groupsByLogin.get("two-hundred-one")).containsOnly("sonar-users");
+ assertThat(groupsByLogin.get("two-hundred-two")).isEmpty();
} finally {
session.close();
}