From 068f55312c888c0736f0ba30929cc2e31c759a91 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Wed, 27 Sep 2017 17:04:02 +0200 Subject: [PATCH] SONAR-1330 Purge edit permissions when deleting quality profile --- .../qualityprofile/QProfileEditGroupsDao.java | 5 ++++ .../QProfileEditGroupsMapper.java | 3 +++ .../qualityprofile/QProfileEditUsersDao.java | 13 ++++++++--- .../QProfileEditUsersMapper.java | 3 +++ .../QProfileEditGroupsMapper.xml | 5 ++++ .../QProfileEditUsersMapper.xml | 5 ++++ .../QProfileEditGroupsDaoTest.java | 23 +++++++++++++++++++ .../QProfileEditUsersDaoTest.java | 23 +++++++++++++++++++ .../QualityProfileDbTester.java | 3 +++ .../qualityprofile/QProfileFactoryImpl.java | 4 ++++ .../qualityprofile/ws/search-example.json | 2 +- .../QProfileFactoryImplTest.java | 17 ++++++++++++++ .../qualityprofile/ws/SearchActionTest.java | 2 +- 13 files changed, 103 insertions(+), 5 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditGroupsDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditGroupsDao.java index ce7859e7d0d..c390e7afee0 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditGroupsDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditGroupsDao.java @@ -32,6 +32,7 @@ import org.sonar.db.user.GroupDto; import static org.sonar.core.util.stream.MoreCollectors.toList; import static org.sonar.db.DatabaseUtils.executeLargeInputs; +import static org.sonar.db.DatabaseUtils.executeLargeUpdates; public class QProfileEditGroupsDao implements Dao { @@ -71,6 +72,10 @@ public class QProfileEditGroupsDao implements Dao { mapper(dbSession).delete(profile.getKee(), group.getId()); } + public void deleteByQProfiles(DbSession dbSession, List qProfiles) { + executeLargeUpdates(qProfiles.stream().map(QProfileDto::getKee).collect(toList()), p -> mapper(dbSession).deleteByQProfiles(p)); + } + private static QProfileEditGroupsMapper mapper(DbSession dbSession) { return dbSession.getMapper(QProfileEditGroupsMapper.class); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditGroupsMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditGroupsMapper.java index 71733115900..561b0f85085 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditGroupsMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditGroupsMapper.java @@ -19,6 +19,7 @@ */ package org.sonar.db.qualityprofile; +import java.util.Collection; import java.util.List; import org.apache.ibatis.annotations.Param; import org.sonar.db.Pagination; @@ -37,4 +38,6 @@ public interface QProfileEditGroupsMapper { void delete(@Param("qProfileUuid") String qProfileUuid, @Param("groupId") int groupId); + void deleteByQProfiles(@Param("qProfileUuids") Collection qProfileUuids); + } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditUsersDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditUsersDao.java index 527ca96d1d6..df41e1f4963 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditUsersDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditUsersDao.java @@ -27,6 +27,9 @@ import org.sonar.db.Pagination; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.user.UserDto; +import static org.sonar.core.util.stream.MoreCollectors.toList; +import static org.sonar.db.DatabaseUtils.executeLargeUpdates; + public class QProfileEditUsersDao implements Dao { private final System2 system2; @@ -39,15 +42,15 @@ public class QProfileEditUsersDao implements Dao { return mapper(dbSession).selectByQProfileAndUser(profile.getKee(), user.getId()) != null; } - public int countByQuery(DbSession dbSession, SearchUsersQuery query){ + public int countByQuery(DbSession dbSession, SearchUsersQuery query) { return mapper(dbSession).countByQuery(query); } - public List selectByQuery(DbSession dbSession, SearchUsersQuery query, Pagination pagination){ + public List selectByQuery(DbSession dbSession, SearchUsersQuery query, Pagination pagination) { return mapper(dbSession).selectByQuery(query, pagination); } - public List selectQProfileUuidsByOrganizationAndUser(DbSession dbSession, OrganizationDto organization, UserDto userDto){ + public List selectQProfileUuidsByOrganizationAndUser(DbSession dbSession, OrganizationDto organization, UserDto userDto) { return mapper(dbSession).selectQProfileUuidsByOrganizationAndUser(organization.getUuid(), userDto.getId()); } @@ -59,6 +62,10 @@ public class QProfileEditUsersDao implements Dao { mapper(dbSession).delete(profile.getKee(), user.getId()); } + public void deleteByQProfiles(DbSession dbSession, List qProfiles) { + executeLargeUpdates(qProfiles.stream().map(QProfileDto::getKee).collect(toList()), p -> mapper(dbSession).deleteByQProfiles(p)); + } + private static QProfileEditUsersMapper mapper(DbSession dbSession) { return dbSession.getMapper(QProfileEditUsersMapper.class); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditUsersMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditUsersMapper.java index 07232efe63f..4397d075714 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditUsersMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditUsersMapper.java @@ -19,6 +19,7 @@ */ package org.sonar.db.qualityprofile; +import java.util.Collection; import java.util.List; import org.apache.ibatis.annotations.Param; import org.sonar.db.Pagination; @@ -36,4 +37,6 @@ public interface QProfileEditUsersMapper { void insert(@Param("dto") QProfileEditUsersDto dto, @Param("now") long now); void delete(@Param("qProfileUuid") String qProfileUuid, @Param("userId") int userId); + + void deleteByQProfiles(@Param("qProfileUuids") Collection qProfileUuids); } diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QProfileEditGroupsMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QProfileEditGroupsMapper.xml index ddc8b09d175..0ce45bd4ee7 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QProfileEditGroupsMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QProfileEditGroupsMapper.xml @@ -104,5 +104,10 @@ and group_id = #{groupId, jdbcType=INTEGER} + + delete from qprofile_edit_groups + where qprofile_uuid in #{qProfileUuid, jdbcType=VARCHAR} + + diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QProfileEditUsersMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QProfileEditUsersMapper.xml index b678ef808d1..1f46018f276 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QProfileEditUsersMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QProfileEditUsersMapper.xml @@ -105,5 +105,10 @@ and user_id = #{userId, jdbcType=INTEGER} + + delete from qprofile_edit_users + where qprofile_uuid in #{qProfileUuid, jdbcType=VARCHAR} + + diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditGroupsDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditGroupsDaoTest.java index 2aaf478f926..82c2f91f882 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditGroupsDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditGroupsDaoTest.java @@ -254,4 +254,27 @@ public class QProfileEditGroupsDaoTest { assertThat(underTest.exists(db.getSession(), profile, group)).isFalse(); } + @Test + public void deleteByQProfiles() { + OrganizationDto organization = db.organizations().insert(); + OrganizationDto anotherOrganization = db.organizations().insert(); + QProfileDto profile1 = db.qualityProfiles().insert(organization); + QProfileDto profile2 = db.qualityProfiles().insert(organization); + QProfileDto profile3 = db.qualityProfiles().insert(organization); + QProfileDto anotherProfile = db.qualityProfiles().insert(anotherOrganization); + GroupDto group1 = db.users().insertGroup(organization); + GroupDto group2 = db.users().insertGroup(organization); + db.qualityProfiles().addGroupPermission(profile1, group1); + db.qualityProfiles().addGroupPermission(profile2, group2); + db.qualityProfiles().addGroupPermission(profile3, group1); + db.qualityProfiles().addGroupPermission(anotherProfile, group1); + + underTest.deleteByQProfiles(db.getSession(), asList(profile1, profile2)); + + assertThat(underTest.exists(db.getSession(), profile1, group1)).isFalse(); + assertThat(underTest.exists(db.getSession(), profile2, group2)).isFalse(); + assertThat(underTest.exists(db.getSession(), profile3, group1)).isTrue(); + assertThat(underTest.exists(db.getSession(), anotherProfile, group1)).isTrue(); + } + } diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditUsersDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditUsersDaoTest.java index 741f396b858..2f7f8298f61 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditUsersDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditUsersDaoTest.java @@ -30,6 +30,7 @@ import org.sonar.db.Pagination; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.user.UserDto; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import static org.assertj.core.api.Assertions.tuple; @@ -286,4 +287,26 @@ public class QProfileEditUsersDaoTest { assertThat(underTest.exists(db.getSession(), profile, user)).isFalse(); } + @Test + public void deleteByQProfiles() { + OrganizationDto organization = db.organizations().insert(); + OrganizationDto anotherOrganization = db.organizations().insert(); + QProfileDto profile1 = db.qualityProfiles().insert(organization); + QProfileDto profile2 = db.qualityProfiles().insert(organization); + QProfileDto profile3 = db.qualityProfiles().insert(organization); + QProfileDto anotherProfile = db.qualityProfiles().insert(anotherOrganization); + UserDto user1 = db.users().insertUser(); + UserDto user2 = db.users().insertUser(); + db.qualityProfiles().addUserPermission(profile1, user1); + db.qualityProfiles().addUserPermission(profile2, user2); + db.qualityProfiles().addUserPermission(profile3, user1); + db.qualityProfiles().addUserPermission(anotherProfile, user1); + + underTest.deleteByQProfiles(db.getSession(), asList(profile1, profile2)); + + assertThat(underTest.exists(db.getSession(), profile1, user1)).isFalse(); + assertThat(underTest.exists(db.getSession(), profile2, user2)).isFalse(); + assertThat(underTest.exists(db.getSession(), profile3, user1)).isTrue(); + assertThat(underTest.exists(db.getSession(), anotherProfile, user1)).isTrue(); + } } diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDbTester.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDbTester.java index 98f86b66360..3fb4a9241db 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDbTester.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDbTester.java @@ -33,6 +33,7 @@ import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; +import static com.google.common.base.Preconditions.checkArgument; import static org.apache.commons.lang.math.RandomUtils.nextInt; import static org.apache.commons.lang.math.RandomUtils.nextLong; import static org.sonar.db.qualityprofile.ActiveRuleDto.createFor; @@ -113,6 +114,7 @@ public class QualityProfileDbTester { } public void addUserPermission(QProfileDto profile, UserDto user){ + checkArgument(!profile.isBuiltIn(), "Built-In profile cannot be used"); dbClient.qProfileEditUsersDao().insert(dbSession, new QProfileEditUsersDto() .setUuid(UuidFactoryFast.getInstance().create()) .setUserId(user.getId()) @@ -122,6 +124,7 @@ public class QualityProfileDbTester { } public void addGroupPermission(QProfileDto profile, GroupDto group){ + checkArgument(!profile.isBuiltIn(), "Built-In profile cannot be used"); dbClient.qProfileEditGroupsDao().insert(dbSession, new QProfileEditGroupsDto() .setUuid(UuidFactoryFast.getInstance().create()) .setGroupId(group.getId()) diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactoryImpl.java index 90bd1b1dacb..804fd3c7e6a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactoryImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactoryImpl.java @@ -127,6 +127,10 @@ public class QProfileFactoryImpl implements QProfileFactory { db.defaultQProfileDao().deleteByQProfileUuids(dbSession, uuids); db.qualityProfileDao().deleteOrgQProfilesByUuids(dbSession, uuids); + // Permissions are only available on custom profiles + db.qProfileEditUsersDao().deleteByQProfiles(dbSession, customProfiles); + db.qProfileEditGroupsDao().deleteByQProfiles(dbSession, customProfiles); + // tables related to rules_profiles and active_rules are deleted // only for custom profiles. Built-in profiles are never // deleted from table rules_profiles. diff --git a/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json index 66df3d862bc..7c3eabe8acc 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json +++ b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json @@ -53,7 +53,7 @@ "ruleUpdatedAt": "2016-12-22T19:10:03+0100", "userUpdatedAt": "2016-06-29T21:57:01+0200", "actions": { - "edit": false, + "edit": true, "setAsDefault": false, "copy": false } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryImplTest.java index f2a0e92b8b2..13a0dc63207 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryImplTest.java @@ -44,6 +44,8 @@ import org.sonar.db.qualityprofile.QProfileDto; import org.sonar.db.qualityprofile.RulesProfileDto; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleParamDto; +import org.sonar.db.user.GroupDto; +import org.sonar.db.user.UserDto; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; @@ -229,6 +231,21 @@ public class QProfileFactoryImplTest { assertQualityProfileFromDb(profile).isNotNull(); } + @Test + public void delete_removes_qprofile_edit_permissions() { + OrganizationDto organization = db.organizations().insert(); + QProfileDto profile = db.qualityProfiles().insert(organization); + UserDto user = db.users().insertUser(); + db.qualityProfiles().addUserPermission(profile, user); + GroupDto group = db.users().insertGroup(organization); + db.qualityProfiles().addGroupPermission(profile, group); + + underTest.delete(dbSession, asList(profile)); + + assertThat(db.countRowsOfTable(dbSession, "qprofile_edit_users")).isZero(); + assertThat(db.countRowsOfTable(dbSession, "qprofile_edit_groups")).isZero(); + } + private QProfileDto createCustomProfile(OrganizationDto org) { QProfileDto profile = db.qualityProfiles().insert(org, p -> p.setLanguage("xoo").setIsBuiltIn(false)); ActiveRuleDto activeRuleDto = db.qualityProfiles().activateRule(profile, rule); diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java index 1e53bbf1ef0..f873af646b4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java @@ -505,7 +505,7 @@ public class SearchActionTest { .forEach(project -> db.qualityProfiles().associateWithProject(project, myBuProfile)); // User UserDto user = db.users().insertUser(); - db.qualityProfiles().addUserPermission(sonarWayCs, user); + db.qualityProfiles().addUserPermission(myCompanyProfile, user); db.qualityProfiles().addUserPermission(myBuProfile, user); userSession.logIn(user); -- 2.39.5