]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-1330 Purge edit permissions when deleting quality profile
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 27 Sep 2017 15:04:02 +0000 (17:04 +0200)
committerStas Vilchik <stas.vilchik@sonarsource.com>
Mon, 2 Oct 2017 15:18:15 +0000 (17:18 +0200)
13 files changed:
server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditGroupsDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditGroupsMapper.java
server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditUsersDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QProfileEditUsersMapper.java
server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QProfileEditGroupsMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QProfileEditUsersMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditGroupsDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QProfileEditUsersDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDbTester.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactoryImpl.java
server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/search-example.json
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryImplTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/SearchActionTest.java

index ce7859e7d0da1088999f3e6dbe71be03f907bb45..c390e7afee0118f343408372801a80905261c287 100644 (file)
@@ -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<QProfileDto> 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);
   }
index 717331159004268657390007f27f059b754ba0df..561b0f850854c57617c7fc8225bcb3d15ff5c484 100644 (file)
@@ -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<String> qProfileUuids);
+
 }
index 527ca96d1d6378091e1243a429cc3c321dc5c7a6..df41e1f49637967cf67d0dfca4efaaabffc0b72b 100644 (file)
@@ -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<UserMembershipDto> selectByQuery(DbSession dbSession, SearchUsersQuery query, Pagination pagination){
+  public List<UserMembershipDto> selectByQuery(DbSession dbSession, SearchUsersQuery query, Pagination pagination) {
     return mapper(dbSession).selectByQuery(query, pagination);
   }
 
-  public List<String> selectQProfileUuidsByOrganizationAndUser(DbSession dbSession, OrganizationDto organization, UserDto userDto){
+  public List<String> 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<QProfileDto> 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);
   }
index 07232efe63f48d2ff29df86375f3912785444fb2..4397d07571446dec5d392b78bde9450b0adc0f8d 100644 (file)
@@ -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<String> qProfileUuids);
 }
index ddc8b09d175cc11146ba643cb83e5675bb2daf5d..0ce45bd4ee7104acd0ea30155b7be13ff18e863f 100644 (file)
     and group_id = #{groupId, jdbcType=INTEGER}
   </delete>
 
+  <delete id="deleteByQProfiles" parameterType="map">
+    delete from qprofile_edit_groups
+    where qprofile_uuid in <foreach collection="qProfileUuids" open="(" close=")" item="qProfileUuid" separator=",">#{qProfileUuid, jdbcType=VARCHAR}</foreach>
+  </delete>
+
 </mapper>
 
index b678ef808d1fee47d66f16bf1d71f5bc2220e13b..1f46018f276b480deb83439891d339f0aec4048c 100644 (file)
     and user_id = #{userId, jdbcType=INTEGER}
   </delete>
 
+  <delete id="deleteByQProfiles" parameterType="map">
+    delete from qprofile_edit_users
+    where qprofile_uuid in <foreach collection="qProfileUuids" open="(" close=")" item="qProfileUuid" separator=",">#{qProfileUuid, jdbcType=VARCHAR}</foreach>
+  </delete>
+
 </mapper>
 
index 2aaf478f926974f14670cae48b2c940bf3ab8980..82c2f91f882a0d32be3726a972ff764632bb80c0 100644 (file)
@@ -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();
+  }
+
 }
index 741f396b8586711bf24522df81dc71a744672040..2f7f8298f61a37e078332aadabb715f77f9c35df 100644 (file)
@@ -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();
+  }
 }
index 98f86b66360eb7de26dc5af2a5edf759011d658b..3fb4a9241dbc627f7e903e118467fd627fb1bbec 100644 (file)
@@ -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())
index 90bd1b1dacb50df30a1b5a44d04de87fda485ebb..804fd3c7e6a3ac6f51622ae3b962e06b93d41cb1 100644 (file)
@@ -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.
index 66df3d862bcbe3ee0353b17cc360911fb6b3e92c..7c3eabe8acc8c1588b17d70756201434c4c4c811 100644 (file)
@@ -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
       }
index f2a0e92b8b2d37b93460faf0a98a5b0e9492834d..13a0dc632079905ba000a7457056e499f56cfb7c 100644 (file)
@@ -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);
index 1e53bbf1ef04e32edcce1795cc36bfc22089e084..f873af646b470d2ba8cd40081f76e68688bb5067 100644 (file)
@@ -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);