* 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;
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;
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;
}
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")
@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();
}
}
* 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;
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;
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
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);
}
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) {
return request.execute().getInput();
}
+
+ private Optional<ComponentDto> selectByKey(String key) {
+ return db.getDbClient().componentDao().selectByKey(db.getSession(), key);
+ }
}