From: Jean-Baptiste Lievremont Date: Mon, 25 May 2015 12:46:08 +0000 (+0200) Subject: SONAR-6474 New WS to delete a group X-Git-Tag: 5.2-RC1~1830 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b24b0f142fd8b43e3c5ee7fefbcfae16e354d319;p=sonarqube.git SONAR-6474 New WS to delete a group --- 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 6e6df811f34..356a5264547 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 @@ -19,10 +19,17 @@ */ package org.sonar.server.db; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.IdentityHashMap; +import java.util.Map; import org.sonar.api.server.ServerSide; import org.sonar.core.issue.db.ActionPlanDao; import org.sonar.core.issue.db.IssueChangeDao; import org.sonar.core.issue.db.IssueFilterDao; +import org.sonar.core.permission.PermissionTemplateDao; import org.sonar.core.persistence.DaoComponent; import org.sonar.core.persistence.Database; import org.sonar.core.persistence.DbSession; @@ -36,6 +43,7 @@ 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.core.user.RoleDao; import org.sonar.server.activity.db.ActivityDao; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.component.db.ComponentIndexDao; @@ -56,13 +64,6 @@ import org.sonar.server.user.db.GroupDao; import org.sonar.server.user.db.UserDao; import org.sonar.server.user.db.UserGroupDao; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.IdentityHashMap; -import java.util.Map; - /** * Facade for all db components, mainly DAOs */ @@ -88,6 +89,8 @@ public class DbClient { private final GroupDao groupDao; private final UserGroupDao userGroupDao; private final GroupMembershipDao groupMembershipDao; + private final RoleDao roleDao; + private final PermissionTemplateDao permissionTemplateDao; private final IssueDao issueDao; private final IssueFilterDao issueFilterDao; private final IssueChangeDao issueChangeDao; @@ -128,6 +131,8 @@ public class DbClient { groupDao = getDao(map, GroupDao.class); userGroupDao = getDao(map, UserGroupDao.class); groupMembershipDao = getDao(map, GroupMembershipDao.class); + roleDao = getDao(map, RoleDao.class); + permissionTemplateDao = getDao(map, PermissionTemplateDao.class); issueDao = getDao(map, IssueDao.class); issueFilterDao = getDao(map, IssueFilterDao.class); issueChangeDao = getDao(map, IssueChangeDao.class); @@ -232,6 +237,14 @@ public class DbClient { return groupMembershipDao; } + public RoleDao roleDao() { + return roleDao; + } + + public PermissionTemplateDao permissionTemplateDao() { + return permissionTemplateDao; + } + public ActionPlanDao actionPlanDao() { return actionPlanDao; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index f79a14e72ca..22c6112ca22 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -19,6 +19,7 @@ */ package org.sonar.server.platform.platformlevel; +import java.util.List; import org.sonar.api.config.EmailSettings; import org.sonar.api.issue.action.Actions; import org.sonar.api.profiles.AnnotationProfileParser; @@ -290,8 +291,6 @@ import org.sonar.server.view.index.ViewIndexer; import org.sonar.server.ws.ListingWs; import org.sonar.server.ws.WebServiceEngine; -import java.util.List; - public class PlatformLevel4 extends PlatformLevel { private final List level4AddedComponents; @@ -498,6 +497,7 @@ public class PlatformLevel4 extends PlatformLevel { UserGroupsWs.class, org.sonar.server.usergroups.ws.SearchAction.class, org.sonar.server.usergroups.ws.CreateAction.class, + org.sonar.server.usergroups.ws.DeleteAction.class, // permissions PermissionFacade.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/db/GroupDao.java b/server/sonar-server/src/main/java/org/sonar/server/user/db/GroupDao.java index eda1a1ad2a3..88229ea14f3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/db/GroupDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/db/GroupDao.java @@ -22,6 +22,7 @@ package org.sonar.server.user.db; import java.util.Date; import java.util.List; +import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.lang.StringUtils; import org.apache.ibatis.session.RowBounds; @@ -30,6 +31,7 @@ import org.sonar.core.persistence.DaoComponent; import org.sonar.core.persistence.DbSession; import org.sonar.core.user.GroupDto; import org.sonar.core.user.GroupMapper; +import org.sonar.server.exceptions.NotFoundException; /** * @since 3.2 @@ -44,9 +46,27 @@ public class GroupDao implements DaoComponent { } public GroupDto selectByKey(DbSession session, String key) { + GroupDto group = selectNullableByKey(session, key); + if (group == null) { + throw new NotFoundException(String.format("Could not find a group with name '%s'", key)); + } + return group; + } + + @CheckForNull + public GroupDto selectNullableByKey(DbSession session, String key) { return mapper(session).selectByKey(key); } + @CheckForNull + public GroupDto selectById(DbSession dbSession, long groupId) { + return mapper(dbSession).selectById(groupId); + } + + public void deleteById(DbSession dbSession, long groupId) { + mapper(dbSession).deleteById(groupId); + } + public int countByQuery(DbSession session, @Nullable String query) { return mapper(session).countByQuery(groupSearchToSql(query)); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/db/UserGroupDao.java b/server/sonar-server/src/main/java/org/sonar/server/user/db/UserGroupDao.java index 60e29f3c1e1..6fc14f52b40 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/db/UserGroupDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/db/UserGroupDao.java @@ -32,6 +32,14 @@ public class UserGroupDao implements DaoComponent { return dto; } + public void delete(DbSession session, UserGroupDto dto) { + mapper(session).delete(dto); + } + + public void deleteMembersByGroupId(DbSession session, long groupId) { + mapper(session).deleteMembersByGroup(groupId); + } + protected UserGroupMapper mapper(DbSession session) { return session.getMapper(UserGroupMapper.class); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/CreateAction.java index edfb2e8aeee..cdc9ad5fcf0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/CreateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/CreateAction.java @@ -121,7 +121,7 @@ public class CreateAction implements UserGroupsWsAction { // There is no database constraint on column groups.name // because MySQL cannot create a unique index // on a UTF-8 VARCHAR larger than 255 characters on InnoDB - if (dbClient.groupDao().selectByKey(session, name) != null) { + if (dbClient.groupDao().selectNullableByKey(session, name) != null) { throw new ServerException(HttpURLConnection.HTTP_CONFLICT, String.format("Name '%s' is already taken", name)); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/DeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/DeleteAction.java new file mode 100644 index 00000000000..71e6c7e3d79 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/DeleteAction.java @@ -0,0 +1,107 @@ +/* + * 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.usergroups.ws; + +import com.google.common.base.Preconditions; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService.NewController; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; +import org.sonar.core.user.GroupDto; +import org.sonar.server.db.DbClient; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.user.UserSession; + +public class DeleteAction implements UserGroupsWsAction { + + private static final String PARAM_ID = "id"; + + private final DbClient dbClient; + private final UserSession userSession; + private final Settings settings; + + public DeleteAction(DbClient dbClient, UserSession userSession, Settings settings) { + this.dbClient = dbClient; + this.userSession = userSession; + this.settings = settings; + } + + @Override + public void define(NewController context) { + context.createAction("delete") + .setDescription("Delete a group. The default group cannot be deleted. Requires System Administrator permission.") + .setHandler(this) + .setSince("5.2") + .setPost(true) + .createParam(PARAM_ID) + .setDescription("ID of the group to delete.") + .setRequired(true); + } + + @Override + public void handle(Request request, Response response) throws Exception { + userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN); + + long groupId = request.mandatoryParamAsLong(PARAM_ID); + + + DbSession dbSession = dbClient.openSession(false); + try { + if (dbClient.groupDao().selectById(dbSession, groupId) == null) { + throw new NotFoundException(String.format("Could not find a group with id=%d", groupId)); + } + + checkNotTryingToDeleteDefaultGroup(dbSession, groupId); + + removeGroupMembers(groupId, dbSession); + removeGroupPermissions(groupId, dbSession); + removeFromPermissionTemplates(groupId, dbSession); + dbClient.groupDao().deleteById(dbSession, groupId); + + dbSession.commit(); + response.noContent(); + } finally { + MyBatis.closeQuietly(dbSession); + } + } + + private void checkNotTryingToDeleteDefaultGroup(DbSession dbSession, long groupId) { + String defaultGroupName = settings.getString(CoreProperties.CORE_DEFAULT_GROUP); + GroupDto defaultGroup = dbClient.groupDao().selectByKey(dbSession, defaultGroupName); + Preconditions.checkArgument(groupId != defaultGroup.getId(), + String.format("Default group '%s' cannot be deleted", defaultGroupName)); + } + + private void removeGroupMembers(long groupId, DbSession dbSession) { + dbClient.userGroupDao().deleteMembersByGroupId(dbSession, groupId); + } + + private void removeGroupPermissions(long groupId, DbSession dbSession) { + dbClient.roleDao().deleteGroupRolesByGroupId(dbSession, groupId); + } + + private void removeFromPermissionTemplates(long groupId, DbSession dbSession) { + dbClient.permissionTemplateDao().removeByGroup(groupId, dbSession); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/db/GroupDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/db/GroupDaoTest.java index bb0efb8baf1..c30587992b5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/db/GroupDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/db/GroupDaoTest.java @@ -72,6 +72,19 @@ public class GroupDaoTest { assertThat(group.getUpdatedAt()).isEqualTo(DateUtils.parseDate("2014-09-08")); } + @Test + public void select_by_id() { + dbTester.prepareDbUnit(getClass(), "select_by_key.xml"); + + GroupDto group = new GroupDao(system2).selectById(session, 1L); + assertThat(group).isNotNull(); + assertThat(group.getId()).isEqualTo(1L); + assertThat(group.getName()).isEqualTo("sonar-users"); + assertThat(group.getDescription()).isEqualTo("Sonar Users"); + assertThat(group.getCreatedAt()).isEqualTo(DateUtils.parseDate("2014-09-07")); + assertThat(group.getUpdatedAt()).isEqualTo(DateUtils.parseDate("2014-09-08")); + } + @Test public void find_by_user_login() { dbTester.prepareDbUnit(getClass(), "find_by_user_login.xml"); @@ -144,4 +157,16 @@ public class GroupDaoTest { // Filter on name assertThat(new GroupDao(system2).countByQuery(session, "sonar")).isEqualTo(2); } + + @Test + public void delete_by_id() { + dbTester.prepareDbUnit(getClass(), "select_by_key.xml"); + + GroupDao groupDao = new GroupDao(system2); + groupDao.deleteById(session, 1L); + session.commit(); + + assertThat(groupDao.countByQuery(session, null)).isZero(); + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/db/UserGroupDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/db/UserGroupDaoTest.java index 3be2dd038e5..a1b72ef3831 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/db/UserGroupDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/db/UserGroupDaoTest.java @@ -59,4 +59,12 @@ public class UserGroupDaoTest { db.assertDbUnit(getClass(), "insert-result.xml", "groups_users"); } + + @Test + public void delete_members_by_group_id() { + db.prepareDbUnit(getClass(), "delete_members_by_group_id.xml"); + dao.deleteMembersByGroupId(session, 1L); + session.commit(); + db.assertDbUnit(getClass(), "delete_members_by_group_id-result.xml", "groups_users"); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/DeleteActionTest.java new file mode 100644 index 00000000000..82c96a928b9 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/DeleteActionTest.java @@ -0,0 +1,173 @@ +/* + * 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.usergroups.ws; + +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.api.utils.System2; +import org.sonar.api.web.UserRole; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.core.permission.PermissionTemplateDao; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.DbTester; +import org.sonar.core.user.GroupDto; +import org.sonar.core.user.GroupRoleDto; +import org.sonar.core.user.RoleDao; +import org.sonar.core.user.UserGroupDto; +import org.sonar.server.db.DbClient; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.user.db.GroupDao; +import org.sonar.server.user.db.UserGroupDao; +import org.sonar.server.ws.WsTester; +import org.sonar.test.DbTests; + +import static org.assertj.core.api.Assertions.assertThat; + +@Category(DbTests.class) +public class DeleteActionTest { + + @ClassRule + public static final DbTester dbTester = new DbTester(); + + @Rule + public UserSessionRule userSession = UserSessionRule.standalone(); + + private WsTester tester; + + private GroupDao groupDao; + + private UserGroupDao userGroupDao; + + private RoleDao roleDao; + + private PermissionTemplateDao permissionTemplateDao; + + private DbSession session; + + private Long defaultGroupId; + + @Before + public void setUp() { + dbTester.truncateTables(); + + groupDao = new GroupDao(System2.INSTANCE); + userGroupDao = new UserGroupDao(); + roleDao = new RoleDao(); + permissionTemplateDao = new PermissionTemplateDao(dbTester.myBatis(), System2.INSTANCE); + + DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), + groupDao, userGroupDao, roleDao, permissionTemplateDao); + + session = dbClient.openSession(false); + + Settings settings = new Settings().setProperty(CoreProperties.CORE_DEFAULT_GROUP, CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE); + GroupDto defaultGroup = groupDao.insert(session, new GroupDto().setName(CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE)); + defaultGroupId = defaultGroup.getId(); + session.commit(); + + tester = new WsTester(new UserGroupsWs(new DeleteAction(dbClient, userSession, settings))); + } + + @After + public void after() { + session.close(); + } + + @Test + public void delete_simple() throws Exception { + GroupDto group = groupDao.insert(session, new GroupDto().setName("to-delete")); + session.commit(); + + loginAsAdmin(); + tester.newPostRequest("api/usergroups", "delete") + .setParam("id", group.getId().toString()) + .execute().assertNoContent(); + } + + @Test + public void delete_with_members() throws Exception { + GroupDto group = groupDao.insert(session, new GroupDto().setName("to-delete")); + userGroupDao.insert(session, new UserGroupDto().setGroupId(group.getId()).setUserId(42L)); + session.commit(); + + loginAsAdmin(); + tester.newPostRequest("api/usergroups", "delete") + .setParam("id", group.getId().toString()) + .execute().assertNoContent(); + + assertThat(dbTester.select("SELECT group_id FROM groups_users")).isEmpty(); + } + + @Test + public void delete_with_permissions() throws Exception { + GroupDto group = groupDao.insert(session, new GroupDto().setName("to-delete")); + roleDao.insertGroupRole(new GroupRoleDto().setGroupId(group.getId()).setResourceId(42L).setRole(UserRole.ADMIN), session); + session.commit(); + + loginAsAdmin(); + tester.newPostRequest("api/usergroups", "delete") + .setParam("id", group.getId().toString()) + .execute().assertNoContent(); + + assertThat(dbTester.select("SELECT group_id FROM group_roles")).isEmpty(); + } + + @Test + public void delete_with_permission_templates() throws Exception { + GroupDto group = groupDao.insert(session, new GroupDto().setName("to-delete")); + permissionTemplateDao.addGroupPermission(42L, group.getId(), UserRole.ADMIN); + session.commit(); + + loginAsAdmin(); + tester.newPostRequest("api/usergroups", "delete") + .setParam("id", group.getId().toString()) + .execute().assertNoContent(); + + assertThat(dbTester.select("SELECT group_id FROM perm_templates_groups")).isEmpty(); + } + + @Test(expected = NotFoundException.class) + public void not_found() throws Exception { + loginAsAdmin(); + tester.newPostRequest("api/usergroups", "delete") + .setParam("id", "42") + .execute(); + } + + @Test(expected = IllegalArgumentException.class) + public void cannot_delete_default_group() throws Exception { + loginAsAdmin(); + tester.newPostRequest("api/usergroups", "delete") + .setParam("id", defaultGroupId.toString()) + .execute(); + } + + private void loginAsAdmin() { + userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + } +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/db/UserGroupDaoTest/delete_members_by_group_id-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/user/db/UserGroupDaoTest/delete_members_by_group_id-result.xml new file mode 100644 index 00000000000..edac414e636 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/db/UserGroupDaoTest/delete_members_by_group_id-result.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/db/UserGroupDaoTest/delete_members_by_group_id.xml b/server/sonar-server/src/test/resources/org/sonar/server/user/db/UserGroupDaoTest/delete_members_by_group_id.xml new file mode 100644 index 00000000000..2430e53dd8e --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/db/UserGroupDaoTest/delete_members_by_group_id.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/sonar-core/src/main/java/org/sonar/core/permission/PermissionTemplateDao.java b/sonar-core/src/main/java/org/sonar/core/permission/PermissionTemplateDao.java index 35fe96d9803..b83ed509044 100644 --- a/sonar-core/src/main/java/org/sonar/core/permission/PermissionTemplateDao.java +++ b/sonar-core/src/main/java/org/sonar/core/permission/PermissionTemplateDao.java @@ -21,29 +21,28 @@ package org.sonar.core.permission; import com.google.common.annotations.VisibleForTesting; +import java.text.Normalizer; +import java.util.Date; +import java.util.List; +import java.util.Map; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; import org.apache.commons.lang.time.DateFormatUtils; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.SqlSession; import org.sonar.api.batch.BatchSide; -import org.sonar.api.server.ServerSide; import org.sonar.api.security.DefaultGroups; +import org.sonar.api.server.ServerSide; import org.sonar.api.utils.System2; +import org.sonar.core.persistence.DaoComponent; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import java.text.Normalizer; -import java.util.Date; -import java.util.List; -import java.util.Map; - import static com.google.common.collect.Maps.newHashMap; @BatchSide @ServerSide -public class PermissionTemplateDao { +public class PermissionTemplateDao implements DaoComponent { public static final String QUERY_PARAMETER = "query"; public static final String TEMPLATE_ID_PARAMETER = "templateId"; diff --git a/sonar-core/src/main/java/org/sonar/core/user/GroupMapper.java b/sonar-core/src/main/java/org/sonar/core/user/GroupMapper.java index 24dfd2e6768..de36b36af7c 100644 --- a/sonar-core/src/main/java/org/sonar/core/user/GroupMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/user/GroupMapper.java @@ -29,6 +29,9 @@ public interface GroupMapper { @CheckForNull GroupDto selectByKey(String name); + @CheckForNull + GroupDto selectById(long groupId); + List selectByUserLogin(String userLogin); void insert(GroupDto groupDto); @@ -36,4 +39,7 @@ public interface GroupMapper { List selectByQuery(String query, RowBounds rowBounds); int countByQuery(String query); + + void deleteById(long groupId); + } diff --git a/sonar-core/src/main/java/org/sonar/core/user/RoleDao.java b/sonar-core/src/main/java/org/sonar/core/user/RoleDao.java index 194f700dd35..7bde8163199 100644 --- a/sonar-core/src/main/java/org/sonar/core/user/RoleDao.java +++ b/sonar-core/src/main/java/org/sonar/core/user/RoleDao.java @@ -20,19 +20,18 @@ package org.sonar.core.user; +import java.util.List; +import javax.annotation.Nullable; import org.apache.ibatis.session.SqlSession; import org.sonar.api.batch.BatchSide; -import org.sonar.api.server.ServerSide; import org.sonar.api.security.DefaultGroups; +import org.sonar.api.server.ServerSide; +import org.sonar.core.persistence.DaoComponent; import org.sonar.core.persistence.DbSession; -import javax.annotation.Nullable; - -import java.util.List; - @ServerSide @BatchSide -public class RoleDao { +public class RoleDao implements DaoComponent { public List selectUserPermissions(DbSession session, String userLogin, @Nullable Long resourceId) { return session.getMapper(RoleMapper.class).selectUserPermissions(userLogin, resourceId); @@ -43,41 +42,42 @@ public class RoleDao { } public void insertGroupRole(GroupRoleDto groupRole, SqlSession session) { - RoleMapper mapper = session.getMapper(RoleMapper.class); - mapper.insertGroupRole(groupRole); + mapper(session).insertGroupRole(groupRole); } public void insertUserRole(UserRoleDto userRole, SqlSession session) { - RoleMapper mapper = session.getMapper(RoleMapper.class); - mapper.insertUserRole(userRole); + mapper(session).insertUserRole(userRole); } public void deleteUserRole(UserRoleDto userRole, SqlSession session) { - RoleMapper mapper = session.getMapper(RoleMapper.class); - mapper.deleteUserRole(userRole); + mapper(session).deleteUserRole(userRole); } public void deleteGroupRole(GroupRoleDto groupRole, SqlSession session) { - RoleMapper mapper = session.getMapper(RoleMapper.class); - mapper.deleteGroupRole(groupRole); + mapper(session).deleteGroupRole(groupRole); } public void deleteGroupRolesByResourceId(Long resourceId, SqlSession session) { - RoleMapper mapper = session.getMapper(RoleMapper.class); - mapper.deleteGroupRolesByResourceId(resourceId); + mapper(session).deleteGroupRolesByResourceId(resourceId); } public void deleteUserRolesByResourceId(Long resourceId, SqlSession session) { - RoleMapper mapper = session.getMapper(RoleMapper.class); - mapper.deleteUserRolesByResourceId(resourceId); + mapper(session).deleteUserRolesByResourceId(resourceId); } public int countResourceGroupRoles(DbSession session, Long resourceId) { - return session.getMapper(RoleMapper.class).countResourceGroupRoles(resourceId); + return mapper(session).countResourceGroupRoles(resourceId); } public int countResourceUserRoles(DbSession session, Long resourceId) { - return session.getMapper(RoleMapper.class).countResourceUserRoles(resourceId); + return mapper(session).countResourceUserRoles(resourceId); } + public void deleteGroupRolesByGroupId(DbSession session, long groupId) { + mapper(session).deleteGroupRolesByGroupId(groupId); + } + + private static RoleMapper mapper(SqlSession session) { + return session.getMapper(RoleMapper.class); + } } diff --git a/sonar-core/src/main/java/org/sonar/core/user/RoleMapper.java b/sonar-core/src/main/java/org/sonar/core/user/RoleMapper.java index 2728b91cbe6..c4d2ca4dbd4 100644 --- a/sonar-core/src/main/java/org/sonar/core/user/RoleMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/user/RoleMapper.java @@ -19,10 +19,9 @@ */ package org.sonar.core.user; -import org.apache.ibatis.annotations.Param; - -import javax.annotation.Nullable; import java.util.List; +import javax.annotation.Nullable; +import org.apache.ibatis.annotations.Param; /** * @since 3.2 @@ -55,4 +54,6 @@ public interface RoleMapper { int countResourceUserRoles(Long resourceId); + void deleteGroupRolesByGroupId(long groupId); + } diff --git a/sonar-core/src/main/java/org/sonar/core/user/UserGroupMapper.java b/sonar-core/src/main/java/org/sonar/core/user/UserGroupMapper.java index 328abc4d1b8..3381852a229 100644 --- a/sonar-core/src/main/java/org/sonar/core/user/UserGroupMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/user/UserGroupMapper.java @@ -24,4 +24,7 @@ public interface UserGroupMapper { void insert(UserGroupDto userGroupDto); + void delete(UserGroupDto dto); + + void deleteMembersByGroup(long groupId); } diff --git a/sonar-core/src/main/resources/org/sonar/core/user/GroupMapper.xml b/sonar-core/src/main/resources/org/sonar/core/user/GroupMapper.xml index b2ffcb62296..132edb40784 100644 --- a/sonar-core/src/main/resources/org/sonar/core/user/GroupMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/user/GroupMapper.xml @@ -20,6 +20,21 @@ + + + + DELETE FROM groups + + id=#{id} + + + + + + delete from group_roles where group_id=#{id} + diff --git a/sonar-core/src/main/resources/org/sonar/core/user/UserGroupMapper.xml b/sonar-core/src/main/resources/org/sonar/core/user/UserGroupMapper.xml index ce48eeae261..8b6b828ec95 100644 --- a/sonar-core/src/main/resources/org/sonar/core/user/UserGroupMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/user/UserGroupMapper.xml @@ -8,4 +8,19 @@ VALUES (#{userId}, #{groupId}) + + DELETE FROM groups_users + + AND user_id = #{userId} + AND group_id = #{groupId} + + + + + DELETE FROM groups_users + + AND group_id = #{groupId} + + + diff --git a/sonar-core/src/test/java/org/sonar/core/user/RoleDaoTest.java b/sonar-core/src/test/java/org/sonar/core/user/RoleDaoTest.java index 932f25c874a..0538f277111 100644 --- a/sonar-core/src/test/java/org/sonar/core/user/RoleDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/user/RoleDaoTest.java @@ -22,16 +22,23 @@ package org.sonar.core.user; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.sonar.api.security.DefaultGroups; import org.sonar.api.web.UserRole; import org.sonar.core.permission.GlobalPermissions; -import org.sonar.core.persistence.AbstractDaoTestCase; import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.DbTester; +import org.sonar.test.DbTests; import static org.assertj.core.api.Assertions.assertThat; -public class RoleDaoTest extends AbstractDaoTestCase { +@Category(DbTests.class) +public class RoleDaoTest { + + @ClassRule + public static final DbTester dbTester = new DbTester(); DbSession session; @@ -39,7 +46,8 @@ public class RoleDaoTest extends AbstractDaoTestCase { @Before public void setUp() { - session = getMyBatis().openSession(false); + dbTester.truncateTables(); + session = dbTester.myBatis().openSession(false); dao = new RoleDao(); } @@ -50,7 +58,7 @@ public class RoleDaoTest extends AbstractDaoTestCase { @Test public void retrieve_global_user_permissions() { - setupData("globalUserPermissions"); + dbTester.prepareDbUnit(getClass(), "globalUserPermissions.xml"); assertThat(dao.selectUserPermissions(session, "admin_user", null)).containsOnly(GlobalPermissions.SYSTEM_ADMIN, GlobalPermissions.QUALITY_PROFILE_ADMIN); assertThat(dao.selectUserPermissions(session, "profile_admin_user", null)).containsOnly(GlobalPermissions.QUALITY_PROFILE_ADMIN); @@ -58,7 +66,7 @@ public class RoleDaoTest extends AbstractDaoTestCase { @Test public void retrieve_resource_user_permissions() { - setupData("resourceUserPermissions"); + dbTester.prepareDbUnit(getClass(), "resourceUserPermissions.xml"); assertThat(dao.selectUserPermissions(session, "admin_user", 1L)).containsOnly(UserRole.ADMIN, UserRole.USER); assertThat(dao.selectUserPermissions(session, "browse_admin_user", 1L)).containsOnly(UserRole.USER); @@ -66,7 +74,7 @@ public class RoleDaoTest extends AbstractDaoTestCase { @Test public void retrieve_global_group_permissions() { - setupData("globalGroupPermissions"); + dbTester.prepareDbUnit(getClass(), "globalGroupPermissions.xml"); assertThat(dao.selectGroupPermissions(session, "sonar-administrators", null)).containsOnly(GlobalPermissions.SYSTEM_ADMIN, GlobalPermissions.QUALITY_PROFILE_ADMIN, GlobalPermissions.DASHBOARD_SHARING); @@ -78,7 +86,7 @@ public class RoleDaoTest extends AbstractDaoTestCase { @Test public void retrieve_resource_group_permissions() { - setupData("resourceGroupPermissions"); + dbTester.prepareDbUnit(getClass(), "resourceGroupPermissions.xml"); assertThat(dao.selectGroupPermissions(session, "sonar-administrators", 1L)).containsOnly(UserRole.ADMIN, UserRole.CODEVIEWER); assertThat(dao.selectGroupPermissions(session, "sonar-users", 1L)).containsOnly(UserRole.CODEVIEWER); @@ -86,50 +94,59 @@ public class RoleDaoTest extends AbstractDaoTestCase { @Test public void delete_global_user_permission() { - setupData("globalUserPermissions"); + dbTester.prepareDbUnit(getClass(), "globalUserPermissions.xml"); UserRoleDto userRoleToDelete = new UserRoleDto().setUserId(200L).setRole(GlobalPermissions.QUALITY_PROFILE_ADMIN); dao.deleteUserRole(userRoleToDelete, session); session.commit(); - checkTable("globalUserPermissions", "user_roles", "user_id", "role"); + dbTester.assertDbUnit(getClass(), "globalUserPermissions-result.xml", "user_roles"); } @Test public void delete_resource_user_permission() { - setupData("resourceUserPermissions"); + dbTester.prepareDbUnit(getClass(), "resourceUserPermissions.xml"); UserRoleDto userRoleToDelete = new UserRoleDto().setUserId(200L).setRole(UserRole.USER).setResourceId(1L); dao.deleteUserRole(userRoleToDelete, session); session.commit(); - checkTable("resourceUserPermissions", "user_roles", "user_id", "role"); + dbTester.assertDbUnit(getClass(), "resourceUserPermissions-result.xml", "user_roles"); } @Test public void delete_global_group_permission() { - setupData("globalGroupPermissions"); + dbTester.prepareDbUnit(getClass(), "globalGroupPermissions.xml"); GroupRoleDto groupRoleToDelete = new GroupRoleDto().setGroupId(100L).setRole(GlobalPermissions.QUALITY_PROFILE_ADMIN); dao.deleteGroupRole(groupRoleToDelete, session); session.commit(); - checkTable("globalGroupPermissions", "group_roles", "group_id", "role"); + dbTester.assertDbUnit(getClass(), "globalGroupPermissions-result.xml", "group_roles"); } @Test public void delete_resource_group_permission() { - setupData("resourceGroupPermissions"); + dbTester.prepareDbUnit(getClass(), "resourceGroupPermissions.xml"); GroupRoleDto groupRoleToDelete = new GroupRoleDto().setGroupId(100L).setRole(UserRole.CODEVIEWER).setResourceId(1L); dao.deleteGroupRole(groupRoleToDelete, session); session.commit(); - checkTable("resourceGroupPermissions", "group_roles", "group_id", "role"); + dbTester.assertDbUnit(getClass(), "resourceGroupPermissions-result.xml", "group_roles"); } + @Test + public void delete_all_group_permissions_by_group_id() { + dbTester.prepareDbUnit(getClass(), "deleteGroupPermissionsByGroupId.xml"); + + dao.deleteGroupRolesByGroupId(session, 100L); + session.commit(); + + dbTester.assertDbUnit(getClass(), "deleteGroupPermissionsByGroupId-result.xml", "group_roles"); + } } diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/deleteGroupPermissionsByGroupId-result.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/deleteGroupPermissionsByGroupId-result.xml new file mode 100644 index 00000000000..a9effb1ea47 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/deleteGroupPermissionsByGroupId-result.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/deleteGroupPermissionsByGroupId.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/deleteGroupPermissionsByGroupId.xml new file mode 100644 index 00000000000..f05b0aebecf --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/deleteGroupPermissionsByGroupId.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalGroupPermissions-result.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalGroupPermissions-result.xml index de8f3571616..d87bfe95e07 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalGroupPermissions-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalGroupPermissions-result.xml @@ -3,13 +3,13 @@ - - - + + + - - + + diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalGroupPermissions.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalGroupPermissions.xml index 750883651eb..2e76afcd3be 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalGroupPermissions.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalGroupPermissions.xml @@ -3,14 +3,14 @@ - - - - + + + + - - + + diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalUserPermissions-result.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalUserPermissions-result.xml index 83fec77b3af..5fd4509c330 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalUserPermissions-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalUserPermissions-result.xml @@ -3,8 +3,8 @@ - - + + diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalUserPermissions.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalUserPermissions.xml index e382ca66a8c..4d95c91f03d 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalUserPermissions.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/globalUserPermissions.xml @@ -3,9 +3,9 @@ - - - + + + diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/resourceGroupPermissions-result.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/resourceGroupPermissions-result.xml index cdfb5b510b3..71650eb675a 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/resourceGroupPermissions-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/resourceGroupPermissions-result.xml @@ -3,12 +3,12 @@ - - + + - + - + diff --git a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/resourceGroupPermissions.xml b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/resourceGroupPermissions.xml index 424faca8a36..8fb07128af7 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/resourceGroupPermissions.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/RoleDaoTest/resourceGroupPermissions.xml @@ -11,6 +11,6 @@ - +