]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6482 WS permissions/groups list permission's groups 465/head
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Wed, 5 Aug 2015 15:40:47 +0000 (17:40 +0200)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Thu, 6 Aug 2015 10:16:40 +0000 (12:16 +0200)
30 files changed:
server/sonar-server/src/main/java/org/sonar/server/permission/GroupWithPermissionQueryResult.java
server/sonar-server/src/main/java/org/sonar/server/permission/PermissionFinder.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/GroupsAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/UsersAction.java
server/sonar-server/src/main/java/org/sonar/server/ws/WsResponseCommonFormat.java
server/sonar-server/src/main/resources/org/sonar/server/permission/ws/groups-example.json [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/permission/ws/users-example.json
server/sonar-server/src/test/java/org/sonar/server/permission/PermissionFinderTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/GroupsActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/default_page_size_is_100.json
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/deprecated_paging.json
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/empty_result.json
server/sonar-server/src/test/resources/org/sonar/server/permission/ws/GroupsActionTest/groups.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/permission/ws/UsersActionTest/users.json
sonar-db/src/main/java/org/sonar/core/permission/GroupWithPermission.java
sonar-db/src/main/java/org/sonar/db/permission/GroupWithPermissionDto.java
sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java
sonar-db/src/main/java/org/sonar/db/permission/PermissionMapper.java
sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java
sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateMapper.java
sonar-db/src/main/resources/org/sonar/db/permission/PermissionMapper.xml
sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml
sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionDaoTest.java
sonar-db/src/test/java/org/sonar/db/permission/GroupWithPermissionTemplateDaoTest.java
sonar-ws/src/main/gen-java/org/sonarqube/ws/Common.java
sonar-ws/src/main/gen-java/org/sonarqube/ws/Permissions.java
sonar-ws/src/main/protobuf/ws-commons.proto
sonar-ws/src/main/protobuf/ws-permissions.proto

index 5058b7552e34909d506ad595e6f53aa5e3978b77..99a4d9b0dd51268e6b3373f2a8ba2e17e6fa45a6 100644 (file)
  */
 package org.sonar.server.permission;
 
-import org.sonar.core.permission.GroupWithPermission;
-
 import java.util.List;
+import org.sonar.core.permission.GroupWithPermission;
 
 public class GroupWithPermissionQueryResult {
 
-  private List<GroupWithPermission> groups;
-  private boolean hasMoreResults;
+  private final List<GroupWithPermission> groups;
+  private final int total;
+  private final boolean hasMoreResults;
 
-  public GroupWithPermissionQueryResult(List<GroupWithPermission> groups, boolean hasMoreResults) {
+  public GroupWithPermissionQueryResult(List<GroupWithPermission> groups, int total) {
     this.groups = groups;
-    this.hasMoreResults = hasMoreResults;
+    this.total = total;
+    this.hasMoreResults = total > groups.size();
   }
 
   public List<GroupWithPermission> groups() {
@@ -41,4 +42,7 @@ public class GroupWithPermissionQueryResult {
     return hasMoreResults;
   }
 
+  public int total() {
+    return total;
+  }
 }
index c9aa9271405e3f3c8a8120ab74f63c435d5470f8..4b6659dac68abcb7c790c4e2a62ab338af9051dc 100644 (file)
@@ -91,7 +91,12 @@ public class PermissionFinder {
    */
   public GroupWithPermissionQueryResult findGroupsWithPermission(PermissionQuery query) {
     Long componentId = componentId(query.component());
-    return toGroupQueryResult(permissionDao.selectGroups(query, componentId), query);
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      return toGroupQueryResult(permissionDao.selectGroups(dbSession, query, componentId), query);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
   }
 
   /**
@@ -99,7 +104,12 @@ public class PermissionFinder {
    */
   public GroupWithPermissionQueryResult findGroupsWithPermissionTemplate(PermissionQuery query) {
     Long permissionTemplateId = templateId(query.template());
-    return toGroupQueryResult(permissionTemplateDao.selectGroups(query, permissionTemplateId), query);
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      return toGroupQueryResult(permissionTemplateDao.selectGroups(dbSession, query, permissionTemplateId), query);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
   }
 
   private static UserWithPermissionQueryResult toUserQueryResult(List<UserWithPermissionDto> dtos, int total) {
@@ -133,7 +143,7 @@ public class PermissionFinder {
 
     Paging paging = Paging.create(query.pageSize(), query.pageIndex(), filteredDtos.size());
     List<GroupWithPermission> pagedGroups = pagedGroups(filteredDtos, paging);
-    return new GroupWithPermissionQueryResult(pagedGroups, paging.hasNextPage());
+    return new GroupWithPermissionQueryResult(pagedGroups, filteredDtos.size());
   }
 
   private Long templateId(String templateKey) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/GroupsAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/GroupsAction.java
new file mode 100644 (file)
index 0000000..a8850b6
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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.server.permission.ws;
+
+import com.google.common.io.Resources;
+import java.util.List;
+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.utils.text.JsonWriter;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.permission.GroupWithPermission;
+import org.sonar.core.util.ProtobufJsonFormat;
+import org.sonar.db.permission.PermissionQuery;
+import org.sonar.server.permission.GroupWithPermissionQueryResult;
+import org.sonar.server.permission.PermissionFinder;
+import org.sonar.server.plugins.MimeTypes;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.Common;
+import org.sonarqube.ws.Permissions;
+
+import static com.google.common.base.Objects.firstNonNull;
+import static org.sonar.server.permission.PermissionQueryParser.toMembership;
+
+public class GroupsAction implements PermissionsWsAction {
+  private final UserSession userSession;
+  private final PermissionFinder permissionFinder;
+
+  public GroupsAction(UserSession userSession, PermissionFinder permissionFinder) {
+    this.userSession = userSession;
+    this.permissionFinder = permissionFinder;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    WebService.NewAction action = context.createAction("groups")
+      .setSince("5.2")
+      .setInternal(true)
+      .setDescription(String.format("List permission's groups.<br /> " +
+        "If the query parameter '%s' is specified, the '%s' parameter is '%s'.",
+        WebService.Param.TEXT_QUERY, WebService.Param.SELECTED, WebService.SelectionMode.ALL.value()))
+      .addPagingParams(100)
+      .addSearchQuery("sonar", "names")
+      .addSelectionModeParam()
+      .setResponseExample(Resources.getResource(getClass(), "groups-example.json"))
+      .setHandler(this);
+
+    action.createParam("permission")
+      .setExampleValue("scan")
+      .setRequired(true)
+      .setPossibleValues(GlobalPermissions.ALL);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    String permission = request.mandatoryParam("permission");
+    String selected = request.param(WebService.Param.SELECTED);
+    int page = request.mandatoryParamAsInt(WebService.Param.PAGE);
+    int pageSize = request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE);
+    String query = request.param(WebService.Param.TEXT_QUERY);
+    if (query != null) {
+      selected = WebService.SelectionMode.ALL.value();
+    }
+
+    userSession
+      .checkLoggedIn()
+      .checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
+
+    PermissionQuery.Builder permissionQuery = PermissionQuery.builder()
+      .permission(permission)
+      .pageIndex(page)
+      .pageSize(pageSize)
+      .membership(toMembership(firstNonNull(selected, WebService.SelectionMode.SELECTED.value())));
+    if (query != null) {
+      permissionQuery.search(query);
+    }
+
+    GroupWithPermissionQueryResult groupsResult = permissionFinder.findGroupsWithPermission(permissionQuery.build());
+    List<GroupWithPermission> groupsWithPermission = groupsResult.groups();
+
+    Permissions.GroupsResponse.Builder groupsResponse = Permissions.GroupsResponse.newBuilder();
+    Permissions.GroupsResponse.Group.Builder group = Permissions.GroupsResponse.Group.newBuilder();
+    Common.Paging.Builder paging = Common.Paging.newBuilder();
+
+    for (GroupWithPermission groupWithPermission : groupsWithPermission) {
+      group
+        .clear()
+        .setName(groupWithPermission.name())
+        .setSelected(groupWithPermission.hasPermission());
+      // anyone group return with id = 0
+      if (groupWithPermission.id() != 0) {
+        group.setId(String.valueOf(groupWithPermission.id()));
+      }
+      if (groupWithPermission.description() != null) {
+        group.setDescription(groupWithPermission.description());
+      }
+
+      groupsResponse.addGroups(group);
+    }
+
+    groupsResponse.setPaging(
+      paging
+        .setPageIndex(page)
+        .setPageSize(pageSize)
+        .setTotal(groupsResult.total())
+      );
+
+    response.stream().setMediaType(MimeTypes.JSON);
+    JsonWriter json = response.newJsonWriter();
+    ProtobufJsonFormat.write(groupsResponse.build(), json);
+    json.close();
+  }
+}
index b69487adaa87392e767a2834d841ca7f2932f1ef..d3c243a95afa7b3942bfcdcf2d30da02ba6d2c62 100644 (file)
@@ -31,6 +31,7 @@ public class PermissionsWsModule extends Module {
       AddUserAction.class,
       RemoveGroupAction.class,
       RemoveUserAction.class,
-      UsersAction.class);
+      UsersAction.class,
+      GroupsAction.class);
   }
 }
index fc3cafe0e2db39030c3325be064d65d834fc8b7b..e6681f9488e5d0fb6387dd272d60ac2ef1e3ec6c 100644 (file)
@@ -112,7 +112,7 @@ public class UsersAction implements PermissionsWsAction {
       userResponse.setPaging(
         paging
           .clear()
-          .setPages(page)
+          .setPageIndex(page)
           .setPageSize(pageSize)
           .setTotal(usersResult.total())
         );
index 0abcf579c232936e817918bd2eb94282e8a4d279..f2379011fe388d1082c3adaba83bed2c88a0e4d6 100644 (file)
  */
 package org.sonar.server.ws;
 
-import com.google.common.base.Strings;
 import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.utils.Paging;
-import org.sonar.db.component.ComponentDto;
 import org.sonar.db.rule.RuleDto;
 import org.sonar.db.user.UserDto;
 import org.sonarqube.ws.Common;
@@ -41,7 +39,6 @@ public class WsResponseCommonFormat {
   public Common.Paging.Builder formatPaging(Paging paging) {
     return Common.Paging.newBuilder()
       .setPageIndex(paging.pageIndex())
-      .setPages(paging.pages())
       .setPageSize(paging.pageSize())
       .setTotal(paging.total());
   }
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/groups-example.json b/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/groups-example.json
new file mode 100644 (file)
index 0000000..f6bef52
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "groups": [
+    {
+      "name": "Anyone",
+      "selected": true
+    },
+    {
+      "id": "1",
+      "name": "sonar-administrators",
+      "description": "System administrators",
+      "selected": true
+    },
+    {
+      "id": "2",
+      "name": "sonar-users",
+      "description": "Any new users created will automatically join this group",
+      "selected": true
+    }
+  ],
+  "paging": {
+    "pageIndex": 1,
+    "pageSize": 100,
+    "total": 3
+  }
+}
index b4bd9daa6b368fc9df16bdc5191de318256cd9fc..c8aaccb45a01cc07d52c26b4a8aeaccaa71063a6 100644 (file)
@@ -14,7 +14,7 @@
   "paging": {
     "pageSize": 100,
     "total": 2,
-    "pages": 1
+    "pageIndex": 1
   }
 }
 
index 440878a0c8bec99e3b3fa7634cea98c765306d61..534bb11d8acb594fd0fde6d64218a1adc1aaff81 100644 (file)
@@ -153,19 +153,20 @@ public class PermissionFinderTest {
 
   @Test
   public void find_groups() {
-    when(permissionDao.selectGroups(any(PermissionQuery.class), anyLong())).thenReturn(
+    when(permissionDao.selectGroups(any(DbSession.class), any(PermissionQuery.class), anyLong())).thenReturn(
       newArrayList(new GroupWithPermissionDto().setName("users").setPermission("user"))
       );
 
     GroupWithPermissionQueryResult result = underTest.findGroupsWithPermission(
       PermissionQuery.builder().permission("user").membership(PermissionQuery.IN).build());
+
     assertThat(result.groups()).hasSize(1);
     assertThat(result.hasMoreResults()).isFalse();
   }
 
   @Test
   public void find_groups_should_be_paginated() {
-    when(permissionDao.selectGroups(any(PermissionQuery.class), anyLong())).thenReturn(newArrayList(
+    when(permissionDao.selectGroups(any(DbSession.class), any(PermissionQuery.class), anyLong())).thenReturn(newArrayList(
       new GroupWithPermissionDto().setName("Anyone").setPermission("user"),
       new GroupWithPermissionDto().setName("Admin").setPermission("user"),
       new GroupWithPermissionDto().setName("Users").setPermission(null),
@@ -191,12 +192,12 @@ public class PermissionFinderTest {
         .permission("user")
         .pageSize(2)
         .pageIndex(3)
-        .build()).hasMoreResults()).isFalse();
+        .build()).hasMoreResults()).isTrue();
   }
 
   @Test
   public void find_groups_should_filter_membership() {
-    when(permissionDao.selectGroups(any(PermissionQuery.class), anyLong())).thenReturn(newArrayList(
+    when(permissionDao.selectGroups(any(DbSession.class), any(PermissionQuery.class), anyLong())).thenReturn(newArrayList(
       new GroupWithPermissionDto().setName("Anyone").setPermission("user"),
       new GroupWithPermissionDto().setName("Admin").setPermission("user"),
       new GroupWithPermissionDto().setName("Users").setPermission(null),
@@ -214,7 +215,7 @@ public class PermissionFinderTest {
 
   @Test
   public void find_groups_with_added_anyone_group() {
-    when(permissionDao.selectGroups(any(PermissionQuery.class), anyLong())).thenReturn(
+    when(permissionDao.selectGroups(any(DbSession.class), any(PermissionQuery.class), anyLong())).thenReturn(
       newArrayList(new GroupWithPermissionDto().setName("users").setPermission("user"))
       );
 
@@ -228,7 +229,7 @@ public class PermissionFinderTest {
 
   @Test
   public void find_groups_without_adding_anyone_group_when_search_text_do_not_matched() {
-    when(permissionDao.selectGroups(any(PermissionQuery.class), anyLong())).thenReturn(
+    when(permissionDao.selectGroups(any(DbSession.class), any(PermissionQuery.class), anyLong())).thenReturn(
       newArrayList(new GroupWithPermissionDto().setName("users").setPermission("user"))
       );
 
@@ -240,7 +241,7 @@ public class PermissionFinderTest {
 
   @Test
   public void find_groups_with_added_anyone_group_when_search_text_matched() {
-    when(permissionDao.selectGroups(any(PermissionQuery.class), anyLong())).thenReturn(
+    when(permissionDao.selectGroups(any(DbSession.class), any(PermissionQuery.class), anyLong())).thenReturn(
       newArrayList(new GroupWithPermissionDto().setName("MyAnyGroup").setPermission("user"))
       );
 
@@ -251,7 +252,7 @@ public class PermissionFinderTest {
 
   @Test
   public void find_groups_without_adding_anyone_group_when_out_membership_selected() {
-    when(permissionDao.selectGroups(any(PermissionQuery.class), anyLong())).thenReturn(
+    when(permissionDao.selectGroups(any(DbSession.class), any(PermissionQuery.class), anyLong())).thenReturn(
       newArrayList(new GroupWithPermissionDto().setName("users").setPermission("user"))
       );
 
@@ -292,7 +293,7 @@ public class PermissionFinderTest {
   public void find_groups_from_permission_template() {
     when(permissionTemplateDao.selectTemplateByKey(anyString())).thenReturn(new PermissionTemplateDto().setId(1L).setKee("my_template"));
 
-    when(permissionTemplateDao.selectGroups(any(PermissionQuery.class), anyLong())).thenReturn(
+    when(permissionTemplateDao.selectGroups(any(DbSession.class), any(PermissionQuery.class), anyLong())).thenReturn(
       newArrayList(new GroupWithPermissionDto().setName("users").setPermission("user"))
       );
 
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/GroupsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/GroupsActionTest.java
new file mode 100644 (file)
index 0000000..094df80
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * 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.server.permission.ws;
+
+import com.google.common.io.Resources;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.server.ws.WebService.SelectionMode;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.GroupRoleDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.permission.PermissionFinder;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.test.JsonAssert.assertJson;
+
+@Category(DbTests.class)
+public class GroupsActionTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+
+  DbClient dbClient;
+  DbSession dbSession;
+  WsActionTester ws;
+  PermissionFinder permissionFinder;
+
+  GroupsAction underTest;
+
+  @Before
+  public void setUp() {
+    dbClient = db.getDbClient();
+    dbSession = db.getSession();
+    permissionFinder = new PermissionFinder(dbClient);
+    userSession.login("login").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+    underTest = new GroupsAction(userSession, permissionFinder);
+    ws = new WsActionTester(underTest);
+
+    GroupDto group1 = dbClient.groupDao().insert(dbSession, new GroupDto()
+      .setName("group-1-name")
+      .setDescription("group-1-description"));
+    GroupDto group2 = dbClient.groupDao().insert(dbSession, new GroupDto()
+      .setName("group-2-name")
+      .setDescription("group-2-description"));
+    GroupDto group3 = dbClient.groupDao().insert(dbSession, new GroupDto()
+      .setName("group-3-name")
+      .setDescription("group-3-description"));
+    dbClient.roleDao().insertGroupRole(dbSession, new GroupRoleDto()
+      .setGroupId(group1.getId())
+      .setRole(GlobalPermissions.SCAN_EXECUTION));
+    dbClient.roleDao().insertGroupRole(dbSession, new GroupRoleDto()
+      .setGroupId(group2.getId())
+      .setRole(GlobalPermissions.SCAN_EXECUTION));
+    dbClient.roleDao().insertGroupRole(dbSession, new GroupRoleDto()
+      .setGroupId(group3.getId())
+      .setRole(GlobalPermissions.SYSTEM_ADMIN));
+    dbSession.commit();
+  }
+
+  @Test
+  public void search_for_groups_with_one_permission() {
+    String result = ws.newRequest()
+      .setParam("permission", "scan")
+      .execute().getInput();
+
+    assertJson(result).isSimilarTo(Resources.getResource(getClass(), "GroupsActionTest/groups.json"));
+  }
+
+  @Test
+  public void search_with_selection() {
+    String result = ws.newRequest()
+      .setParam("permission", "scan")
+      .setParam("selected", SelectionMode.ALL.value())
+      .execute().getInput();
+
+    assertThat(result).containsSequence(DefaultGroups.ANYONE, "group-1", "group-2", "group-3");
+  }
+
+  @Test
+  public void search_groups_with_pagination() {
+    String result = ws.newRequest()
+      .setParam("permission", "scan")
+      .setParam(Param.PAGE_SIZE, "1")
+      .setParam(Param.PAGE, "2")
+      .execute().getInput();
+
+    assertThat(result).contains("group-2")
+      .doesNotContain("group-1")
+      .doesNotContain("group-3");
+  }
+
+  @Test
+  public void search_groups_with_query() {
+    String result = ws.newRequest()
+      .setParam("permission", "scan")
+      .setParam(Param.TEXT_QUERY, "group-")
+      .execute().getInput();
+
+    assertThat(result)
+      .contains("group-1", "group-2", "group-3")
+      .doesNotContain(DefaultGroups.ANYONE);
+
+  }
+
+  @Test
+  public void fail_if_not_logged_in() {
+    expectedException.expect(UnauthorizedException.class);
+    userSession.anonymous();
+
+    ws.newRequest()
+      .setParam("permission", "scan")
+      .execute();
+  }
+
+  @Test
+  public void fail_if_insufficient_privileges() {
+    expectedException.expect(ForbiddenException.class);
+    userSession.login("login");
+
+    ws.newRequest()
+      .setParam("permission", "scan")
+      .execute();
+  }
+
+  @Test
+  public void fail_if_permission_is_not_specified() {
+    expectedException.expect(IllegalArgumentException.class);
+
+    ws.newRequest()
+      .execute();
+  }
+}
index f85654d5c1f3f8befe2e8cf0583a7032c7007006..0b5afc3f979264b0ad6da43e527110bb7cc2c24c 100644 (file)
@@ -30,6 +30,6 @@ public class PermissionsWsModuleTest {
   public void verify_count_of_added_components() {
     ComponentContainer container = new ComponentContainer();
     new PermissionsWsModule().configure(container);
-    assertThat(container.size()).isEqualTo(8);
+    assertThat(container.size()).isEqualTo(9);
   }
 }
index 0448735ef0c0ac59ebe9dc1d38ce5c458beb3dbc..acda7495d2552b9299b4253ffeb084ea11d4ed8e 100644 (file)
@@ -5,8 +5,7 @@
   "paging": {
     "pageIndex": 1,
     "pageSize": 100,
-    "total": 0,
-    "pages": 0
+    "total": 0
   },
   "issues": []
 }
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/permission/ws/GroupsActionTest/groups.json b/server/sonar-server/src/test/resources/org/sonar/server/permission/ws/GroupsActionTest/groups.json
new file mode 100644 (file)
index 0000000..f48cdd2
--- /dev/null
@@ -0,0 +1,19 @@
+{
+  "groups": [
+    {
+      "name": "group-1-name",
+      "description": "group-1-description",
+      "selected": true
+    },
+    {
+      "name": "group-2-name",
+      "description": "group-2-description",
+      "selected": true
+    }
+  ],
+  "paging": {
+    "pageIndex": 1,
+    "pageSize": 100,
+    "total": 2
+  }
+}
index a3ecb8c0729aef69c96d39ac2fc4a50cdb576860..6be0c984be22ba1379f3206b45969a4bd5063024 100644 (file)
@@ -14,6 +14,6 @@
   "paging": {
     "pageSize": 100,
     "total": 2,
-    "pages": 1
+    "pageIndex": 1
   }
 }
index 0dcc1d7ce1deb3a85816834f890413a5fd80fca7..29f3a296c2bca1f3b086c6bb24541f34722be247 100644 (file)
@@ -27,10 +27,20 @@ import org.apache.commons.lang.builder.ToStringStyle;
 
 public class GroupWithPermission {
 
+  private long id;
   private String name;
   private String description;
   private boolean hasPermission;
 
+  public long id() {
+    return id;
+  }
+
+  public GroupWithPermission setId(Long id) {
+    this.id = id;
+    return this;
+  }
+
   public String name() {
     return name;
   }
index 2dbcd04203cb250f5965b37d72107840eac0ced2..3df694d581409ff681d2bedd205e238d8223faea 100644 (file)
@@ -26,10 +26,19 @@ import org.sonar.core.permission.GroupWithPermission;
 
 public class GroupWithPermissionDto {
 
+  private long id;
   private String name;
   private String permission;
   private String description;
 
+  public long getId() {
+    return id;
+  }
+
+  public void setId(long id) {
+    this.id = id;
+  }
+
   public String getName() {
     return name;
   }
@@ -61,6 +70,7 @@ public class GroupWithPermissionDto {
 
   public GroupWithPermission toGroupWithPermission() {
     return new GroupWithPermission()
+      .setId(id)
       .setName(name)
       .setDescription(description)
       .hasPermission(permission != null);
index ae1ae1b65daae1df36292da50addaf9786273776..033a7fa5cc40cf726e0d036d98ca28eb7c384484 100644 (file)
@@ -71,20 +71,33 @@ public class PermissionDao implements Dao {
    *
    * @return a non paginated list of groups.
    */
+  public List<GroupWithPermissionDto> selectGroups(DbSession session, PermissionQuery query, @Nullable Long componentId) {
+    Map<String, Object> params = groupsParameters(query, componentId);
+    return mapper(session).selectGroups(params);
+  }
+
   public List<GroupWithPermissionDto> selectGroups(PermissionQuery query, @Nullable Long componentId) {
-    SqlSession session = myBatis.openSession(false);
+    DbSession session = myBatis.openSession(false);
     try {
-      Map<String, Object> params = newHashMap();
-      params.put(QUERY_PARAMETER, query);
-      params.put(COMPONENT_ID_PARAMETER, componentId);
-      params.put("anyoneGroup", DefaultGroups.ANYONE);
-
-      return mapper(session).selectGroups(params);
+      return selectGroups(session, query, componentId);
     } finally {
       MyBatis.closeQuietly(session);
     }
   }
 
+  public int countGroups(DbSession session, PermissionQuery query, @Nullable Long componentId) {
+    Map<String, Object> parameters = groupsParameters(query, componentId);
+    return mapper(session).countGroups(parameters);
+  }
+
+  private static Map<String, Object> groupsParameters(PermissionQuery query, @Nullable Long componentId) {
+    Map<String, Object> params = newHashMap();
+    params.put(QUERY_PARAMETER, query);
+    params.put(COMPONENT_ID_PARAMETER, componentId);
+    params.put("anyoneGroup", DefaultGroups.ANYONE);
+    return params;
+  }
+
   private PermissionMapper mapper(SqlSession session) {
     return session.getMapper(PermissionMapper.class);
   }
index 0bf57813c535c12a90e387523e952960ed5205ae..8fa088809fe80eb4980fa3519d7eae605b12fc60 100644 (file)
@@ -28,7 +28,9 @@ public interface PermissionMapper {
 
   List<UserWithPermissionDto> selectUsers(Map<String, Object> parameters, RowBounds rowBounds);
 
+  int countUsers(Map<String, Object> parameters);
+
   List<GroupWithPermissionDto> selectGroups(Map<String, Object> parameters);
 
-  int countUsers(Map<String, Object> parameters);
+  int countGroups(Map<String, Object> parameters);
 }
index 30945f54e72b81e0687c4dd7d9caf64faff47fe5..e94b748435331a677d91638df70c0d485401f709 100644 (file)
@@ -89,19 +89,33 @@ public class PermissionTemplateDao implements Dao {
    * Membership parameter from query is not taking into account in order to deal more easily with the 'Anyone' group.
    * @return a non paginated list of groups.
    */
+  public List<GroupWithPermissionDto> selectGroups(DbSession session, PermissionQuery query, Long templateId) {
+    Map<String, Object> params = groupsParamaters(query, templateId);
+    return mapper(session).selectGroups(params);
+  }
+
   public List<GroupWithPermissionDto> selectGroups(PermissionQuery query, Long templateId) {
-    SqlSession session = myBatis.openSession(false);
+    DbSession session = myBatis.openSession(false);
     try {
-      Map<String, Object> params = newHashMap();
-      params.put(QUERY_PARAMETER, query);
-      params.put(TEMPLATE_ID_PARAMETER, templateId);
-      params.put("anyoneGroup", DefaultGroups.ANYONE);
-      return mapper(session).selectGroups(params);
+      return selectGroups(session, query, templateId);
     } finally {
       MyBatis.closeQuietly(session);
     }
   }
 
+  public int countGroups(DbSession session, PermissionQuery query, Long templateId) {
+    Map<String, Object> parameters = groupsParamaters(query, templateId);
+    return mapper(session).countGroups(parameters);
+  }
+
+  private Map<String, Object> groupsParamaters(PermissionQuery query, Long templateId) {
+    Map<String, Object> params = newHashMap();
+    params.put(QUERY_PARAMETER, query);
+    params.put(TEMPLATE_ID_PARAMETER, templateId);
+    params.put("anyoneGroup", DefaultGroups.ANYONE);
+    return params;
+  }
+
   @CheckForNull
   public PermissionTemplateDto selectTemplateByKey(DbSession session, String templateKey) {
     return mapper(session).selectByKey(templateKey);
index be35219518e0c757208cdaa6b39cabc36e2a99e2..bd3aaeb3afa9a329dee4cde876b4dd2a9663fef8 100644 (file)
@@ -60,4 +60,6 @@ public interface PermissionTemplateMapper {
   List<UserWithPermissionDto> selectUsers(Map<String, Object> params, RowBounds rowBounds);
 
   int countUsers(Map<String, Object> params);
+
+  int countGroups(Map<String, Object> parameters);
 }
index a2e01badf9bc050376170243da0548dd52af9ca1..99d8dd14ea41a4ade9fae02e9ee5d6f0b99f578d 100644 (file)
@@ -41,8 +41,8 @@
   </sql>
 
   <select id="selectGroups" parameterType="map" resultType="GroupWithPermission">
-    SELECT name, description, permission FROM
-    (SELECT g.name as name, g.description as description, group_role.role as permission
+    SELECT id, name, description, permission FROM
+    (SELECT g.id as id, g.name as name, g.description as description, group_role.role as permission
     FROM groups g
     LEFT JOIN group_roles group_role ON group_role.group_id=g.id
     AND group_role.role=#{query.permission}
@@ -54,7 +54,7 @@
     </if>
     UNION
     -- Add Anyone group permission
-    SELECT #{anyoneGroup} as name, NULL as description, group_role.role as permission
+    SELECT 0 as id, #{anyoneGroup} as name, NULL as description, group_role.role as permission
     FROM group_roles group_role
     <where>
       AND group_role.role=#{query.permission}
     ORDER BY groups.name
   </select>
 
+  <select id="countGroups" parameterType="map" resultType="int">
+    SELECT count(name) FROM
+    (SELECT g.name as name
+    FROM groups g
+    LEFT JOIN group_roles group_role ON group_role.group_id=g.id
+    AND group_role.role=#{query.permission}
+    <if test="componentId != null">
+      AND group_role.resource_id=#{componentId}
+    </if>
+    <if test="componentId == null">
+      AND group_role.resource_id IS NULL
+    </if>
+    UNION
+    -- Add Anyone group permission
+    SELECT #{anyoneGroup} as name
+    FROM group_roles group_role
+    <where>
+      AND group_role.role=#{query.permission}
+      AND group_role.group_id IS NULL
+      <if test="componentId != null">
+        AND group_role.resource_id=#{componentId}
+      </if>
+      <if test="componentId == null">
+        AND group_role.resource_id IS NULL
+      </if>
+    </where>
+    ) groups
+    <where>
+      <if test="query.search() != null">
+        AND (UPPER(groups.name) LIKE #{query.searchSql} ESCAPE '/')
+      </if>
+    </where>
+  </select>
 </mapper>
index 5ca9eb2859fc89fbd07c14c925368e95e91e97ce..260baeb1d9052d3d90ed336bb22d2a95b3f0162d 100644 (file)
     ORDER BY groups.name
   </select>
 
+  <select id="countGroups" parameterType="map" resultType="int">
+    SELECT count(name) FROM
+    (SELECT g.name as name, g.description as description, ptg.permission_reference as permission
+    FROM groups g
+    LEFT JOIN perm_templates_groups ptg ON ptg.group_id=g.id
+    AND ptg.permission_reference=#{query.permission}
+    AND ptg.template_id=#{templateId}
+    UNION
+    -- Add Anyone group permission
+    SELECT #{anyoneGroup} as name, NULL as description, ptg.permission_reference as permission
+    FROM perm_templates_groups ptg
+    <where>
+      AND ptg.permission_reference=#{query.permission}
+      AND ptg.template_id=#{templateId}
+      AND ptg.group_id IS NULL
+    </where>
+    ) groups
+    <where>
+      <if test="query.search() != null">
+        AND (UPPER(groups.name) LIKE #{query.searchSql} ESCAPE '/')
+      </if>
+    </where>
+  </select>
+
   <select id="selectByKey" parameterType="String" resultType="PermissionTemplate">
     SELECT id, name, kee, description, key_pattern AS keyPattern, created_at AS createdAt, updated_at AS updatedAt
     FROM permission_templates
index c70a48e343d99414e8025d6675ef106cecbde254..44a2a0aa549ef08f41bfe06a8ae8c1bce8e683e1 100644 (file)
@@ -25,6 +25,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.sonar.api.utils.System2;
+import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.test.DbTests;
 
@@ -36,16 +37,17 @@ public class GroupWithPermissionDaoTest {
   private static final long COMPONENT_ID = 100L;
 
   @Rule
-  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+  public DbTester db = DbTester.create(System2.INSTANCE);
+  DbSession session = db.getSession();
 
-  PermissionDao dao = dbTester.getDbClient().permissionDao();
+  PermissionDao underTest = db.getDbClient().permissionDao();
 
   @Test
   public void select_groups_for_project_permission() {
-    dbTester.prepareDbUnit(getClass(), "groups_with_permissions.xml");
+    db.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
     PermissionQuery query = PermissionQuery.builder().permission("user").build();
-    List<GroupWithPermissionDto> result = dao.selectGroups(query, COMPONENT_ID);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, query, COMPONENT_ID);
     assertThat(result).hasSize(4);
 
     GroupWithPermissionDto anyone = result.get(0);
@@ -71,11 +73,11 @@ public class GroupWithPermissionDaoTest {
 
   @Test
   public void anyone_group_is_not_returned_when_it_has_no_permission() {
-    dbTester.prepareDbUnit(getClass(), "groups_with_permissions.xml");
+    db.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
     // Anyone group has not the permission 'admin', so it's not returned
     PermissionQuery query = PermissionQuery.builder().permission("admin").build();
-    List<GroupWithPermissionDto> result = dao.selectGroups(query, COMPONENT_ID);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, query, COMPONENT_ID);
     assertThat(result).hasSize(3);
 
     GroupWithPermissionDto group1 = result.get(0);
@@ -93,10 +95,10 @@ public class GroupWithPermissionDaoTest {
 
   @Test
   public void select_groups_for_global_permission() {
-    dbTester.prepareDbUnit(getClass(), "groups_with_permissions.xml");
+    db.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
     PermissionQuery query = PermissionQuery.builder().permission("admin").build();
-    List<GroupWithPermissionDto> result = dao.selectGroups(query, null);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, query, null);
     assertThat(result).hasSize(3);
 
     GroupWithPermissionDto group1 = result.get(0);
@@ -114,22 +116,25 @@ public class GroupWithPermissionDaoTest {
 
   @Test
   public void search_by_groups_name() {
-    dbTester.prepareDbUnit(getClass(), "groups_with_permissions.xml");
+    db.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
-    List<GroupWithPermissionDto> result = dao.selectGroups(PermissionQuery.builder().permission("user").search("aDMini").build(), COMPONENT_ID);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").search("aDMini").build(), COMPONENT_ID);
     assertThat(result).hasSize(1);
     assertThat(result.get(0).getName()).isEqualTo("sonar-administrators");
 
-    result = dao.selectGroups(PermissionQuery.builder().permission("user").search("sonar").build(), COMPONENT_ID);
+    result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").search("sonar").build(), COMPONENT_ID);
     assertThat(result).hasSize(3);
   }
 
   @Test
   public void search_groups_should_be_sorted_by_group_name() {
-    dbTester.prepareDbUnit(getClass(), "groups_with_permissions_should_be_sorted_by_group_name.xml");
+    db.prepareDbUnit(getClass(), "groups_with_permissions_should_be_sorted_by_group_name.xml");
+
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").build(), COMPONENT_ID);
+    int count = underTest.countGroups(session, PermissionQuery.builder().permission("user").build(), COMPONENT_ID);
 
-    List<GroupWithPermissionDto> result = dao.selectGroups(PermissionQuery.builder().permission("user").build(), COMPONENT_ID);
     assertThat(result).hasSize(4);
+    assertThat(count).isEqualTo(4);
     assertThat(result.get(0).getName()).isEqualTo("Anyone");
     assertThat(result.get(1).getName()).isEqualTo("sonar-administrators");
     assertThat(result.get(2).getName()).isEqualTo("sonar-reviewers");
index 51d852d1398ac1ce52ff99a1e61bb27b0e8e0bab..8087b3e7dc555765f6962dfa89ac74e85d213a78 100644 (file)
@@ -25,6 +25,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.sonar.api.utils.System2;
+import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.test.DbTests;
 
@@ -37,17 +38,20 @@ public class GroupWithPermissionTemplateDaoTest {
 
   @Rule
   public DbTester dbTester = DbTester.create(System2.INSTANCE);
+  DbSession session = dbTester.getSession();
 
-  PermissionTemplateDao dao = dbTester.getDbClient().permissionTemplateDao();
+  PermissionTemplateDao underTest = dbTester.getDbClient().permissionTemplateDao();
 
   @Test
   public void select_groups() {
     dbTester.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
     PermissionQuery query = PermissionQuery.builder().permission("user").build();
-    List<GroupWithPermissionDto> result = dao.selectGroups(query, TEMPLATE_ID);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, query, TEMPLATE_ID);
+    int count = underTest.countGroups(session, query, TEMPLATE_ID);
 
     assertThat(result).hasSize(4);
+    assertThat(count).isEqualTo(4);
 
     GroupWithPermissionDto anyone = result.get(0);
     assertThat(anyone.getName()).isEqualTo("Anyone");
@@ -76,7 +80,7 @@ public class GroupWithPermissionTemplateDaoTest {
 
     // Anyone group has not the permission 'admin', so it's not returned
     PermissionQuery query = PermissionQuery.builder().permission("admin").build();
-    List<GroupWithPermissionDto> result = dao.selectGroups(query, TEMPLATE_ID);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, query, TEMPLATE_ID);
     assertThat(result).hasSize(3);
 
     GroupWithPermissionDto group1 = result.get(0);
@@ -96,11 +100,11 @@ public class GroupWithPermissionTemplateDaoTest {
   public void search_by_groups_name() {
     dbTester.prepareDbUnit(getClass(), "groups_with_permissions.xml");
 
-    List<GroupWithPermissionDto> result = dao.selectGroups(PermissionQuery.builder().permission("user").search("aDMini").build(), TEMPLATE_ID);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").search("aDMini").build(), TEMPLATE_ID);
     assertThat(result).hasSize(1);
     assertThat(result.get(0).getName()).isEqualTo("sonar-administrators");
 
-    result = dao.selectGroups(PermissionQuery.builder().permission("user").search("sonar").build(), TEMPLATE_ID);
+    result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").search("sonar").build(), TEMPLATE_ID);
     assertThat(result).hasSize(3);
   }
 
@@ -108,7 +112,7 @@ public class GroupWithPermissionTemplateDaoTest {
   public void search_groups_should_be_sorted_by_group_name() {
     dbTester.prepareDbUnit(getClass(), "groups_with_permissions_should_be_sorted_by_group_name.xml");
 
-    List<GroupWithPermissionDto> result = dao.selectGroups(PermissionQuery.builder().permission("user").build(), TEMPLATE_ID);
+    List<GroupWithPermissionDto> result = underTest.selectGroups(session, PermissionQuery.builder().permission("user").build(), TEMPLATE_ID);
     assertThat(result).hasSize(4);
     assertThat(result.get(0).getName()).isEqualTo("Anyone");
     assertThat(result.get(1).getName()).isEqualTo("sonar-administrators");
index 2d337377590f0aa3add0f6201a13acdc42e698bd..910a5297e82da95039f0e7921aa0fcf5a455abe7 100644 (file)
@@ -247,15 +247,6 @@ public final class Common {
      * <code>optional int32 total = 3;</code>
      */
     int getTotal();
-
-    /**
-     * <code>optional int32 pages = 4;</code>
-     */
-    boolean hasPages();
-    /**
-     * <code>optional int32 pages = 4;</code>
-     */
-    int getPages();
   }
   /**
    * Protobuf type {@code sonarqube.ws.commons.Paging}
@@ -324,11 +315,6 @@ public final class Common {
               total_ = input.readInt32();
               break;
             }
-            case 32: {
-              bitField0_ |= 0x00000008;
-              pages_ = input.readInt32();
-              break;
-            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -414,26 +400,10 @@ public final class Common {
       return total_;
     }
 
-    public static final int PAGES_FIELD_NUMBER = 4;
-    private int pages_;
-    /**
-     * <code>optional int32 pages = 4;</code>
-     */
-    public boolean hasPages() {
-      return ((bitField0_ & 0x00000008) == 0x00000008);
-    }
-    /**
-     * <code>optional int32 pages = 4;</code>
-     */
-    public int getPages() {
-      return pages_;
-    }
-
     private void initFields() {
       pageIndex_ = 0;
       pageSize_ = 0;
       total_ = 0;
-      pages_ = 0;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -457,9 +427,6 @@ public final class Common {
       if (((bitField0_ & 0x00000004) == 0x00000004)) {
         output.writeInt32(3, total_);
       }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        output.writeInt32(4, pages_);
-      }
       getUnknownFields().writeTo(output);
     }
 
@@ -481,10 +448,6 @@ public final class Common {
         size += com.google.protobuf.CodedOutputStream
           .computeInt32Size(3, total_);
       }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt32Size(4, pages_);
-      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -608,8 +571,6 @@ public final class Common {
         bitField0_ = (bitField0_ & ~0x00000002);
         total_ = 0;
         bitField0_ = (bitField0_ & ~0x00000004);
-        pages_ = 0;
-        bitField0_ = (bitField0_ & ~0x00000008);
         return this;
       }
 
@@ -650,10 +611,6 @@ public final class Common {
           to_bitField0_ |= 0x00000004;
         }
         result.total_ = total_;
-        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
-          to_bitField0_ |= 0x00000008;
-        }
-        result.pages_ = pages_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -679,9 +636,6 @@ public final class Common {
         if (other.hasTotal()) {
           setTotal(other.getTotal());
         }
-        if (other.hasPages()) {
-          setPages(other.getPages());
-        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -805,38 +759,6 @@ public final class Common {
         return this;
       }
 
-      private int pages_ ;
-      /**
-       * <code>optional int32 pages = 4;</code>
-       */
-      public boolean hasPages() {
-        return ((bitField0_ & 0x00000008) == 0x00000008);
-      }
-      /**
-       * <code>optional int32 pages = 4;</code>
-       */
-      public int getPages() {
-        return pages_;
-      }
-      /**
-       * <code>optional int32 pages = 4;</code>
-       */
-      public Builder setPages(int value) {
-        bitField0_ |= 0x00000008;
-        pages_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional int32 pages = 4;</code>
-       */
-      public Builder clearPages() {
-        bitField0_ = (bitField0_ & ~0x00000008);
-        pages_ = 0;
-        onChanged();
-        return this;
-      }
-
       // @@protoc_insertion_point(builder_scope:sonarqube.ws.commons.Paging)
     }
 
@@ -4995,22 +4917,22 @@ public final class Common {
   static {
     java.lang.String[] descriptorData = {
       "\n\020ws-commons.proto\022\024sonarqube.ws.commons" +
-      "\"K\n\006Paging\022\021\n\tpageIndex\030\001 \001(\005\022\020\n\010pageSiz" +
-      "e\030\002 \001(\005\022\r\n\005total\030\003 \001(\005\022\r\n\005pages\030\004 \001(\005\"K\n" +
-      "\005Facet\022\020\n\010property\030\001 \001(\t\0220\n\006values\030\002 \003(\013" +
-      "2 .sonarqube.ws.commons.FacetValue\"(\n\nFa" +
-      "cetValue\022\013\n\003val\030\001 \001(\t\022\r\n\005count\030\002 \001(\003\"s\n\004" +
-      "Rule\022\013\n\003key\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\022\014\n\004lang\030" +
-      "\003 \001(\t\0220\n\006status\030\004 \001(\0162 .sonarqube.ws.com" +
-      "mons.RuleStatus\022\020\n\010langName\030\005 \001(\t\"B\n\004Use" +
-      "r\022\r\n\005login\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\022\r\n\005email\030",
-      "\003 \001(\t\022\016\n\006active\030\004 \001(\010\"W\n\tTextRange\022\021\n\tst" +
-      "artLine\030\001 \001(\005\022\017\n\007endLine\030\002 \001(\005\022\023\n\013startO" +
-      "ffset\030\003 \001(\005\022\021\n\tendOffset\030\004 \001(\005*E\n\010Severi" +
-      "ty\022\010\n\004INFO\020\000\022\t\n\005MINOR\020\001\022\t\n\005MAJOR\020\002\022\014\n\010CR" +
-      "ITICAL\020\003\022\013\n\007BLOCKER\020\004*>\n\nRuleStatus\022\010\n\004B" +
-      "ETA\020\000\022\016\n\nDEPRECATED\020\001\022\t\n\005READY\020\002\022\013\n\007REMO" +
-      "VED\020\003B\034\n\020org.sonarqube.wsB\006CommonH\001"
+      "\"<\n\006Paging\022\021\n\tpageIndex\030\001 \001(\005\022\020\n\010pageSiz" +
+      "e\030\002 \001(\005\022\r\n\005total\030\003 \001(\005\"K\n\005Facet\022\020\n\010prope" +
+      "rty\030\001 \001(\t\0220\n\006values\030\002 \003(\0132 .sonarqube.ws" +
+      ".commons.FacetValue\"(\n\nFacetValue\022\013\n\003val" +
+      "\030\001 \001(\t\022\r\n\005count\030\002 \001(\003\"s\n\004Rule\022\013\n\003key\030\001 \001" +
+      "(\t\022\014\n\004name\030\002 \001(\t\022\014\n\004lang\030\003 \001(\t\0220\n\006status" +
+      "\030\004 \001(\0162 .sonarqube.ws.commons.RuleStatus" +
+      "\022\020\n\010langName\030\005 \001(\t\"B\n\004User\022\r\n\005login\030\001 \001(" +
+      "\t\022\014\n\004name\030\002 \001(\t\022\r\n\005email\030\003 \001(\t\022\016\n\006active",
+      "\030\004 \001(\010\"W\n\tTextRange\022\021\n\tstartLine\030\001 \001(\005\022\017" +
+      "\n\007endLine\030\002 \001(\005\022\023\n\013startOffset\030\003 \001(\005\022\021\n\t" +
+      "endOffset\030\004 \001(\005*E\n\010Severity\022\010\n\004INFO\020\000\022\t\n" +
+      "\005MINOR\020\001\022\t\n\005MAJOR\020\002\022\014\n\010CRITICAL\020\003\022\013\n\007BLO" +
+      "CKER\020\004*>\n\nRuleStatus\022\010\n\004BETA\020\000\022\016\n\nDEPREC" +
+      "ATED\020\001\022\t\n\005READY\020\002\022\013\n\007REMOVED\020\003B\034\n\020org.so" +
+      "narqube.wsB\006CommonH\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
         new com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
@@ -5029,7 +4951,7 @@ public final class Common {
     internal_static_sonarqube_ws_commons_Paging_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_sonarqube_ws_commons_Paging_descriptor,
-        new java.lang.String[] { "PageIndex", "PageSize", "Total", "Pages", });
+        new java.lang.String[] { "PageIndex", "PageSize", "Total", });
     internal_static_sonarqube_ws_commons_Facet_descriptor =
       getDescriptor().getMessageTypes().get(1);
     internal_static_sonarqube_ws_commons_Facet_fieldAccessorTable = new
index afdadda56190180294b3a6ef7a3ae1ccb3910a6c..ef482c4ff2a96ebf8702fa54468325488099ef35 100644 (file)
@@ -201,11 +201,11 @@ public final class Permissions {
           getNameBytes();
 
       /**
-       * <code>optional bool selected = 4;</code>
+       * <code>optional bool selected = 3;</code>
        */
       boolean hasSelected();
       /**
-       * <code>optional bool selected = 4;</code>
+       * <code>optional bool selected = 3;</code>
        */
       boolean getSelected();
     }
@@ -273,7 +273,7 @@ public final class Permissions {
                 name_ = bs;
                 break;
               }
-              case 32: {
+              case 24: {
                 bitField0_ |= 0x00000004;
                 selected_ = input.readBool();
                 break;
@@ -402,16 +402,16 @@ public final class Permissions {
         }
       }
 
-      public static final int SELECTED_FIELD_NUMBER = 4;
+      public static final int SELECTED_FIELD_NUMBER = 3;
       private boolean selected_;
       /**
-       * <code>optional bool selected = 4;</code>
+       * <code>optional bool selected = 3;</code>
        */
       public boolean hasSelected() {
         return ((bitField0_ & 0x00000004) == 0x00000004);
       }
       /**
-       * <code>optional bool selected = 4;</code>
+       * <code>optional bool selected = 3;</code>
        */
       public boolean getSelected() {
         return selected_;
@@ -442,7 +442,7 @@ public final class Permissions {
           output.writeBytes(2, getNameBytes());
         }
         if (((bitField0_ & 0x00000004) == 0x00000004)) {
-          output.writeBool(4, selected_);
+          output.writeBool(3, selected_);
         }
         getUnknownFields().writeTo(output);
       }
@@ -463,7 +463,7 @@ public final class Permissions {
         }
         if (((bitField0_ & 0x00000004) == 0x00000004)) {
           size += com.google.protobuf.CodedOutputStream
-            .computeBoolSize(4, selected_);
+            .computeBoolSize(3, selected_);
         }
         size += getUnknownFields().getSerializedSize();
         memoizedSerializedSize = size;
@@ -838,19 +838,19 @@ public final class Permissions {
 
         private boolean selected_ ;
         /**
-         * <code>optional bool selected = 4;</code>
+         * <code>optional bool selected = 3;</code>
          */
         public boolean hasSelected() {
           return ((bitField0_ & 0x00000004) == 0x00000004);
         }
         /**
-         * <code>optional bool selected = 4;</code>
+         * <code>optional bool selected = 3;</code>
          */
         public boolean getSelected() {
           return selected_;
         }
         /**
-         * <code>optional bool selected = 4;</code>
+         * <code>optional bool selected = 3;</code>
          */
         public Builder setSelected(boolean value) {
           bitField0_ |= 0x00000004;
@@ -859,7 +859,7 @@ public final class Permissions {
           return this;
         }
         /**
-         * <code>optional bool selected = 4;</code>
+         * <code>optional bool selected = 3;</code>
          */
         public Builder clearSelected() {
           bitField0_ = (bitField0_ & ~0x00000004);
@@ -1595,59 +1595,1830 @@ public final class Permissions {
     // @@protoc_insertion_point(class_scope:sonarqube.ws.permissions.UsersResponse)
   }
 
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_sonarqube_ws_permissions_UsersResponse_descriptor;
-  private static
-    com.google.protobuf.GeneratedMessage.FieldAccessorTable
-      internal_static_sonarqube_ws_permissions_UsersResponse_fieldAccessorTable;
-  private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_sonarqube_ws_permissions_UsersResponse_User_descriptor;
-  private static
-    com.google.protobuf.GeneratedMessage.FieldAccessorTable
-      internal_static_sonarqube_ws_permissions_UsersResponse_User_fieldAccessorTable;
+  public interface GroupsResponseOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:sonarqube.ws.permissions.GroupsResponse)
+      com.google.protobuf.MessageOrBuilder {
 
-  public static com.google.protobuf.Descriptors.FileDescriptor
-      getDescriptor() {
-    return descriptor;
+    /**
+     * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+     */
+    java.util.List<org.sonarqube.ws.Permissions.GroupsResponse.Group> 
+        getGroupsList();
+    /**
+     * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+     */
+    org.sonarqube.ws.Permissions.GroupsResponse.Group getGroups(int index);
+    /**
+     * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+     */
+    int getGroupsCount();
+    /**
+     * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+     */
+    java.util.List<? extends org.sonarqube.ws.Permissions.GroupsResponse.GroupOrBuilder> 
+        getGroupsOrBuilderList();
+    /**
+     * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+     */
+    org.sonarqube.ws.Permissions.GroupsResponse.GroupOrBuilder getGroupsOrBuilder(
+        int index);
+
+    /**
+     * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+     */
+    boolean hasPaging();
+    /**
+     * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+     */
+    org.sonarqube.ws.Common.Paging getPaging();
+    /**
+     * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+     */
+    org.sonarqube.ws.Common.PagingOrBuilder getPagingOrBuilder();
   }
-  private static com.google.protobuf.Descriptors.FileDescriptor
-      descriptor;
-  static {
-    java.lang.String[] descriptorData = {
-      "\n\024ws-permissions.proto\022\030sonarqube.ws.per" +
-      "missions\032\020ws-commons.proto\"\261\001\n\rUsersResp" +
-      "onse\022;\n\005users\030\001 \003(\0132,.sonarqube.ws.permi" +
-      "ssions.UsersResponse.User\022,\n\006paging\030\002 \001(" +
-      "\0132\034.sonarqube.ws.commons.Paging\0325\n\004User\022" +
-      "\r\n\005login\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\022\020\n\010selected" +
-      "\030\004 \001(\010B!\n\020org.sonarqube.wsB\013PermissionsH" +
-      "\001"
-    };
-    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
-        new com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
-          public com.google.protobuf.ExtensionRegistry assignDescriptors(
-              com.google.protobuf.Descriptors.FileDescriptor root) {
-            descriptor = root;
-            return null;
+  /**
+   * Protobuf type {@code sonarqube.ws.permissions.GroupsResponse}
+   *
+   * <pre>
+   * WS api/permissions/groups for internal use only
+   * </pre>
+   */
+  public static final class GroupsResponse extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:sonarqube.ws.permissions.GroupsResponse)
+      GroupsResponseOrBuilder {
+    // Use GroupsResponse.newBuilder() to construct.
+    private GroupsResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private GroupsResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final GroupsResponse defaultInstance;
+    public static GroupsResponse getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public GroupsResponse getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private GroupsResponse(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+                groups_ = new java.util.ArrayList<org.sonarqube.ws.Permissions.GroupsResponse.Group>();
+                mutable_bitField0_ |= 0x00000001;
+              }
+              groups_.add(input.readMessage(org.sonarqube.ws.Permissions.GroupsResponse.Group.PARSER, extensionRegistry));
+              break;
+            }
+            case 18: {
+              org.sonarqube.ws.Common.Paging.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000001) == 0x00000001)) {
+                subBuilder = paging_.toBuilder();
+              }
+              paging_ = input.readMessage(org.sonarqube.ws.Common.Paging.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(paging_);
+                paging_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000001;
+              break;
+            }
           }
-        };
-    com.google.protobuf.Descriptors.FileDescriptor
-      .internalBuildGeneratedFileFrom(descriptorData,
-        new com.google.protobuf.Descriptors.FileDescriptor[] {
-          org.sonarqube.ws.Common.getDescriptor(),
-        }, assigner);
-    internal_static_sonarqube_ws_permissions_UsersResponse_descriptor =
-      getDescriptor().getMessageTypes().get(0);
-    internal_static_sonarqube_ws_permissions_UsersResponse_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
-        internal_static_sonarqube_ws_permissions_UsersResponse_descriptor,
-        new java.lang.String[] { "Users", "Paging", });
-    internal_static_sonarqube_ws_permissions_UsersResponse_User_descriptor =
-      internal_static_sonarqube_ws_permissions_UsersResponse_descriptor.getNestedTypes().get(0);
-    internal_static_sonarqube_ws_permissions_UsersResponse_User_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
-        internal_static_sonarqube_ws_permissions_UsersResponse_User_descriptor,
-        new java.lang.String[] { "Login", "Name", "Selected", });
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+          groups_ = java.util.Collections.unmodifiableList(groups_);
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_GroupsResponse_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_GroupsResponse_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.sonarqube.ws.Permissions.GroupsResponse.class, org.sonarqube.ws.Permissions.GroupsResponse.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<GroupsResponse> PARSER =
+        new com.google.protobuf.AbstractParser<GroupsResponse>() {
+      public GroupsResponse parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new GroupsResponse(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<GroupsResponse> getParserForType() {
+      return PARSER;
+    }
+
+    public interface GroupOrBuilder extends
+        // @@protoc_insertion_point(interface_extends:sonarqube.ws.permissions.GroupsResponse.Group)
+        com.google.protobuf.MessageOrBuilder {
+
+      /**
+       * <code>optional string id = 1;</code>
+       */
+      boolean hasId();
+      /**
+       * <code>optional string id = 1;</code>
+       */
+      java.lang.String getId();
+      /**
+       * <code>optional string id = 1;</code>
+       */
+      com.google.protobuf.ByteString
+          getIdBytes();
+
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      boolean hasName();
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      java.lang.String getName();
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      com.google.protobuf.ByteString
+          getNameBytes();
+
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      boolean hasDescription();
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      java.lang.String getDescription();
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      com.google.protobuf.ByteString
+          getDescriptionBytes();
+
+      /**
+       * <code>optional bool selected = 4;</code>
+       */
+      boolean hasSelected();
+      /**
+       * <code>optional bool selected = 4;</code>
+       */
+      boolean getSelected();
+    }
+    /**
+     * Protobuf type {@code sonarqube.ws.permissions.GroupsResponse.Group}
+     */
+    public static final class Group extends
+        com.google.protobuf.GeneratedMessage implements
+        // @@protoc_insertion_point(message_implements:sonarqube.ws.permissions.GroupsResponse.Group)
+        GroupOrBuilder {
+      // Use Group.newBuilder() to construct.
+      private Group(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+        super(builder);
+        this.unknownFields = builder.getUnknownFields();
+      }
+      private Group(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+      private static final Group defaultInstance;
+      public static Group getDefaultInstance() {
+        return defaultInstance;
+      }
+
+      public Group getDefaultInstanceForType() {
+        return defaultInstance;
+      }
+
+      private final com.google.protobuf.UnknownFieldSet unknownFields;
+      @java.lang.Override
+      public final com.google.protobuf.UnknownFieldSet
+          getUnknownFields() {
+        return this.unknownFields;
+      }
+      private Group(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        initFields();
+        int mutable_bitField0_ = 0;
+        com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+            com.google.protobuf.UnknownFieldSet.newBuilder();
+        try {
+          boolean done = false;
+          while (!done) {
+            int tag = input.readTag();
+            switch (tag) {
+              case 0:
+                done = true;
+                break;
+              default: {
+                if (!parseUnknownField(input, unknownFields,
+                                       extensionRegistry, tag)) {
+                  done = true;
+                }
+                break;
+              }
+              case 10: {
+                com.google.protobuf.ByteString bs = input.readBytes();
+                bitField0_ |= 0x00000001;
+                id_ = bs;
+                break;
+              }
+              case 18: {
+                com.google.protobuf.ByteString bs = input.readBytes();
+                bitField0_ |= 0x00000002;
+                name_ = bs;
+                break;
+              }
+              case 26: {
+                com.google.protobuf.ByteString bs = input.readBytes();
+                bitField0_ |= 0x00000004;
+                description_ = bs;
+                break;
+              }
+              case 32: {
+                bitField0_ |= 0x00000008;
+                selected_ = input.readBool();
+                break;
+              }
+            }
+          }
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          throw e.setUnfinishedMessage(this);
+        } catch (java.io.IOException e) {
+          throw new com.google.protobuf.InvalidProtocolBufferException(
+              e.getMessage()).setUnfinishedMessage(this);
+        } finally {
+          this.unknownFields = unknownFields.build();
+          makeExtensionsImmutable();
+        }
+      }
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_GroupsResponse_Group_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_GroupsResponse_Group_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonarqube.ws.Permissions.GroupsResponse.Group.class, org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder.class);
+      }
+
+      public static com.google.protobuf.Parser<Group> PARSER =
+          new com.google.protobuf.AbstractParser<Group>() {
+        public Group parsePartialFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+          return new Group(input, extensionRegistry);
+        }
+      };
+
+      @java.lang.Override
+      public com.google.protobuf.Parser<Group> getParserForType() {
+        return PARSER;
+      }
+
+      private int bitField0_;
+      public static final int ID_FIELD_NUMBER = 1;
+      private java.lang.Object id_;
+      /**
+       * <code>optional string id = 1;</code>
+       */
+      public boolean hasId() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>optional string id = 1;</code>
+       */
+      public java.lang.String getId() {
+        java.lang.Object ref = id_;
+        if (ref instanceof java.lang.String) {
+          return (java.lang.String) ref;
+        } else {
+          com.google.protobuf.ByteString bs = 
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            id_ = s;
+          }
+          return s;
+        }
+      }
+      /**
+       * <code>optional string id = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getIdBytes() {
+        java.lang.Object ref = id_;
+        if (ref instanceof java.lang.String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          id_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+
+      public static final int NAME_FIELD_NUMBER = 2;
+      private java.lang.Object name_;
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      public boolean hasName() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      public java.lang.String getName() {
+        java.lang.Object ref = name_;
+        if (ref instanceof java.lang.String) {
+          return (java.lang.String) ref;
+        } else {
+          com.google.protobuf.ByteString bs = 
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            name_ = s;
+          }
+          return s;
+        }
+      }
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      public com.google.protobuf.ByteString
+          getNameBytes() {
+        java.lang.Object ref = name_;
+        if (ref instanceof java.lang.String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          name_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+
+      public static final int DESCRIPTION_FIELD_NUMBER = 3;
+      private java.lang.Object description_;
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      public boolean hasDescription() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      public java.lang.String getDescription() {
+        java.lang.Object ref = description_;
+        if (ref instanceof java.lang.String) {
+          return (java.lang.String) ref;
+        } else {
+          com.google.protobuf.ByteString bs = 
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            description_ = s;
+          }
+          return s;
+        }
+      }
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      public com.google.protobuf.ByteString
+          getDescriptionBytes() {
+        java.lang.Object ref = description_;
+        if (ref instanceof java.lang.String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          description_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+
+      public static final int SELECTED_FIELD_NUMBER = 4;
+      private boolean selected_;
+      /**
+       * <code>optional bool selected = 4;</code>
+       */
+      public boolean hasSelected() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional bool selected = 4;</code>
+       */
+      public boolean getSelected() {
+        return selected_;
+      }
+
+      private void initFields() {
+        id_ = "";
+        name_ = "";
+        description_ = "";
+        selected_ = false;
+      }
+      private byte memoizedIsInitialized = -1;
+      public final boolean isInitialized() {
+        byte isInitialized = memoizedIsInitialized;
+        if (isInitialized == 1) return true;
+        if (isInitialized == 0) return false;
+
+        memoizedIsInitialized = 1;
+        return true;
+      }
+
+      public void writeTo(com.google.protobuf.CodedOutputStream output)
+                          throws java.io.IOException {
+        getSerializedSize();
+        if (((bitField0_ & 0x00000001) == 0x00000001)) {
+          output.writeBytes(1, getIdBytes());
+        }
+        if (((bitField0_ & 0x00000002) == 0x00000002)) {
+          output.writeBytes(2, getNameBytes());
+        }
+        if (((bitField0_ & 0x00000004) == 0x00000004)) {
+          output.writeBytes(3, getDescriptionBytes());
+        }
+        if (((bitField0_ & 0x00000008) == 0x00000008)) {
+          output.writeBool(4, selected_);
+        }
+        getUnknownFields().writeTo(output);
+      }
+
+      private int memoizedSerializedSize = -1;
+      public int getSerializedSize() {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+
+        size = 0;
+        if (((bitField0_ & 0x00000001) == 0x00000001)) {
+          size += com.google.protobuf.CodedOutputStream
+            .computeBytesSize(1, getIdBytes());
+        }
+        if (((bitField0_ & 0x00000002) == 0x00000002)) {
+          size += com.google.protobuf.CodedOutputStream
+            .computeBytesSize(2, getNameBytes());
+        }
+        if (((bitField0_ & 0x00000004) == 0x00000004)) {
+          size += com.google.protobuf.CodedOutputStream
+            .computeBytesSize(3, getDescriptionBytes());
+        }
+        if (((bitField0_ & 0x00000008) == 0x00000008)) {
+          size += com.google.protobuf.CodedOutputStream
+            .computeBoolSize(4, selected_);
+        }
+        size += getUnknownFields().getSerializedSize();
+        memoizedSerializedSize = size;
+        return size;
+      }
+
+      private static final long serialVersionUID = 0L;
+      @java.lang.Override
+      protected java.lang.Object writeReplace()
+          throws java.io.ObjectStreamException {
+        return super.writeReplace();
+      }
+
+      public static org.sonarqube.ws.Permissions.GroupsResponse.Group parseFrom(
+          com.google.protobuf.ByteString data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static org.sonarqube.ws.Permissions.GroupsResponse.Group parseFrom(
+          com.google.protobuf.ByteString data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static org.sonarqube.ws.Permissions.GroupsResponse.Group parseFrom(byte[] data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static org.sonarqube.ws.Permissions.GroupsResponse.Group parseFrom(
+          byte[] data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static org.sonarqube.ws.Permissions.GroupsResponse.Group parseFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input);
+      }
+      public static org.sonarqube.ws.Permissions.GroupsResponse.Group parseFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input, extensionRegistry);
+      }
+      public static org.sonarqube.ws.Permissions.GroupsResponse.Group parseDelimitedFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return PARSER.parseDelimitedFrom(input);
+      }
+      public static org.sonarqube.ws.Permissions.GroupsResponse.Group parseDelimitedFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseDelimitedFrom(input, extensionRegistry);
+      }
+      public static org.sonarqube.ws.Permissions.GroupsResponse.Group parseFrom(
+          com.google.protobuf.CodedInputStream input)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input);
+      }
+      public static org.sonarqube.ws.Permissions.GroupsResponse.Group parseFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input, extensionRegistry);
+      }
+
+      public static Builder newBuilder() { return Builder.create(); }
+      public Builder newBuilderForType() { return newBuilder(); }
+      public static Builder newBuilder(org.sonarqube.ws.Permissions.GroupsResponse.Group prototype) {
+        return newBuilder().mergeFrom(prototype);
+      }
+      public Builder toBuilder() { return newBuilder(this); }
+
+      @java.lang.Override
+      protected Builder newBuilderForType(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        Builder builder = new Builder(parent);
+        return builder;
+      }
+      /**
+       * Protobuf type {@code sonarqube.ws.permissions.GroupsResponse.Group}
+       */
+      public static final class Builder extends
+          com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+          // @@protoc_insertion_point(builder_implements:sonarqube.ws.permissions.GroupsResponse.Group)
+          org.sonarqube.ws.Permissions.GroupsResponse.GroupOrBuilder {
+        public static final com.google.protobuf.Descriptors.Descriptor
+            getDescriptor() {
+          return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_GroupsResponse_Group_descriptor;
+        }
+
+        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+            internalGetFieldAccessorTable() {
+          return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_GroupsResponse_Group_fieldAccessorTable
+              .ensureFieldAccessorsInitialized(
+                  org.sonarqube.ws.Permissions.GroupsResponse.Group.class, org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder.class);
+        }
+
+        // Construct using org.sonarqube.ws.Permissions.GroupsResponse.Group.newBuilder()
+        private Builder() {
+          maybeForceBuilderInitialization();
+        }
+
+        private Builder(
+            com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+          super(parent);
+          maybeForceBuilderInitialization();
+        }
+        private void maybeForceBuilderInitialization() {
+          if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          }
+        }
+        private static Builder create() {
+          return new Builder();
+        }
+
+        public Builder clear() {
+          super.clear();
+          id_ = "";
+          bitField0_ = (bitField0_ & ~0x00000001);
+          name_ = "";
+          bitField0_ = (bitField0_ & ~0x00000002);
+          description_ = "";
+          bitField0_ = (bitField0_ & ~0x00000004);
+          selected_ = false;
+          bitField0_ = (bitField0_ & ~0x00000008);
+          return this;
+        }
+
+        public Builder clone() {
+          return create().mergeFrom(buildPartial());
+        }
+
+        public com.google.protobuf.Descriptors.Descriptor
+            getDescriptorForType() {
+          return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_GroupsResponse_Group_descriptor;
+        }
+
+        public org.sonarqube.ws.Permissions.GroupsResponse.Group getDefaultInstanceForType() {
+          return org.sonarqube.ws.Permissions.GroupsResponse.Group.getDefaultInstance();
+        }
+
+        public org.sonarqube.ws.Permissions.GroupsResponse.Group build() {
+          org.sonarqube.ws.Permissions.GroupsResponse.Group result = buildPartial();
+          if (!result.isInitialized()) {
+            throw newUninitializedMessageException(result);
+          }
+          return result;
+        }
+
+        public org.sonarqube.ws.Permissions.GroupsResponse.Group buildPartial() {
+          org.sonarqube.ws.Permissions.GroupsResponse.Group result = new org.sonarqube.ws.Permissions.GroupsResponse.Group(this);
+          int from_bitField0_ = bitField0_;
+          int to_bitField0_ = 0;
+          if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+            to_bitField0_ |= 0x00000001;
+          }
+          result.id_ = id_;
+          if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+            to_bitField0_ |= 0x00000002;
+          }
+          result.name_ = name_;
+          if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+            to_bitField0_ |= 0x00000004;
+          }
+          result.description_ = description_;
+          if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+            to_bitField0_ |= 0x00000008;
+          }
+          result.selected_ = selected_;
+          result.bitField0_ = to_bitField0_;
+          onBuilt();
+          return result;
+        }
+
+        public Builder mergeFrom(com.google.protobuf.Message other) {
+          if (other instanceof org.sonarqube.ws.Permissions.GroupsResponse.Group) {
+            return mergeFrom((org.sonarqube.ws.Permissions.GroupsResponse.Group)other);
+          } else {
+            super.mergeFrom(other);
+            return this;
+          }
+        }
+
+        public Builder mergeFrom(org.sonarqube.ws.Permissions.GroupsResponse.Group other) {
+          if (other == org.sonarqube.ws.Permissions.GroupsResponse.Group.getDefaultInstance()) return this;
+          if (other.hasId()) {
+            bitField0_ |= 0x00000001;
+            id_ = other.id_;
+            onChanged();
+          }
+          if (other.hasName()) {
+            bitField0_ |= 0x00000002;
+            name_ = other.name_;
+            onChanged();
+          }
+          if (other.hasDescription()) {
+            bitField0_ |= 0x00000004;
+            description_ = other.description_;
+            onChanged();
+          }
+          if (other.hasSelected()) {
+            setSelected(other.getSelected());
+          }
+          this.mergeUnknownFields(other.getUnknownFields());
+          return this;
+        }
+
+        public final boolean isInitialized() {
+          return true;
+        }
+
+        public Builder mergeFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+          org.sonarqube.ws.Permissions.GroupsResponse.Group parsedMessage = null;
+          try {
+            parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+            parsedMessage = (org.sonarqube.ws.Permissions.GroupsResponse.Group) e.getUnfinishedMessage();
+            throw e;
+          } finally {
+            if (parsedMessage != null) {
+              mergeFrom(parsedMessage);
+            }
+          }
+          return this;
+        }
+        private int bitField0_;
+
+        private java.lang.Object id_ = "";
+        /**
+         * <code>optional string id = 1;</code>
+         */
+        public boolean hasId() {
+          return ((bitField0_ & 0x00000001) == 0x00000001);
+        }
+        /**
+         * <code>optional string id = 1;</code>
+         */
+        public java.lang.String getId() {
+          java.lang.Object ref = id_;
+          if (!(ref instanceof java.lang.String)) {
+            com.google.protobuf.ByteString bs =
+                (com.google.protobuf.ByteString) ref;
+            java.lang.String s = bs.toStringUtf8();
+            if (bs.isValidUtf8()) {
+              id_ = s;
+            }
+            return s;
+          } else {
+            return (java.lang.String) ref;
+          }
+        }
+        /**
+         * <code>optional string id = 1;</code>
+         */
+        public com.google.protobuf.ByteString
+            getIdBytes() {
+          java.lang.Object ref = id_;
+          if (ref instanceof String) {
+            com.google.protobuf.ByteString b = 
+                com.google.protobuf.ByteString.copyFromUtf8(
+                    (java.lang.String) ref);
+            id_ = b;
+            return b;
+          } else {
+            return (com.google.protobuf.ByteString) ref;
+          }
+        }
+        /**
+         * <code>optional string id = 1;</code>
+         */
+        public Builder setId(
+            java.lang.String value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+          id_ = value;
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>optional string id = 1;</code>
+         */
+        public Builder clearId() {
+          bitField0_ = (bitField0_ & ~0x00000001);
+          id_ = getDefaultInstance().getId();
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>optional string id = 1;</code>
+         */
+        public Builder setIdBytes(
+            com.google.protobuf.ByteString value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+          id_ = value;
+          onChanged();
+          return this;
+        }
+
+        private java.lang.Object name_ = "";
+        /**
+         * <code>optional string name = 2;</code>
+         */
+        public boolean hasName() {
+          return ((bitField0_ & 0x00000002) == 0x00000002);
+        }
+        /**
+         * <code>optional string name = 2;</code>
+         */
+        public java.lang.String getName() {
+          java.lang.Object ref = name_;
+          if (!(ref instanceof java.lang.String)) {
+            com.google.protobuf.ByteString bs =
+                (com.google.protobuf.ByteString) ref;
+            java.lang.String s = bs.toStringUtf8();
+            if (bs.isValidUtf8()) {
+              name_ = s;
+            }
+            return s;
+          } else {
+            return (java.lang.String) ref;
+          }
+        }
+        /**
+         * <code>optional string name = 2;</code>
+         */
+        public com.google.protobuf.ByteString
+            getNameBytes() {
+          java.lang.Object ref = name_;
+          if (ref instanceof String) {
+            com.google.protobuf.ByteString b = 
+                com.google.protobuf.ByteString.copyFromUtf8(
+                    (java.lang.String) ref);
+            name_ = b;
+            return b;
+          } else {
+            return (com.google.protobuf.ByteString) ref;
+          }
+        }
+        /**
+         * <code>optional string name = 2;</code>
+         */
+        public Builder setName(
+            java.lang.String value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+          name_ = value;
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>optional string name = 2;</code>
+         */
+        public Builder clearName() {
+          bitField0_ = (bitField0_ & ~0x00000002);
+          name_ = getDefaultInstance().getName();
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>optional string name = 2;</code>
+         */
+        public Builder setNameBytes(
+            com.google.protobuf.ByteString value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+          name_ = value;
+          onChanged();
+          return this;
+        }
+
+        private java.lang.Object description_ = "";
+        /**
+         * <code>optional string description = 3;</code>
+         */
+        public boolean hasDescription() {
+          return ((bitField0_ & 0x00000004) == 0x00000004);
+        }
+        /**
+         * <code>optional string description = 3;</code>
+         */
+        public java.lang.String getDescription() {
+          java.lang.Object ref = description_;
+          if (!(ref instanceof java.lang.String)) {
+            com.google.protobuf.ByteString bs =
+                (com.google.protobuf.ByteString) ref;
+            java.lang.String s = bs.toStringUtf8();
+            if (bs.isValidUtf8()) {
+              description_ = s;
+            }
+            return s;
+          } else {
+            return (java.lang.String) ref;
+          }
+        }
+        /**
+         * <code>optional string description = 3;</code>
+         */
+        public com.google.protobuf.ByteString
+            getDescriptionBytes() {
+          java.lang.Object ref = description_;
+          if (ref instanceof String) {
+            com.google.protobuf.ByteString b = 
+                com.google.protobuf.ByteString.copyFromUtf8(
+                    (java.lang.String) ref);
+            description_ = b;
+            return b;
+          } else {
+            return (com.google.protobuf.ByteString) ref;
+          }
+        }
+        /**
+         * <code>optional string description = 3;</code>
+         */
+        public Builder setDescription(
+            java.lang.String value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+          description_ = value;
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>optional string description = 3;</code>
+         */
+        public Builder clearDescription() {
+          bitField0_ = (bitField0_ & ~0x00000004);
+          description_ = getDefaultInstance().getDescription();
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>optional string description = 3;</code>
+         */
+        public Builder setDescriptionBytes(
+            com.google.protobuf.ByteString value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+          description_ = value;
+          onChanged();
+          return this;
+        }
+
+        private boolean selected_ ;
+        /**
+         * <code>optional bool selected = 4;</code>
+         */
+        public boolean hasSelected() {
+          return ((bitField0_ & 0x00000008) == 0x00000008);
+        }
+        /**
+         * <code>optional bool selected = 4;</code>
+         */
+        public boolean getSelected() {
+          return selected_;
+        }
+        /**
+         * <code>optional bool selected = 4;</code>
+         */
+        public Builder setSelected(boolean value) {
+          bitField0_ |= 0x00000008;
+          selected_ = value;
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>optional bool selected = 4;</code>
+         */
+        public Builder clearSelected() {
+          bitField0_ = (bitField0_ & ~0x00000008);
+          selected_ = false;
+          onChanged();
+          return this;
+        }
+
+        // @@protoc_insertion_point(builder_scope:sonarqube.ws.permissions.GroupsResponse.Group)
+      }
+
+      static {
+        defaultInstance = new Group(true);
+        defaultInstance.initFields();
+      }
+
+      // @@protoc_insertion_point(class_scope:sonarqube.ws.permissions.GroupsResponse.Group)
+    }
+
+    private int bitField0_;
+    public static final int GROUPS_FIELD_NUMBER = 1;
+    private java.util.List<org.sonarqube.ws.Permissions.GroupsResponse.Group> groups_;
+    /**
+     * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+     */
+    public java.util.List<org.sonarqube.ws.Permissions.GroupsResponse.Group> getGroupsList() {
+      return groups_;
+    }
+    /**
+     * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+     */
+    public java.util.List<? extends org.sonarqube.ws.Permissions.GroupsResponse.GroupOrBuilder> 
+        getGroupsOrBuilderList() {
+      return groups_;
+    }
+    /**
+     * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+     */
+    public int getGroupsCount() {
+      return groups_.size();
+    }
+    /**
+     * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+     */
+    public org.sonarqube.ws.Permissions.GroupsResponse.Group getGroups(int index) {
+      return groups_.get(index);
+    }
+    /**
+     * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+     */
+    public org.sonarqube.ws.Permissions.GroupsResponse.GroupOrBuilder getGroupsOrBuilder(
+        int index) {
+      return groups_.get(index);
+    }
+
+    public static final int PAGING_FIELD_NUMBER = 2;
+    private org.sonarqube.ws.Common.Paging paging_;
+    /**
+     * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+     */
+    public boolean hasPaging() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+     */
+    public org.sonarqube.ws.Common.Paging getPaging() {
+      return paging_;
+    }
+    /**
+     * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+     */
+    public org.sonarqube.ws.Common.PagingOrBuilder getPagingOrBuilder() {
+      return paging_;
+    }
+
+    private void initFields() {
+      groups_ = java.util.Collections.emptyList();
+      paging_ = org.sonarqube.ws.Common.Paging.getDefaultInstance();
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      for (int i = 0; i < groups_.size(); i++) {
+        output.writeMessage(1, groups_.get(i));
+      }
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeMessage(2, paging_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      for (int i = 0; i < groups_.size(); i++) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(1, groups_.get(i));
+      }
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(2, paging_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.sonarqube.ws.Permissions.GroupsResponse parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonarqube.ws.Permissions.GroupsResponse parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.GroupsResponse parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonarqube.ws.Permissions.GroupsResponse parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.GroupsResponse parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonarqube.ws.Permissions.GroupsResponse parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.GroupsResponse parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.sonarqube.ws.Permissions.GroupsResponse parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.GroupsResponse parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonarqube.ws.Permissions.GroupsResponse parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.sonarqube.ws.Permissions.GroupsResponse prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code sonarqube.ws.permissions.GroupsResponse}
+     *
+     * <pre>
+     * WS api/permissions/groups for internal use only
+     * </pre>
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:sonarqube.ws.permissions.GroupsResponse)
+        org.sonarqube.ws.Permissions.GroupsResponseOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_GroupsResponse_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_GroupsResponse_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonarqube.ws.Permissions.GroupsResponse.class, org.sonarqube.ws.Permissions.GroupsResponse.Builder.class);
+      }
+
+      // Construct using org.sonarqube.ws.Permissions.GroupsResponse.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          getGroupsFieldBuilder();
+          getPagingFieldBuilder();
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        if (groupsBuilder_ == null) {
+          groups_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
+        } else {
+          groupsBuilder_.clear();
+        }
+        if (pagingBuilder_ == null) {
+          paging_ = org.sonarqube.ws.Common.Paging.getDefaultInstance();
+        } else {
+          pagingBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000002);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_GroupsResponse_descriptor;
+      }
+
+      public org.sonarqube.ws.Permissions.GroupsResponse getDefaultInstanceForType() {
+        return org.sonarqube.ws.Permissions.GroupsResponse.getDefaultInstance();
+      }
+
+      public org.sonarqube.ws.Permissions.GroupsResponse build() {
+        org.sonarqube.ws.Permissions.GroupsResponse result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.sonarqube.ws.Permissions.GroupsResponse buildPartial() {
+        org.sonarqube.ws.Permissions.GroupsResponse result = new org.sonarqube.ws.Permissions.GroupsResponse(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (groupsBuilder_ == null) {
+          if (((bitField0_ & 0x00000001) == 0x00000001)) {
+            groups_ = java.util.Collections.unmodifiableList(groups_);
+            bitField0_ = (bitField0_ & ~0x00000001);
+          }
+          result.groups_ = groups_;
+        } else {
+          result.groups_ = groupsBuilder_.build();
+        }
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        if (pagingBuilder_ == null) {
+          result.paging_ = paging_;
+        } else {
+          result.paging_ = pagingBuilder_.build();
+        }
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.sonarqube.ws.Permissions.GroupsResponse) {
+          return mergeFrom((org.sonarqube.ws.Permissions.GroupsResponse)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.sonarqube.ws.Permissions.GroupsResponse other) {
+        if (other == org.sonarqube.ws.Permissions.GroupsResponse.getDefaultInstance()) return this;
+        if (groupsBuilder_ == null) {
+          if (!other.groups_.isEmpty()) {
+            if (groups_.isEmpty()) {
+              groups_ = other.groups_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+            } else {
+              ensureGroupsIsMutable();
+              groups_.addAll(other.groups_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.groups_.isEmpty()) {
+            if (groupsBuilder_.isEmpty()) {
+              groupsBuilder_.dispose();
+              groupsBuilder_ = null;
+              groups_ = other.groups_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+              groupsBuilder_ = 
+                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+                   getGroupsFieldBuilder() : null;
+            } else {
+              groupsBuilder_.addAllMessages(other.groups_);
+            }
+          }
+        }
+        if (other.hasPaging()) {
+          mergePaging(other.getPaging());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.sonarqube.ws.Permissions.GroupsResponse parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.sonarqube.ws.Permissions.GroupsResponse) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      private java.util.List<org.sonarqube.ws.Permissions.GroupsResponse.Group> groups_ =
+        java.util.Collections.emptyList();
+      private void ensureGroupsIsMutable() {
+        if (!((bitField0_ & 0x00000001) == 0x00000001)) {
+          groups_ = new java.util.ArrayList<org.sonarqube.ws.Permissions.GroupsResponse.Group>(groups_);
+          bitField0_ |= 0x00000001;
+         }
+      }
+
+      private com.google.protobuf.RepeatedFieldBuilder<
+          org.sonarqube.ws.Permissions.GroupsResponse.Group, org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder, org.sonarqube.ws.Permissions.GroupsResponse.GroupOrBuilder> groupsBuilder_;
+
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public java.util.List<org.sonarqube.ws.Permissions.GroupsResponse.Group> getGroupsList() {
+        if (groupsBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(groups_);
+        } else {
+          return groupsBuilder_.getMessageList();
+        }
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public int getGroupsCount() {
+        if (groupsBuilder_ == null) {
+          return groups_.size();
+        } else {
+          return groupsBuilder_.getCount();
+        }
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public org.sonarqube.ws.Permissions.GroupsResponse.Group getGroups(int index) {
+        if (groupsBuilder_ == null) {
+          return groups_.get(index);
+        } else {
+          return groupsBuilder_.getMessage(index);
+        }
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public Builder setGroups(
+          int index, org.sonarqube.ws.Permissions.GroupsResponse.Group value) {
+        if (groupsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureGroupsIsMutable();
+          groups_.set(index, value);
+          onChanged();
+        } else {
+          groupsBuilder_.setMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public Builder setGroups(
+          int index, org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder builderForValue) {
+        if (groupsBuilder_ == null) {
+          ensureGroupsIsMutable();
+          groups_.set(index, builderForValue.build());
+          onChanged();
+        } else {
+          groupsBuilder_.setMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public Builder addGroups(org.sonarqube.ws.Permissions.GroupsResponse.Group value) {
+        if (groupsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureGroupsIsMutable();
+          groups_.add(value);
+          onChanged();
+        } else {
+          groupsBuilder_.addMessage(value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public Builder addGroups(
+          int index, org.sonarqube.ws.Permissions.GroupsResponse.Group value) {
+        if (groupsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureGroupsIsMutable();
+          groups_.add(index, value);
+          onChanged();
+        } else {
+          groupsBuilder_.addMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public Builder addGroups(
+          org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder builderForValue) {
+        if (groupsBuilder_ == null) {
+          ensureGroupsIsMutable();
+          groups_.add(builderForValue.build());
+          onChanged();
+        } else {
+          groupsBuilder_.addMessage(builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public Builder addGroups(
+          int index, org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder builderForValue) {
+        if (groupsBuilder_ == null) {
+          ensureGroupsIsMutable();
+          groups_.add(index, builderForValue.build());
+          onChanged();
+        } else {
+          groupsBuilder_.addMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public Builder addAllGroups(
+          java.lang.Iterable<? extends org.sonarqube.ws.Permissions.GroupsResponse.Group> values) {
+        if (groupsBuilder_ == null) {
+          ensureGroupsIsMutable();
+          com.google.protobuf.AbstractMessageLite.Builder.addAll(
+              values, groups_);
+          onChanged();
+        } else {
+          groupsBuilder_.addAllMessages(values);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public Builder clearGroups() {
+        if (groupsBuilder_ == null) {
+          groups_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
+          onChanged();
+        } else {
+          groupsBuilder_.clear();
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public Builder removeGroups(int index) {
+        if (groupsBuilder_ == null) {
+          ensureGroupsIsMutable();
+          groups_.remove(index);
+          onChanged();
+        } else {
+          groupsBuilder_.remove(index);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder getGroupsBuilder(
+          int index) {
+        return getGroupsFieldBuilder().getBuilder(index);
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public org.sonarqube.ws.Permissions.GroupsResponse.GroupOrBuilder getGroupsOrBuilder(
+          int index) {
+        if (groupsBuilder_ == null) {
+          return groups_.get(index);  } else {
+          return groupsBuilder_.getMessageOrBuilder(index);
+        }
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public java.util.List<? extends org.sonarqube.ws.Permissions.GroupsResponse.GroupOrBuilder> 
+           getGroupsOrBuilderList() {
+        if (groupsBuilder_ != null) {
+          return groupsBuilder_.getMessageOrBuilderList();
+        } else {
+          return java.util.Collections.unmodifiableList(groups_);
+        }
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder addGroupsBuilder() {
+        return getGroupsFieldBuilder().addBuilder(
+            org.sonarqube.ws.Permissions.GroupsResponse.Group.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder addGroupsBuilder(
+          int index) {
+        return getGroupsFieldBuilder().addBuilder(
+            index, org.sonarqube.ws.Permissions.GroupsResponse.Group.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .sonarqube.ws.permissions.GroupsResponse.Group groups = 1;</code>
+       */
+      public java.util.List<org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder> 
+           getGroupsBuilderList() {
+        return getGroupsFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilder<
+          org.sonarqube.ws.Permissions.GroupsResponse.Group, org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder, org.sonarqube.ws.Permissions.GroupsResponse.GroupOrBuilder> 
+          getGroupsFieldBuilder() {
+        if (groupsBuilder_ == null) {
+          groupsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+              org.sonarqube.ws.Permissions.GroupsResponse.Group, org.sonarqube.ws.Permissions.GroupsResponse.Group.Builder, org.sonarqube.ws.Permissions.GroupsResponse.GroupOrBuilder>(
+                  groups_,
+                  ((bitField0_ & 0x00000001) == 0x00000001),
+                  getParentForChildren(),
+                  isClean());
+          groups_ = null;
+        }
+        return groupsBuilder_;
+      }
+
+      private org.sonarqube.ws.Common.Paging paging_ = org.sonarqube.ws.Common.Paging.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.sonarqube.ws.Common.Paging, org.sonarqube.ws.Common.Paging.Builder, org.sonarqube.ws.Common.PagingOrBuilder> pagingBuilder_;
+      /**
+       * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+       */
+      public boolean hasPaging() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+       */
+      public org.sonarqube.ws.Common.Paging getPaging() {
+        if (pagingBuilder_ == null) {
+          return paging_;
+        } else {
+          return pagingBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+       */
+      public Builder setPaging(org.sonarqube.ws.Common.Paging value) {
+        if (pagingBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          paging_ = value;
+          onChanged();
+        } else {
+          pagingBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000002;
+        return this;
+      }
+      /**
+       * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+       */
+      public Builder setPaging(
+          org.sonarqube.ws.Common.Paging.Builder builderForValue) {
+        if (pagingBuilder_ == null) {
+          paging_ = builderForValue.build();
+          onChanged();
+        } else {
+          pagingBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000002;
+        return this;
+      }
+      /**
+       * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+       */
+      public Builder mergePaging(org.sonarqube.ws.Common.Paging value) {
+        if (pagingBuilder_ == null) {
+          if (((bitField0_ & 0x00000002) == 0x00000002) &&
+              paging_ != org.sonarqube.ws.Common.Paging.getDefaultInstance()) {
+            paging_ =
+              org.sonarqube.ws.Common.Paging.newBuilder(paging_).mergeFrom(value).buildPartial();
+          } else {
+            paging_ = value;
+          }
+          onChanged();
+        } else {
+          pagingBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000002;
+        return this;
+      }
+      /**
+       * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+       */
+      public Builder clearPaging() {
+        if (pagingBuilder_ == null) {
+          paging_ = org.sonarqube.ws.Common.Paging.getDefaultInstance();
+          onChanged();
+        } else {
+          pagingBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000002);
+        return this;
+      }
+      /**
+       * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+       */
+      public org.sonarqube.ws.Common.Paging.Builder getPagingBuilder() {
+        bitField0_ |= 0x00000002;
+        onChanged();
+        return getPagingFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+       */
+      public org.sonarqube.ws.Common.PagingOrBuilder getPagingOrBuilder() {
+        if (pagingBuilder_ != null) {
+          return pagingBuilder_.getMessageOrBuilder();
+        } else {
+          return paging_;
+        }
+      }
+      /**
+       * <code>optional .sonarqube.ws.commons.Paging paging = 2;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.sonarqube.ws.Common.Paging, org.sonarqube.ws.Common.Paging.Builder, org.sonarqube.ws.Common.PagingOrBuilder> 
+          getPagingFieldBuilder() {
+        if (pagingBuilder_ == null) {
+          pagingBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.sonarqube.ws.Common.Paging, org.sonarqube.ws.Common.Paging.Builder, org.sonarqube.ws.Common.PagingOrBuilder>(
+                  getPaging(),
+                  getParentForChildren(),
+                  isClean());
+          paging_ = null;
+        }
+        return pagingBuilder_;
+      }
+
+      // @@protoc_insertion_point(builder_scope:sonarqube.ws.permissions.GroupsResponse)
+    }
+
+    static {
+      defaultInstance = new GroupsResponse(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:sonarqube.ws.permissions.GroupsResponse)
+  }
+
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_permissions_UsersResponse_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_permissions_UsersResponse_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_permissions_UsersResponse_User_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_permissions_UsersResponse_User_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_permissions_GroupsResponse_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_permissions_GroupsResponse_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_permissions_GroupsResponse_Group_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_permissions_GroupsResponse_Group_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\024ws-permissions.proto\022\030sonarqube.ws.per" +
+      "missions\032\020ws-commons.proto\"\261\001\n\rUsersResp" +
+      "onse\022;\n\005users\030\001 \003(\0132,.sonarqube.ws.permi" +
+      "ssions.UsersResponse.User\022,\n\006paging\030\002 \001(" +
+      "\0132\034.sonarqube.ws.commons.Paging\0325\n\004User\022" +
+      "\r\n\005login\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\022\020\n\010selected" +
+      "\030\003 \001(\010\"\310\001\n\016GroupsResponse\022>\n\006groups\030\001 \003(" +
+      "\0132..sonarqube.ws.permissions.GroupsRespo" +
+      "nse.Group\022,\n\006paging\030\002 \001(\0132\034.sonarqube.ws" +
+      ".commons.Paging\032H\n\005Group\022\n\n\002id\030\001 \001(\t\022\014\n\004",
+      "name\030\002 \001(\t\022\023\n\013description\030\003 \001(\t\022\020\n\010selec" +
+      "ted\030\004 \001(\010B!\n\020org.sonarqube.wsB\013Permissio" +
+      "nsH\001"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+        new com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
+          public com.google.protobuf.ExtensionRegistry assignDescriptors(
+              com.google.protobuf.Descriptors.FileDescriptor root) {
+            descriptor = root;
+            return null;
+          }
+        };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+          org.sonarqube.ws.Common.getDescriptor(),
+        }, assigner);
+    internal_static_sonarqube_ws_permissions_UsersResponse_descriptor =
+      getDescriptor().getMessageTypes().get(0);
+    internal_static_sonarqube_ws_permissions_UsersResponse_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_permissions_UsersResponse_descriptor,
+        new java.lang.String[] { "Users", "Paging", });
+    internal_static_sonarqube_ws_permissions_UsersResponse_User_descriptor =
+      internal_static_sonarqube_ws_permissions_UsersResponse_descriptor.getNestedTypes().get(0);
+    internal_static_sonarqube_ws_permissions_UsersResponse_User_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_permissions_UsersResponse_User_descriptor,
+        new java.lang.String[] { "Login", "Name", "Selected", });
+    internal_static_sonarqube_ws_permissions_GroupsResponse_descriptor =
+      getDescriptor().getMessageTypes().get(1);
+    internal_static_sonarqube_ws_permissions_GroupsResponse_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_permissions_GroupsResponse_descriptor,
+        new java.lang.String[] { "Groups", "Paging", });
+    internal_static_sonarqube_ws_permissions_GroupsResponse_Group_descriptor =
+      internal_static_sonarqube_ws_permissions_GroupsResponse_descriptor.getNestedTypes().get(0);
+    internal_static_sonarqube_ws_permissions_GroupsResponse_Group_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_permissions_GroupsResponse_Group_descriptor,
+        new java.lang.String[] { "Id", "Name", "Description", "Selected", });
     org.sonarqube.ws.Common.getDescriptor();
   }
 
index fee84a0680cf607942313fc4971ca6a9de8482cb..78a2705d3ff81e7df45d803be2dca1578b4f3bf1 100644 (file)
@@ -28,7 +28,6 @@ message Paging {
   optional int32 pageIndex = 1;
   optional int32 pageSize = 2;
   optional int32 total = 3;
-  optional int32 pages = 4;
 }
 
 message Facet {
index f68c26c792f23040b1e6a390cbca77238cd5ea04..151b3fa14236cfb6b8053f3ff42d086fadb30783 100644 (file)
@@ -32,9 +32,23 @@ message UsersResponse {
   message User {
     optional string login = 1;
     optional string name = 2;
-    optional bool selected = 4;
+    optional bool selected = 3;
   }
 
   repeated User users = 1;
   optional sonarqube.ws.commons.Paging paging = 2;
 }
+
+// WS api/permissions/groups for internal use only
+message GroupsResponse {
+
+  message Group {
+    optional string id = 1;
+    optional string name = 2;
+    optional string description = 3;
+    optional bool selected = 4;
+  }
+
+  repeated Group groups = 1;
+  optional sonarqube.ws.commons.Paging paging = 2;
+}