]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-15154 add audit logs about projects, portfolios and apps
authorlukasz-jarocki-sonarsource <77498856+lukasz-jarocki-sonarsource@users.noreply.github.com>
Fri, 23 Jul 2021 09:45:00 +0000 (11:45 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 27 Jul 2021 20:03:03 +0000 (20:03 +0000)
24 files changed:
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistComponentsStep.java
server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditPersister.java
server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/ComponentKeyNewValue.java [new file with mode: 0644]
server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/ComponentNewValue.java [new file with mode: 0644]
server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/ProjectNewValue.java [new file with mode: 0644]
server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentKeyUpdaterDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/project/ProjectDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java
server/sonar-db-dao/src/test/java/org/sonar/db/alm/setting/ProjectAlmSettingDaoWithPersisterTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/audit/model/ComponentKeyNewValueTest.java [new file with mode: 0644]
server/sonar-db-dao/src/test/java/org/sonar/db/audit/model/ComponentNewValueTest.java [new file with mode: 0644]
server/sonar-db-dao/src/test/java/org/sonar/db/audit/model/ProjectNewValueTest.java [new file with mode: 0644]
server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentKeyUpdaterDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/project/ProjectDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
server/sonar-server-common/src/test/java/org/sonar/server/component/index/ComponentIndexerTest.java
server/sonar-server-common/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexerTest.java
server/sonar-webserver-es/src/test/java/org/sonar/server/permission/index/PermissionIndexerTest.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentCleanerService.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/UpdateVisibilityAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/component/ws/SuggestionsActionTest.java

index dc9ab683f8d2f9d7ac71d6c94e88461bbeaf24c7..af25cfd94c07c43ad73241b43c2d55ce102ff63b 100644 (file)
@@ -51,6 +51,8 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentUpdateDto;
 
 import static java.util.Optional.ofNullable;
+import static org.sonar.api.resources.Qualifiers.PROJECT;
+import static org.sonar.api.resources.Qualifiers.VIEW;
 import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER;
 import static org.sonar.db.component.ComponentDto.UUID_PATH_OF_ROOT;
 import static org.sonar.db.component.ComponentDto.UUID_PATH_SEPARATOR;
@@ -106,7 +108,7 @@ public class PersistComponentsStep implements ComputationStep {
         .visit(treeRootHolder.getRoot());
 
       disableRemainingComponents(dbSession, existingDtosByUuids.values());
-      ensureConsistentVisibility(dbSession, projectUuid, isRootPrivate);
+      ensureConsistentVisibility(dbSession, projectUuid, isRootPrivate, treeRootHolder.getRoot().getType());
 
       dbSession.commit();
     }
@@ -133,8 +135,15 @@ public class PersistComponentsStep implements ComputationStep {
     disabledComponentsHolder.setUuids(uuids);
   }
 
-  private void ensureConsistentVisibility(DbSession dbSession, String projectUuid, boolean isRootPrivate) {
-    dbClient.componentDao().setPrivateForRootComponentUuid(dbSession, projectUuid, isRootPrivate);
+  private void ensureConsistentVisibility(DbSession dbSession, String projectUuid, boolean isRootPrivate,
+    Component.Type type) {
+    String qualifier = null;
+    if (type == Component.Type.PROJECT) {
+      qualifier = PROJECT;
+    } else if (type == Component.Type.VIEW) {
+      qualifier = VIEW;
+    }
+    dbClient.componentDao().setPrivateForRootComponentUuid(dbSession, projectUuid, isRootPrivate, qualifier);
   }
 
   private static boolean isRootPrivate(Component root, Map<String, ComponentDto> existingDtosByUuids) {
@@ -242,7 +251,7 @@ public class PersistComponentsStep implements ComputationStep {
       Optional<ComponentUpdateDto> update = compareForUpdate(existingComponent, componentDto);
       if (update.isPresent()) {
         ComponentUpdateDto updateDto = update.get();
-        dbClient.componentDao().update(dbSession, updateDto);
+        dbClient.componentDao().update(dbSession, updateDto, componentDto.qualifier());
 
         // update the fields in memory in order the PathAwareVisitor.Path
         // to be up-to-date
@@ -268,7 +277,7 @@ public class PersistComponentsStep implements ComputationStep {
       ComponentDto res = createBase(project);
 
       res.setScope(Scopes.PROJECT);
-      res.setQualifier(Qualifiers.PROJECT);
+      res.setQualifier(PROJECT);
       res.setName(project.getName());
       res.setLongName(res.name());
       res.setDescription(project.getDescription());
@@ -346,7 +355,7 @@ public class PersistComponentsStep implements ComputationStep {
       ComponentDto res = createBase(projectView);
 
       res.setScope(Scopes.FILE);
-      res.setQualifier(Qualifiers.PROJECT);
+      res.setQualifier(PROJECT);
       res.setName(projectView.getName());
       res.setLongName(res.name());
       res.setCopyComponentUuid(projectView.getProjectViewAttributes().getProjectUuid());
index abeb69ff0e10eb55b7c2071e275e9cc39dce8149..3875dcbc61bed96899f8a17d9396a11a08d008a1 100644 (file)
@@ -23,6 +23,8 @@ import org.sonar.core.extension.PlatformLevel;
 import org.sonar.db.DbSession;
 import org.sonar.db.audit.model.NewValue;
 
+import javax.annotation.Nullable;
+
 @PlatformLevel(1)
 public interface AuditPersister {
 
@@ -107,4 +109,19 @@ public interface AuditPersister {
   void deletePersonalAccessToken(DbSession dbSession, NewValue newValue);
 
   boolean isTrackedProperty(String propertyKey);
+
+  void addComponent(DbSession dbSession, NewValue newValue, String qualifier);
+
+  void deleteComponent(DbSession dbSession, NewValue newValue, @Nullable String qualifier);
+
+  void updateComponent(DbSession dbSession, NewValue newValue, String qualifier);
+
+  void setPrivateForComponentUuid(DbSession session, NewValue componentNewValue, @Nullable String qualifier);
+
+  void updateComponentVisibility(DbSession session, NewValue projectNewValue, String qualifier);
+
+  void componentKeyUpdate(DbSession session, NewValue componentKeyNewValue, String qualifier);
+
+  void componentKeyBranchUpdate(DbSession session, NewValue componentKeyNewValue, String qualifier);
+
 }
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/ComponentKeyNewValue.java b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/ComponentKeyNewValue.java
new file mode 100644 (file)
index 0000000..84a485f
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.audit.model;
+
+public class ComponentKeyNewValue implements NewValue{
+
+  private final String componentUuid;
+  private final String oldKey;
+  private final String newKey;
+
+  public ComponentKeyNewValue(String componentUuid, String oldKey, String newKey) {
+    this.componentUuid = componentUuid;
+    this.oldKey = oldKey;
+    this.newKey = newKey;
+  }
+
+  public String getComponentUuid() {
+    return componentUuid;
+  }
+
+  public String getOldKey() {
+    return oldKey;
+  }
+
+  public String getNewKey() {
+    return newKey;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("{");
+    addField(sb, "\"componentUuid\": ", this.getComponentUuid(), true);
+    addField(sb, "\"oldKey\": ", this.getOldKey(), true);
+    addField(sb, "\"newKey\": ", this.getNewKey(), true);
+    endString(sb);
+    return sb.toString();
+  }
+
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/ComponentNewValue.java b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/ComponentNewValue.java
new file mode 100644 (file)
index 0000000..e40c970
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.audit.model;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.ObjectUtils;
+
+import static org.sonar.api.resources.Qualifiers.APP;
+import static org.sonar.api.resources.Qualifiers.PROJECT;
+import static org.sonar.api.resources.Qualifiers.VIEW;
+
+public class ComponentNewValue implements NewValue {
+
+  private String componentUuid;
+  private String componentName;
+  @Nullable
+  private String description;
+  private String rootComponentUuid;
+  private String path;
+  private String key;
+  private Boolean isPrivate;
+  private Boolean isEnabled;
+  private String prefix;
+
+
+  public ComponentNewValue(String componentUuid, String qualifier) {
+    this.componentUuid = componentUuid;
+    this.generateComponentPrefix(qualifier);
+  }
+
+  public ComponentNewValue(String componentUuid, String name, String qualifier) {
+    this.componentUuid = componentUuid;
+    this.componentName = name;
+    this.generateComponentPrefix(qualifier);
+  }
+
+  public ComponentNewValue(String rootComponentUuid, boolean isPrivate, @Nullable String qualifier) {
+    this.rootComponentUuid = rootComponentUuid;
+    this.isPrivate = isPrivate;
+    this.generateComponentPrefix(qualifier);
+  }
+
+  public ComponentNewValue(String uuid, String name, String key, boolean enabled, String path, String qualifier) {
+    this.componentUuid = uuid;
+    this.componentName = name;
+    this.isEnabled = enabled;
+    this.path = path;
+    this.key = key;
+    this.generateComponentPrefix(qualifier);
+  }
+
+  public ComponentNewValue(String uuid, boolean isPrivate, String name, @Nullable String description, String qualifier) {
+    this.componentUuid = uuid;
+    this.isPrivate = isPrivate;
+    this.componentName = name;
+    this.description = description;
+    this.generateComponentPrefix(qualifier);
+  }
+
+  public String getComponentUuid() {
+    return componentUuid;
+  }
+
+  public String getComponentName() {
+    return componentName;
+  }
+
+  @CheckForNull
+  public String getDescription() {
+    return description;
+  }
+
+  public String getKey() {
+    return key;
+  }
+
+  public boolean isPrivate() {
+    return isPrivate;
+  }
+
+  private void generateComponentPrefix(String qualifier) {
+    if (qualifier == null) {
+      this.prefix = "component";
+      return ;
+    }
+    switch (qualifier) {
+      case VIEW:
+        this.prefix = "portfolio";
+        break;
+      case APP:
+        this.prefix = "application";
+        break;
+      case PROJECT:
+        this.prefix = "project";
+        break;
+      default:
+        this.prefix = "component";
+        break;
+    }
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("{");
+    addField(sb, "\"" + this.prefix + "Uuid\": ", this.componentUuid, true);
+    addField(sb, "\"rootComponentUuid\": ", this.rootComponentUuid, true);
+    addField(sb, "\"" + this.prefix + "Name\": ", this.componentName, true);
+    addField(sb, "\"description\": ", this.description, true);
+    addField(sb, "\"oldKey\": ", this.key, true);
+    addField(sb, "\"path\": ", this.path, true);
+    addField(sb, "\"isPrivate\": ", ObjectUtils.toString(this.isPrivate), false);
+    addField(sb, "\"isEnabled\": ", ObjectUtils.toString(this.isEnabled), false);
+    endString(sb);
+    return sb.toString();
+  }
+
+}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/ProjectNewValue.java b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/ProjectNewValue.java
new file mode 100644 (file)
index 0000000..e10b52d
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.audit.model;
+
+import org.apache.commons.lang.ObjectUtils;
+
+public class ProjectNewValue implements NewValue{
+
+  private final String uuid;
+  private String name;
+  private String description;
+  private Boolean isPrivate;
+
+  public ProjectNewValue(String uuid, String name) {
+    this.uuid = uuid;
+    this.name = name;
+  }
+
+  public ProjectNewValue(String uuid, boolean isPrivate) {
+    this.uuid = uuid;
+    this.isPrivate = isPrivate;
+  }
+
+  public ProjectNewValue(String uuid, boolean isPrivate, String name, String description) {
+    this.uuid = uuid;
+    this.isPrivate = isPrivate;
+    this.name = name;
+    this.description = description;
+  }
+
+  public String getUuid() {
+    return uuid;
+  }
+
+  public String getDescription() {
+    return description;
+  }
+
+  public boolean isPrivate() {
+    return isPrivate;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("{");
+    addField(sb, "\"projectUuid\": ", this.uuid, true);
+    addField(sb, "\"description\": ", this.description, true);
+    addField(sb, "\"name\": ", this.name, true);
+    addField(sb, "\"isPrivate\": ", ObjectUtils.toString(this.isPrivate), false);
+    endString(sb);
+    return sb.toString();
+  }
+}
index 7a1b2b8ecaa7dc5ee6941e3bdc54dbc85260d168..4d18a0194d8c6e0d01b9be3bfcb39f6a111ca255 100644 (file)
@@ -38,6 +38,8 @@ import org.sonar.api.resources.Scopes;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
 import org.sonar.db.RowNotFoundException;
+import org.sonar.db.audit.AuditPersister;
+import org.sonar.db.audit.model.ComponentNewValue;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Collections.emptyList;
@@ -51,6 +53,16 @@ import static org.sonar.db.component.ComponentDto.generateBranchKey;
 import static org.sonar.db.component.ComponentDto.generatePullRequestKey;
 
 public class ComponentDao implements Dao {
+  private AuditPersister auditPersister;
+
+  public ComponentDao() {
+    //intentionally empty
+  }
+
+  public ComponentDao(AuditPersister auditPersister) {
+    this.auditPersister = auditPersister;
+  }
+
   private static List<ComponentDto> selectByQueryImpl(DbSession session, ComponentQuery query, int offset, int limit) {
     if (query.hasEmptySetOfComponents()) {
       return emptyList();
@@ -326,6 +338,9 @@ public class ComponentDao implements Dao {
   }
 
   public void insert(DbSession session, ComponentDto item) {
+    if (auditPersister != null) {
+      auditPersister.addComponent(session, new ComponentNewValue(item.uuid(), item.name(), item.qualifier()), item.qualifier());
+    }
     mapper(session).insert(item);
   }
 
@@ -341,7 +356,11 @@ public class ComponentDao implements Dao {
     insert(session, Stream.concat(Stream.of(item), Arrays.stream(others)));
   }
 
-  public void update(DbSession session, ComponentUpdateDto component) {
+  public void update(DbSession session, ComponentUpdateDto component, String qualifier) {
+    if (auditPersister != null) {
+      auditPersister.updateComponent(session, new ComponentNewValue(component.getUuid(), component.getBName(),
+        component.getBKey(), component.isBEnabled(), component.getBPath(), qualifier), qualifier);
+    }
     mapper(session).update(component);
   }
 
@@ -357,11 +376,17 @@ public class ComponentDao implements Dao {
     mapper(session).resetBChangedForRootComponentUuid(projectUuid);
   }
 
-  public void setPrivateForRootComponentUuid(DbSession session, String projectUuid, boolean isPrivate) {
+  public void setPrivateForRootComponentUuid(DbSession session, String projectUuid, boolean isPrivate, @Nullable String qualifier) {
+    if(auditPersister != null) {
+      auditPersister.setPrivateForComponentUuid(session, new ComponentNewValue(projectUuid, isPrivate, qualifier), qualifier);
+    }
     mapper(session).setPrivateForRootComponentUuid(projectUuid, isPrivate);
   }
 
-  public void delete(DbSession session, String componentUuid) {
+  public void delete(DbSession session, String componentUuid, String qualifier) {
+    if (auditPersister != null) {
+      auditPersister.deleteComponent(session, new ComponentNewValue(componentUuid, qualifier), qualifier);
+    }
     mapper(session).delete(componentUuid);
   }
 
index 26b7abae577e764dec0e24bd66c5040e4ebc88a0..f528fd015ae8c0185e329e5d642cc83c33f46686 100644 (file)
@@ -38,6 +38,8 @@ import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.Scopes;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
+import org.sonar.db.audit.AuditPersister;
+import org.sonar.db.audit.model.ComponentKeyNewValue;
 
 import static org.sonar.core.component.ComponentKeys.checkProjectKey;
 import static org.sonar.db.component.ComponentDto.BRANCH_KEY_SEPARATOR;
@@ -50,6 +52,15 @@ import static org.sonar.db.component.ComponentDto.generateBranchKey;
  */
 public class ComponentKeyUpdaterDao implements Dao {
 
+  private AuditPersister auditPersister;
+
+  public ComponentKeyUpdaterDao() {
+  }
+
+  public ComponentKeyUpdaterDao(AuditPersister auditPersister) {
+    this.auditPersister = auditPersister;
+  }
+
   public void updateKey(DbSession dbSession, String projectUuid, String newKey) {
     ComponentKeyUpdaterMapper mapper = dbSession.getMapper(ComponentKeyUpdaterMapper.class);
     checkExistentKey(mapper, newKey);
@@ -70,7 +81,7 @@ public class ComponentKeyUpdaterDao implements Dao {
 
     // and then proceed with the batch UPDATE at once
     runBatchUpdateForAllResources(resources, projectOldKey, newKey, mapper, (resource, oldKey) -> {
-    });
+    }, dbSession);
   }
 
   public void updateApplicationBranchKey(DbSession dbSession, String appBranchUuid, String appKey, String newBranchName) {
@@ -84,6 +95,10 @@ public class ComponentKeyUpdaterDao implements Dao {
     appBranch.setKey(newAppBranchKey);
     mapper.updateComponent(appBranch);
 
+    if(auditPersister != null) {
+      auditPersister.componentKeyBranchUpdate(dbSession, new ComponentKeyNewValue(appBranchUuid, appBranchOldKey, newAppBranchKey), Qualifiers.APP);
+    }
+
     String oldAppBranchFragment = appBranchOldKey.replace(BRANCH_KEY_SEPARATOR, "");
     String newAppBranchFragment = appKey + newBranchName;
     for (ResourceDto appBranchResource : mapper.selectProjectResources(appBranchUuid)) {
@@ -157,7 +172,7 @@ public class ComponentKeyUpdaterDao implements Dao {
           if (rekeyedResourceFilter.test(rekeyedResource)) {
             rekeyedResources.add(rekeyedResource);
           }
-        });
+        }, session);
     }
     return rekeyedResources;
   }
@@ -174,8 +189,8 @@ public class ComponentKeyUpdaterDao implements Dao {
     return key;
   }
 
-  private static void runBatchUpdateForAllResources(Collection<ResourceDto> resources, String oldKey, String newKey, ComponentKeyUpdaterMapper mapper,
-    @Nullable BiConsumer<ResourceDto, String> consumer) {
+  private void runBatchUpdateForAllResources(Collection<ResourceDto> resources, String oldKey, String newKey, ComponentKeyUpdaterMapper mapper,
+    @Nullable BiConsumer<ResourceDto, String> consumer, DbSession dbSession) {
     for (ResourceDto resource : resources) {
       String oldResourceKey = resource.getKey();
       String newResourceKey = newKey + oldResourceKey.substring(oldKey.length());
@@ -187,6 +202,10 @@ public class ComponentKeyUpdaterDao implements Dao {
       }
       mapper.updateComponent(resource);
       if (resource.getScope().equals(Scopes.PROJECT) && (resource.getQualifier().equals(Qualifiers.PROJECT) || resource.getQualifier().equals(Qualifiers.APP))) {
+        if(auditPersister != null) {
+          auditPersister.componentKeyUpdate(dbSession,
+            new ComponentKeyNewValue(resource.getUuid(), oldResourceKey, newResourceKey), resource.getQualifier());
+        }
         mapper.updateProject(oldResourceKey, newResourceKey);
       }
 
index 796c61b99e458296e86014e07919e248c828bf87..02c397dc41d5f8f6e1d6756dfc9a062386848bca 100644 (file)
@@ -26,16 +26,32 @@ import java.util.Set;
 import org.sonar.api.utils.System2;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
+import org.sonar.db.audit.AuditPersister;
+import org.sonar.db.audit.model.ComponentNewValue;
 
 public class ProjectDao implements Dao {
   private final System2 system2;
+  private AuditPersister auditPersister;
 
   public ProjectDao(System2 system2) {
     this.system2 = system2;
   }
 
-  public void insert(DbSession session, ProjectDto item) {
-    mapper(session).insert(item);
+  public ProjectDao(System2 system2, AuditPersister auditPersister) {
+    this.system2 = system2;
+    this.auditPersister = auditPersister;
+  }
+
+  public void insert(DbSession session, ProjectDto project) {
+    this.insert(session, project, false);
+  }
+
+  public void insert(DbSession session, ProjectDto project, boolean track) {
+    if (track && auditPersister != null) {
+      auditPersister.addComponent(session, new ComponentNewValue(project.getUuid(), project.getName(), project.getQualifier()),
+        project.getQualifier());
+    }
+    mapper(session).insert(project);
   }
 
   public Optional<ProjectDto> selectProjectByKey(DbSession session, String key) {
@@ -87,11 +103,10 @@ public class ProjectDao implements Dao {
     return mapper(session).selectByUuids(uuids);
   }
 
-  public void updateKey(DbSession session, String uuid, String newKey) {
-    mapper(session).updateKey(uuid, newKey, system2.now());
-  }
-
-  public void updateVisibility(DbSession session, String uuid, boolean isPrivate) {
+  public void updateVisibility(DbSession session, String uuid, boolean isPrivate, String qualifier) {
+    if (auditPersister != null) {
+      auditPersister.updateComponentVisibility(session, new ComponentNewValue(uuid, isPrivate, qualifier), qualifier);
+    }
     mapper(session).updateVisibility(uuid, isPrivate, system2.now());
   }
 
@@ -100,6 +115,11 @@ public class ProjectDao implements Dao {
   }
 
   public void update(DbSession session, ProjectDto project) {
+    if (auditPersister != null) {
+      auditPersister.updateComponent(session, new ComponentNewValue(project.getUuid(), project.isPrivate(),
+        project.getName(), project.getDescription(), project.getQualifier()), project.getQualifier());
+    }
+
     mapper(session).update(project);
   }
 
index 45bf942973a4ec57eecd6a2c0bcf1b58bd97d91d..ac746986d51e73718f0bc9b0156a3dea956e669a 100644 (file)
@@ -35,6 +35,8 @@ import org.sonar.api.utils.log.Loggers;
 import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
+import org.sonar.db.audit.AuditPersister;
+import org.sonar.db.audit.model.ComponentNewValue;
 import org.sonar.db.component.BranchMapper;
 import org.sonar.db.component.ComponentDto;
 
@@ -50,11 +52,17 @@ public class PurgeDao implements Dao {
   private static final String SCOPE_PROJECT = "PRJ";
 
   private final System2 system2;
+  private AuditPersister auditPersister;
 
   public PurgeDao(System2 system2) {
     this.system2 = system2;
   }
 
+  public PurgeDao(System2 system2, AuditPersister auditPersister) {
+    this.system2 = system2;
+    this.auditPersister = auditPersister;
+  }
+
   public void purge(DbSession session, PurgeConfiguration conf, PurgeListener listener, PurgeProfiler profiler) {
     PurgeMapper mapper = session.getMapper(PurgeMapper.class);
     PurgeCommands commands = new PurgeCommands(session, mapper, profiler, system2);
@@ -178,7 +186,7 @@ public class PurgeDao implements Dao {
     deleteRootComponent(uuid, purgeMapper, purgeCommands);
   }
 
-  public void deleteProject(DbSession session, String uuid) {
+  public void deleteProject(DbSession session, String uuid, String qualifier) {
     PurgeProfiler profiler = new PurgeProfiler();
     PurgeMapper purgeMapper = mapper(session);
     PurgeCommands purgeCommands = new PurgeCommands(session, profiler, system2);
@@ -190,6 +198,10 @@ public class PurgeDao implements Dao {
 
     deleteRootComponent(uuid, purgeMapper, purgeCommands);
 
+    if (auditPersister != null) {
+      auditPersister.deleteComponent(session, new ComponentNewValue(uuid, qualifier), qualifier);
+    }
+
     logProfiling(profiler, start);
   }
 
index 5aa197847be1b3c3423f5a31e4dd4bc31e8a9e9c..25d3ce811ea9f0ab4af493b35f7f3403cd6f1568 100644 (file)
@@ -69,7 +69,7 @@ public class ProjectAlmSettingDaoWithPersisterTest {
       .extracting(DevOpsPlatformSettingNewValue::getDevOpsPlatformSettingUuid, DevOpsPlatformSettingNewValue::getKey,
         DevOpsPlatformSettingNewValue::getProjectUuid, DevOpsPlatformSettingNewValue::getProjectName)
       .containsExactly(githubAlmSetting.getUuid(), githubAlmSetting.getKey(), project.getUuid(), project.getName());
-    assertThat(newValue.toString()).doesNotContain("url");
+    assertThat(newValue.toString()).doesNotContain("\"url\"");
 
     AlmSettingDto anotherGithubAlmSetting = db.almSettings().insertGitHubAlmSetting();
     system2.setNow(A_DATE_LATER);
@@ -87,7 +87,7 @@ public class ProjectAlmSettingDaoWithPersisterTest {
       .containsExactly(anotherGithubAlmSetting.getUuid(), anotherGithubAlmSetting.getKey(), project.getUuid(), project.getName(),
         newProjectAlmSettingDto.getAlmRepo(), newProjectAlmSettingDto.getAlmSlug(),
         newProjectAlmSettingDto.getSummaryCommentEnabled(), newProjectAlmSettingDto.getMonorepo());
-    assertThat(newValue.toString()).doesNotContain("url");
+    assertThat(newValue.toString()).doesNotContain("\"url\"");
   }
 
   @Test
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/audit/model/ComponentKeyNewValueTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/audit/model/ComponentKeyNewValueTest.java
new file mode 100644 (file)
index 0000000..564ebaa
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.audit.model;
+
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ComponentKeyNewValueTest {
+
+  @Test
+  public void toString_generatesValidJson() throws ParseException {
+    ComponentKeyNewValue newValue = new ComponentKeyNewValue("uuid", "a", "b");
+
+    JSONObject jsonObject = (JSONObject) new JSONParser().parse(newValue.toString());
+
+    assertThat(jsonObject.size()).isEqualTo(3);
+  }
+}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/audit/model/ComponentNewValueTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/audit/model/ComponentNewValueTest.java
new file mode 100644 (file)
index 0000000..8e95279
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.audit.model;
+
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ComponentNewValueTest {
+
+  @Test
+  public void toString_generatesValidJson() throws ParseException {
+    ComponentNewValue newValue = new ComponentNewValue("uuid", "name", "key", true, "path", "qualifier");
+
+    JSONObject jsonObject = (JSONObject) new JSONParser().parse(newValue.toString());
+
+    assertThat(jsonObject.size()).isEqualTo(5);
+  }
+
+  @Test
+  public void toString_addsPortfolioPrefix() {
+    ComponentNewValue newValue = new ComponentNewValue("uuid", "name", "key", true, "path", "VW");
+
+    assertThat(newValue.toString()).contains("portfolioUuid");
+  }
+
+  @Test
+  public void toString_addsProjectPrefix() {
+    ComponentNewValue newValue = new ComponentNewValue("uuid", "name", "key", true, "path", "TRK");
+
+    assertThat(newValue.toString()).contains("projectUuid");
+  }
+
+  @Test
+  public void toString_addsApplicationPrefix() {
+    ComponentNewValue newValue = new ComponentNewValue("uuid", "name", "key", true, "path", "APP");
+
+    assertThat(newValue.toString()).contains("applicationUuid");
+  }
+
+}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/audit/model/ProjectNewValueTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/audit/model/ProjectNewValueTest.java
new file mode 100644 (file)
index 0000000..45735b4
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.audit.model;
+
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ProjectNewValueTest {
+
+  @Test
+  public void toString_generatesValidJson() throws ParseException {
+    ProjectNewValue newValue = new ProjectNewValue("uuid", true, "name", "description");
+
+    JSONObject jsonObject = (JSONObject) new JSONParser().parse(newValue.toString());
+
+    assertThat(jsonObject.size()).isEqualTo(4);
+  }
+
+}
index 83c3124d05ddc9ca6eecbf7ee07776a0c3830a0c..ee252a2de8066c90ddb7f99235b8ac9993eb47fc 100644 (file)
@@ -23,25 +23,11 @@ import com.google.common.collect.ImmutableMap;
 import com.tngtech.java.junit.dataprovider.DataProvider;
 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
 import com.tngtech.java.junit.dataprovider.UseDataProvider;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Random;
-import java.util.Set;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
-import javax.annotation.Nullable;
 import org.assertj.core.api.ListAssert;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mockito;
 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.Scopes;
@@ -49,6 +35,8 @@ import org.sonar.api.utils.System2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.RowNotFoundException;
+import org.sonar.db.audit.AuditPersister;
+import org.sonar.db.audit.model.ComponentNewValue;
 import org.sonar.db.issue.IssueDto;
 import org.sonar.db.metric.MetricDto;
 import org.sonar.db.project.ProjectDto;
@@ -68,6 +56,10 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.assertj.core.api.Assertions.entry;
 import static org.assertj.core.api.Assertions.tuple;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.sonar.api.issue.Issue.STATUS_CLOSED;
 import static org.sonar.api.issue.Issue.STATUS_CONFIRMED;
 import static org.sonar.api.issue.Issue.STATUS_OPEN;
@@ -89,6 +81,21 @@ import static org.sonar.db.component.ComponentTesting.newSubView;
 import static org.sonar.db.component.ComponentTesting.newView;
 import static org.sonar.db.component.ComponentTreeQuery.Strategy.CHILDREN;
 import static org.sonar.db.component.ComponentTreeQuery.Strategy.LEAVES;
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Random;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
 
 @RunWith(DataProviderRunner.class)
 public class ComponentDaoTest {
@@ -106,9 +113,12 @@ public class ComponentDaoTest {
   @Rule
   public DbTester db = DbTester.create(system2);
 
+  private final AuditPersister auditPersister = mock(AuditPersister.class);
+
   private final Random random = new Random();
   private final DbSession dbSession = db.getSession();
   private final ComponentDao underTest = new ComponentDao();
+  private final ComponentDao underTestWithAuditPersister = new ComponentDao(auditPersister);
 
   private static ComponentTreeQuery.Builder newTreeQuery(String baseUuid) {
     return ComponentTreeQuery.builder()
@@ -323,15 +333,15 @@ public class ComponentDaoTest {
     assertThat(underTest.selectByKeysAndBranches(db.getSession(), ImmutableMap.of(
       projectBranch.getKey(), projectBranch.getBranch(),
       applicationBranch.getKey(), applicationBranch.getBranch())))
-        .extracting(ComponentDto::getKey, ComponentDto::getBranch)
-        .containsExactlyInAnyOrder(
-          tuple(projectBranch.getKey(), "my_branch"),
-          tuple(applicationBranch.getKey(), "my_branch"));
+      .extracting(ComponentDto::getKey, ComponentDto::getBranch)
+      .containsExactlyInAnyOrder(
+        tuple(projectBranch.getKey(), "my_branch"),
+        tuple(applicationBranch.getKey(), "my_branch"));
     assertThat(underTest.selectByKeysAndBranches(db.getSession(), ImmutableMap.of(
       projectBranch.getKey(), "unknown",
       "unknown", projectBranch.getBranch())))
-        .extracting(ComponentDto::getDbKey)
-        .isEmpty();
+      .extracting(ComponentDto::getDbKey)
+      .isEmpty();
     assertThat(underTest.selectByKeysAndBranches(db.getSession(), Collections.emptyMap())).isEmpty();
   }
 
@@ -1229,7 +1239,7 @@ public class ComponentDaoTest {
       .setBModuleUuidPath("moduleUuidPath")
       .setBName("name")
       .setBPath("path")
-      .setBQualifier("qualifier"));
+      .setBQualifier("qualifier"), "qualifier");
     dbSession.commit();
 
     Map<String, Object> row = selectBColumnsForUuid("U1");
@@ -1306,7 +1316,7 @@ public class ComponentDaoTest {
     ComponentDto project1 = db.components().insertPrivateProject(t -> t.setDbKey("PROJECT_1"));
     db.components().insertPrivateProject(t -> t.setDbKey("PROJECT_2"));
 
-    underTest.delete(dbSession, project1.uuid());
+    underTest.delete(dbSession, project1.uuid(), null);
     dbSession.commit();
 
     assertThat(underTest.selectByKey(dbSession, "PROJECT_1")).isEmpty();
@@ -1773,7 +1783,7 @@ public class ComponentDaoTest {
       db.components().insertComponent(newPrivateProjectDto().setRootUuid(uuid1).setProjectUuid("foo").setPrivate(false)).uuid(),
     };
 
-    underTest.setPrivateForRootComponentUuid(db.getSession(), uuid1, true);
+    underTest.setPrivateForRootComponentUuid(db.getSession(), uuid1, true, null);
 
     assertThat(privateFlagOfUuid(uuids[0])).isTrue();
     assertThat(privateFlagOfUuid(uuids[1])).isTrue();
@@ -1781,7 +1791,7 @@ public class ComponentDaoTest {
     assertThat(privateFlagOfUuid(uuids[3])).isFalse();
     assertThat(privateFlagOfUuid(uuids[4])).isFalse();
 
-    underTest.setPrivateForRootComponentUuid(db.getSession(), uuid1, false);
+    underTest.setPrivateForRootComponentUuid(db.getSession(), uuid1, false, null);
 
     assertThat(privateFlagOfUuid(uuids[0])).isFalse();
     assertThat(privateFlagOfUuid(uuids[1])).isFalse();
@@ -1789,7 +1799,7 @@ public class ComponentDaoTest {
     assertThat(privateFlagOfUuid(uuids[3])).isFalse();
     assertThat(privateFlagOfUuid(uuids[4])).isFalse();
 
-    underTest.setPrivateForRootComponentUuid(db.getSession(), uuid2, false);
+    underTest.setPrivateForRootComponentUuid(db.getSession(), uuid2, false, null);
 
     assertThat(privateFlagOfUuid(uuids[0])).isFalse();
     assertThat(privateFlagOfUuid(uuids[1])).isFalse();
@@ -1797,7 +1807,7 @@ public class ComponentDaoTest {
     assertThat(privateFlagOfUuid(uuids[3])).isFalse();
     assertThat(privateFlagOfUuid(uuids[4])).isFalse();
 
-    underTest.setPrivateForRootComponentUuid(db.getSession(), uuid2, true);
+    underTest.setPrivateForRootComponentUuid(db.getSession(), uuid2, true, null);
 
     assertThat(privateFlagOfUuid(uuids[0])).isFalse();
     assertThat(privateFlagOfUuid(uuids[1])).isFalse();
@@ -1883,6 +1893,43 @@ public class ComponentDaoTest {
     assertThat(result).isEmpty();
   }
 
+  @Test
+  public void delete_auditPersisterIsCalled() {
+    underTestWithAuditPersister.delete(dbSession, "anyUuid", APP);
+
+    verify(auditPersister, Mockito.times(1))
+      .deleteComponent(any(DbSession.class), any(ComponentNewValue.class), anyString());
+  }
+
+  @Test
+  public void setPrivateForRootComponentUuid_auditPersisterIsCalled() {
+    underTestWithAuditPersister.setPrivateForRootComponentUuid(dbSession, "anyUuid", false, APP);
+
+    verify(auditPersister, Mockito.times(1))
+      .setPrivateForComponentUuid(any(DbSession.class), any(ComponentNewValue.class), anyString());
+  }
+
+  @Test
+  public void update_auditPersisterIsCalled() {
+    ComponentUpdateDto app = new ComponentUpdateDto();
+    app.setBQualifier(APP);
+
+    underTestWithAuditPersister.update(dbSession, app, APP);
+
+    verify(auditPersister, Mockito.times(1))
+      .updateComponent(any(DbSession.class), any(ComponentNewValue.class), anyString());
+  }
+
+  @Test
+  public void insert_auditPersisterIsCalled() {
+    ComponentDto app = ComponentTesting.newApplication();
+
+    underTestWithAuditPersister.insert(dbSession, app);
+
+    verify(auditPersister, Mockito.times(1))
+      .addComponent(any(DbSession.class), any(ComponentNewValue.class), anyString());
+  }
+
   private boolean privateFlagOfUuid(String uuid) {
     return underTest.selectByUuid(db.getSession(), uuid).get().isPrivate();
   }
index cbc62eff9b0124983abaf69c29a4db7f4feb6a62..eae4e6960f542416594e99827566628eac64fe44 100644 (file)
@@ -33,11 +33,18 @@ import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
+import org.sonar.db.audit.AuditPersister;
+import org.sonar.db.audit.model.ComponentKeyNewValue;
 import org.sonar.db.component.ComponentKeyUpdaterDao.RekeyedResource;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.entry;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.sonar.db.component.BranchType.PULL_REQUEST;
 import static org.sonar.db.component.ComponentDto.BRANCH_KEY_SEPARATOR;
 import static org.sonar.db.component.ComponentDto.generateBranchKey;
@@ -54,9 +61,11 @@ public class ComponentKeyUpdaterDaoTest {
 
   @Rule
   public DbTester db = DbTester.create(System2.INSTANCE);
+  private AuditPersister auditPersister = mock(AuditPersister.class);
   private DbClient dbClient = db.getDbClient();
   private DbSession dbSession = db.getSession();
   private ComponentKeyUpdaterDao underTest = db.getDbClient().componentKeyUpdaterDao();
+  private ComponentKeyUpdaterDao underTestWithAuditPersister = new ComponentKeyUpdaterDao(auditPersister);
 
   @Test
   public void updateKey_changes_the_key_of_tree_of_components() {
@@ -142,6 +151,18 @@ public class ComponentKeyUpdaterDaoTest {
     underTest.updateApplicationBranchKey(dbSession, appBranch.uuid(), app.getDbKey(), "newName");
   }
 
+  @Test
+  public void updateApplicationBranchKey_callsAuditPersister() {
+    ComponentDto app = db.components().insertPublicProject();
+    ComponentDto appBranch = db.components().insertProjectBranch(app);
+    db.components().insertProjectBranch(app, b -> b.setKey("newName"));
+
+    underTestWithAuditPersister.updateApplicationBranchKey(dbSession, appBranch.uuid(), app.getDbKey(), "newName2");
+
+    verify(auditPersister, times(1))
+      .componentKeyBranchUpdate(any(DbSession.class), any(ComponentKeyNewValue.class), anyString());
+  }
+
   @Test
   public void updateKey_updates_branches_too() {
     ComponentDto project = db.components().insertPublicProject();
@@ -304,7 +325,7 @@ public class ComponentKeyUpdaterDaoTest {
     db.components().insertComponent(newModuleDto(project).setDbKey("my_project:module"));
     db.components().insertComponent(newModuleDto(project).setDbKey("my_project:inactive_module").setEnabled(false));
 
-    Set<RekeyedResource> rekeyedResources = underTest.bulkUpdateKey(dbSession, "A", "my_", "your_", doNotReturnAnyRekeyedResource());
+    Set<RekeyedResource> rekeyedResources = underTestWithAuditPersister.bulkUpdateKey(dbSession, "A", "my_", "your_", doNotReturnAnyRekeyedResource());
 
     List<ComponentDto> result = dbClient.componentDao().selectAllComponentsFromProjectKey(dbSession, "your_project");
     assertThat(result)
@@ -478,6 +499,30 @@ public class ComponentKeyUpdaterDaoTest {
     assertThat(computeNewKey("my_project", "my_", "$()_")).isEqualTo("$()_project");
   }
 
+  @Test
+  public void updateKey_callsAuditPersister() {
+    db.components().insertComponent(newPrivateProjectDto("A").setDbKey("my_project"));
+
+    underTestWithAuditPersister.updateKey(dbSession, "A", "your_project");
+
+    verify(auditPersister, times(1))
+      .componentKeyUpdate(any(DbSession.class), any(ComponentKeyNewValue.class), anyString());
+  }
+
+  @Test
+  public void bulkUpdate_callsAuditPersister() {
+    ComponentDto project = db.components().insertComponent(newPrivateProjectDto("A").setDbKey("project"));
+    db.components().insertComponent(newModuleDto(project).setDbKey("project:enabled-module"));
+    db.components().insertComponent(newModuleDto(project).setDbKey("project:disabled-module").setEnabled(false));
+
+    thrown.expect(IllegalArgumentException.class);
+
+    underTest.simulateBulkUpdateKey(dbSession, "A", "project", "project?");
+
+    verify(auditPersister, times(1))
+      .componentKeyUpdate(any(DbSession.class), any(ComponentKeyNewValue.class), anyString());
+  }
+
   private Predicate<RekeyedResource> doNotReturnAnyRekeyedResource() {
     return a -> false;
   }
index 73e21debb125ae6a67e82aeb2f33637c655b57f0..1714a26161327be57f0628dce8c7425d904721b6 100644 (file)
@@ -378,7 +378,7 @@ public class IssueDaoTest {
         }
 
         // disable component and test again => not returned anymore
-        db.getDbClient().componentDao().update(db.getSession(), ComponentUpdateDto.copyFrom(component).setBEnabled(false).setBChanged(true));
+        db.getDbClient().componentDao().update(db.getSession(), ComponentUpdateDto.copyFrom(component).setBEnabled(false).setBChanged(true), component.qualifier());
         db.getDbClient().componentDao().applyBChangesForRootComponentUuid(db.getSession(), projectUuid);
         db.commit();
         assertThat(db.getDbClient().componentDao().selectByUuid(db.getSession(), component.uuid()).get().isEnabled())
index e89b99f3571c6024bee9b3916f0a15da90fc4caa..9ebae98075c34d6114963048fe31eda7d417cc65 100644 (file)
@@ -25,15 +25,22 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 import javax.annotation.Nullable;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
+import org.sonar.db.audit.AuditPersister;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.tuple;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
 
 public class ProjectDaoTest {
 
@@ -42,7 +49,10 @@ public class ProjectDaoTest {
   @Rule
   public DbTester db = DbTester.create(system2);
 
+  private final AuditPersister auditPersister = mock(AuditPersister.class);
+
   private final ProjectDao projectDao = new ProjectDao(system2);
+  private final ProjectDao projectDaoWithAuditPersister = new ProjectDao(system2, auditPersister);
 
   @Test
   public void should_insert_and_select_by_uuid() {
@@ -138,8 +148,8 @@ public class ProjectDaoTest {
     assertProject(projectsByUuids.get(0), "projectName_p1", "projectKee_o1_p1",  "uuid_o1_p1", "desc_p1", "tag1,tag2", true);
     assertProject(projectsByUuids.get(1), "projectName_p2", "projectKee_o1_p2",  "uuid_o1_p2", "desc_p2", "tag1,tag2", false);
 
-    projectDao.updateVisibility(db.getSession(), dto1.getUuid(), false);
-    projectDao.updateVisibility(db.getSession(), dto2.getUuid(), true);
+    projectDao.updateVisibility(db.getSession(), dto1.getUuid(), false, Qualifiers.PROJECT);
+    projectDao.updateVisibility(db.getSession(), dto2.getUuid(), true, Qualifiers.PROJECT);
 
     projectsByUuids = projectDao.selectByUuids(db.getSession(), new HashSet<>(Arrays.asList("uuid_o1_p1", "uuid_o1_p2")));
     assertThat(projectsByUuids).hasSize(2);
@@ -177,6 +187,42 @@ public class ProjectDaoTest {
     assertThat(projectsByUuids).isEmpty();
   }
 
+  @Test
+  public void insert_withoutTrack_shouldNotCallAuditPersister() {
+    ProjectDto dto1 = createProject("o1", "p1");
+
+    projectDaoWithAuditPersister.insert(db.getSession(), dto1, false);
+
+    verifyNoInteractions(auditPersister);
+  }
+
+  @Test
+  public void insert_withTrack_shouldCallAuditPersister() {
+    ProjectDto dto1 = createProject("o1", "p1");
+
+    projectDaoWithAuditPersister.insert(db.getSession(), dto1, true);
+
+    verify(auditPersister, times(1)).addComponent(any(), any(), any());
+  }
+
+  @Test
+  public void updateVisibility_shouldCallAuditPersister() {
+    ProjectDto dto1 = createProject("o1", "p1");
+
+    projectDaoWithAuditPersister.updateVisibility(db.getSession(), dto1.getUuid(), false, Qualifiers.PROJECT);
+
+    verify(auditPersister, times(1)).updateComponentVisibility(any(), any(), any());
+  }
+
+  @Test
+  public void update_shouldCallAuditPersister() {
+    ProjectDto dto1 = createProject("o1", "p1");
+
+    projectDaoWithAuditPersister.update(db.getSession(), dto1);
+
+    verify(auditPersister, times(1)).updateComponent(any(), any(), any());
+  }
+
   private void assertProject(ProjectDto dto, String name, String kee, String uuid, String desc, @Nullable String tags, boolean isPrivate) {
     assertThat(dto).extracting("name", "kee", "key","uuid", "description", "tagsString", "private")
       .containsExactly(name, kee, kee, uuid, desc, tags, isPrivate);
index 89ae1e1c96dc98ebb9d2854bd165225109d6a141..375d425eecf1120e0e4a1b8598e4f90df2942a53 100644 (file)
@@ -48,6 +48,8 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.alm.setting.AlmSettingDto;
+import org.sonar.db.audit.AuditPersister;
+import org.sonar.db.audit.model.ComponentNewValue;
 import org.sonar.db.ce.CeActivityDto;
 import org.sonar.db.ce.CeQueueDto;
 import org.sonar.db.ce.CeQueueDto.Status;
@@ -88,6 +90,8 @@ import static java.util.Collections.emptySet;
 import static java.util.Collections.singletonList;
 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
@@ -119,7 +123,9 @@ public class PurgeDaoTest {
 
   private final DbClient dbClient = db.getDbClient();
   private final DbSession dbSession = db.getSession();
+  private final AuditPersister auditPersister = mock(AuditPersister.class);
   private final PurgeDao underTest = db.getDbClient().purgeDao();
+  private final PurgeDao underTestWithPersister = new PurgeDao(system2, auditPersister);
 
   @Test
   public void purge_failed_ce_tasks() {
@@ -531,7 +537,7 @@ public class PurgeDaoTest {
     IssueDto otherIssue2 = db.issues().insert(rule, otherProject, otherFile);
     FileSourceDto otherFileSource = db.fileSources().insertFileSource(otherFile);
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("components")).containsOnly(otherProject.uuid(), otherModule.uuid(), otherDirectory.uuid(), otherFile.uuid());
@@ -542,6 +548,15 @@ public class PurgeDaoTest {
     assertThat(uuidsIn("file_sources", "file_uuid")).containsOnly(otherFileSource.getFileUuid());
   }
 
+  @Test
+  public void delete_project_and_persist() {
+    ComponentDto project = db.components().insertPrivateProject();
+
+    underTestWithPersister.deleteProject(dbSession, project.uuid(), project.qualifier());
+
+    verify(auditPersister).deleteComponent(any(DbSession.class), any(ComponentNewValue.class), anyString());
+  }
+
   @Test
   public void delete_application() {
     MetricDto metric = db.measures().insertMetric();
@@ -569,7 +584,7 @@ public class PurgeDaoTest {
     db.components().addProjectBranchToApplicationBranch(dbClient.branchDao().selectByUuid(dbSession, appBranch.uuid()).get(), projectBranch);
     db.components().addProjectBranchToApplicationBranch(dbClient.branchDao().selectByUuid(dbSession, otherAppBranch.uuid()).get(), projectBranch);
 
-    underTest.deleteProject(dbSession, app.uuid());
+    underTest.deleteProject(dbSession, app.uuid(), app.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("components")).containsOnly(project.uuid(), otherApp.uuid(), otherAppBranch.uuid());
@@ -629,7 +644,7 @@ public class PurgeDaoTest {
     WebhookDto webhookNotDeleted = db.webhooks().insertWebhook(projectNotToBeDeleted);
     WebhookDeliveryLiteDto webhookDeliveryNotDeleted = db.webhookDelivery().insert(webhookNotDeleted);
 
-    underTest.deleteProject(dbSession, project1.getUuid());
+    underTest.deleteProject(dbSession, project1.getUuid(), project1.getQualifier());
 
     assertThat(uuidsIn("webhooks")).containsOnly(webhookNotDeleted.getUuid());
     assertThat(uuidsIn("webhook_deliveries")).containsOnly(webhookDeliveryNotDeleted.getUuid());
@@ -652,7 +667,7 @@ public class PurgeDaoTest {
     CeActivityDto notDeletedActivity = insertCeActivity(anotherLivingProject);
     dbSession.commit();
 
-    underTest.deleteProject(dbSession, projectToBeDeleted.uuid());
+    underTest.deleteProject(dbSession, projectToBeDeleted.uuid(), projectToBeDeleted.qualifier());
     dbSession.commit();
 
     assertThat(uuidsOfTable("ce_activity"))
@@ -679,13 +694,13 @@ public class PurgeDaoTest {
     insertCeTaskInput("non existing task");
     dbSession.commit();
 
-    underTest.deleteProject(dbSession, branch.uuid());
+    underTest.deleteProject(dbSession, branch.uuid(), branch.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_activity")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
     assertThat(taskUuidsIn("ce_task_input")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_activity")).containsOnly(anotherProjectTask.getUuid());
@@ -711,13 +726,13 @@ public class PurgeDaoTest {
     insertCeScannerContext("non existing task");
     dbSession.commit();
 
-    underTest.deleteProject(dbSession, branch.uuid());
+    underTest.deleteProject(dbSession, branch.uuid(), branch.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_activity")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
     assertThat(taskUuidsIn("ce_scanner_context")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_activity")).containsOnly(anotherProjectTask.getUuid());
@@ -743,13 +758,13 @@ public class PurgeDaoTest {
     insertCeTaskCharacteristics("non existing task", 5);
     dbSession.commit();
 
-    underTest.deleteProject(dbSession, branch.uuid());
+    underTest.deleteProject(dbSession, branch.uuid(), branch.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_activity")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
     assertThat(taskUuidsIn("ce_task_characteristics")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_activity")).containsOnly(anotherProjectTask.getUuid());
@@ -775,13 +790,13 @@ public class PurgeDaoTest {
     insertCeTaskMessages("non existing task", 5);
     dbSession.commit();
 
-    underTest.deleteProject(dbSession, branch.uuid());
+    underTest.deleteProject(dbSession, branch.uuid(), branch.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_activity")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
     assertThat(taskUuidsIn("ce_task_message")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_activity")).containsOnly(anotherProjectTask.getUuid());
@@ -801,7 +816,7 @@ public class PurgeDaoTest {
 
     assertThat(uuidsIn("user_dismissed_messages")).containsOnly(msg1.getUuid(), msg2.getUuid(), msg3.getUuid());
 
-    underTest.deleteProject(dbSession, project.getUuid());
+    underTest.deleteProject(dbSession, project.getUuid(), project.getQualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("user_dismissed_messages")).containsOnly(msg3.getUuid());
@@ -819,7 +834,7 @@ public class PurgeDaoTest {
     dbClient.ceQueueDao().insert(dbSession, createCeQueue(anotherLivingProject, Status.PENDING));
     dbSession.commit();
 
-    underTest.deleteProject(dbSession, projectToBeDeleted.uuid());
+    underTest.deleteProject(dbSession, projectToBeDeleted.uuid(), projectToBeDeleted.qualifier());
     dbSession.commit();
 
     assertThat(db.countRowsOfTable("ce_queue")).isEqualTo(1);
@@ -845,13 +860,13 @@ public class PurgeDaoTest {
     insertCeTaskInput("non existing task");
     dbSession.commit();
 
-    underTest.deleteProject(dbSession, branch.uuid());
+    underTest.deleteProject(dbSession, branch.uuid(), branch.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_queue")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
     assertThat(taskUuidsIn("ce_task_input")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_queue")).containsOnly(anotherProjectTask.getUuid());
@@ -877,14 +892,14 @@ public class PurgeDaoTest {
     insertCeScannerContext("non existing task");
     dbSession.commit();
 
-    underTest.deleteProject(dbSession, branch.uuid());
+    underTest.deleteProject(dbSession, branch.uuid(), branch.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_queue")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
     assertThat(taskUuidsIn("ce_scanner_context"))
       .containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_queue")).containsOnly(anotherProjectTask.getUuid());
@@ -910,14 +925,14 @@ public class PurgeDaoTest {
     insertCeTaskCharacteristics("non existing task", 5);
     dbSession.commit();
 
-    underTest.deleteProject(dbSession, branch.uuid());
+    underTest.deleteProject(dbSession, branch.uuid(), branch.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_queue")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
     assertThat(taskUuidsIn("ce_task_characteristics"))
       .containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_queue")).containsOnly(anotherProjectTask.getUuid());
@@ -943,14 +958,14 @@ public class PurgeDaoTest {
     insertCeTaskMessages("non existing task", 5);
     dbSession.commit();
 
-    underTest.deleteProject(dbSession, branch.uuid());
+    underTest.deleteProject(dbSession, branch.uuid(), branch.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_queue")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
     assertThat(taskUuidsIn("ce_task_message"))
       .containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("ce_queue")).containsOnly(anotherProjectTask.getUuid());
@@ -991,14 +1006,14 @@ public class PurgeDaoTest {
     db.events().insertEventComponentChanges(anotherProjectEvent, anotherProjectAnalysis, randomChangeCategory(), referencedProjectB, null);
 
     // deleting referenced project does not delete any data
-    underTest.deleteProject(dbSession, referencedProjectA.uuid());
+    underTest.deleteProject(dbSession, referencedProjectA.uuid(), referencedProjectA.qualifier());
 
     assertThat(db.countRowsOfTable("event_component_changes"))
       .isEqualTo(7);
     assertThat(db.countRowsOfTable("events"))
       .isEqualTo(7);
 
-    underTest.deleteProject(dbSession, branch.uuid());
+    underTest.deleteProject(dbSession, branch.uuid(), branch.qualifier());
     assertThat(uuidsIn("event_component_changes", "event_component_uuid"))
       .containsOnly(project.uuid(), anotherBranch.uuid(), anotherProject.uuid());
     assertThat(db.countRowsOfTable("event_component_changes"))
@@ -1006,7 +1021,7 @@ public class PurgeDaoTest {
     assertThat(uuidsIn("events"))
       .containsOnly(projectEvent1.getUuid(), projectEvent2.getUuid(), projectEvent3.getUuid(), anotherBranchEvent.getUuid(), anotherProjectEvent.getUuid());
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
     assertThat(uuidsIn("event_component_changes", "event_component_uuid"))
       .containsOnly(anotherBranch.uuid(), anotherProject.uuid());
     assertThat(db.countRowsOfTable("event_component_changes"))
@@ -1044,7 +1059,7 @@ public class PurgeDaoTest {
     assertThat(db.countRowsOfTable("issues")).isGreaterThan(issueCount);
     assertThat(db.countRowsOfTable("project_branches")).isGreaterThan(branchCount);
 
-    underTest.deleteProject(dbSession, projectToDelete.uuid());
+    underTest.deleteProject(dbSession, projectToDelete.uuid(), projectToDelete.qualifier());
     dbSession.commit();
 
     assertThat(db.countRowsOfTable("components")).isEqualTo(projectEntryCount);
@@ -1062,7 +1077,7 @@ public class PurgeDaoTest {
     ComponentDto otherSubView = db.components().insertComponent(newSubView(otherView));
     ComponentDto otherProjectCopy = db.components().insertComponent(newProjectCopy(project, otherSubView));
 
-    underTest.deleteProject(dbSession, view.uuid());
+    underTest.deleteProject(dbSession, view.uuid(), view.qualifier());
     dbSession.commit();
 
     assertThat(uuidsIn("components"))
@@ -1314,7 +1329,7 @@ public class PurgeDaoTest {
     dbClient.webhookDeliveryDao().insert(dbSession, newDto().setComponentUuid(project.uuid()).setUuid("D1").setDurationMs(1000).setWebhookUuid("webhook-uuid"));
     dbClient.webhookDeliveryDao().insert(dbSession, newDto().setComponentUuid("P2").setUuid("D2").setDurationMs(1000).setWebhookUuid("webhook-uuid"));
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
 
     assertThat(selectAllDeliveryUuids(db, dbSession)).containsOnly("D2");
   }
@@ -1325,7 +1340,7 @@ public class PurgeDaoTest {
     dbClient.projectMappingsDao().put(dbSession, "a.key.type", "a.key", project.uuid());
     dbClient.projectMappingsDao().put(dbSession, "a.key.type", "another.key", "D2");
 
-    underTest.deleteProject(dbSession, project.uuid());
+    underTest.deleteProject(dbSession, project.uuid(), project.qualifier());
 
     assertThat(dbClient.projectMappingsDao().get(dbSession, "a.key.type", "a.key")).isEmpty();
     assertThat(dbClient.projectMappingsDao().get(dbSession, "a.key.type", "another.key")).isNotEmpty();
@@ -1339,7 +1354,7 @@ public class PurgeDaoTest {
     db.almSettings().insertGitlabProjectAlmSetting(almSettingDto, project);
     db.almSettings().insertGitlabProjectAlmSetting(almSettingDto, otherProject);
 
-    underTest.deleteProject(dbSession, project.getUuid());
+    underTest.deleteProject(dbSession, project.getUuid(), project.getQualifier());
 
     assertThat(dbClient.projectAlmSettingDao().selectByProject(dbSession, project)).isEmpty();
     assertThat(dbClient.projectAlmSettingDao().selectByProject(dbSession, otherProject)).isNotEmpty();
@@ -1378,7 +1393,7 @@ public class PurgeDaoTest {
     db.measures().insertLiveMeasure(project2, metric);
     db.measures().insertLiveMeasure(module2, metric);
 
-    underTest.deleteProject(dbSession, project1.uuid());
+    underTest.deleteProject(dbSession, project1.uuid(), project1.qualifier());
 
     assertThat(dbClient.liveMeasureDao().selectByComponentUuidsAndMetricUuids(dbSession, asList(project1.uuid(), module1.uuid()), asList(metric.getUuid()))).isEmpty();
     assertThat(dbClient.liveMeasureDao().selectByComponentUuidsAndMetricUuids(dbSession, asList(project2.uuid(), module2.uuid()), asList(metric.getUuid()))).hasSize(2);
index 93345f875d9c79872b934cb4308a107302c652cb..c4bd1e54ab9778bab94474f35cc634eecc78ffdc 100644 (file)
  */
 package org.sonar.server.component.index;
 
-import java.util.Arrays;
-import java.util.Collection;
 import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.builder.SearchSourceBuilder;
 import org.junit.Rule;
 import org.junit.Test;
+import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
@@ -46,6 +45,8 @@ import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_COM
 import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_CREATION;
 import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_DELETION;
 import static org.sonar.server.es.newindex.DefaultIndexSettingsElement.SORTABLE_ANALYZER;
+import java.util.Arrays;
+import java.util.Collection;
 
 public class ComponentIndexerTest {
 
@@ -206,7 +207,7 @@ public class ComponentIndexerTest {
     indexProject(project, PROJECT_CREATION);
     assertThatIndexHasSize(1);
 
-    db.getDbClient().componentDao().delete(db.getSession(), project.uuid());
+    db.getDbClient().componentDao().delete(db.getSession(), project.uuid(), Qualifiers.PROJECT);
     indexProject(project, PROJECT_DELETION);
 
     assertThatIndexHasSize(0);
@@ -245,7 +246,7 @@ public class ComponentIndexerTest {
   private void updateDb(ComponentDto component) {
     ComponentUpdateDto updateComponent = ComponentUpdateDto.copyFrom(component);
     updateComponent.setBChanged(true);
-    dbClient.componentDao().update(dbSession, updateComponent);
+    dbClient.componentDao().update(dbSession, updateComponent, component.qualifier());
     dbClient.componentDao().applyBChangesForRootComponentUuid(dbSession, component.getRootUuid());
     dbSession.commit();
   }
index 0fd7899f31653921f50eaf2c772a11dd906fe037..ad817103a7078ec54483ce903dfa62094d8f1061 100644 (file)
@@ -235,7 +235,7 @@ public class ProjectMeasuresIndexerTest {
     indexProject(project, PROJECT_CREATION);
     assertThatIndexContainsOnly(project);
 
-    db.getDbClient().purgeDao().deleteProject(db.getSession(), project.uuid());
+    db.getDbClient().purgeDao().deleteProject(db.getSession(), project.uuid(), Qualifiers.PROJECT);
     IndexingResult result = indexProject(project, PROJECT_DELETION);
 
     assertThat(es.countDocuments(TYPE_PROJECT_MEASURES)).isZero();
index 76028e096d916031158769e8861fe3c92c0bd15b..77de29c71fd67ff3423f014d88895f8613cc913e 100644 (file)
  */
 package org.sonar.server.permission.index;
 
-import java.util.Collection;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
@@ -44,6 +44,7 @@ import static org.sonar.api.web.UserRole.ADMIN;
 import static org.sonar.api.web.UserRole.USER;
 import static org.sonar.server.es.ProjectIndexer.Cause.PERMISSION_CHANGE;
 import static org.sonar.server.permission.index.IndexAuthorizationConstants.TYPE_AUTHORIZATION;
+import java.util.Collection;
 
 public class PermissionIndexerTest {
 
@@ -97,7 +98,7 @@ public class PermissionIndexerTest {
     assertThat(es.countDocuments(INDEX_TYPE_FOO_AUTH)).isEqualTo(2);
 
     // Simulate a indexation issue
-    db.getDbClient().componentDao().delete(db.getSession(), project1.uuid());
+    db.getDbClient().componentDao().delete(db.getSession(), project1.uuid(), Qualifiers.PROJECT);
     underTest.prepareForRecovery(db.getSession(), asList(project1.uuid()), ProjectIndexer.Cause.PROJECT_DELETION);
     assertThat(db.countRowsOfTable(db.getSession(), "es_queue")).isEqualTo(1);
     Collection<EsQueueDto> esQueueDtos = db.getDbClient().esQueueDao().selectForRecovery(db.getSession(), Long.MAX_VALUE, 2);
@@ -313,7 +314,7 @@ public class PermissionIndexerTest {
     indexPermissions(project, ProjectIndexer.Cause.PROJECT_CREATION);
     verifyAuthorized(project, user);
 
-    db.getDbClient().componentDao().delete(db.getSession(), project.uuid());
+    db.getDbClient().componentDao().delete(db.getSession(), project.uuid(), Qualifiers.PROJECT);
     indexPermissions(project, ProjectIndexer.Cause.PROJECT_DELETION);
 
     verifyNotAuthorized(project, user);
index 3608e3685b25cdbb5f2325d851c759bc00e915d9..669e360f4d116c5ff72526567b65db68d020eb6b 100644 (file)
@@ -66,20 +66,20 @@ public class ComponentCleanerService {
   }
 
   public void delete(DbSession dbSession, ProjectDto project) {
-    dbClient.purgeDao().deleteProject(dbSession, project.getUuid());
+    dbClient.purgeDao().deleteProject(dbSession, project.getUuid(), project.getQualifier());
     dbClient.userDao().cleanHomepage(dbSession, project);
     projectIndexers.commitAndIndexProjects(dbSession, singletonList(project), PROJECT_DELETION);
   }
 
   public void deleteApplication(DbSession dbSession, ProjectDto application) {
-    dbClient.purgeDao().deleteProject(dbSession, application.getUuid());
+    dbClient.purgeDao().deleteProject(dbSession, application.getUuid(), application.getQualifier());
     dbClient.userDao().cleanHomepage(dbSession, application);
     projectIndexers.commitAndIndexProjects(dbSession, singletonList(application), PROJECT_DELETION);
   }
 
   public void delete(DbSession dbSession, ComponentDto project) {
     checkArgument(!hasNotProjectScope(project) && !isNotDeletable(project) && project.getMainBranchProjectUuid() == null, "Only projects can be deleted");
-    dbClient.purgeDao().deleteProject(dbSession, project.uuid());
+    dbClient.purgeDao().deleteProject(dbSession, project.uuid(), project.qualifier());
     dbClient.userDao().cleanHomepage(dbSession, project);
     projectIndexers.commitAndIndexComponents(dbSession, singletonList(project), PROJECT_DELETION);
   }
index 97a1335980e8c5cd69aa3776b0f3cb777987b73a..72634b9b37726093acf9ac54ea886bb54efb88d8 100644 (file)
@@ -130,10 +130,10 @@ public class UpdateVisibilityAction implements ProjectsWsAction {
 
   private void setPrivateForRootComponentUuid(DbSession dbSession, ComponentDto component, boolean isPrivate) {
     String uuid = component.uuid();
-    dbClient.componentDao().setPrivateForRootComponentUuid(dbSession, uuid, isPrivate);
+    dbClient.componentDao().setPrivateForRootComponentUuid(dbSession, uuid, isPrivate, component.qualifier());
 
     if (component.qualifier().equals(Qualifiers.PROJECT) || component.qualifier().equals(Qualifiers.APP)) {
-      dbClient.projectDao().updateVisibility(dbSession, uuid, isPrivate);
+      dbClient.projectDao().updateVisibility(dbSession, uuid, isPrivate, component.qualifier());
     }
 
     ComponentMapper mapper = dbSession.getMapper(ComponentMapper.class);
index da71abf575a5beffb05d28cb4a1ac2f225bc112e..3531eeed00a4128f5cf415ae2d8f7cf2b2819ed3 100644 (file)
  */
 package org.sonar.server.component.ws;
 
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import javax.annotation.Nullable;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -76,6 +72,10 @@ import static org.sonar.server.component.ws.SuggestionsAction.PARAM_QUERY;
 import static org.sonar.server.component.ws.SuggestionsAction.PARAM_RECENTLY_BROWSED;
 import static org.sonar.server.component.ws.SuggestionsAction.SHORT_INPUT_WARNING;
 import static org.sonar.test.JsonAssert.assertJson;
+import javax.annotation.Nullable;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 public class SuggestionsActionTest {
   private static final String[] SUGGESTION_QUALIFIERS = Stream.of(SuggestionCategory.values())
@@ -394,7 +394,7 @@ public class SuggestionsActionTest {
     componentIndexer.indexAll();
     authorizationIndexerTester.allowOnlyAnyone(project);
 
-    db.getDbClient().componentDao().delete(db.getSession(), project.uuid());
+    db.getDbClient().componentDao().delete(db.getSession(), project.uuid(), PROJECT);
     db.commit();
 
     SuggestionsWsResponse response = ws.newRequest()