From 912e9886ae4a982781c99afd7881dd9b0e934565 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lievremont Date: Tue, 5 May 2015 15:38:14 +0200 Subject: [PATCH] SONAR-6470 New Java WS to show a user's groups --- .../java/org/sonar/server/db/DbClient.java | 7 + .../server/platform/ServerComponents.java | 1 + .../sonar/server/user/ws/GroupsAction.java | 139 ++++++++++++ .../sonar/server/user/ws/example-groups.json | 9 + .../server/user/ws/GroupsActionTest.java | 199 ++++++++++++++++++ .../server/user/ws/GroupsActionTest/all.json | 8 + .../user/ws/GroupsActionTest/all_admin.json | 7 + .../user/ws/GroupsActionTest/all_page1.json | 8 + .../user/ws/GroupsActionTest/all_page2.json | 8 + .../user/ws/GroupsActionTest/all_users.json | 7 + .../user/ws/GroupsActionTest/deselected.json | 7 + .../user/ws/GroupsActionTest/empty.json | 5 + .../user/ws/GroupsActionTest/selected.json | 7 + .../sonar/core/user/GroupMembershipDao.java | 17 +- .../sonar/core/user/GroupMembershipMapper.xml | 13 +- .../core/user/GroupMembershipDaoTest.java | 50 ++++- 16 files changed, 476 insertions(+), 16 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java create mode 100644 server/sonar-server/src/main/resources/org/sonar/server/user/ws/example-groups.json create mode 100644 server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_admin.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_page1.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_page2.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_users.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/deselected.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/empty.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/selected.json diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java b/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java index d3340efd5fe..78fc76fde3f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java +++ b/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java @@ -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; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index 0fd77b02562..b6347f84e61 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -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 index 00000000000..f493c2f4eb0 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java @@ -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 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 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 index 00000000000..ef1ca05b086 --- /dev/null +++ b/server/sonar-server/src/main/resources/org/sonar/server/user/ws/example-groups.json @@ -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 index 00000000000..487e5168911 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java @@ -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 index 00000000000..af9bb6d1dd2 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all.json @@ -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 index 00000000000..9310fce67e5 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_admin.json @@ -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 index 00000000000..230e55493eb --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_page1.json @@ -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 index 00000000000..054d1f53f7b --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_page2.json @@ -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 index 00000000000..021346810c1 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/all_users.json @@ -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 index 00000000000..9310fce67e5 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/deselected.json @@ -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 index 00000000000..2160187bbb6 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/empty.json @@ -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 index 00000000000..021346810c1 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/GroupsActionTest/selected.json @@ -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/sonar-core/src/main/java/org/sonar/core/user/GroupMembershipDao.java b/sonar-core/src/main/java/org/sonar/core/user/GroupMembershipDao.java index 6cc67f26e95..145bef37faa 100644 --- a/sonar-core/src/main/java/org/sonar/core/user/GroupMembershipDao.java +++ b/sonar-core/src/main/java/org/sonar/core/user/GroupMembershipDao.java @@ -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 selectGroups(GroupMembershipQuery query, Long userId, int offset, int limit) { SqlSession session = mybatis.openSession(false); try { - Map 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 selectGroups(SqlSession session, GroupMembershipQuery query, Long userId, int offset, int limit) { + Map 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 params = ImmutableMap.of("query", query, "userId", userId); + return session.selectOne("org.sonar.core.user.GroupMembershipMapper.countGroups", params); + } + @VisibleForTesting List selectGroups(GroupMembershipQuery query, Long userId) { return selectGroups(query, userId, 0, Integer.MAX_VALUE); diff --git a/sonar-core/src/main/resources/org/sonar/core/user/GroupMembershipMapper.xml b/sonar-core/src/main/resources/org/sonar/core/user/GroupMembershipMapper.xml index 5a7c4dd214d..5c7654c0cb9 100644 --- a/sonar-core/src/main/resources/org/sonar/core/user/GroupMembershipMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/user/GroupMembershipMapper.xml @@ -3,8 +3,7 @@ - + SELECT g.id as id, g.name as name, g.description as description, gu.user_id as userId + ORDER BY g.name + + diff --git a/sonar-core/src/test/java/org/sonar/core/user/GroupMembershipDaoTest.java b/sonar-core/src/test/java/org/sonar/core/user/GroupMembershipDaoTest.java index bad880abb04..ea1fd3bdd5a 100644 --- a/sonar-core/src/test/java/org/sonar/core/user/GroupMembershipDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/user/GroupMembershipDaoTest.java @@ -21,25 +21,34 @@ 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 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 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 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 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 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 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(); + } + } } -- 2.39.5