]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7299 Move code related to project creation to ComponentUpdater
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 23 Jan 2017 13:54:39 +0000 (14:54 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 24 Jan 2017 17:36:49 +0000 (18:36 +0100)
14 files changed:
server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java
server/sonar-server/src/main/java/org/sonar/server/component/ComponentUpdater.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java
server/sonar-server/src/main/java/org/sonar/server/component/NewComponent.java
server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
server/sonar-server/src/main/java/org/sonar/server/project/ws/CreateAction.java
server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceTest.java
server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceUpdateKeyTest.java
server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java
server/sonar-server/src/test/java/org/sonar/server/component/ws/BulkUpdateKeyActionTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java
server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java

index f525fb70326e6016fa4099e553f8a679c2212772..6a01a84147329996cffccde148852ba66941f664 100644 (file)
@@ -23,24 +23,16 @@ import com.google.common.base.Joiner;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Sets;
 import java.util.Collection;
-import java.util.Date;
 import java.util.List;
-import java.util.Locale;
 import java.util.Set;
 import javax.annotation.Nullable;
 import org.sonar.api.ce.ComputeEngineSide;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.resources.Scopes;
 import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.System2;
 import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentKeys;
-import org.sonar.core.util.Uuids;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.server.component.index.ComponentIndexer;
-import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.measure.index.ProjectMeasuresIndexer;
 import org.sonar.server.user.UserSession;
@@ -55,22 +47,19 @@ import static org.sonar.server.ws.WsUtils.checkRequest;
 @ComputeEngineSide
 public class ComponentService {
   private final DbClient dbClient;
-  private final I18n i18n;
   private final UserSession userSession;
-  private final System2 system2;
   private final ProjectMeasuresIndexer projectMeasuresIndexer;
   private final ComponentIndexer componentIndexer;
 
-  public ComponentService(DbClient dbClient, I18n i18n, UserSession userSession, System2 system2, ProjectMeasuresIndexer projectMeasuresIndexer,
+  public ComponentService(DbClient dbClient, UserSession userSession, ProjectMeasuresIndexer projectMeasuresIndexer,
     ComponentIndexer componentIndexer) {
     this.dbClient = dbClient;
-    this.i18n = i18n;
     this.userSession = userSession;
-    this.system2 = system2;
     this.projectMeasuresIndexer = projectMeasuresIndexer;
     this.componentIndexer = componentIndexer;
   }
 
+  // TODO should be moved to ComponentUpdater
   public void updateKey(DbSession dbSession, ComponentDto component, String newKey) {
     userSession.checkComponentUuidPermission(UserRole.ADMIN, component.projectUuid());
     checkIsProjectOrModule(component);
@@ -80,76 +69,25 @@ public class ComponentService {
     index(component.uuid());
   }
 
+  // TODO should be moved to ComponentUpdater
   public void bulkUpdateKey(DbSession dbSession, String projectUuid, String stringToReplace, String replacementString) {
     dbClient.componentKeyUpdaterDao().bulkUpdateKey(dbSession, projectUuid, stringToReplace, replacementString);
     dbSession.commit();
     index(projectUuid);
   }
 
-  // Used by SQ and Governance
-  public ComponentDto create(DbSession session, NewComponent newComponent) {
-    checkKeyFormat(newComponent.qualifier(), newComponent.key());
-    ComponentDto rootComponent = createRootComponent(session, newComponent);
-    removeDuplicatedProjects(session, rootComponent.getKey());
-    index(rootComponent.uuid());
-    return rootComponent;
-  }
-
   private void index(String projectUuid) {
     projectMeasuresIndexer.index(projectUuid);
     componentIndexer.indexByProjectUuid(projectUuid);
   }
 
-  /**
-   * No permission check must be done when inserting a new developer as it's done on Compute Engine side.
-   * No check must be done on the key
-   * No need to remove duplicated components as it's not possible to create the same developer twice in the same time.
-   */
-  public ComponentDto createDeveloper(DbSession session, NewComponent newComponent) {
-    return createRootComponent(session, newComponent);
-  }
-
-  private ComponentDto createRootComponent(DbSession session, NewComponent newComponent) {
-    checkBranchFormat(newComponent.qualifier(), newComponent.branch());
-    String keyWithBranch = ComponentKeys.createKey(newComponent.key(), newComponent.branch());
-    if (dbClient.componentDao().selectByKey(session, keyWithBranch).isPresent()) {
-      throw new BadRequestException(formatMessage("Could not create %s, key already exists: %s", newComponent.qualifier(), keyWithBranch));
-    }
-
-    String uuid = Uuids.create();
-    ComponentDto component = new ComponentDto()
-      .setOrganizationUuid(newComponent.getOrganizationUuid())
-      .setUuid(uuid)
-      .setUuidPath(ComponentDto.UUID_PATH_OF_ROOT)
-      .setRootUuid(uuid)
-      .setModuleUuid(null)
-      .setModuleUuidPath(ComponentDto.UUID_PATH_SEPARATOR + uuid + ComponentDto.UUID_PATH_SEPARATOR)
-      .setProjectUuid(uuid)
-      .setKey(keyWithBranch)
-      .setDeprecatedKey(keyWithBranch)
-      .setName(newComponent.name())
-      .setLongName(newComponent.name())
-      .setScope(Scopes.PROJECT)
-      .setQualifier(newComponent.qualifier())
-      .setCreatedAt(new Date(system2.now()));
-    dbClient.componentDao().insert(session, component);
-    dbClient.componentIndexDao().indexResource(session, component.uuid());
-    session.commit();
-    return component;
-  }
-
-  /**
-   * On MySQL, as PROJECTS.KEE is not unique, if the same project is provisioned multiple times, then it will be duplicated in the database.
-   * So, after creating a project, we commit, and we search in the db if their are some duplications and we remove them.
-   *
-   * SONAR-6332
-   */
-  private void removeDuplicatedProjects(DbSession session, String projectKey) {
-    List<ComponentDto> duplicated = dbClient.componentDao().selectComponentsHavingSameKeyOrderedById(session, projectKey);
-    for (int i = 1; i < duplicated.size(); i++) {
-      dbClient.componentDao().delete(session, duplicated.get(i).getId());
+  public Collection<String> componentUuids(@Nullable Collection<String> componentKeys) {
+    DbSession session = dbClient.openSession(false);
+    try {
+      return componentUuids(session, componentKeys, false);
+    } finally {
+      dbClient.closeSession(session);
     }
-    session.commit();
   }
 
   public Collection<String> componentUuids(DbSession session, @Nullable Collection<String> componentKeys, boolean ignoreMissingComponents) {
@@ -196,24 +134,8 @@ public class ComponentService {
     return directoryPaths;
   }
 
-  private void checkKeyFormat(String qualifier, String kee) {
-    checkRequest(isValidModuleKey(kee), formatMessage("Malformed key for %s: %s. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.",
-      qualifier, kee));
-  }
-
   private static void checkProjectOrModuleKeyFormat(String key) {
     checkRequest(isValidModuleKey(key), "Malformed key for '%s'. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.", key);
   }
 
-  private void checkBranchFormat(String qualifier, @Nullable String branch) {
-    if (branch != null && !ComponentKeys.isValidBranch(branch)) {
-      throw new BadRequestException(formatMessage("Malformed branch for %s: %s. Allowed characters are alphanumeric, '-', '_', '.' and '/', with at least one non-digit.",
-        qualifier, branch));
-    }
-  }
-
-  private String formatMessage(String message, String qualifier, String key) {
-    return String.format(message, i18n.message(Locale.getDefault(), "qualifier." + qualifier, "Project"), key);
-  }
-
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentUpdater.java
new file mode 100644 (file)
index 0000000..9c4d329
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.server.component;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import javax.annotation.Nullable;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.utils.System2;
+import org.sonar.core.component.ComponentKeys;
+import org.sonar.core.util.Uuids;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.component.index.ComponentIndexer;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.favorite.FavoriteUpdater;
+import org.sonar.server.measure.index.ProjectMeasuresIndexer;
+import org.sonar.server.permission.PermissionTemplateService;
+
+import static org.sonar.api.resources.Qualifiers.PROJECT;
+import static org.sonar.core.component.ComponentKeys.isValidModuleKey;
+import static org.sonar.server.ws.WsUtils.checkRequest;
+
+public class ComponentUpdater {
+
+  private final DbClient dbClient;
+  private final I18n i18n;
+  private final System2 system2;
+  private final PermissionTemplateService permissionTemplateService;
+  private final FavoriteUpdater favoriteUpdater;
+  private final ProjectMeasuresIndexer projectMeasuresIndexer;
+  private final ComponentIndexer componentIndexer;
+
+  public ComponentUpdater(DbClient dbClient, I18n i18n, System2 system2,
+    PermissionTemplateService permissionTemplateService, FavoriteUpdater favoriteUpdater,
+    ProjectMeasuresIndexer projectMeasuresIndexer, ComponentIndexer componentIndexer) {
+    this.dbClient = dbClient;
+    this.i18n = i18n;
+    this.system2 = system2;
+    this.projectMeasuresIndexer = projectMeasuresIndexer;
+    this.componentIndexer = componentIndexer;
+    this.permissionTemplateService = permissionTemplateService;
+    this.favoriteUpdater = favoriteUpdater;
+  }
+
+  /**
+   * - Create component
+   * - Apply default permission template
+   * - Add component to favorite if the component has the 'Project Creators' permission
+   * - Index component if es indexes
+   */
+  public ComponentDto create(DbSession dbSession, NewComponent newComponent, @Nullable Long userId) {
+    checkKeyFormat(newComponent.qualifier(), newComponent.key());
+    ComponentDto componentDto = createRootComponent(dbSession, newComponent);
+    removeDuplicatedProjects(dbSession, componentDto.getKey());
+    handlePermissionTemplate(dbSession, componentDto, newComponent.getOrganizationUuid(), userId);
+    dbSession.commit();
+    index(componentDto.uuid());
+    return componentDto;
+  }
+
+  private ComponentDto createRootComponent(DbSession session, NewComponent newComponent) {
+    checkBranchFormat(newComponent.qualifier(), newComponent.branch());
+    String keyWithBranch = ComponentKeys.createKey(newComponent.key(), newComponent.branch());
+    if (dbClient.componentDao().selectByKey(session, keyWithBranch).isPresent()) {
+      throw new BadRequestException(formatMessage("Could not create %s, key already exists: %s", newComponent.qualifier(), keyWithBranch));
+    }
+
+    String uuid = Uuids.create();
+    ComponentDto component = new ComponentDto()
+      .setOrganizationUuid(newComponent.getOrganizationUuid())
+      .setUuid(uuid)
+      .setUuidPath(ComponentDto.UUID_PATH_OF_ROOT)
+      .setRootUuid(uuid)
+      .setModuleUuid(null)
+      .setModuleUuidPath(ComponentDto.UUID_PATH_SEPARATOR + uuid + ComponentDto.UUID_PATH_SEPARATOR)
+      .setProjectUuid(uuid)
+      .setKey(keyWithBranch)
+      .setDeprecatedKey(keyWithBranch)
+      .setName(newComponent.name())
+      .setLongName(newComponent.name())
+      .setScope(Scopes.PROJECT)
+      .setQualifier(newComponent.qualifier())
+      .setCreatedAt(new Date(system2.now()));
+    dbClient.componentDao().insert(session, component);
+    dbClient.componentIndexDao().indexResource(session, component.uuid());
+    return component;
+  }
+
+  /**
+   * On MySQL, as PROJECTS.KEE is not unique, if the same project is provisioned multiple times, then it will be duplicated in the database.
+   * So, after creating a project, we commit, and we search in the db if their are some duplications and we remove them.
+   *
+   * SONAR-6332
+   */
+  private void removeDuplicatedProjects(DbSession session, String projectKey) {
+    List<ComponentDto> duplicated = dbClient.componentDao().selectComponentsHavingSameKeyOrderedById(session, projectKey);
+    for (int i = 1; i < duplicated.size(); i++) {
+      dbClient.componentDao().delete(session, duplicated.get(i).getId());
+    }
+  }
+
+  private void handlePermissionTemplate(DbSession dbSession, ComponentDto componentDto, String organizationUuid, @Nullable Long userId) {
+    permissionTemplateService.applyDefault(dbSession, organizationUuid, componentDto, userId);
+    if (componentDto.qualifier().equals(PROJECT) && permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(dbSession, organizationUuid, componentDto)) {
+      favoriteUpdater.add(dbSession, componentDto, userId);
+    }
+  }
+
+  private void checkKeyFormat(String qualifier, String kee) {
+    checkRequest(isValidModuleKey(kee), formatMessage("Malformed key for %s: %s. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.",
+      qualifier, kee));
+  }
+
+  private void checkBranchFormat(String qualifier, @Nullable String branch) {
+    if (branch != null && !ComponentKeys.isValidBranch(branch)) {
+      throw new BadRequestException(formatMessage("Malformed branch for %s: %s. Allowed characters are alphanumeric, '-', '_', '.' and '/', with at least one non-digit.",
+        qualifier, branch));
+    }
+  }
+
+  private String formatMessage(String message, String qualifier, String key) {
+    return String.format(message, i18n.message(Locale.getDefault(), "qualifier." + qualifier, "Project"), key);
+  }
+
+  private void index(String projectUuid) {
+    projectMeasuresIndexer.index(projectUuid);
+    componentIndexer.indexByProjectUuid(projectUuid);
+  }
+}
index f1cbd928f1b62c5a6dd68ecda1502793a17eb0fa..d95404ec115732fbcdbc18a8cf4ccaac51b17d3f 100644 (file)
  */
 package org.sonar.server.component;
 
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.resources.Qualifiers;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.server.favorite.FavoriteUpdater;
 import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.permission.PermissionTemplateService;
+import org.sonar.server.user.UserSession;
 
 import static org.sonar.server.component.NewComponent.newComponentBuilder;
 
@@ -36,50 +31,36 @@ import static org.sonar.server.component.NewComponent.newComponentBuilder;
  */
 public class DefaultRubyComponentService {
 
+  private final UserSession userSession;
   private final DbClient dbClient;
-  private final ComponentService componentService;
-  private final PermissionTemplateService permissionTemplateService;
-  private final FavoriteUpdater favoriteUpdater;
+  private final ComponentUpdater componentUpdater;
   private final DefaultOrganizationProvider defaultOrganizationProvider;
 
-  public DefaultRubyComponentService(DbClient dbClient, ComponentService componentService,
-    PermissionTemplateService permissionTemplateService, FavoriteUpdater favoriteUpdater,
+  public DefaultRubyComponentService(UserSession userSession, DbClient dbClient, ComponentUpdater componentUpdater,
     DefaultOrganizationProvider defaultOrganizationProvider) {
+    this.userSession = userSession;
     this.dbClient = dbClient;
-    this.componentService = componentService;
-    this.permissionTemplateService = permissionTemplateService;
-    this.favoriteUpdater = favoriteUpdater;
+    this.componentUpdater = componentUpdater;
     this.defaultOrganizationProvider = defaultOrganizationProvider;
   }
 
   // Used in GOV
-  @CheckForNull
+  /**
+   * @deprecated Use {@link ComponentUpdater#create(DbSession, NewComponent, Long)} instead
+   */
+  @Deprecated
   public Long createComponent(String key, String name, String qualifier) {
     try (DbSession dbSession = dbClient.openSession(false)) {
-      return createComponent(dbSession, key, null, name, qualifier);
+      return componentUpdater.create(
+        dbSession,
+        newComponentBuilder()
+          .setOrganizationUuid(defaultOrganizationProvider.get().getUuid())
+          .setKey(key)
+          .setName(name)
+          .setQualifier(qualifier)
+          .build(),
+        userSession.isLoggedIn() ? userSession.getUserId().longValue() : null).getId();
     }
   }
 
-  public long createComponent(DbSession dbSession, String key, @Nullable String branch, String name, @Nullable String qualifier) {
-    ComponentDto provisionedComponent = componentService.create(
-      dbSession,
-      newComponentBuilder()
-        .setOrganizationUuid(defaultOrganizationProvider.get().getUuid())
-        .setKey(key)
-        .setName(name)
-        .setQualifier(qualifier)
-        .setBranch(branch)
-        .build());
-    String organizationUuid = defaultOrganizationProvider.get().getUuid();
-    permissionTemplateService.applyDefaultPermissionTemplate(dbSession, organizationUuid, provisionedComponent.getKey());
-    if (Qualifiers.PROJECT.equals(provisionedComponent.qualifier())
-      && permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(dbSession, organizationUuid, provisionedComponent)) {
-      // TODO Set userId as null as this method will be removed in a next commit
-      favoriteUpdater.add(dbSession, provisionedComponent, null);
-      dbSession.commit();
-    }
-
-    return provisionedComponent.getId();
-  }
-
 }
index d9e514413961b8192225d9ab36983b384f47acaa..29da48b50c2d9820d611fd369975edb68dde37be 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.server.component;
 
 import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 import org.sonar.api.resources.Qualifiers;
 
@@ -90,7 +91,7 @@ public class NewComponent {
       return this;
     }
 
-    public Builder setBranch(String branch) {
+    public Builder setBranch(@Nullable String branch) {
       this.branch = branch;
       return this;
     }
index 42186f3f891d43a1bf36fe8c0d10ba1a1ecb946b..fe3170cfc73988e25ab78323217fc45e496744d0 100644 (file)
@@ -34,10 +34,9 @@ import org.sonar.db.DbSession;
 import org.sonar.db.ce.CeTaskTypes;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
-import org.sonar.server.component.ComponentService;
+import org.sonar.server.component.ComponentUpdater;
 import org.sonar.server.component.NewComponent;
 import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.favorite.FavoriteUpdater;
 import org.sonar.server.permission.PermissionTemplateService;
 import org.sonar.server.user.UserSession;
 
@@ -53,19 +52,17 @@ public class ReportSubmitter {
 
   private final CeQueue queue;
   private final UserSession userSession;
-  private final ComponentService componentService;
+  private final ComponentUpdater componentUpdater;
   private final PermissionTemplateService permissionTemplateService;
   private final DbClient dbClient;
-  private final FavoriteUpdater favoriteUpdater;
 
-  public ReportSubmitter(CeQueue queue, UserSession userSession, ComponentService componentService,
-    PermissionTemplateService permissionTemplateService, DbClient dbClient, FavoriteUpdater favoriteUpdater) {
+  public ReportSubmitter(CeQueue queue, UserSession userSession, ComponentUpdater componentUpdater,
+    PermissionTemplateService permissionTemplateService, DbClient dbClient) {
     this.queue = queue;
     this.userSession = userSession;
-    this.componentService = componentService;
+    this.componentUpdater = componentUpdater;
     this.permissionTemplateService = permissionTemplateService;
     this.dbClient = dbClient;
-    this.favoriteUpdater = favoriteUpdater;
   }
 
   /**
@@ -115,15 +112,7 @@ public class ReportSubmitter {
       .setBranch(projectBranch)
       .setQualifier(Qualifiers.PROJECT)
       .build();
-    ComponentDto project = componentService.create(dbSession, newProject);
-    if (permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(dbSession, organizationUuid, project)) {
-      favoriteUpdater.add(dbSession, project, projectCreatorUserId);
-      dbSession.commit();
-    }
-
-    permissionTemplateService.applyDefault(dbSession, organizationUuid, project, projectCreatorUserId);
-
-    return project;
+    return componentUpdater.create(dbSession, newProject, projectCreatorUserId);
   }
 
   private CeTask submitReport(DbSession dbSession, InputStream reportInput, ComponentDto project) {
index 48008257cbb6c4a837611bee48533381bd441530..a5dc9695fa1640b86dff7da0d7b5664ee66fce8a 100644 (file)
@@ -38,7 +38,7 @@ import org.sonar.server.ce.ws.CeWsModule;
 import org.sonar.server.component.ComponentCleanerService;
 import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.component.ComponentService;
-import org.sonar.server.component.DefaultRubyComponentService;
+import org.sonar.server.component.ComponentUpdater;
 import org.sonar.server.component.index.ComponentIndex;
 import org.sonar.server.component.index.ComponentIndexDefinition;
 import org.sonar.server.component.index.ComponentIndexer;
@@ -359,8 +359,8 @@ public class PlatformLevel4 extends PlatformLevel {
       ProjectsWsModule.class,
       ProjectsEsModule.class,
       ComponentsWsModule.class,
-      DefaultRubyComponentService.class,
       ComponentService.class,
+      ComponentUpdater.class,
       ComponentFinder.class,
       NewAlerts.class,
       NewAlerts.newMetadata(),
index b661f8d11f874c35972e0c82ce83af4f20508bca..b3eaa57b7f7c04ac72fbb07942ad07a602abdc6e 100644 (file)
@@ -25,10 +25,8 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
-import org.sonar.server.component.ComponentService;
-import org.sonar.server.favorite.FavoriteUpdater;
+import org.sonar.server.component.ComponentUpdater;
 import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.permission.PermissionTemplateService;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.WsProjects.CreateWsResponse;
 import org.sonarqube.ws.client.project.CreateRequest;
@@ -49,18 +47,13 @@ public class CreateAction implements ProjectsWsAction {
 
   private final DbClient dbClient;
   private final UserSession userSession;
-  private final ComponentService componentService;
+  private final ComponentUpdater componentUpdater;
   private final DefaultOrganizationProvider defaultOrganizationProvider;
-  private final PermissionTemplateService permissionTemplateService;
-  private final FavoriteUpdater favoriteUpdater;
 
-  public CreateAction(DbClient dbClient, UserSession userSession, ComponentService componentService, PermissionTemplateService permissionTemplateService,
-    FavoriteUpdater favoriteUpdater, DefaultOrganizationProvider defaultOrganizationProvider) {
+  public CreateAction(DbClient dbClient, UserSession userSession, ComponentUpdater componentUpdater, DefaultOrganizationProvider defaultOrganizationProvider) {
     this.dbClient = dbClient;
     this.userSession = userSession;
-    this.componentService = componentService;
-    this.permissionTemplateService = permissionTemplateService;
-    this.favoriteUpdater = favoriteUpdater;
+    this.componentUpdater = componentUpdater;
     this.defaultOrganizationProvider = defaultOrganizationProvider;
   }
 
@@ -99,29 +92,19 @@ public class CreateAction implements ProjectsWsAction {
   }
 
   private CreateWsResponse doHandle(CreateRequest request) {
-    String organizationUuid = defaultOrganizationProvider.get().getUuid();
     try (DbSession dbSession = dbClient.openSession(false)) {
-      ComponentDto componentDto = componentService.create(dbSession, newComponentBuilder()
-        .setOrganizationUuid(organizationUuid)
+      ComponentDto componentDto = componentUpdater.create(dbSession, newComponentBuilder()
+        .setOrganizationUuid(defaultOrganizationProvider.get().getUuid())
         .setKey(request.getKey())
         .setName(request.getName())
         .setBranch(request.getBranch())
         .setQualifier(PROJECT)
-        .build());
-      handlePermissionTemplate(dbSession, componentDto, organizationUuid);
+        .build(),
+        userSession.isLoggedIn() ? userSession.getUserId().longValue() : null);
       return toCreateResponse(componentDto);
     }
   }
 
-  private void handlePermissionTemplate(DbSession dbSession, ComponentDto componentDto, String organizationUuid) {
-    Long userId = userSession.isLoggedIn() ? userSession.getUserId().longValue() : null;
-    permissionTemplateService.applyDefault(dbSession, organizationUuid, componentDto, userId);
-    if (permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(dbSession, organizationUuid, componentDto)) {
-      favoriteUpdater.add(dbSession, componentDto, userId);
-      dbSession.commit();
-    }
-  }
-
   private static CreateRequest toCreateRequest(Request request) {
     return CreateRequest.builder()
       .setKey(request.mandatoryParam(PARAM_PROJECT))
index 6722c0350a72d48b6faae345392811a604c26555..7a587713b0daf7554902905b12f0c773f5df5806 100644 (file)
  */
 package org.sonar.server.component;
 
-import com.google.common.base.Optional;
 import java.util.Arrays;
 import org.junit.Before;
+import org.assertj.core.api.Fail;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.config.MapSettings;
-import org.sonar.api.resources.Qualifiers;
 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.component.ComponentDao;
 import org.sonar.db.component.ComponentDbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
-import org.sonar.db.component.ResourceIndexDao;
-import org.sonar.db.organization.OrganizationDto;
 import org.sonar.server.component.index.ComponentIndexDefinition;
 import org.sonar.server.component.index.ComponentIndexer;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.i18n.I18nRule;
+import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition;
 import org.sonar.server.measure.index.ProjectMeasuresIndexer;
 import org.sonar.server.tester.UserSessionRule;
 
-import static com.google.common.collect.Lists.newArrayList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.guava.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
 import static org.sonar.db.component.ComponentTesting.newFileDto;
 import static org.sonar.db.component.ComponentTesting.newModuleDto;
 import static org.sonar.db.component.ComponentTesting.newProjectDto;
-import static org.sonar.server.component.NewComponent.newComponentBuilder;
-import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES;
-import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE;
 
 public class ComponentServiceTest {
 
-  private System2 system2 = System2.INSTANCE;
-
   @Rule
   public UserSessionRule userSession = UserSessionRule.standalone();
   @Rule
@@ -80,225 +64,10 @@ public class ComponentServiceTest {
   private ComponentDbTester componentDb = new ComponentDbTester(dbTester);
   private DbClient dbClient = dbTester.getDbClient();
   private DbSession dbSession = dbTester.getSession();
-  private I18nRule i18n = new I18nRule();
-  private ProjectMeasuresIndexer projectMeasuresIndexer = new ProjectMeasuresIndexer(system2, dbClient, es.client());
+  private ProjectMeasuresIndexer projectMeasuresIndexer = new ProjectMeasuresIndexer(System2.INSTANCE, dbClient, es.client());
   private ComponentIndexer componentIndexer = new ComponentIndexer(dbClient, es.client());
-  private OrganizationDto organization;
-
-  private ComponentService underTest;
-
-  @Before
-  public void setUp() {
-    i18n.put("qualifier.TRK", "Project");
-
-    underTest = new ComponentService(dbClient, i18n, userSession, system2, projectMeasuresIndexer, componentIndexer);
-    organization = dbTester.organizations().insert();
-  }
-
-  @Test
-  public void create_project() {
-    userSession.login("john").setGlobalPermissions(PROVISIONING);
-
-    String key = underTest.create(
-      dbSession,
-      newComponentBuilder()
-        .setOrganizationUuid(organization.getUuid())
-        .setKey("struts")
-        .setName("Struts project")
-        .build())
-      .getKey();
-
-    ComponentDto project = dbTester.getDbClient().componentDao().selectOrFailByKey(dbSession, key);
-    assertThat(project.getOrganizationUuid()).isEqualTo(organization.getUuid());
-    assertThat(project.key()).isEqualTo("struts");
-    assertThat(project.deprecatedKey()).isEqualTo("struts");
-    assertThat(project.uuid()).isNotNull();
-    assertThat(project.projectUuid()).isEqualTo(project.uuid());
-    assertThat(project.moduleUuid()).isNull();
-    assertThat(project.moduleUuidPath()).isEqualTo("." + project.uuid() + ".");
-    assertThat(project.name()).isEqualTo("Struts project");
-    assertThat(project.longName()).isEqualTo("Struts project");
-    assertThat(project.scope()).isEqualTo("PRJ");
-    assertThat(project.qualifier()).isEqualTo("TRK");
-    assertThat(project.getCreatedAt()).isNotNull();
-
-    assertProjectIsInIndex(project.uuid());
-  }
-
-  @Test
-  public void create_new_project_with_branch() {
-    userSession.login("john").setGlobalPermissions(PROVISIONING);
-
-    String key = underTest.create(
-      dbSession,
-      newComponentBuilder()
-        .setOrganizationUuid(organization.getUuid())
-        .setKey("struts")
-        .setName("Struts project")
-        .setBranch("origin/branch")
-        .build())
-      .getKey();
-
-    ComponentDto project = dbTester.getDbClient().componentDao().selectOrFailByKey(dbSession, key);
-    assertThat(project.getOrganizationUuid()).isEqualTo(organization.getUuid());
-    assertThat(project.key()).isEqualTo("struts:origin/branch");
-    assertThat(project.deprecatedKey()).isEqualTo("struts:origin/branch");
-  }
-
-  @Test
-  public void create_view() {
-    userSession.login("john").setGlobalPermissions(PROVISIONING);
-
-    String key = underTest.create(
-      dbSession,
-      newComponentBuilder()
-        .setOrganizationUuid(organization.getUuid())
-        .setKey("all-project")
-        .setName("All Projects")
-        .setQualifier(Qualifiers.VIEW)
-        .build())
-      .getKey();
-
-    ComponentDto project = dbTester.getDbClient().componentDao().selectOrFailByKey(dbSession, key);
-    assertThat(project.getOrganizationUuid()).isEqualTo(organization.getUuid());
-    assertThat(project.key()).isEqualTo("all-project");
-    assertThat(project.deprecatedKey()).isEqualTo("all-project");
-    assertThat(project.uuid()).isNotNull();
-    assertThat(project.projectUuid()).isEqualTo(project.uuid());
-    assertThat(project.moduleUuid()).isNull();
-    assertThat(project.moduleUuidPath()).isEqualTo("." + project.uuid() + ".");
-    assertThat(project.name()).isEqualTo("All Projects");
-    assertThat(project.longName()).isEqualTo("All Projects");
-    assertThat(project.scope()).isEqualTo("PRJ");
-    assertThat(project.qualifier()).isEqualTo("VW");
-    assertThat(project.getCreatedAt()).isNotNull();
-
-    assertIndexIsEmpty();
-  }
-
-  @Test
-  public void create_developer() throws Exception {
-    // No permission should be required to create a developer
-    userSession.anonymous();
-
-    String key = underTest.createDeveloper(
-      dbSession,
-      newComponentBuilder()
-        .setOrganizationUuid(organization.getUuid())
-        .setKey("DEV:jon.name@mail.com")
-        .setName("John")
-        .setQualifier("DEV")
-        .build())
-      .getKey();
-    dbTester.getSession().commit();
-
-    ComponentDto dev = dbTester.getDbClient().componentDao().selectOrFailByKey(dbSession, key);
-    assertThat(dev.getOrganizationUuid()).isEqualTo(organization.getUuid());
-    assertThat(dev.key()).isEqualTo("DEV:jon.name@mail.com");
-    assertThat(dev.deprecatedKey()).isEqualTo("DEV:jon.name@mail.com");
-    assertThat(dev.uuid()).isNotNull();
-    assertThat(dev.projectUuid()).isEqualTo(dev.uuid());
-    assertThat(dev.moduleUuid()).isNull();
-    assertThat(dev.moduleUuidPath()).isEqualTo("." + dev.uuid() + ".");
-    assertThat(dev.name()).isEqualTo("John");
-    assertThat(dev.longName()).isEqualTo("John");
-    assertThat(dev.scope()).isEqualTo("PRJ");
-    assertThat(dev.qualifier()).isEqualTo("DEV");
-    assertThat(dev.getCreatedAt()).isNotNull();
-
-    assertIndexIsEmpty();
-  }
 
-  @Test
-  public void fail_to_create_new_component_on_invalid_key() {
-    userSession.login("john").setGlobalPermissions(PROVISIONING);
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("Malformed key for Project: struts?parent. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.");
-
-    underTest.create(
-      dbSession,
-      newComponentBuilder()
-        .setOrganizationUuid(organization.getUuid())
-        .setKey("struts?parent")
-        .setName("Struts project")
-        .build());
-  }
-
-  @Test
-  public void fail_to_create_new_component_on_invalid_branch() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("Malformed branch for Project: origin?branch. Allowed characters are alphanumeric, '-', '_', '.' and '/', with at least one non-digit.");
-
-    userSession.login("john").setGlobalPermissions(PROVISIONING);
-
-    underTest.create(
-      dbSession,
-      newComponentBuilder()
-        .setOrganizationUuid(organization.getUuid())
-        .setKey("struts")
-        .setName("Struts project")
-        .setBranch("origin?branch")
-        .build());
-  }
-
-  @Test
-  public void fail_to_create_new_component_if_key_already_exists() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("Could not create Project, key already exists: struts");
-
-    userSession.login("john").setGlobalPermissions(PROVISIONING);
-    ComponentDto project = ComponentTesting.newProjectDto(dbTester.organizations().insert()).setKey("struts");
-    dbClient.componentDao().insert(dbSession, project);
-    dbSession.commit();
-
-    underTest.create(
-      dbSession,
-      newComponentBuilder()
-        .setOrganizationUuid(organization.getUuid())
-        .setKey("struts")
-        .setName("Struts project")
-        .build());
-  }
-
-  @Test
-  public void remove_duplicated_components_when_creating_project() throws Exception {
-    String projectKey = "PROJECT_KEY";
-
-    userSession.login("john").setGlobalPermissions(PROVISIONING);
-
-    DbSession session = mock(DbSession.class);
-
-    ComponentDao componentDao = mock(ComponentDao.class);
-    when(componentDao.selectByKey(session, projectKey)).thenReturn(Optional.absent());
-
-    DbClient dbClient = mock(DbClient.class);
-    when(dbClient.openSession(false)).thenReturn(session);
-    when(dbClient.componentDao()).thenReturn(componentDao);
-    when(dbClient.componentIndexDao()).thenReturn(mock(ResourceIndexDao.class));
-
-    doAnswer(invocation -> {
-      ((ComponentDto) invocation.getArguments()[1]).setId(1L);
-      return null;
-    }).when(componentDao).insert(eq(session), any(ComponentDto.class));
-
-    OrganizationDto organizationDto = dbTester.organizations().insert();
-    when(componentDao.selectComponentsHavingSameKeyOrderedById(session, projectKey)).thenReturn(newArrayList(
-      ComponentTesting.newProjectDto(organizationDto).setId(1L).setKey(projectKey),
-      ComponentTesting.newProjectDto(organizationDto).setId(2L).setKey(projectKey),
-      ComponentTesting.newProjectDto(organizationDto).setId(3L).setKey(projectKey)));
-
-    underTest = new ComponentService(dbClient, i18n, userSession, System2.INSTANCE, projectMeasuresIndexer, componentIndexer);
-    underTest.create(
-      session,
-      newComponentBuilder()
-        .setOrganizationUuid(organization.getUuid())
-        .setKey(projectKey)
-        .setName(projectKey)
-        .build());
-
-    verify(componentDao).delete(session, 2L);
-    verify(componentDao).delete(session, 3L);
-  }
+  private ComponentService underTest = new ComponentService(dbClient, userSession, projectMeasuresIndexer, componentIndexer);
 
   @Test
   public void should_fail_silently_on_components_not_found_if_told_so() {
@@ -338,12 +107,4 @@ public class ComponentServiceTest {
     return componentDb.insertComponent(newProjectDto(dbTester.organizations().insert()).setKey("sample:root"));
   }
 
-  private void assertProjectIsInIndex(String uuid) {
-    assertThat(es.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).containsOnly(uuid);
-  }
-
-  private void assertIndexIsEmpty() {
-    assertThat(es.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).isEmpty();
-  }
-
 }
index d7bbb9c0b07f3fc0422d30df9f32a4cd9fc6ef61..abe3040e5b73d2a1401a4459a83f36c204ebe4a6 100644 (file)
@@ -21,7 +21,6 @@
 package org.sonar.server.component;
 
 import org.elasticsearch.action.search.SearchRequestBuilder;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -40,7 +39,6 @@ import org.sonar.server.component.index.ComponentIndexer;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.i18n.I18nRule;
 import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition;
 import org.sonar.server.measure.index.ProjectMeasuresIndexer;
 import org.sonar.server.tester.UserSessionRule;
@@ -76,16 +74,9 @@ public class ComponentServiceUpdateKeyTest {
   private DbClient dbClient = db.getDbClient();
   private DbSession dbSession = db.getSession();
 
-  private I18nRule i18n = new I18nRule();
-
   private ProjectMeasuresIndexer projectMeasuresIndexer = new ProjectMeasuresIndexer(system2, dbClient, es.client());
   private ComponentIndexer componentIndexer = new ComponentIndexer(dbClient, es.client());
-  private ComponentService underTest = new ComponentService(dbClient, i18n, userSession, system2, projectMeasuresIndexer, componentIndexer);
-
-  @Before
-  public void setUp() {
-    i18n.put("qualifier.TRK", "Project");
-  }
+  private ComponentService underTest = new ComponentService(dbClient, userSession, projectMeasuresIndexer, componentIndexer);
 
   @Test
   public void update_project_key() {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java
new file mode 100644 (file)
index 0000000..16ea360
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.server.component;
+
+import com.google.common.base.Optional;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.config.MapSettings;
+import org.sonar.api.config.Settings;
+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.component.ComponentDao;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.ResourceIndexDao;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.permission.template.PermissionTemplateDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.component.index.ComponentIndexDefinition;
+import org.sonar.server.component.index.ComponentIndexer;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.favorite.FavoriteUpdater;
+import org.sonar.server.i18n.I18nRule;
+import org.sonar.server.issue.index.IssueIndexDefinition;
+import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition;
+import org.sonar.server.measure.index.ProjectMeasuresIndexer;
+import org.sonar.server.permission.PermissionTemplateService;
+import org.sonar.server.permission.index.PermissionIndexer;
+import org.sonar.server.view.index.ViewIndexDefinition;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.resources.Qualifiers.VIEW;
+import static org.sonar.api.web.UserRole.USER;
+import static org.sonar.server.component.NewComponent.newComponentBuilder;
+import static org.sonar.server.component.index.ComponentIndexDefinition.INDEX_COMPONENTS;
+import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_COMPONENT;
+import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES;
+import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE;
+
+public class ComponentUpdaterTest {
+
+  private static final String DEFAULT_PROJECT_KEY = "project-key";
+  private static final String DEFAULT_PROJECT_NAME = "project-name";
+
+  private System2 system2 = System2.INSTANCE;
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Rule
+  public DbTester db = DbTester.create(system2);
+
+  @Rule
+  public EsTester es = new EsTester(
+    new ComponentIndexDefinition(new MapSettings()),
+    new ProjectMeasuresIndexDefinition(new MapSettings()),
+    new IssueIndexDefinition(new MapSettings()),
+    new ViewIndexDefinition(new MapSettings()));
+
+  @Rule
+  public I18nRule i18n = new I18nRule().put("qualifier.TRK", "Project");
+
+  private Settings settings = new MapSettings();
+
+  private PermissionTemplateDto permissionTemplateDto;
+
+  ComponentUpdater underTest = new ComponentUpdater(db.getDbClient(), i18n, system2,
+    new PermissionTemplateService(db.getDbClient(), settings, new PermissionIndexer(db.getDbClient(), es.client()), null),
+    new FavoriteUpdater(db.getDbClient()),
+    new ProjectMeasuresIndexer(system2, db.getDbClient(), es.client()),
+    new ComponentIndexer(db.getDbClient(), es.client()));
+
+  @Before
+  public void setUp() throws Exception {
+    permissionTemplateDto = db.permissionTemplates().insertTemplate();
+    setTemplateAsDefault(permissionTemplateDto);
+  }
+
+  @Test
+  public void create_project() throws Exception {
+    ComponentDto project = underTest.create(db.getSession(),
+      NewComponent.newComponentBuilder()
+        .setKey(DEFAULT_PROJECT_KEY)
+        .setName(DEFAULT_PROJECT_NAME)
+        .setOrganizationUuid(db.getDefaultOrganization().getUuid())
+        .build(),
+      null);
+
+    assertThat(project.getKey()).isEqualTo(DEFAULT_PROJECT_KEY);
+    assertThat(project.deprecatedKey()).isEqualTo(DEFAULT_PROJECT_KEY);
+    assertThat(project.name()).isEqualTo(DEFAULT_PROJECT_NAME);
+    assertThat(project.longName()).isEqualTo(DEFAULT_PROJECT_NAME);
+    assertThat(project.qualifier()).isEqualTo("TRK");
+    assertThat(project.scope()).isEqualTo("PRJ");
+    assertThat(project.getOrganizationUuid()).isEqualTo(db.getDefaultOrganization().getUuid());
+    assertThat(project.uuid()).isNotNull();
+    assertThat(project.projectUuid()).isEqualTo(project.uuid());
+    assertThat(project.moduleUuid()).isNull();
+    assertThat(project.moduleUuidPath()).isEqualTo("." + project.uuid() + ".");
+    assertThat(project.getCreatedAt()).isNotNull();
+    assertThat(db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY)).isNotNull();
+  }
+
+  @Test
+  public void create_project_with_branch() throws Exception {
+    ComponentDto project = underTest.create(db.getSession(),
+      NewComponent.newComponentBuilder()
+        .setKey(DEFAULT_PROJECT_KEY)
+        .setName(DEFAULT_PROJECT_NAME)
+        .setBranch("origin/master")
+        .setOrganizationUuid(db.getDefaultOrganization().getUuid())
+        .build(),
+      null);
+
+    assertThat(project.getKey()).isEqualTo("project-key:origin/master");
+  }
+
+  @Test
+  public void remove_duplicated_components_when_creating_project() throws Exception {
+    String projectKey = "PROJECT_KEY";
+
+    DbSession session = mock(DbSession.class);
+
+    ComponentDao componentDao = mock(ComponentDao.class);
+    when(componentDao.selectByKey(session, projectKey)).thenReturn(Optional.absent());
+
+    DbClient dbClient = mock(DbClient.class);
+    when(dbClient.openSession(false)).thenReturn(session);
+    when(dbClient.componentDao()).thenReturn(componentDao);
+    when(dbClient.componentIndexDao()).thenReturn(mock(ResourceIndexDao.class));
+
+    doAnswer(invocation -> {
+      ((ComponentDto) invocation.getArguments()[1]).setId(1L);
+      return null;
+    }).when(componentDao).insert(eq(session), any(ComponentDto.class));
+
+    OrganizationDto organization = db.getDefaultOrganization();
+    when(componentDao.selectComponentsHavingSameKeyOrderedById(session, projectKey)).thenReturn(newArrayList(
+      ComponentTesting.newProjectDto(organization).setId(1L).setKey(projectKey),
+      ComponentTesting.newProjectDto(organization).setId(2L).setKey(projectKey),
+      ComponentTesting.newProjectDto(organization).setId(3L).setKey(projectKey)));
+
+    underTest = new ComponentUpdater(dbClient, i18n, System2.INSTANCE, mock(PermissionTemplateService.class), null, mock(ProjectMeasuresIndexer.class),
+      mock(ComponentIndexer.class));
+    underTest.create(
+      session,
+      newComponentBuilder()
+        .setOrganizationUuid(organization.getUuid())
+        .setKey(projectKey)
+        .setName(projectKey)
+        .build(),
+      null);
+
+    verify(componentDao).delete(session, 2L);
+    verify(componentDao).delete(session, 3L);
+  }
+
+  @Test
+  public void verify_permission_template_is_applied() throws Exception {
+    UserDto userDto = db.users().insertUser();
+    db.permissionTemplates().addUserToTemplate(permissionTemplateDto.getId(), userDto.getId(), USER);
+
+    ComponentDto project = underTest.create(db.getSession(),
+      NewComponent.newComponentBuilder()
+        .setKey(DEFAULT_PROJECT_KEY)
+        .setName(DEFAULT_PROJECT_NAME)
+        .setOrganizationUuid(db.getDefaultOrganization().getUuid())
+        .build(),
+      null);
+
+    assertThat(db.users().selectProjectPermissionsOfUser(userDto, project)).containsOnly(USER);
+  }
+
+  @Test
+  public void add_project_to_favorite_when_user() throws Exception {
+    UserDto userDto = db.users().insertUser();
+    db.permissionTemplates().addProjectCreatorToTemplate(permissionTemplateDto.getId(), USER);
+
+    ComponentDto project = underTest.create(db.getSession(),
+      NewComponent.newComponentBuilder()
+        .setKey(DEFAULT_PROJECT_KEY)
+        .setName(DEFAULT_PROJECT_NAME)
+        .setOrganizationUuid(db.getDefaultOrganization().getUuid())
+        .build(),
+      userDto.getId());
+
+    assertThat(db.favorites().hasFavorite(project, userDto.getId())).isTrue();
+  }
+
+  @Test
+  public void does_not_add_project_to_favorite_when_no_user() throws Exception {
+    db.permissionTemplates().addProjectCreatorToTemplate(permissionTemplateDto.getId(), USER);
+
+    ComponentDto project = underTest.create(db.getSession(),
+      NewComponent.newComponentBuilder()
+        .setKey(DEFAULT_PROJECT_KEY)
+        .setName(DEFAULT_PROJECT_NAME)
+        .setOrganizationUuid(db.getDefaultOrganization().getUuid())
+        .build(),
+      null);
+
+    assertThat(db.favorites().hasNoFavorite(project)).isTrue();
+  }
+
+  @Test
+  public void does_not_add_project_to_favorite_when_project_has_no_permission_on_template() throws Exception {
+    UserDto userDto = db.users().insertUser();
+
+    ComponentDto project = underTest.create(db.getSession(),
+      NewComponent.newComponentBuilder()
+        .setKey(DEFAULT_PROJECT_KEY)
+        .setName(DEFAULT_PROJECT_NAME)
+        .setOrganizationUuid(db.getDefaultOrganization().getUuid())
+        .build(),
+      null);
+
+    assertThat(db.favorites().hasNoFavorite(project)).isTrue();
+  }
+
+  @Test
+  public void verify_project_exists_in_es_indexes() throws Exception {
+    ComponentDto project = underTest.create(db.getSession(),
+      NewComponent.newComponentBuilder()
+        .setKey(DEFAULT_PROJECT_KEY)
+        .setName(DEFAULT_PROJECT_NAME)
+        .setOrganizationUuid(db.getDefaultOrganization().getUuid())
+        .build(),
+      null);
+
+    assertThat(es.getIds(INDEX_COMPONENTS, TYPE_COMPONENT)).containsOnly(project.uuid());
+    assertThat(es.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).containsOnly(project.uuid());
+  }
+
+  @Test
+  public void fail_when_project_already_exists() throws Exception {
+    db.components().insertComponent(ComponentTesting.newProjectDto(db.getDefaultOrganization()).setKey(DEFAULT_PROJECT_KEY));
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("Could not create Project, key already exists: project-key");
+
+    underTest.create(db.getSession(),
+      NewComponent.newComponentBuilder()
+        .setKey(DEFAULT_PROJECT_KEY)
+        .setName(DEFAULT_PROJECT_NAME)
+        .setOrganizationUuid(db.getDefaultOrganization().getUuid())
+        .build(),
+      null);
+  }
+
+  @Test
+  public void fail_when_key_has_bad_format() throws Exception {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("Malformed key for Project: 1234");
+
+    underTest.create(db.getSession(),
+      NewComponent.newComponentBuilder()
+        .setKey("1234")
+        .setName(DEFAULT_PROJECT_NAME)
+        .setOrganizationUuid(db.getDefaultOrganization().getUuid())
+        .build(),
+      null);
+  }
+
+  @Test
+  public void fail_to_create_new_component_on_invalid_branch() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("Malformed branch for Project: origin?branch. Allowed characters are alphanumeric, '-', '_', '.' and '/', with at least one non-digit.");
+
+    underTest.create(db.getSession(),
+      NewComponent.newComponentBuilder()
+        .setKey(DEFAULT_PROJECT_KEY)
+        .setName(DEFAULT_PROJECT_NAME)
+        .setBranch("origin?branch")
+        .setOrganizationUuid(db.getDefaultOrganization().getUuid())
+        .build(),
+      null);
+  }
+
+  @Test
+  public void create_view() {
+    ComponentDto view = underTest.create(db.getSession(),
+      NewComponent.newComponentBuilder()
+        .setKey("view-key")
+        .setName("view-name")
+        .setQualifier(VIEW)
+        .setOrganizationUuid(db.getDefaultOrganization().getUuid())
+        .build(),
+      null);
+
+    assertThat(view.getKey()).isEqualTo("view-key");
+    assertThat(view.name()).isEqualTo("view-name");
+    assertThat(view.qualifier()).isEqualTo("VW");
+    assertThat(es.getIds(INDEX_COMPONENTS, TYPE_COMPONENT)).containsOnly(view.uuid());
+    // Indexes related to project measures, issues and views are not indexed
+    assertThat(es.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).isEmpty();
+    assertThat(es.getIds(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION)).isEmpty();
+    assertThat(es.getIds(ViewIndexDefinition.INDEX, ViewIndexDefinition.TYPE_VIEW)).isEmpty();
+  }
+
+  private void setTemplateAsDefault(PermissionTemplateDto permissionTemplateDto) {
+    settings.appendProperty("sonar.permission.template.default", permissionTemplateDto.getUuid());
+  }
+
+}
index 9b2db1113f35091c19767ddfd1ab2027afe5a450..7602bc354fcea951200ee34e76aacb870804adc2 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.server.component;
 
+import java.util.List;
+import java.util.Map;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -32,15 +34,16 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.server.component.index.ComponentIndexDefinition;
 import org.sonar.server.component.index.ComponentIndexer;
 import org.sonar.server.es.EsTester;
-import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.favorite.FavoriteUpdater;
 import org.sonar.server.i18n.I18nRule;
+import org.sonar.server.issue.index.IssueIndexDefinition;
 import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition;
 import org.sonar.server.measure.index.ProjectMeasuresIndexer;
 import org.sonar.server.organization.DefaultOrganizationProvider;
 import org.sonar.server.organization.TestDefaultOrganizationProvider;
 import org.sonar.server.permission.PermissionTemplateService;
 import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.view.index.ViewIndexDefinition;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Matchers.any;
@@ -48,7 +51,6 @@ import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
 
 public class DefaultRubyComponentServiceTest {
 
@@ -57,24 +59,26 @@ public class DefaultRubyComponentServiceTest {
   @Rule
   public DbTester db = DbTester.create(system2);
   @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
+  public EsTester es = new EsTester(
+    new ComponentIndexDefinition(new MapSettings()),
+    new ProjectMeasuresIndexDefinition(new MapSettings()),
+    new IssueIndexDefinition(new MapSettings()),
+    new ViewIndexDefinition(new MapSettings()));
   @Rule
-  public EsTester es = new EsTester(new ProjectMeasuresIndexDefinition(new MapSettings()),
-    new ComponentIndexDefinition(new MapSettings()));
+  public UserSessionRule userSession = UserSessionRule.standalone();
 
   private I18nRule i18n = new I18nRule();
-
   private DbClient dbClient = db.getDbClient();
   private DbSession dbSession = db.getSession();
 
-  private ComponentService componentService = new ComponentService(dbClient, i18n, userSession, system2,
-    new ProjectMeasuresIndexer(system2, dbClient, es.client()), new ComponentIndexer(dbClient, es.client()));
   private PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class);
   private FavoriteUpdater favoriteUpdater = mock(FavoriteUpdater.class);
+  private ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), i18n, system2, permissionTemplateService, favoriteUpdater,
+    new ProjectMeasuresIndexer(system2, db.getDbClient(), es.client()),
+    new ComponentIndexer(db.getDbClient(), es.client()));
   private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
 
-  private DefaultRubyComponentService underTest = new DefaultRubyComponentService(dbClient, componentService,
-    permissionTemplateService, favoriteUpdater, defaultOrganizationProvider);
+  private DefaultRubyComponentService underTest = new DefaultRubyComponentService(userSession, dbClient, componentUpdater, defaultOrganizationProvider);
 
   private String defaultOrganizationUuid;
 
@@ -85,7 +89,7 @@ public class DefaultRubyComponentServiceTest {
 
   @Test
   public void create_component() {
-    userSession.login("john").setGlobalPermissions(PROVISIONING);
+    userSession.login("john").setUserId(100);
     String componentKey = "new-project";
     String componentName = "New Project";
     String qualifier = Qualifiers.PROJECT;
@@ -98,14 +102,7 @@ public class DefaultRubyComponentServiceTest {
     assertThat(project.name()).isEqualTo(componentName);
     assertThat(project.qualifier()).isEqualTo(qualifier);
     assertThat(project.getId()).isEqualTo(result);
-    verify(permissionTemplateService).applyDefaultPermissionTemplate(any(DbSession.class), eq(defaultOrganizationUuid), eq(componentKey));
-    verify(favoriteUpdater).add(any(DbSession.class), eq(project), eq(null));
-  }
-
-  @Test(expected = BadRequestException.class)
-  public void should_throw_if_malformed_key1() {
-    userSession.login("john").setGlobalPermissions(PROVISIONING);
-    underTest.createComponent("1234", "New Project", Qualifiers.PROJECT);
+    verify(permissionTemplateService).applyDefault(any(DbSession.class), eq(defaultOrganizationUuid), any(ComponentDto.class), eq(100L));
   }
 
 }
index 0c468c869485c17c9331cc6583d3f624b682b690..511a6afba2e550e7bd4d8cf010f295e260a330ef 100644 (file)
@@ -93,7 +93,7 @@ public class BulkUpdateKeyActionTest {
 
   private WsActionTester ws = new WsActionTester(
     new BulkUpdateKeyAction(dbClient, componentFinder,
-      new ComponentService(dbClient, null, null, null, new ProjectMeasuresIndexer(system2, dbClient, es.client()), new ComponentIndexer(dbClient, es.client())),
+      new ComponentService(dbClient, null, new ProjectMeasuresIndexer(system2, dbClient, es.client()), new ComponentIndexer(dbClient, es.client())),
       userSession));
 
   @Before
index 99b49a96a8935f0fd75ea80dbefa9abeaef441ca..09ef9ebd833b1f383ff4c685b665404eca3dc05f 100644 (file)
@@ -37,7 +37,7 @@ import org.sonar.db.DbTester;
 import org.sonar.db.ce.CeTaskTypes;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
-import org.sonar.server.component.ComponentService;
+import org.sonar.server.component.ComponentUpdater;
 import org.sonar.server.component.NewComponent;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
@@ -75,11 +75,11 @@ public class ReportSubmitterTest {
   private String defaultOrganizationKey;
   private String defaultOrganizationUuid;
   private CeQueue queue = mock(CeQueueImpl.class);
-  private ComponentService componentService = mock(ComponentService.class);
+  private ComponentUpdater componentUpdater = mock(ComponentUpdater.class);
   private PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class);
   private FavoriteUpdater favoriteUpdater = mock(FavoriteUpdater.class);
 
-  private ReportSubmitter underTest = new ReportSubmitter(queue, userSession, componentService, permissionTemplateService, db.getDbClient(), favoriteUpdater);
+  private ReportSubmitter underTest = new ReportSubmitter(queue, userSession, componentUpdater, permissionTemplateService, db.getDbClient());
 
   @Before
   public void setUp() throws Exception {
@@ -138,7 +138,7 @@ public class ReportSubmitterTest {
 
     mockSuccessfulPrepareSubmitCall();
     ComponentDto createdProject = new ComponentDto().setId(23L).setUuid(PROJECT_UUID).setKey(PROJECT_KEY);
-    when(componentService.create(any(DbSession.class), any(NewComponent.class))).thenReturn(createdProject);
+    when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(createdProject);
     when(permissionTemplateService.wouldUserHavePermissionWithDefaultTemplate(any(DbSession.class), eq(organization.getUuid()), anyLong(), eq(SCAN_EXECUTION), anyString(),
       eq(PROJECT_KEY), eq(Qualifiers.PROJECT)))
         .thenReturn(true);
@@ -147,8 +147,6 @@ public class ReportSubmitterTest {
     underTest.submit(organization.getKey(), PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}"));
 
     verifyReportIsPersisted(TASK_UUID);
-    verify(permissionTemplateService).applyDefault(any(DbSession.class), eq(organization.getUuid()), eq(createdProject), anyLong());
-    verify(favoriteUpdater).add(any(DbSession.class), eq(createdProject), eq(null));
     verify(queue).submit(argThat(new TypeSafeMatcher<CeTaskSubmit>() {
       @Override
       protected boolean matchesSafely(CeTaskSubmit submit) {
@@ -169,7 +167,7 @@ public class ReportSubmitterTest {
 
     mockSuccessfulPrepareSubmitCall();
     ComponentDto createdProject = new ComponentDto().setId(23L).setUuid(PROJECT_UUID).setKey(PROJECT_KEY);
-    when(componentService.create(any(DbSession.class), any(NewComponent.class))).thenReturn(createdProject);
+    when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(createdProject);
     when(permissionTemplateService.wouldUserHavePermissionWithDefaultTemplate(any(DbSession.class), eq(defaultOrganizationUuid), anyLong(), eq(SCAN_EXECUTION), anyString(),
       eq(PROJECT_KEY), eq(Qualifiers.PROJECT)))
         .thenReturn(true);
@@ -185,7 +183,7 @@ public class ReportSubmitterTest {
     userSession.setGlobalPermissions(SCAN_EXECUTION, PROVISIONING);
 
     mockSuccessfulPrepareSubmitCall();
-    when(componentService.create(any(DbSession.class), any(NewComponent.class))).thenReturn(new ComponentDto().setId(23L).setUuid(PROJECT_UUID).setKey(PROJECT_KEY));
+    when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(new ComponentDto().setId(23L).setUuid(PROJECT_UUID).setKey(PROJECT_KEY));
     when(permissionTemplateService.wouldUserHavePermissionWithDefaultTemplate(any(DbSession.class), eq(defaultOrganizationUuid), anyLong(), eq(SCAN_EXECUTION), anyString(),
       eq(PROJECT_KEY), eq(Qualifiers.PROJECT)))
         .thenReturn(true);
@@ -233,7 +231,7 @@ public class ReportSubmitterTest {
     userSession.addProjectUuidPermissions(SCAN_EXECUTION, PROJECT_UUID);
 
     mockSuccessfulPrepareSubmitCall();
-    when(componentService.create(any(DbSession.class), any(NewComponent.class))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setKey(PROJECT_KEY));
+    when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setKey(PROJECT_KEY));
 
     thrown.expect(ForbiddenException.class);
     underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}"));
index 8610fc8f404e4dc8c1fc4125203a0e16c1aaa6fa..dbce259b8874e0ec7236960779a693ea38a0440b 100644 (file)
@@ -36,7 +36,7 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
 import org.sonar.db.permission.template.PermissionTemplateDto;
 import org.sonar.db.user.UserDto;
-import org.sonar.server.component.ComponentService;
+import org.sonar.server.component.ComponentUpdater;
 import org.sonar.server.component.index.ComponentIndexDefinition;
 import org.sonar.server.component.index.ComponentIndexer;
 import org.sonar.server.es.EsTester;
@@ -101,11 +101,11 @@ public class CreateActionTest {
   private WsActionTester ws = new WsActionTester(
     new CreateAction(
       db.getDbClient(), userSession,
-      new ComponentService(db.getDbClient(), i18n, userSession, system2,
+      new ComponentUpdater(db.getDbClient(), i18n, system2,
+        new PermissionTemplateService(db.getDbClient(), settings, new PermissionIndexer(db.getDbClient(), es.client()), userSession),
+        new FavoriteUpdater(db.getDbClient()),
         new ProjectMeasuresIndexer(system2, db.getDbClient(), es.client()),
         new ComponentIndexer(db.getDbClient(), es.client())),
-      new PermissionTemplateService(db.getDbClient(), settings, new PermissionIndexer(db.getDbClient(), es.client()), userSession),
-      new FavoriteUpdater(db.getDbClient()),
       defaultOrganizationProvider));
 
   @Before