]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10536 no longer possible to analyse a module that was removed from another...
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 5 Apr 2018 19:06:07 +0000 (21:06 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Fri, 6 Apr 2018 11:32:52 +0000 (13:32 +0200)
server/sonar-server/src/main/java/org/sonar/server/project/ws/UpdateKeyAction.java
server/sonar-server/src/test/java/org/sonar/server/project/ws/UpdateKeyActionTest.java

index 4f14b4793e8bdc4ae2b9d8570ab2d75fb6bd15df..bda6d52b9551f0d5261918828e838b4e5035ac5a 100644 (file)
@@ -17,9 +17,9 @@
  * 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.project.ws;
 
+import com.google.common.base.Optional;
 import org.sonar.api.server.ws.Change;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
@@ -27,11 +27,10 @@ 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.ComponentFinder;
-import org.sonar.server.component.ComponentFinder.ParamNames;
 import org.sonar.server.component.ComponentService;
-import org.sonarqube.ws.client.project.UpdateKeyWsRequest;
+import org.sonar.server.exceptions.NotFoundException;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
 import static org.sonarqube.ws.client.project.ProjectsWsParameters.ACTION_UPDATE_KEY;
 import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_FROM;
@@ -40,12 +39,10 @@ import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_TO;
 
 public class UpdateKeyAction implements ProjectsWsAction {
   private final DbClient dbClient;
-  private final ComponentFinder componentFinder;
   private final ComponentService componentService;
 
-  public UpdateKeyAction(DbClient dbClient, ComponentFinder componentFinder, ComponentService componentService) {
+  public UpdateKeyAction(DbClient dbClient, ComponentService componentService) {
     this.dbClient = dbClient;
-    this.componentFinder = componentFinder;
     this.componentService = componentService;
   }
 
@@ -57,19 +54,20 @@ public class UpdateKeyAction implements ProjectsWsAction {
   public WebService.NewAction doDefine(WebService.NewController context) {
     WebService.NewAction action = context.createAction(ACTION_UPDATE_KEY)
       .setDescription("Update a project or module key and all its sub-components keys.<br>" +
-        "Either '%s' or '%s' must be provided.<br> " +
-        "Requires one of the following permissions: " +
-        "<ul>" +
-        "<li>'Administer System'</li>" +
-        "<li>'Administer' rights on the specified project</li>" +
-        "</ul>",
+          "Either '%s' or '%s' must be provided.<br> " +
+          "Requires one of the following permissions: " +
+          "<ul>" +
+          "<li>'Administer System'</li>" +
+          "<li>'Administer' rights on the specified project</li>" +
+          "</ul>",
         PARAM_FROM, PARAM_PROJECT_ID)
       .setSince("6.1")
       .setPost(true)
       .setHandler(this);
 
     action.setChangelog(
-      new Change("6.4", "Move from api/components/update_key to api/projects/update_key"));
+      new Change("6.4", "Move from api/components/update_key to api/projects/update_key"),
+      new Change("7.1", "Ability to update key of a disabled module"));
 
     action.createParam(PARAM_PROJECT_ID)
       .setDescription("Project or module id")
@@ -93,22 +91,24 @@ public class UpdateKeyAction implements ProjectsWsAction {
 
   @Override
   public void handle(Request request, Response response) throws Exception {
-    doHandle(toWsRequest(request));
-    response.noContent();
-  }
+    String uuid = request.param(PARAM_PROJECT_ID);
+    String key = request.param(PARAM_FROM);
+    String newKey = request.mandatoryParam(PARAM_TO);
+    checkArgument(uuid != null ^ key != null, "Either '%s' or '%s' must be provided", PARAM_PROJECT_ID, PARAM_FROM);
 
-  private void doHandle(UpdateKeyWsRequest request) {
     try (DbSession dbSession = dbClient.openSession(false)) {
-      ComponentDto projectOrModule = componentFinder.getByUuidOrKey(dbSession, request.getId(), request.getKey(), ParamNames.PROJECT_ID_AND_FROM);
-      componentService.updateKey(dbSession, projectOrModule, request.getNewKey());
-    }
-  }
+      Optional<ComponentDto> component;
+      if (uuid != null) {
+        component = dbClient.componentDao().selectByUuid(dbSession, uuid);
+      } else {
+        component = dbClient.componentDao().selectByKey(dbSession, key);
+      }
+      if (!component.isPresent() || component.get().getMainBranchProjectUuid() != null) {
+        throw new NotFoundException("Component not found");
+      }
 
-  private static UpdateKeyWsRequest toWsRequest(Request request) {
-    return UpdateKeyWsRequest.builder()
-      .setId(request.param(PARAM_PROJECT_ID))
-      .setKey(request.param(PARAM_FROM))
-      .setNewKey(request.mandatoryParam(PARAM_TO))
-      .build();
+      componentService.updateKey(dbSession, component.get(), newKey);
+    }
+    response.noContent();
   }
 }
index 975a4a61aba514558f47e24005354dac66ab8be4..0b5f8e6d5e0ad82805d087f42a1c45dc233e6da3 100644 (file)
@@ -17,9 +17,9 @@
  * 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.project.ws;
 
+import com.google.common.base.Optional;
 import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
@@ -27,23 +27,21 @@ import org.junit.rules.ExpectedException;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
 import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
 import org.sonar.server.component.ComponentService;
-import org.sonar.server.component.TestComponentFinder;
+import org.sonar.server.es.ProjectIndexers;
+import org.sonar.server.es.ProjectIndexersImpl;
+import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.TestRequest;
 import org.sonar.server.ws.WsActionTester;
 
 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.mock;
-import static org.mockito.Mockito.verify;
 import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_FROM;
 import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECT_ID;
 import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_TO;
@@ -55,55 +53,104 @@ public class UpdateKeyActionTest {
   public ExpectedException expectedException = ExpectedException.none();
   @Rule
   public DbTester db = DbTester.create(System2.INSTANCE);
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+  private DbClient dbClient = db.getDbClient();
+  private ProjectIndexers projectIndexers = new ProjectIndexersImpl();
+  private ComponentService componentService = new ComponentService(dbClient, userSessionRule, projectIndexers);
+  private WsActionTester ws = new WsActionTester(new UpdateKeyAction(dbClient, componentService));
 
-  ComponentDbTester componentDb = new ComponentDbTester(db);
-  DbClient dbClient = db.getDbClient();
+  @Test
+  public void update_key_of_project_referenced_by_its_key() {
+    ComponentDto project = insertProject();
+    userSessionRule.addProjectPermission(UserRole.ADMIN, project);
 
-  ComponentService componentService = mock(ComponentService.class);
+    callByKey(project.getKey(), ANOTHER_KEY);
 
-  WsActionTester ws = new WsActionTester(new org.sonar.server.project.ws.UpdateKeyAction(dbClient, TestComponentFinder.from(db), componentService));
+    assertThat(selectByKey(project.getKey()).isPresent()).isFalse();
+    assertThat(selectByKey(ANOTHER_KEY).get().uuid()).isEqualTo(project.uuid());
+  }
 
   @Test
-  public void call_by_key() {
+  public void update_key_of_project_referenced_by_its_uuid() {
     ComponentDto project = insertProject();
+    userSessionRule.addProjectPermission(UserRole.ADMIN, project);
 
-    callByKey(project.getDbKey(), ANOTHER_KEY);
+    callByUuid(project.uuid(), ANOTHER_KEY);
 
-    assertCallComponentService(ANOTHER_KEY);
+    assertThat(selectByKey(project.getKey()).isPresent()).isFalse();
+    assertThat(selectByKey(ANOTHER_KEY).get().uuid()).isEqualTo(project.uuid());
   }
 
   @Test
-  public void call_by_uuid() {
+  public void update_key_of_module_referenced_by_its_uuid() {
     ComponentDto project = insertProject();
+    ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project));
+    userSessionRule.addProjectPermission(UserRole.ADMIN, project);
 
-    callByUuid(project.uuid(), ANOTHER_KEY);
+    callByUuid(module.uuid(), ANOTHER_KEY);
 
-    assertCallComponentService(ANOTHER_KEY);
+    assertThat(selectByKey(project.getKey()).isPresent()).isTrue();
+    assertThat(selectByKey(module.getKey()).isPresent()).isFalse();
+    assertThat(selectByKey(ANOTHER_KEY).get().uuid()).isEqualTo(module.uuid());
   }
 
   @Test
-  public void fail_if_new_key_is_not_provided() {
-    expectedException.expect(IllegalArgumentException.class);
+  public void update_key_of_disabled_module() {
+    ComponentDto project = insertProject();
+    ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project).setEnabled(false));
+    userSessionRule.addProjectPermission(UserRole.ADMIN, project);
+
+    callByKey(module.getKey(), ANOTHER_KEY);
+
+    assertThat(selectByKey(project.getKey()).isPresent()).isTrue();
+    assertThat(selectByKey(module.getKey()).isPresent()).isFalse();
+    ComponentDto loadedModule = selectByKey(ANOTHER_KEY).get();
+    assertThat(loadedModule.uuid()).isEqualTo(module.uuid());
+    assertThat(loadedModule.isEnabled()).isFalse();
+  }
+
 
+  @Test
+  public void fail_if_not_authorized() {
     ComponentDto project = insertProject();
+    userSessionRule.addProjectPermission(UserRole.USER, project);
+
+    expectedException.expect(ForbiddenException.class);
+    expectedException.expectMessage("Insufficient privileges");
 
-    callByKey(project.getDbKey(), null);
+    callByKey(project.getKey(), ANOTHER_KEY);
+  }
+
+  @Test
+  public void fail_if_new_key_is_not_provided() {
+    ComponentDto project = insertProject();
+    userSessionRule.addProjectPermission(UserRole.ADMIN, project);
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("The 'to' parameter is missing");
+
+    callByKey(project.getKey(), null);
   }
 
   @Test
   public void fail_if_uuid_nor_key_provided() {
     expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Either 'projectId' or 'from' must be provided");
 
     call(null, null, ANOTHER_KEY);
   }
 
   @Test
-  public void fail_if_uuid_and_key_provided() {
+  public void fail_if_both_uuid_and_key_provided() {
+    ComponentDto project = insertProject();
+    userSessionRule.addProjectPermission(UserRole.ADMIN, project);
+
     expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Either 'projectId' or 'from' must be provided");
 
-    ComponentDto project = insertProject();
 
-    call(project.uuid(), project.getDbKey(), ANOTHER_KEY);
+    call(project.uuid(), project.getKey(), ANOTHER_KEY);
   }
 
   @Test
@@ -117,20 +164,22 @@ public class UpdateKeyActionTest {
   public void fail_when_using_branch_db_key() throws Exception {
     ComponentDto project = db.components().insertMainBranch();
     ComponentDto branch = db.components().insertProjectBranch(project);
+    userSessionRule.addProjectPermission(UserRole.ADMIN, project);
 
     expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage(String.format("Component key '%s' not found", branch.getDbKey()));
+    expectedException.expectMessage("Component not found");
 
     callByKey(branch.getDbKey(), ANOTHER_KEY);
   }
 
   @Test
-  public void fail_when_using_branch_uuid() throws Exception {
+  public void fail_when_using_branch_uuid() {
     ComponentDto project = db.components().insertMainBranch();
     ComponentDto branch = db.components().insertProjectBranch(project);
+    userSessionRule.addProjectPermission(UserRole.ADMIN, project);
 
     expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage(String.format("Component id '%s' not found", branch.uuid()));
+    expectedException.expectMessage("Component not found");
 
     callByUuid(branch.uuid(), ANOTHER_KEY);
   }
@@ -142,26 +191,23 @@ public class UpdateKeyActionTest {
     assertThat(definition.since()).isEqualTo("6.1");
     assertThat(definition.isPost()).isTrue();
     assertThat(definition.key()).isEqualTo("update_key");
+    assertThat(definition.changelog()).hasSize(2);
     assertThat(definition.params())
       .hasSize(3)
       .extracting(Param::key)
       .containsOnlyOnce("projectId", "from", "to");
   }
 
-  private void assertCallComponentService(@Nullable String newKey) {
-    verify(componentService).updateKey(any(DbSession.class), any(ComponentDto.class), eq(newKey));
-  }
-
   private ComponentDto insertProject() {
-    return componentDb.insertComponent(ComponentTesting.newPrivateProjectDto(db.organizations().insert()));
+    return db.components().insertComponent(ComponentTesting.newPrivateProjectDto(db.organizations().insert()));
   }
 
-  private String callByUuid(@Nullable String uuid, @Nullable String newKey) {
-    return call(uuid, null, newKey);
+  private void callByUuid(@Nullable String uuid, @Nullable String newKey) {
+    call(uuid, null, newKey);
   }
 
-  private String callByKey(@Nullable String key, @Nullable String newKey) {
-    return call(null, key, newKey);
+  private void callByKey(@Nullable String key, @Nullable String newKey) {
+    call(null, key, newKey);
   }
 
   private String call(@Nullable String uuid, @Nullable String key, @Nullable String newKey) {
@@ -179,4 +225,8 @@ public class UpdateKeyActionTest {
 
     return request.execute().getInput();
   }
+
+  private Optional<ComponentDto> selectByKey(String key) {
+    return db.getDbClient().componentDao().selectByKey(db.getSession(), key);
+  }
 }