@@ -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; | |||
} |
@@ -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<Object> 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, |
@@ -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)); | |||
} |
@@ -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); | |||
} |
@@ -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)); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -0,0 +1,6 @@ | |||
<dataset> | |||
<groups_users user_id="1" group_id="2"/> | |||
<groups_users user_id="2" group_id="2"/> | |||
</dataset> |
@@ -0,0 +1,8 @@ | |||
<dataset> | |||
<groups_users user_id="1" group_id="1"/> | |||
<groups_users user_id="2" group_id="1"/> | |||
<groups_users user_id="1" group_id="2"/> | |||
<groups_users user_id="2" group_id="2"/> | |||
</dataset> |
@@ -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"; |
@@ -29,6 +29,9 @@ public interface GroupMapper { | |||
@CheckForNull | |||
GroupDto selectByKey(String name); | |||
@CheckForNull | |||
GroupDto selectById(long groupId); | |||
List<GroupDto> selectByUserLogin(String userLogin); | |||
void insert(GroupDto groupDto); | |||
@@ -36,4 +39,7 @@ public interface GroupMapper { | |||
List<GroupDto> selectByQuery(String query, RowBounds rowBounds); | |||
int countByQuery(String query); | |||
void deleteById(long groupId); | |||
} |
@@ -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<String> 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); | |||
} | |||
} |
@@ -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); | |||
} |
@@ -24,4 +24,7 @@ public interface UserGroupMapper { | |||
void insert(UserGroupDto userGroupDto); | |||
void delete(UserGroupDto dto); | |||
void deleteMembersByGroup(long groupId); | |||
} |
@@ -20,6 +20,21 @@ | |||
</where> | |||
</select> | |||
<select id="selectById" parameterType="long" resultType="Group"> | |||
SELECT <include refid="groupColumns"/> | |||
FROM groups g | |||
<where> | |||
g.id=#{id} | |||
</where> | |||
</select> | |||
<delete id="deleteById" parameterType="long"> | |||
DELETE FROM groups | |||
<where> | |||
id=#{id} | |||
</where> | |||
</delete> | |||
<select id="selectByUserLogin" parameterType="string" resultType="Group"> | |||
SELECT <include refid="groupColumns"/> | |||
FROM groups g |
@@ -111,4 +111,8 @@ | |||
SELECT count(id) | |||
FROM group_roles WHERE resource_id=#{id} | |||
</select> | |||
<delete id="deleteGroupRolesByGroupId" parameterType="long"> | |||
delete from group_roles where group_id=#{id} | |||
</delete> | |||
</mapper> |
@@ -8,4 +8,19 @@ | |||
VALUES (#{userId}, #{groupId}) | |||
</insert> | |||
<delete id="delete" parameterType="UserGroup"> | |||
DELETE FROM groups_users | |||
<where> | |||
AND user_id = #{userId} | |||
AND group_id = #{groupId} | |||
</where> | |||
</delete> | |||
<delete id="deleteMembersByGroup" parameterType="long"> | |||
DELETE FROM groups_users | |||
<where> | |||
AND group_id = #{groupId} | |||
</where> | |||
</delete> | |||
</mapper> |
@@ -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"); | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
<dataset> | |||
<groups id="100" name="sonar-administrators"/> | |||
<groups id="101" name="sonar-users"/> | |||
<group_roles id="4" group_id="101" role="shareDashboard" resource_id="[null]"/> | |||
<group_roles id="5" group_id="[null]" role="scan" resource_id="[null]"/> | |||
<group_roles id="6" group_id="[null]" role="dryRunScan" resource_id="[null]"/> | |||
<group_roles id="7" group_id="102" role="admin" resource_id="1"/> | |||
</dataset> |
@@ -0,0 +1,18 @@ | |||
<dataset> | |||
<groups id="100" name="sonar-administrators"/> | |||
<groups id="101" name="sonar-users"/> | |||
<!-- All 3 lines with group_id 100 will be deleted --> | |||
<group_roles id="1" group_id="100" role="admin" resource_id="[null]"/> | |||
<group_roles id="2" group_id="100" role="profileadmin" resource_id="1"/> | |||
<group_roles id="3" group_id="100" role="shareDashboard" resource_id="[null]"/> | |||
<group_roles id="4" group_id="101" role="shareDashboard" resource_id="[null]"/> | |||
<group_roles id="5" group_id="[null]" role="scan" resource_id="[null]"/> | |||
<group_roles id="6" group_id="[null]" role="dryRunScan" resource_id="[null]"/> | |||
<group_roles id="7" group_id="102" role="admin" resource_id="1"/> | |||
</dataset> |
@@ -3,13 +3,13 @@ | |||
<groups id="100" name="sonar-administrators"/> | |||
<groups id="101" name="sonar-users"/> | |||
<group_roles id="1" group_id="100" role="admin"/> | |||
<group_roles id="3" group_id="100" role="shareDashboard"/> | |||
<group_roles id="4" group_id="101" role="shareDashboard"/> | |||
<group_roles id="1" group_id="100" role="admin" resource_id="[null]"/> | |||
<group_roles id="3" group_id="100" role="shareDashboard" resource_id="[null]"/> | |||
<group_roles id="4" group_id="101" role="shareDashboard" resource_id="[null]"/> | |||
<!-- Group 'anyone' has a NULL group_id --> | |||
<group_roles id="5" group_id="[null]" role="scan"/> | |||
<group_roles id="6" group_id="[null]" role="dryRunScan"/> | |||
<group_roles id="5" group_id="[null]" role="scan" resource_id="[null]"/> | |||
<group_roles id="6" group_id="[null]" role="dryRunScan" resource_id="[null]"/> | |||
<group_roles id="7" group_id="102" role="admin" resource_id="1"/> | |||
@@ -3,14 +3,14 @@ | |||
<groups id="100" name="sonar-administrators"/> | |||
<groups id="101" name="sonar-users"/> | |||
<group_roles id="1" group_id="100" role="admin"/> | |||
<group_roles id="2" group_id="100" role="profileadmin"/> | |||
<group_roles id="3" group_id="100" role="shareDashboard"/> | |||
<group_roles id="4" group_id="101" role="shareDashboard"/> | |||
<group_roles id="1" group_id="100" role="admin" resource_id="[null]"/> | |||
<group_roles id="2" group_id="100" role="profileadmin" resource_id="[null]"/> | |||
<group_roles id="3" group_id="100" role="shareDashboard" resource_id="[null]"/> | |||
<group_roles id="4" group_id="101" role="shareDashboard" resource_id="[null]"/> | |||
<!-- Group 'anyone' has a NULL group_id --> | |||
<group_roles id="5" group_id="[null]" role="scan"/> | |||
<group_roles id="6" group_id="[null]" role="dryRunScan"/> | |||
<group_roles id="5" group_id="[null]" role="scan" resource_id="[null]"/> | |||
<group_roles id="6" group_id="[null]" role="dryRunScan" resource_id="[null]"/> | |||
<!-- Component permission, it should not be returned with global permissions --> | |||
<group_roles id="7" group_id="102" role="admin" resource_id="1"/> |
@@ -3,8 +3,8 @@ | |||
<users id="200" login="admin_user" name="admin_user" active="[true]"/> | |||
<users id="201" login="profile_admin_user" name="profile_admin_user" active="[true]"/> | |||
<user_roles id="1" user_id="200" role="admin"/> | |||
<user_roles id="3" user_id="201" role="profileadmin"/> | |||
<user_roles id="1" user_id="200" role="admin" resource_id="[null]"/> | |||
<user_roles id="3" user_id="201" role="profileadmin" resource_id="[null]"/> | |||
<user_roles id="4" user_id="200" role="admin" resource_id="1"/> | |||
@@ -3,9 +3,9 @@ | |||
<users id="200" login="admin_user" name="admin_user" active="[true]"/> | |||
<users id="201" login="profile_admin_user" name="profile_admin_user" active="[true]"/> | |||
<user_roles id="1" user_id="200" role="admin"/> | |||
<user_roles id="2" user_id="200" role="profileadmin"/> | |||
<user_roles id="3" user_id="201" role="profileadmin"/> | |||
<user_roles id="1" user_id="200" role="admin" resource_id="[null]"/> | |||
<user_roles id="2" user_id="200" role="profileadmin" resource_id="[null]"/> | |||
<user_roles id="3" user_id="201" role="profileadmin" resource_id="[null]"/> | |||
<!-- Component permission, it should not be returned with global permissions --> | |||
<user_roles id="4" user_id="200" role="admin" resource_id="1"/> |
@@ -3,12 +3,12 @@ | |||
<groups id="100" name="sonar-administrators"/> | |||
<groups id="101" name="sonar-users"/> | |||
<group_roles id="1" group_id="100" role="admin"/> | |||
<group_roles id="3" group_id="101" role="codeviewer"/> | |||
<group_roles id="1" group_id="100" role="admin" resource_id="1"/> | |||
<group_roles id="3" group_id="101" role="codeviewer" resource_id="1"/> | |||
<!-- Group 'anyone' has a NULL group_id --> | |||
<group_roles id="4" group_id="[null]" role="user"/> | |||
<group_roles id="4" group_id="[null]" role="user" resource_id="1"/> | |||
<group_roles id="5" group_id="100" role="admin"/> | |||
<group_roles id="5" group_id="100" role="admin" resource_id="[null]"/> | |||
</dataset> |
@@ -11,6 +11,6 @@ | |||
<group_roles id="4" group_id="[null]" role="user" resource_id="1"/> | |||
<!-- Global permission, it should not be returned with component permissions --> | |||
<group_roles id="5" group_id="100" role="admin"/> | |||
<group_roles id="5" group_id="100" role="admin" resource_id="[null]"/> | |||
</dataset> |