aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java62
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/SearchActionTest.java169
-rw-r--r--server/sonar-web/src/main/js/apps/groups/groups.js6
-rw-r--r--sonar-ws/src/main/protobuf/ws-user_groups.proto5
4 files changed, 115 insertions, 127 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java
index 695300fa2d8..15f70e04fe5 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java
@@ -24,12 +24,13 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.NewController;
import org.sonar.api.server.ws.WebService.Param;
-import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.utils.Paging;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
@@ -39,13 +40,17 @@ import org.sonar.server.es.SearchOptions;
import org.sonar.server.user.UserSession;
import static org.apache.commons.lang.StringUtils.defaultIfBlank;
+import static org.sonar.api.utils.Paging.forPageIndex;
+import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
import static org.sonar.server.es.SearchOptions.MAX_LIMIT;
import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_ORGANIZATION_KEY;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
+import static org.sonarqube.ws.WsUserGroups.Group;
+import static org.sonarqube.ws.WsUserGroups.SearchWsResponse;
public class SearchAction implements UserGroupsWsAction {
- private static final String FIELD_ID = "id";
private static final String FIELD_NAME = "name";
private static final String FIELD_DESCRIPTION = "description";
private static final String FIELD_MEMBERS_COUNT = "membersCount";
@@ -71,7 +76,8 @@ public class SearchAction implements UserGroupsWsAction {
.setSince("5.2")
.addFieldsParam(ALL_FIELDS)
.addPagingParams(100, MAX_LIMIT)
- .addSearchQuery("sonar-users", "names");
+ .addSearchQuery("sonar-users", "names")
+ .setChangelog(new Change("6.4", "Paging response fields moved to a Paging object"));
action.createParam(PARAM_ORGANIZATION_KEY)
.setDescription("Key of organization. If not set then groups are searched in default organization.")
@@ -95,32 +101,12 @@ public class SearchAction implements UserGroupsWsAction {
userSession.checkLoggedIn().checkPermission(ADMINISTER, organization);
int limit = dbClient.groupDao().countByQuery(dbSession, organization.getUuid(), query);
+ Paging paging = forPageIndex(page).withPageSize(pageSize).andTotal(limit);
List<GroupDto> groups = dbClient.groupDao().selectByQuery(dbSession, organization.getUuid(), query, options.getOffset(), pageSize);
List<Integer> groupIds = groups.stream().map(GroupDto::getId).collect(MoreCollectors.toList(groups.size()));
Map<String, Integer> userCountByGroup = dbClient.groupMembershipDao().countUsersByGroups(dbSession, groupIds);
-
- JsonWriter json = response.newJsonWriter().beginObject();
- options.writeJson(json, limit);
- writeGroups(json, groups, userCountByGroup, fields);
- json.endObject().close();
- }
- }
-
- private static void writeGroups(JsonWriter json, List<GroupDto> groups, Map<String, Integer> userCountByGroup, Set<String> fields) {
- json.name("groups").beginArray();
- for (GroupDto group : groups) {
- writeGroup(json, group, userCountByGroup.get(group.getName()), fields);
+ writeProtobuf(buildResponse(groups, userCountByGroup, fields, paging), request, response);
}
- json.endArray();
- }
-
- private static void writeGroup(JsonWriter json, GroupDto group, Integer memberCount, Set<String> fields) {
- json.beginObject()
- .prop(FIELD_ID, group.getId().toString())
- .prop(FIELD_NAME, fields.contains(FIELD_NAME) ? group.getName() : null)
- .prop(FIELD_DESCRIPTION, fields.contains(FIELD_DESCRIPTION) ? group.getDescription() : null)
- .prop(FIELD_MEMBERS_COUNT, fields.contains(FIELD_MEMBERS_COUNT) ? memberCount : null)
- .endObject();
}
private static Set<String> neededFields(Request request) {
@@ -133,4 +119,30 @@ public class SearchAction implements UserGroupsWsAction {
}
return fields;
}
+
+ private static SearchWsResponse buildResponse(List<GroupDto> groups, Map<String, Integer> userCountByGroup, Set<String> fields, Paging paging) {
+ SearchWsResponse.Builder responseBuilder = SearchWsResponse.newBuilder();
+ groups.forEach(group -> responseBuilder.addGroups(toWsGroup(group, userCountByGroup.get(group.getName()), fields)));
+ responseBuilder.getPagingBuilder()
+ .setPageIndex(paging.pageIndex())
+ .setPageSize(paging.pageSize())
+ .setTotal(paging.total())
+ .build();
+ return responseBuilder.build();
+ }
+
+ private static Group toWsGroup(GroupDto group, Integer memberCount, Set<String> fields) {
+ Group.Builder groupBuilder = Group.newBuilder().setId(group.getId());
+ if (fields.contains(FIELD_NAME)) {
+ groupBuilder.setName(group.getName());
+ }
+ if (fields.contains(FIELD_DESCRIPTION)) {
+ setNullable(group.getDescription(), groupBuilder::setDescription);
+ }
+ if (fields.contains(FIELD_MEMBERS_COUNT)) {
+ groupBuilder.setMembersCount(memberCount);
+ }
+ return groupBuilder.build();
+ }
+
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/SearchActionTest.java
index b5b5acf73bf..169661b3f9f 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/SearchActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/SearchActionTest.java
@@ -19,10 +19,11 @@
*/
package org.sonar.server.usergroups.ws;
+import com.google.common.base.Throwables;
+import java.io.IOException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.api.server.ws.WebService.Param;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
import org.sonar.db.organization.OrganizationDto;
@@ -33,12 +34,20 @@ import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.Common.Paging;
+import org.sonarqube.ws.MediaTypes;
import static org.apache.commons.lang.StringUtils.capitalize;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.sonar.api.server.ws.WebService.Param.FIELDS;
+import static org.sonar.api.server.ws.WebService.Param.PAGE;
+import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
+import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
import static org.sonar.db.user.GroupTesting.newGroupDto;
-import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonarqube.ws.WsUserGroups.Group;
+import static org.sonarqube.ws.WsUserGroups.SearchWsResponse;
public class SearchActionTest {
@@ -57,14 +66,10 @@ public class SearchActionTest {
public void search_empty() throws Exception {
loginAsDefaultOrgAdmin();
- String result = newRequest().execute().getInput();
+ SearchWsResponse response = call(ws.newRequest());
- assertJson(result).isSimilarTo("{\n" +
- " \"p\": 1,\n" +
- " \"ps\": 100,\n" +
- " \"total\": 0,\n" +
- " \"groups\": []\n" +
- "}");
+ assertThat(response.getGroupsList()).isEmpty();
+ assertThat(response.getPaging().getTotal()).isZero();
}
@Test
@@ -76,17 +81,14 @@ public class SearchActionTest {
insertGroup(db.getDefaultOrganization(), "customer3", 0);
loginAsDefaultOrgAdmin();
- String result = newRequest().execute().getInput();
-
- assertJson(result).isSimilarTo("{\n" +
- " \"groups\": [\n" +
- " {\"name\": \"admins\", \"description\": \"Admins\", \"membersCount\": 0},\n" +
- " {\"name\": \"customer1\", \"description\": \"Customer1\", \"membersCount\": 0},\n" +
- " {\"name\": \"customer2\", \"description\": \"Customer2\", \"membersCount\": 0},\n" +
- " {\"name\": \"customer3\", \"description\": \"Customer3\", \"membersCount\": 0},\n" +
- " {\"name\": \"users\", \"description\": \"Users\", \"membersCount\": 0}\n" +
- " ]\n" +
- "}");
+ SearchWsResponse response = call(ws.newRequest());
+
+ assertThat(response.getGroupsList()).extracting(Group::getName, Group::getDescription, Group::getMembersCount).containsOnly(
+ tuple("admins", "Admins", 0),
+ tuple("customer1", "Customer1", 0),
+ tuple("customer2", "Customer2", 0),
+ tuple("customer3", "Customer3", 0),
+ tuple("users", "Users", 0));
}
@Test
@@ -98,17 +100,14 @@ public class SearchActionTest {
insertGroup(db.getDefaultOrganization(), "customer3", 0);
loginAsDefaultOrgAdmin();
- String result = newRequest().execute().getInput();
-
- assertJson(result).isSimilarTo("{\n" +
- " \"groups\": [\n" +
- " {\"name\": \"admins\", \"description\": \"Admins\", \"membersCount\": 1},\n" +
- " {\"name\": \"customer1\", \"description\": \"Customer1\", \"membersCount\": 0},\n" +
- " {\"name\": \"customer2\", \"description\": \"Customer2\", \"membersCount\": 4},\n" +
- " {\"name\": \"customer3\", \"description\": \"Customer3\", \"membersCount\": 0},\n" +
- " {\"name\": \"users\", \"description\": \"Users\", \"membersCount\": 5}\n" +
- " ]\n" +
- "}\n");
+ SearchWsResponse response = call(ws.newRequest());
+
+ assertThat(response.getGroupsList()).extracting(Group::getName, Group::getDescription, Group::getMembersCount).containsOnly(
+ tuple("admins", "Admins", 1),
+ tuple("customer1", "Customer1", 0),
+ tuple("customer2", "Customer2", 4),
+ tuple("customer3", "Customer3", 0),
+ tuple("users", "Users", 5));
}
@Test
@@ -120,15 +119,12 @@ public class SearchActionTest {
insertGroup(db.getDefaultOrganization(), "customer%_%/3", 0);
loginAsDefaultOrgAdmin();
- String result = newRequest().setParam(Param.TEXT_QUERY, "tomer%_%/").execute().getInput();
+ SearchWsResponse response = call(ws.newRequest().setParam(TEXT_QUERY, "tomer%_%/"));
- assertJson(result).ignoreFields("id").isSimilarTo("{\n" +
- " \"groups\": [\n" +
- " {\"name\": \"customer%_%/1\", \"description\": \"Customer%_%/1\", \"membersCount\": 0},\n" +
- " {\"name\": \"customer%_%/2\", \"description\": \"Customer%_%/2\", \"membersCount\": 0},\n" +
- " {\"name\": \"customer%_%/3\", \"description\": \"Customer%_%/3\", \"membersCount\": 0}\n" +
- " ]\n" +
- "}\n");
+ assertThat(response.getGroupsList()).extracting(Group::getName, Group::getDescription, Group::getMembersCount).containsOnly(
+ tuple("customer%_%/1", "Customer%_%/1", 0),
+ tuple("customer%_%/2", "Customer%_%/2", 0),
+ tuple("customer%_%/3", "Customer%_%/3", 0));
}
@Test
@@ -140,31 +136,22 @@ public class SearchActionTest {
insertGroup(db.getDefaultOrganization(), "customer3", 0);
loginAsDefaultOrgAdmin();
- assertJson(newRequest().setParam(Param.PAGE_SIZE, "3").execute().getInput()).isSimilarTo("{\n" +
- " \"p\": 1,\n" +
- " \"ps\": 3,\n" +
- " \"total\": 5,\n" +
- " \"groups\": [\n" +
- " {\"name\": \"admins\", \"description\": \"Admins\", \"membersCount\": 0},\n" +
- " {\"name\": \"customer1\", \"description\": \"Customer1\", \"membersCount\": 0},\n" +
- " {\"name\": \"customer2\", \"description\": \"Customer2\", \"membersCount\": 0}\n" +
- " ]\n" +
- "}\n");
- assertJson(newRequest().setParam(Param.PAGE_SIZE, "3").setParam(Param.PAGE, "2").execute().getInput()).isSimilarTo("{\n" +
- " \"p\": 2,\n" +
- " \"ps\": 3,\n" +
- " \"total\": 5,\n" +
- " \"groups\": [\n" +
- " {\"name\": \"customer3\", \"description\": \"Customer3\", \"membersCount\": 0},\n" +
- " {\"name\": \"users\", \"description\": \"Users\", \"membersCount\": 0}\n" +
- " ]\n" +
- "}\n");
- assertJson(newRequest().setParam(Param.PAGE_SIZE, "3").setParam(Param.PAGE, "3").execute().getInput()).isSimilarTo("{\n" +
- " \"p\": 3,\n" +
- " \"ps\": 3,\n" +
- " \"total\": 5,\n" +
- " \"groups\": []\n" +
- "}\n");
+ SearchWsResponse response = call(ws.newRequest().setParam(PAGE_SIZE, "3"));
+ assertThat(response.getPaging()).extracting(Paging::getPageIndex, Paging::getPageSize, Paging::getTotal).containsOnly(1, 3, 5);
+ assertThat(response.getGroupsList()).extracting(Group::getName, Group::getDescription, Group::getMembersCount).containsOnly(
+ tuple("admins", "Admins", 0),
+ tuple("customer1", "Customer1", 0),
+ tuple("customer2", "Customer2", 0));
+
+ response = call(ws.newRequest().setParam(PAGE_SIZE, "3").setParam(PAGE, "2"));
+ assertThat(response.getPaging()).extracting(Paging::getPageIndex, Paging::getPageSize, Paging::getTotal).containsOnly(2, 3, 5);
+ assertThat(response.getGroupsList()).extracting(Group::getName, Group::getDescription, Group::getMembersCount).containsOnly(
+ tuple("customer3", "Customer3", 0),
+ tuple("users", "Users", 0));
+
+ response = call(ws.newRequest().setParam(PAGE_SIZE, "3").setParam(PAGE, "3"));
+ assertThat(response.getPaging()).extracting(Paging::getPageIndex, Paging::getPageSize, Paging::getTotal).containsOnly(3, 3, 5);
+ assertThat(response.getGroupsList()).isEmpty();
}
@Test
@@ -172,35 +159,16 @@ public class SearchActionTest {
insertGroup(db.getDefaultOrganization(), "sonar-users", 0);
loginAsDefaultOrgAdmin();
- assertThat(newRequest().execute().getInput())
- .contains("id")
- .contains("name")
- .contains("description")
- .contains("membersCount");
-
- assertThat(newRequest().setParam(Param.FIELDS, "").execute().getInput())
- .contains("id")
- .contains("name")
- .contains("description")
- .contains("membersCount");
-
- assertThat(newRequest().setParam(Param.FIELDS, "name").execute().getInput())
- .contains("id")
- .contains("name")
- .doesNotContain("description")
- .doesNotContain("membersCount");
-
- assertThat(newRequest().setParam(Param.FIELDS, "description").execute().getInput())
- .contains("id")
- .doesNotContain("name")
- .contains("description")
- .doesNotContain("membersCount");
-
- assertThat(newRequest().setParam(Param.FIELDS, "membersCount").execute().getInput())
- .contains("id")
- .doesNotContain("name")
- .doesNotContain("description")
- .contains("membersCount");
+ assertThat(call(ws.newRequest()).getGroupsList()).extracting(Group::hasId, Group::hasName, Group::hasDescription, Group::hasMembersCount)
+ .containsOnly(tuple(true, true, true, true));
+ assertThat(call(ws.newRequest().setParam(FIELDS, "")).getGroupsList()).extracting(Group::hasId, Group::hasName, Group::hasDescription, Group::hasMembersCount)
+ .containsOnly(tuple(true, true, true, true));
+ assertThat(call(ws.newRequest().setParam(FIELDS, "name")).getGroupsList()).extracting(Group::hasId, Group::hasName, Group::hasDescription, Group::hasMembersCount)
+ .containsOnly(tuple(true, true, false, false));
+ assertThat(call(ws.newRequest().setParam(FIELDS, "description")).getGroupsList()).extracting(Group::hasId, Group::hasName, Group::hasDescription, Group::hasMembersCount)
+ .containsOnly(tuple(true, false, true, false));
+ assertThat(call(ws.newRequest().setParam(FIELDS, "membersCount")).getGroupsList()).extracting(Group::hasId, Group::hasName, Group::hasDescription, Group::hasMembersCount)
+ .containsOnly(tuple(true, false, false, true));
}
@Test
@@ -212,9 +180,9 @@ public class SearchActionTest {
loginAsDefaultOrgAdmin();
userSession.addPermission(ADMINISTER, org);
- String result = newRequest().setParam("organization", org.getKey()).execute().getInput();
+ SearchWsResponse response = call(ws.newRequest().setParam("organization", org.getKey()));
- assertJson(result).isSimilarTo("{\"groups\":[{\"id\":\"" + group.getId() + "\",\"name\":\"users\"}]}\n");
+ assertThat(response.getGroupsList()).extracting(Group::getId, Group::getName).containsOnly(tuple(group.getId().longValue(), "users"));
}
@Test
@@ -222,11 +190,16 @@ public class SearchActionTest {
userSession.anonymous();
expectedException.expect(UnauthorizedException.class);
- newRequest().execute();
+ call(ws.newRequest());
}
- private TestRequest newRequest() {
- return ws.newRequest();
+ private SearchWsResponse call(TestRequest request) {
+ request.setMediaType(MediaTypes.PROTOBUF);
+ try {
+ return SearchWsResponse.parseFrom(request.execute().getInputStream());
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
}
private void insertGroup(OrganizationDto org, String name, int numberOfMembers) {
diff --git a/server/sonar-web/src/main/js/apps/groups/groups.js b/server/sonar-web/src/main/js/apps/groups/groups.js
index e21b53ec6af..8cfd82d3512 100644
--- a/server/sonar-web/src/main/js/apps/groups/groups.js
+++ b/server/sonar-web/src/main/js/apps/groups/groups.js
@@ -32,9 +32,9 @@ export default Backbone.Collection.extend({
},
parse(r) {
- this.total = +r.total;
- this.p = +r.p;
- this.ps = +r.ps;
+ this.total = +r.paging.total;
+ this.p = +r.paging.pageIndex;
+ this.ps = +r.paging.pageSize;
return r.groups;
},
diff --git a/sonar-ws/src/main/protobuf/ws-user_groups.proto b/sonar-ws/src/main/protobuf/ws-user_groups.proto
index cd57e802bc3..d9fc797f484 100644
--- a/sonar-ws/src/main/protobuf/ws-user_groups.proto
+++ b/sonar-ws/src/main/protobuf/ws-user_groups.proto
@@ -20,6 +20,8 @@ syntax = "proto2";
package sonarqube.ws.usergroup;
+import "ws-commons.proto";
+
option java_package = "org.sonarqube.ws";
option java_outer_classname = "WsUserGroups";
option optimize_for = SPEED;
@@ -36,7 +38,8 @@ message UpdateWsResponse {
// WS api/user_groups/search
message SearchWsResponse {
- repeated Group groups = 1;
+ optional sonarqube.ws.commons.Paging paging = 1;
+ repeated Group groups = 2;
}
message Group {