aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/ws/CreateAction.java20
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsSupport.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ComponentUpdaterTest.java16
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java74
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/project/CreateRequest.java13
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsService.java1
-rw-r--r--sonar-ws/src/test/java/org/sonarqube/ws/client/project/ProjectsServiceTest.java16
7 files changed, 108 insertions, 34 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/CreateAction.java
index 4267b349a9a..2ffa96b7c03 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/CreateAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/CreateAction.java
@@ -25,15 +25,18 @@ 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.db.organization.OrganizationDto;
import org.sonar.server.component.ComponentUpdater;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.WsProjects.CreateWsResponse;
import org.sonarqube.ws.client.project.CreateRequest;
+import static java.util.Optional.ofNullable;
import static org.sonar.api.resources.Qualifiers.PROJECT;
import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
import static org.sonar.server.component.NewComponent.newComponentBuilder;
+import static org.sonar.server.project.ws.ProjectsWsSupport.PARAM_ORGANIZATION;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.project.ProjectsWsParameters.ACTION_CREATE;
@@ -43,14 +46,17 @@ import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECT
public class CreateAction implements ProjectsWsAction {
- public static final String DEPRECATED_PARAM_KEY = "key";
+ private static final String DEPRECATED_PARAM_KEY = "key";
+ private final ProjectsWsSupport support;
private final DbClient dbClient;
private final UserSession userSession;
private final ComponentUpdater componentUpdater;
private final DefaultOrganizationProvider defaultOrganizationProvider;
- public CreateAction(DbClient dbClient, UserSession userSession, ComponentUpdater componentUpdater, DefaultOrganizationProvider defaultOrganizationProvider) {
+ public CreateAction(ProjectsWsSupport support, DbClient dbClient, UserSession userSession, ComponentUpdater componentUpdater,
+ DefaultOrganizationProvider defaultOrganizationProvider) {
+ this.support = support;
this.dbClient = dbClient;
this.userSession = userSession;
this.componentUpdater = componentUpdater;
@@ -83,19 +89,24 @@ public class CreateAction implements ProjectsWsAction {
action.createParam(PARAM_BRANCH)
.setDescription("SCM Branch of the project. The key of the project will become key:branch, for instance 'SonarQube:branch-5.0'")
.setExampleValue("branch-5.0");
+
+ support.addOrganizationParam(action);
}
@Override
public void handle(Request request, Response response) throws Exception {
- userSession.checkPermission(PROVISIONING);
CreateRequest createRequest = toCreateRequest(request);
writeProtobuf(doHandle(createRequest), request, response);
}
private CreateWsResponse doHandle(CreateRequest request) {
try (DbSession dbSession = dbClient.openSession(false)) {
+ OrganizationDto organization = support.getOrganization(dbSession, ofNullable(request.getOrganization())
+ .orElseGet(defaultOrganizationProvider.get()::getKey));
+ userSession.checkOrganizationPermission(organization.getUuid(), PROVISIONING);
+
ComponentDto componentDto = componentUpdater.create(dbSession, newComponentBuilder()
- .setOrganizationUuid(defaultOrganizationProvider.get().getUuid())
+ .setOrganizationUuid(organization.getUuid())
.setKey(request.getKey())
.setName(request.getName())
.setBranch(request.getBranch())
@@ -108,6 +119,7 @@ public class CreateAction implements ProjectsWsAction {
private static CreateRequest toCreateRequest(Request request) {
return CreateRequest.builder()
+ .setOrganization(request.param(PARAM_ORGANIZATION))
.setKey(request.mandatoryParam(PARAM_PROJECT))
.setName(request.mandatoryParam(PARAM_NAME))
.setBranch(request.param(PARAM_BRANCH))
diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsSupport.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsSupport.java
index e587cbfff33..813cb6d101d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsSupport.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsSupport.java
@@ -27,7 +27,7 @@ import org.sonar.db.organization.OrganizationDto;
import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
public class ProjectsWsSupport {
- static final String PARAM_ORGANIZATION = "organization";
+ public static final String PARAM_ORGANIZATION = "organization";
private final DbClient dbClient;
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
index 5442ad996d3..541aebe1e7e 100644
--- 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
@@ -180,6 +180,22 @@ public class ComponentUpdaterTest {
}
@Test
+ public void fail_when_project_key_already_exists_on_other_organization() throws Exception {
+ ComponentDto existing = db.components().insertProject(db.organizations().insert());
+
+ expectedException.expect(BadRequestException.class);
+ expectedException.expectMessage("Could not create Project, key already exists: " + existing.key());
+
+ underTest.create(db.getSession(),
+ NewComponent.newComponentBuilder()
+ .setKey(existing.key())
+ .setName(DEFAULT_PROJECT_NAME)
+ .setOrganizationUuid(existing.getOrganizationUuid())
+ .build(),
+ null);
+ }
+
+ @Test
public void fail_when_key_has_bad_format() throws Exception {
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Malformed key for Project: 1234");
diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java
index 7a7411062e2..3e0ee7ad05b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java
@@ -32,6 +32,7 @@ import org.sonar.api.utils.System2;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
+import org.sonar.db.organization.OrganizationDto;
import org.sonar.server.component.ComponentUpdater;
import org.sonar.server.component.NewComponent;
import org.sonar.server.exceptions.BadRequestException;
@@ -54,6 +55,7 @@ import static org.mockito.Mockito.when;
import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
import static org.sonar.core.permission.GlobalPermissions.QUALITY_GATE_ADMIN;
import static org.sonar.core.util.Protobuf.setNullable;
+import static org.sonar.server.project.ws.ProjectsWsSupport.PARAM_ORGANIZATION;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.client.WsRequest.Method.POST;
import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_NAME;
@@ -71,24 +73,26 @@ public class CreateActionTest {
public DbTester db = DbTester.create(system2);
@Rule
public UserSessionRule userSession = UserSessionRule.standalone();
+
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
private ComponentUpdater componentUpdater = mock(ComponentUpdater.class, Mockito.RETURNS_MOCKS);
private WsActionTester ws = new WsActionTester(
- new CreateAction(
- db.getDbClient(), userSession,
- componentUpdater,
- defaultOrganizationProvider));
+ new CreateAction(
+ new ProjectsWsSupport(db.getDbClient()),
+ db.getDbClient(), userSession,
+ componentUpdater,
+ defaultOrganizationProvider));
@Test
public void create_project() throws Exception {
- userSession.setGlobalPermissions(PROVISIONING);
+ userSession.addOrganizationPermission(db.getDefaultOrganization(), PROVISIONING);
expectSuccessfulCallToComponentUpdater();
CreateWsResponse response = call(CreateRequest.builder()
- .setKey(DEFAULT_PROJECT_KEY)
- .setName(DEFAULT_PROJECT_NAME)
- .build());
+ .setKey(DEFAULT_PROJECT_KEY)
+ .setName(DEFAULT_PROJECT_NAME)
+ .build());
assertThat(response.getProject().getKey()).isEqualTo(DEFAULT_PROJECT_KEY);
assertThat(response.getProject().getName()).isEqualTo(DEFAULT_PROJECT_NAME);
@@ -97,13 +101,13 @@ public class CreateActionTest {
@Test
public void create_project_with_branch() throws Exception {
- userSession.setGlobalPermissions(PROVISIONING);
+ userSession.addOrganizationPermission(db.getDefaultOrganization(), PROVISIONING);
call(CreateRequest.builder()
- .setKey(DEFAULT_PROJECT_KEY)
- .setName(DEFAULT_PROJECT_NAME)
- .setBranch("origin/master")
- .build());
+ .setKey(DEFAULT_PROJECT_KEY)
+ .setName(DEFAULT_PROJECT_NAME)
+ .setBranch("origin/master")
+ .build());
NewComponent called = verifyCallToComponentUpdater();
assertThat(called.key()).isEqualTo(DEFAULT_PROJECT_KEY);
@@ -112,13 +116,15 @@ public class CreateActionTest {
@Test
public void create_project_with_deprecated_parameter() throws Exception {
- userSession.setGlobalPermissions(PROVISIONING);
+ OrganizationDto organization = db.organizations().insert();
+ userSession.addOrganizationPermission(organization, PROVISIONING);
ws.newRequest()
- .setMethod(POST.name())
- .setParam("key", DEFAULT_PROJECT_KEY)
- .setParam(PARAM_NAME, DEFAULT_PROJECT_NAME)
- .execute();
+ .setMethod(POST.name())
+ .setParam("organization", organization.getKey())
+ .setParam("key", DEFAULT_PROJECT_KEY)
+ .setParam(PARAM_NAME, DEFAULT_PROJECT_NAME)
+ .execute();
NewComponent called = verifyCallToComponentUpdater();
assertThat(called.key()).isEqualTo(DEFAULT_PROJECT_KEY);
@@ -127,15 +133,17 @@ public class CreateActionTest {
@Test
public void fail_when_project_already_exists() throws Exception {
- userSession.setGlobalPermissions(PROVISIONING);
+ OrganizationDto organization = db.organizations().insert();
when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), anyLong())).thenThrow(new BadRequestException("already exists"));
+ userSession.addOrganizationPermission(organization, PROVISIONING);
expectedException.expect(BadRequestException.class);
call(CreateRequest.builder()
- .setKey(DEFAULT_PROJECT_KEY)
- .setName(DEFAULT_PROJECT_NAME)
- .build());
+ .setOrganization(organization.getKey())
+ .setKey(DEFAULT_PROJECT_KEY)
+ .setName(DEFAULT_PROJECT_NAME)
+ .build());
}
@Test
@@ -166,13 +174,13 @@ public class CreateActionTest {
@Test
public void test_example() {
- userSession.setGlobalPermissions(PROVISIONING);
+ userSession.addOrganizationPermission(db.getDefaultOrganization(), PROVISIONING);
expectSuccessfulCallToComponentUpdater();
String result = ws.newRequest()
- .setParam("key", DEFAULT_PROJECT_KEY)
- .setParam("name", DEFAULT_PROJECT_NAME)
- .execute().getInput();
+ .setParam("key", DEFAULT_PROJECT_KEY)
+ .setParam("name", DEFAULT_PROJECT_NAME)
+ .execute().getInput();
assertJson(result).isSimilarTo(getClass().getResource("create-example.json"));
}
@@ -185,13 +193,21 @@ public class CreateActionTest {
Assertions.assertThat(definition.since()).isEqualTo("4.0");
Assertions.assertThat(definition.isInternal()).isFalse();
Assertions.assertThat(definition.responseExampleAsString()).isNotEmpty();
- Assertions.assertThat(definition.params()).hasSize(3);
+
+ Assertions.assertThat(definition.params()).hasSize(4);
+
+ WebService.Param organization = definition.param(PARAM_ORGANIZATION);
+ Assertions.assertThat(organization.description()).isEqualTo("The key of the organization");
+ Assertions.assertThat(organization.isInternal()).isTrue();
+ Assertions.assertThat(organization.isRequired()).isFalse();
+ Assertions.assertThat(organization.since()).isEqualTo("6.3");
}
private CreateWsResponse call(CreateRequest request) {
TestRequest httpRequest = ws.newRequest()
- .setMethod(POST.name())
- .setMediaType(MediaTypes.PROTOBUF);
+ .setMethod(POST.name())
+ .setMediaType(MediaTypes.PROTOBUF);
+ setNullable(request.getOrganization(), e -> httpRequest.setParam("organization", e));
setNullable(request.getKey(), e -> httpRequest.setParam("project", e));
setNullable(request.getName(), e -> httpRequest.setParam("name", e));
setNullable(request.getBranch(), e -> httpRequest.setParam("branch", e));
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/CreateRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/CreateRequest.java
index b68e7746999..06ab43c2270 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/CreateRequest.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/CreateRequest.java
@@ -26,16 +26,23 @@ import javax.annotation.concurrent.Immutable;
@Immutable
public class CreateRequest {
+ private final String organization;
private final String key;
private final String name;
private final String branch;
private CreateRequest(Builder builder) {
+ this.organization = builder.organization;
this.key = builder.key;
this.name = builder.name;
this.branch = builder.branch;
}
+ @CheckForNull
+ public String getOrganization() {
+ return organization;
+ }
+
public String getKey() {
return key;
}
@@ -54,6 +61,7 @@ public class CreateRequest {
}
public static class Builder {
+ private String organization;
private String key;
private String name;
private String branch;
@@ -61,6 +69,11 @@ public class CreateRequest {
private Builder() {
}
+ public Builder setOrganization(String organization) {
+ this.organization = organization;
+ return this;
+ }
+
public Builder setKey(String key) {
this.key = key;
return this;
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsService.java
index 37f0db639a7..328045fbd86 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsService.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsService.java
@@ -48,6 +48,7 @@ public class ProjectsService extends BaseService {
*/
public CreateWsResponse create(CreateRequest project) {
PostRequest request = new PostRequest(path(ACTION_CREATE))
+ .setParam("organization", project.getOrganization())
.setParam(PARAM_PROJECT, project.getKey())
.setParam(PARAM_NAME, project.getName())
.setParam(PARAM_BRANCH, project.getBranch());
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/project/ProjectsServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/project/ProjectsServiceTest.java
index 94fc4c2b91e..1d3e3c51881 100644
--- a/sonar-ws/src/test/java/org/sonarqube/ws/client/project/ProjectsServiceTest.java
+++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/project/ProjectsServiceTest.java
@@ -51,6 +51,22 @@ public class ProjectsServiceTest {
}
@Test
+ public void creates_project_on_organization() {
+ underTest.create(CreateRequest.builder()
+ .setOrganization("org_key")
+ .setKey("project_key")
+ .setName("Project Name")
+ .build());
+
+ assertThat(serviceTester.getPostParser()).isSameAs(WsProjects.CreateWsResponse.parser());
+ assertThat(serviceTester.getPostRequest().getPath()).isEqualTo("api/projects/create");
+ assertThat(serviceTester.getPostRequest().getParams()).containsOnly(
+ entry("organization", "org_key"),
+ entry("project", "project_key"),
+ entry("name", "Project Name"));
+ }
+
+ @Test
public void creates_project_on_branch() {
underTest.create(CreateRequest.builder()
.setKey("project_key")