]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6470 New Java WS to show a user's groups
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Tue, 5 May 2015 13:38:14 +0000 (15:38 +0200)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Thu, 7 May 2015 14:40:09 +0000 (16:40 +0200)
16 files changed:
server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/user/ws/example-groups.json [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_admin.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_page1.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_page2.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_users.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/deselected.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/empty.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/selected.json [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/user/GroupMembershipDao.java
sonar-core/src/main/resources/org/sonar/core/user/GroupMembershipMapper.xml
sonar-core/src/test/java/org/sonar/core/user/GroupMembershipDaoTest.java

index d3340efd5fe1b473254523ed3579aaddbf022db2..78fc76fde3f110b956d82465cd4e6ed3fdc18a8c 100644 (file)
@@ -34,6 +34,7 @@ import org.sonar.core.technicaldebt.db.CharacteristicDao;
 import org.sonar.core.template.LoadedTemplateDao;
 import org.sonar.core.user.AuthorDao;
 import org.sonar.core.user.AuthorizationDao;
+import org.sonar.core.user.GroupMembershipDao;
 import org.sonar.server.activity.db.ActivityDao;
 import org.sonar.server.component.db.ComponentDao;
 import org.sonar.server.component.db.ComponentIndexDao;
@@ -85,6 +86,7 @@ public class DbClient implements ServerComponent {
   private final UserDao userDao;
   private final GroupDao groupDao;
   private final UserGroupDao userGroupDao;
+  private final GroupMembershipDao groupMembershipDao;
   private final IssueDao issueDao;
   private final IssueFilterDao issueFilterDao;
   private final IssueChangeDao issueChangeDao;
@@ -124,6 +126,7 @@ public class DbClient implements ServerComponent {
     userDao = getDao(map, UserDao.class);
     groupDao = getDao(map, GroupDao.class);
     userGroupDao = getDao(map, UserGroupDao.class);
+    groupMembershipDao = getDao(map, GroupMembershipDao.class);
     issueDao = getDao(map, IssueDao.class);
     issueFilterDao = getDao(map, IssueFilterDao.class);
     issueChangeDao = getDao(map, IssueChangeDao.class);
@@ -224,6 +227,10 @@ public class DbClient implements ServerComponent {
     return userGroupDao;
   }
 
+  public GroupMembershipDao groupMembershipDao() {
+    return groupMembershipDao;
+  }
+
   public ActionPlanDao actionPlanDao() {
     return actionPlanDao;
   }
index 0fd77b02562fe64d781d6ed8912b713fd03566d8..b6347f84e61217fbda7bae0a6728481a4a30ed6d 100644 (file)
@@ -762,6 +762,7 @@ class ServerComponents {
     pico.addSingleton(org.sonar.server.user.ws.ChangePasswordAction.class);
     pico.addSingleton(org.sonar.server.user.ws.CurrentUserAction.class);
     pico.addSingleton(org.sonar.server.user.ws.SearchAction.class);
+    pico.addSingleton(org.sonar.server.user.ws.GroupsAction.class);
     pico.addSingleton(org.sonar.server.issue.ws.AuthorsAction.class);
     pico.addSingleton(FavoritesWs.class);
     pico.addSingleton(UserPropertiesWs.class);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java
new file mode 100644 (file)
index 0000000..f493c2f
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * 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.user.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.utils.Paging;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.user.GroupMembershipDto;
+import org.sonar.core.user.GroupMembershipQuery;
+import org.sonar.core.user.UserDto;
+import org.sonar.server.db.DbClient;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+
+public class GroupsAction implements BaseUsersWsAction {
+
+  private static final String PARAM_LOGIN = "login";
+  private static final String PARAM_SELECTED = "selected";
+  private static final String PARAM_QUERY = "q";
+
+  private static final String SELECTION_ALL = "all";
+  private static final String SELECTION_SELECTED = "selected";
+  private static final String SELECTION_DESELECTED = "deselected";
+
+  private final DbClient dbClient;
+
+  public GroupsAction(DbClient dbClient) {
+    this.dbClient = dbClient;
+  }
+
+  @Override
+  public void define(NewController context) {
+    NewAction action = context.createAction("groups")
+      .setDescription("List the groups a user belongs to.")
+      .setHandler(this)
+      .setResponseExample(getClass().getResource("example-groups.json"))
+      .setSince("5.2");
+
+    action.createParam(PARAM_LOGIN)
+      .setDescription("A user login")
+      .setExampleValue("admin")
+      .setRequired(true);
+
+    action.createParam(PARAM_SELECTED)
+      .setDescription("If specified, only show groups the user is member of (selected) or not (deselected).")
+      .setPossibleValues(SELECTION_SELECTED, SELECTION_DESELECTED, SELECTION_ALL)
+      .setDefaultValue(SELECTION_ALL);
+
+    action.createParam(PARAM_QUERY)
+      .setDescription("If specified, only show groups whose name contains the query.")
+      .setExampleValue("user");
+
+    action.addPagingParams(25);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    String login = request.mandatoryParam(PARAM_LOGIN);
+    int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE);
+    int page = request.mandatoryParamAsInt(Param.PAGE);
+    String queryString = request.param(PARAM_QUERY);
+    String selected = request.param(PARAM_SELECTED);
+
+    GroupMembershipQuery query = GroupMembershipQuery.builder()
+      .login(login)
+      .groupSearch(queryString)
+      .membership(getMembership(selected))
+      .pageIndex(page)
+      .pageSize(pageSize)
+      .build();
+
+    DbSession session = dbClient.openSession(false);
+    try {
+      UserDto user = dbClient.userDao().selectByLogin(session, login);
+      int total = dbClient.groupMembershipDao().countGroups(session, query, user.getId());
+      Paging paging = Paging.create(pageSize, page, total);
+      List<GroupMembershipDto> groups = dbClient.groupMembershipDao().selectGroups(session, query, user.getId(), paging.offset(), pageSize);
+
+      JsonWriter json = response.newJsonWriter().beginObject();
+      writeGroups(json, groups);
+      writePaging(json, paging);
+      json.endObject().close();
+    } finally {
+      session.close();
+    }
+  }
+
+  private void writeGroups(JsonWriter json, List<GroupMembershipDto> groups) {
+    json.name("groups").beginArray();
+    for (GroupMembershipDto group : groups) {
+      json.beginObject()
+        .prop("name", group.getName())
+        .prop("description", group.getDescription())
+        .prop("selected", group.getUserId() != null)
+        .endObject();
+    }
+    json.endArray();
+  }
+
+  private void writePaging(JsonWriter json, Paging paging) {
+    json.prop("p", paging.pageIndex())
+      .prop("ps", paging.pageSize())
+      .prop("total", paging.total());
+  }
+
+  private String getMembership(@Nullable String selected) {
+    String membership = GroupMembershipQuery.ANY;
+    if (SELECTION_SELECTED.equals(selected)) {
+      membership = GroupMembershipQuery.IN;
+    } else if (SELECTION_DESELECTED.equals(selected)) {
+      membership = GroupMembershipQuery.OUT;
+    }
+    return membership;
+  }
+}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/user/ws/example-groups.json b/server/sonar-server/src/main/resources/org/sonar/server/user/ws/example-groups.json
new file mode 100644 (file)
index 0000000..ef1ca05
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "p": 1,
+  "ps": 25,
+  "total": 2,
+  "groups": [
+    {"name": "sonar-admins", "description": "Sonar Admins", "selected": false},
+    {"name": "sonar-users", "description": "Sonar Users", "selected": true}
+  ]
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java
new file mode 100644 (file)
index 0000000..487e516
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * 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.user.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.user.GroupDto;
+import org.sonar.core.user.GroupMembershipDao;
+import org.sonar.core.user.UserDto;
+import org.sonar.core.user.UserGroupDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.db.GroupDao;
+import org.sonar.server.user.db.UserDao;
+import org.sonar.server.user.db.UserGroupDao;
+import org.sonar.server.ws.WsTester;
+
+public class GroupsActionTest {
+
+  @ClassRule
+  public static final DbTester dbTester = new DbTester();
+
+  WebService.Controller controller;
+
+  WsTester tester;
+
+  DbClient dbClient;
+
+  DbSession session;
+
+  @Before
+  public void setUp() throws Exception {
+    dbTester.truncateTables();
+
+    System2 system2 = new System2();
+    UserDao userDao = new UserDao(dbTester.myBatis(), system2);
+    GroupDao groupDao = new GroupDao(system2);
+    UserGroupDao userGroupDao = new UserGroupDao();
+    GroupMembershipDao groupMembershipDao = new GroupMembershipDao(dbTester.myBatis());
+
+    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), userDao, groupDao, userGroupDao, groupMembershipDao);
+    session = dbClient.openSession(false);
+    session.commit();
+
+    tester = new WsTester(new UsersWs(new GroupsAction(dbClient)));
+    controller = tester.controller("api/users");
+
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    session.close();
+  }
+
+  @Test(expected = NotFoundException.class)
+  public void fail_on_unknown_user() throws Exception {
+    tester.newGetRequest("api/users", "groups")
+      .setParam("login", "john").execute();
+  }
+
+  @Test
+  public void empty_groups() throws Exception {
+    createUser();
+    session.commit();
+
+    tester.newGetRequest("api/users", "groups")
+      .setParam("login", "john")
+      .execute()
+      .assertJson(getClass(), "empty.json");
+  }
+
+  @Test
+  public void all_groups() throws Exception {
+    UserDto user = createUser();
+    GroupDto usersGroup = createGroup("sonar-users", "Sonar Users");
+    createGroup("sonar-admins", "Sonar Admins");
+    addUserToGroup(user, usersGroup);
+    session.commit();
+
+    tester.newGetRequest("api/users", "groups")
+      .setParam("login", "john")
+      .execute()
+      .assertJson(getClass(), "all.json");
+  }
+
+  @Test
+  public void selected_groups() throws Exception {
+    UserDto user = createUser();
+    GroupDto usersGroup = createGroup("sonar-users", "Sonar Users");
+    createGroup("sonar-admins", "Sonar Admins");
+    addUserToGroup(user, usersGroup);
+    session.commit();
+
+    tester.newGetRequest("api/users", "groups")
+      .setParam("login", "john")
+      .setParam("selected", "selected")
+      .execute()
+      .assertJson(getClass(), "selected.json");
+  }
+
+  @Test
+  public void deselected_groups() throws Exception {
+    UserDto user = createUser();
+    GroupDto usersGroup = createGroup("sonar-users", "Sonar Users");
+    createGroup("sonar-admins", "Sonar Admins");
+    addUserToGroup(user, usersGroup);
+    session.commit();
+
+    tester.newGetRequest("api/users", "groups")
+      .setParam("login", "john")
+      .setParam("selected", "deselected")
+      .execute()
+      .assertJson(getClass(), "deselected.json");
+  }
+
+  private UserDto createUser() {
+    return dbClient.userDao().insert(session, new UserDto()
+      .setActive(true)
+      .setEmail("john@email.com")
+      .setLogin("john")
+      .setName("John")
+      .setScmAccounts("jn"));
+  }
+
+  @Test
+  public void paging() throws Exception {
+    UserDto user = createUser();
+    GroupDto usersGroup = createGroup("sonar-users", "Sonar Users");
+    createGroup("sonar-admins", "Sonar Admins");
+    addUserToGroup(user, usersGroup);
+    session.commit();
+
+    tester.newGetRequest("api/users", "groups")
+      .setParam("login", "john")
+      .setParam("ps", "1")
+      .execute()
+      .assertJson(getClass(), "all_page1.json");
+
+    tester.newGetRequest("api/users", "groups")
+      .setParam("login", "john")
+      .setParam("ps", "1")
+      .setParam("p", "2")
+      .execute()
+      .assertJson(getClass(), "all_page2.json");
+  }
+
+  @Test
+  public void filtering() throws Exception {
+    UserDto user = createUser();
+    GroupDto usersGroup = createGroup("sonar-users", "Sonar Users");
+    createGroup("sonar-admins", "Sonar Admins");
+    addUserToGroup(user, usersGroup);
+    session.commit();
+
+    tester.newGetRequest("api/users", "groups")
+      .setParam("login", "john")
+      .setParam("q", "users")
+      .execute()
+      .assertJson(getClass(), "all_users.json");
+
+    tester.newGetRequest("api/users", "groups")
+      .setParam("login", "john")
+      .setParam("q", "admin")
+      .execute()
+      .assertJson(getClass(), "all_admin.json");
+  }
+
+  private GroupDto createGroup(String name, String description) {
+    return dbClient.groupDao().insert(session, new GroupDto().setName(name).setDescription(description));
+  }
+
+  private void addUserToGroup(UserDto user, GroupDto usersGroup) {
+    dbClient.userGroupDao().insert(session, new UserGroupDto().setUserId(user.getId()).setGroupId(usersGroup.getId()));
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all.json
new file mode 100644 (file)
index 0000000..af9bb6d
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "p": 1,
+  "total": 2,
+  "groups": [
+    {"name": "sonar-admins", "description": "Sonar Admins", "selected": false},
+    {"name": "sonar-users", "description": "Sonar Users", "selected": true}
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_admin.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_admin.json
new file mode 100644 (file)
index 0000000..9310fce
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "p": 1,
+  "total": 1,
+  "groups": [
+    {"name": "sonar-admins", "description": "Sonar Admins", "selected": false}
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_page1.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_page1.json
new file mode 100644 (file)
index 0000000..230e554
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "p": 1,
+  "ps": 1,
+  "total": 2,
+  "groups": [
+    {"name": "sonar-admins", "description": "Sonar Admins", "selected": false}
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_page2.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_page2.json
new file mode 100644 (file)
index 0000000..054d1f5
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "p": 2,
+  "ps": 1,
+  "total": 2,
+  "groups": [
+    {"name": "sonar-users", "description": "Sonar Users", "selected": true}
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_users.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_users.json
new file mode 100644 (file)
index 0000000..0213468
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "p": 1,
+  "total": 1,
+  "groups": [
+    {"name": "sonar-users", "description": "Sonar Users", "selected": true}
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/deselected.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/deselected.json
new file mode 100644 (file)
index 0000000..9310fce
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "p": 1,
+  "total": 1,
+  "groups": [
+    {"name": "sonar-admins", "description": "Sonar Admins", "selected": false}
+  ]
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/empty.json
new file mode 100644 (file)
index 0000000..2160187
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "p": 1,
+  "total": 0,
+  "groups": []
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/selected.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/selected.json
new file mode 100644 (file)
index 0000000..0213468
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "p": 1,
+  "total": 1,
+  "groups": [
+    {"name": "sonar-users", "description": "Sonar Users", "selected": true}
+  ]
+}
\ No newline at end of file
index 6cc67f26e95979d5f113c4cd06c4b946d0542105..145bef37faa0309e91544ce3feb1d714eccc2c67 100644 (file)
@@ -24,12 +24,13 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableMap;
 import org.apache.ibatis.session.RowBounds;
 import org.apache.ibatis.session.SqlSession;
+import org.sonar.core.persistence.DaoComponent;
 import org.sonar.core.persistence.MyBatis;
 
 import java.util.List;
 import java.util.Map;
 
-public class GroupMembershipDao {
+public class GroupMembershipDao implements DaoComponent {
 
   private final MyBatis mybatis;
 
@@ -37,16 +38,26 @@ public class GroupMembershipDao {
     this.mybatis = mybatis;
   }
 
+  // TODO Remove this method and associated client code when the UI is migrated to Backbone
   public List<GroupMembershipDto> selectGroups(GroupMembershipQuery query, Long userId, int offset, int limit) {
     SqlSession session = mybatis.openSession(false);
     try {
-      Map<String, Object> params = ImmutableMap.of("query", query, "userId", userId);
-      return session.selectList("org.sonar.core.user.GroupMembershipMapper.selectGroups", params, new RowBounds(offset, limit));
+      return selectGroups(session, query, userId, offset, limit);
     } finally {
       MyBatis.closeQuietly(session);
     }
   }
 
+  public List<GroupMembershipDto> selectGroups(SqlSession session, GroupMembershipQuery query, Long userId, int offset, int limit) {
+    Map<String, Object> params = ImmutableMap.of("query", query, "userId", userId);
+    return session.selectList("org.sonar.core.user.GroupMembershipMapper.selectGroups", params, new RowBounds(offset, limit));
+  }
+
+  public int countGroups(SqlSession session, GroupMembershipQuery query, Long userId) {
+    Map<String, Object> params = ImmutableMap.of("query", query, "userId", userId);
+    return session.selectOne("org.sonar.core.user.GroupMembershipMapper.countGroups", params);
+  }
+
   @VisibleForTesting
   List<GroupMembershipDto> selectGroups(GroupMembershipQuery query, Long userId) {
     return selectGroups(query, userId, 0, Integer.MAX_VALUE);
index 5a7c4dd214d8f67be4f47b829f958041fa58838d..5c7654c0cb9783395b0493a42d7c69d7326d613c 100644 (file)
@@ -3,8 +3,7 @@
 
 <mapper namespace="org.sonar.core.user.GroupMembershipMapper">
 
-  <select id="selectGroups" parameterType="map" resultType="GroupMembership">
-    SELECT g.id as id, g.name as name, g.description as description, gu.user_id as userId
+  <sql id="commonClauses">
     FROM groups g
     LEFT JOIN groups_users gu ON gu.group_id=g.id AND gu.user_id=#{userId}
     <where>
         AND (UPPER(g.name) LIKE #{query.groupSearchSql} ESCAPE '/')
       </if>
     </where>
+  </sql>
+
+  <select id="selectGroups" parameterType="map" resultType="GroupMembership">
+    SELECT g.id as id, g.name as name, g.description as description, gu.user_id as userId
+    <include refid="commonClauses" />
     ORDER BY g.name
   </select>
 
+  <select id="countGroups" parameterType="map" resultType="int">
+    SELECT COUNT(g.id)
+    <include refid="commonClauses" />
+  </select>
+
 </mapper>
index bad880abb046a8ae137e7e5cb8551ed5a2d2c33f..ea1fd3bdd5a87d577c41826362f8e5678bc5bbbc 100644 (file)
 package org.sonar.core.user;
 
 import org.junit.Before;
+import org.junit.ClassRule;
 import org.junit.Test;
-import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.junit.experimental.categories.Category;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.test.DbTests;
 
 import java.util.List;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-public class GroupMembershipDaoTest extends AbstractDaoTestCase {
+@Category(DbTests.class)
+public class GroupMembershipDaoTest {
+
+  @ClassRule
+  public static final DbTester dbTester = new DbTester();
 
   private GroupMembershipDao dao;
 
   @Before
   public void setUp() {
-    dao = new GroupMembershipDao(getMyBatis());
+    dbTester.truncateTables();
+    dao = new GroupMembershipDao(dbTester.myBatis());
   }
 
   @Test
   public void select_all_groups_by_query() throws Exception {
-    setupData("shared");
+    dbTester.prepareDbUnit(getClass(), "shared.xml");
 
     GroupMembershipQuery query = GroupMembershipQuery.builder().login("arthur").build();
     List<GroupMembershipDto> result = dao.selectGroups(query, 200L);
@@ -48,7 +57,7 @@ public class GroupMembershipDaoTest extends AbstractDaoTestCase {
 
   @Test
   public void select_user_group() throws Exception {
-    setupData("select_user_group");
+    dbTester.prepareDbUnit(getClass(), "select_user_group.xml");
 
     GroupMembershipQuery query = GroupMembershipQuery.builder().login("arthur").build();
     List<GroupMembershipDto> result = dao.selectGroups(query, 201L);
@@ -63,7 +72,7 @@ public class GroupMembershipDaoTest extends AbstractDaoTestCase {
 
   @Test
   public void select_user_groups_by_query() throws Exception {
-    setupData("shared");
+    dbTester.prepareDbUnit(getClass(), "shared.xml");
 
     // 200 is member of 3 groups
     assertThat(dao.selectGroups(GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.IN).build(), 200L)).hasSize(3);
@@ -75,7 +84,7 @@ public class GroupMembershipDaoTest extends AbstractDaoTestCase {
 
   @Test
   public void select_groups_not_affected_to_a_user_by_query() throws Exception {
-    setupData("shared");
+    dbTester.prepareDbUnit(getClass(), "shared.xml");
 
     // 200 is member of 3 groups
     assertThat(dao.selectGroups(GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.OUT).build(), 200L)).isEmpty();
@@ -87,7 +96,7 @@ public class GroupMembershipDaoTest extends AbstractDaoTestCase {
 
   @Test
   public void search_by_group_name() throws Exception {
-    setupData("shared");
+    dbTester.prepareDbUnit(getClass(), "shared.xml");
 
     List<GroupMembershipDto> result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").groupSearch("user").build(), 200L);
     assertThat(result).hasSize(1);
@@ -100,7 +109,7 @@ public class GroupMembershipDaoTest extends AbstractDaoTestCase {
 
   @Test
   public void search_by_group_name_with_capitalization() throws Exception {
-    setupData("shared");
+    dbTester.prepareDbUnit(getClass(), "shared.xml");
 
     List<GroupMembershipDto> result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").groupSearch("UsER").build(), 200L);
     assertThat(result).hasSize(1);
@@ -113,7 +122,7 @@ public class GroupMembershipDaoTest extends AbstractDaoTestCase {
 
   @Test
   public void should_be_sorted_by_group_name() throws Exception {
-    setupData("should_be_sorted_by_group_name");
+    dbTester.prepareDbUnit(getClass(), "should_be_sorted_by_group_name.xml");
 
     List<GroupMembershipDto> result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").build(), 200L);
     assertThat(result).hasSize(3);
@@ -124,7 +133,7 @@ public class GroupMembershipDaoTest extends AbstractDaoTestCase {
 
   @Test
   public void should_be_paginated() throws Exception {
-    setupData("shared");
+    dbTester.prepareDbUnit(getClass(), "shared.xml");
 
     List<GroupMembershipDto> result = dao.selectGroups(GroupMembershipQuery.builder().login("arthur").build(), 200L, 0, 2);
     assertThat(result).hasSize(2);
@@ -141,4 +150,23 @@ public class GroupMembershipDaoTest extends AbstractDaoTestCase {
     assertThat(result.get(0).getName()).isEqualTo("sonar-users");
   }
 
+  @Test
+  public void count_groups() throws Exception {
+    dbTester.prepareDbUnit(getClass(), "shared.xml");
+    DbSession session = dbTester.myBatis().openSession(false);
+
+    try {
+      // 200 is member of 3 groups
+      assertThat(dao.countGroups(session, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.IN).build(), 200L)).isEqualTo(3);
+      assertThat(dao.countGroups(session, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.OUT).build(), 200L)).isZero();
+      // 201 is member of 1 group on 3
+      assertThat(dao.countGroups(session, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.IN).build(), 201L)).isEqualTo(1);
+      assertThat(dao.countGroups(session, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.OUT).build(), 201L)).isEqualTo(2);
+      // 999 is member of 0 group
+      assertThat(dao.countGroups(session, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.IN).build(), 999L)).isZero();
+      assertThat(dao.countGroups(session, GroupMembershipQuery.builder().login("arthur").membership(GroupMembershipQuery.OUT).build(), 2999L)).isEqualTo(3);
+    } finally {
+      session.close();
+    }
+  }
 }