aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDao.java4
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMapper.java2
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml9
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/project/ws/CreateAction.java17
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java86
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/project/CreateRequest.java19
-rw-r--r--sonar-ws/src/main/protobuf/ws-projects.proto1
7 files changed, 133 insertions, 5 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDao.java
index a6513bd16b1..4ddc575bd86 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDao.java
@@ -117,6 +117,10 @@ public class OrganizationDao implements Dao {
return getMapper(dbSession).selectNewProjectPrivateByUuid(organization.getUuid());
}
+ public void setNewProjectPrivate(DbSession dbSession, OrganizationDto organization, boolean newProjectPrivate) {
+ getMapper(dbSession).updateNewProjectPrivate(organization.getUuid(), newProjectPrivate, system2.now());
+ }
+
public int update(DbSession dbSession, OrganizationDto organization) {
checkDto(organization);
organization.setUpdatedAt(system2.now());
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMapper.java
index fb024e3c934..5f891da130a 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMapper.java
@@ -70,5 +70,7 @@ public interface OrganizationMapper {
void updateDefaultGroupId(@Param("organizationUuid") String organizationUuid,
@Param("defaultGroupId") int defaultGroupId, @Param("now") long now);
+ void updateNewProjectPrivate(@Param("organizationUuid") String organizationUuid, @Param("newProjectPrivate") boolean newProjectPrivate, @Param("now") long now);
+
int deleteByUuid(@Param("uuid") String uuid);
}
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml
index c9394628103..ee804cfdf04 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml
@@ -256,6 +256,15 @@
uuid = #{organizationUuid, jdbcType=VARCHAR}
</update>
+ <update id="updateNewProjectPrivate">
+ update organizations
+ set
+ new_project_private = #{newProjectPrivate, jdbcType=INTEGER},
+ updated_at = #{now, jdbcType=BIGINT}
+ where
+ uuid = #{organizationUuid, jdbcType=VARCHAR}
+ </update>
+
<delete id="deleteByUuid">
delete from organizations
where
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 afd1579bad0..45d0c69a3cc 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
@@ -48,6 +48,7 @@ import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECT
public class CreateAction implements ProjectsWsAction {
private static final String DEPRECATED_PARAM_KEY = "key";
+ static final String PARAM_VISIBILITY = "visibility";
private final ProjectsWsSupport support;
private final DbClient dbClient;
@@ -76,8 +77,7 @@ public class CreateAction implements ProjectsWsAction {
action.setChangelog(
new Change("6.3", "The response format has been updated and does not contain the database ID anymore"),
- new Change("6.3", "The 'key' parameter has been renamed 'project'")
- );
+ new Change("6.3", "The 'key' parameter has been renamed 'project'"));
action.createParam(PARAM_PROJECT)
.setDescription("Key of the project")
@@ -94,6 +94,14 @@ public class CreateAction implements ProjectsWsAction {
.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");
+ action.createParam(PARAM_VISIBILITY)
+ .setDescription("Whether the created project should be visible to everyone, or only specific user/groups.<br/>" +
+ "If no visibility is specified, the default project visibility of the organization will be used.")
+ .setRequired(false)
+ .setInternal(true)
+ .setSince("6.4")
+ .setPossibleValues("private", "public");
+
support.addOrganizationParam(action);
}
@@ -114,6 +122,7 @@ public class CreateAction implements ProjectsWsAction {
.setKey(request.getKey())
.setName(request.getName())
.setBranch(request.getBranch())
+ .setPrivate(request.getVisibility().map("private"::equals).orElseGet(() -> dbClient.organizationDao().getNewProjectPrivate(dbSession, organization)))
.setQualifier(PROJECT)
.build(),
userSession.isLoggedIn() ? userSession.getUserId() : null);
@@ -127,6 +136,7 @@ public class CreateAction implements ProjectsWsAction {
.setKey(request.mandatoryParam(PARAM_PROJECT))
.setName(request.mandatoryParam(PARAM_NAME))
.setBranch(request.param(PARAM_BRANCH))
+ .setVisibility(request.param(PARAM_VISIBILITY))
.build();
}
@@ -135,7 +145,8 @@ public class CreateAction implements ProjectsWsAction {
.setProject(CreateWsResponse.Project.newBuilder()
.setKey(componentDto.key())
.setName(componentDto.name())
- .setQualifier(componentDto.qualifier()))
+ .setQualifier(componentDto.qualifier())
+ .setVisibility(componentDto.isPrivate() ? "private" : "public"))
.build();
}
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 6287a347a27..cc6e2ba5f52 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
@@ -51,10 +51,13 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS;
+import static org.sonar.server.project.ws.CreateAction.PARAM_VISIBILITY;
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_BRANCH;
import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_NAME;
+import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECT;
public class CreateActionTest {
@@ -179,6 +182,72 @@ public class CreateActionTest {
}
@Test
+ public void apply_project_visibility_public() {
+ OrganizationDto organization = db.organizations().insert();
+ userSession.addPermission(PROVISION_PROJECTS, organization);
+ expectSuccessfulCallToComponentUpdater();
+
+ CreateWsResponse result = ws.newRequest()
+ .setParam("key", DEFAULT_PROJECT_KEY)
+ .setParam("name", DEFAULT_PROJECT_NAME)
+ .setParam("organization", organization.getKey())
+ .setParam("visibility", "public")
+ .executeProtobuf(CreateWsResponse.class);
+
+ assertThat(result.getProject().getVisibility()).isEqualTo("public");
+ }
+
+ @Test
+ public void apply_project_visibility_private() {
+ OrganizationDto organization = db.organizations().insert();
+ userSession.addPermission(PROVISION_PROJECTS, organization);
+ expectSuccessfulCallToComponentUpdater();
+
+ CreateWsResponse result = ws.newRequest()
+ .setParam("key", DEFAULT_PROJECT_KEY)
+ .setParam("name", DEFAULT_PROJECT_NAME)
+ .setParam("organization", organization.getKey())
+ .setParam("visibility", "private")
+ .executeProtobuf(CreateWsResponse.class);
+
+ assertThat(result.getProject().getVisibility()).isEqualTo("private");
+ }
+
+ @Test
+ public void apply_default_project_visibility_public() {
+ OrganizationDto organization = db.organizations().insert();
+ db.getDbClient().organizationDao().setNewProjectPrivate(db.getSession(), organization, false);
+ db.commit();
+ userSession.addPermission(PROVISION_PROJECTS, organization);
+ expectSuccessfulCallToComponentUpdater();
+
+ CreateWsResponse result = ws.newRequest()
+ .setParam("key", DEFAULT_PROJECT_KEY)
+ .setParam("name", DEFAULT_PROJECT_NAME)
+ .setParam("organization", organization.getKey())
+ .executeProtobuf(CreateWsResponse.class);
+
+ assertThat(result.getProject().getVisibility()).isEqualTo("public");
+ }
+
+ @Test
+ public void apply_default_project_visibility_private() {
+ OrganizationDto organization = db.organizations().insert();
+ db.getDbClient().organizationDao().setNewProjectPrivate(db.getSession(), organization, true);
+ db.commit();
+ userSession.addPermission(PROVISION_PROJECTS, organization);
+ expectSuccessfulCallToComponentUpdater();
+
+ CreateWsResponse result = ws.newRequest()
+ .setParam("key", DEFAULT_PROJECT_KEY)
+ .setParam("name", DEFAULT_PROJECT_NAME)
+ .setParam("organization", organization.getKey())
+ .executeProtobuf(CreateWsResponse.class);
+
+ assertThat(result.getProject().getVisibility()).isEqualTo("private");
+ }
+
+ @Test
public void definition() {
WebService.Action definition = ws.getDef();
@@ -187,13 +256,26 @@ public class CreateActionTest {
Assertions.assertThat(definition.isInternal()).isFalse();
Assertions.assertThat(definition.responseExampleAsString()).isNotEmpty();
- Assertions.assertThat(definition.params()).hasSize(4);
+ Assertions.assertThat(definition.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder(
+ PARAM_VISIBILITY,
+ PARAM_ORGANIZATION,
+ PARAM_NAME,
+ PARAM_PROJECT,
+ PARAM_BRANCH
+ );
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");
+
+ WebService.Param isPrivate = definition.param(PARAM_VISIBILITY);
+ Assertions.assertThat(isPrivate.description()).isNotEmpty();
+ Assertions.assertThat(isPrivate.isInternal()).isTrue();
+ Assertions.assertThat(isPrivate.isRequired()).isFalse();
+ Assertions.assertThat(isPrivate.since()).isEqualTo("6.4");
+ Assertions.assertThat(isPrivate.possibleValues()).containsExactlyInAnyOrder("private", "public");
}
private CreateWsResponse call(CreateRequest request) {
@@ -215,7 +297,7 @@ public class CreateActionTest {
private void expectSuccessfulCallToComponentUpdater() {
when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), anyInt())).thenAnswer(invocation -> {
NewComponent newC = invocation.getArgumentAt(1, NewComponent.class);
- return new ComponentDto().setKey(newC.key()).setQualifier(newC.qualifier()).setName(newC.name());
+ return new ComponentDto().setKey(newC.key()).setQualifier(newC.qualifier()).setName(newC.name()).setPrivate(newC.isPrivate());
});
}
}
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 962e04f2150..8a03fff7c13 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
@@ -19,10 +19,14 @@
*/
package org.sonarqube.ws.client.project;
+import java.util.Optional;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Arrays.asList;
+
@Immutable
public class CreateRequest {
@@ -30,12 +34,15 @@ public class CreateRequest {
private final String key;
private final String name;
private final String branch;
+ @CheckForNull
+ private final String visibility;
private CreateRequest(Builder builder) {
this.organization = builder.organization;
this.key = builder.key;
this.name = builder.name;
this.branch = builder.branch;
+ this.visibility = builder.visibility;
}
@CheckForNull
@@ -56,6 +63,10 @@ public class CreateRequest {
return branch;
}
+ public Optional<String> getVisibility() {
+ return Optional.ofNullable(visibility);
+ }
+
public static Builder builder() {
return new Builder();
}
@@ -65,6 +76,8 @@ public class CreateRequest {
private String key;
private String name;
private String branch;
+ @CheckForNull
+ private String visibility;
private Builder() {
}
@@ -89,6 +102,12 @@ public class CreateRequest {
return this;
}
+ public Builder setVisibility(@Nullable String visibility) {
+ checkArgument(visibility == null || asList("private", "public").contains(visibility), "Unexpected visibility '" + visibility + "'");
+ this.visibility = visibility;
+ return this;
+ }
+
public CreateRequest build() {
return new CreateRequest(this);
}
diff --git a/sonar-ws/src/main/protobuf/ws-projects.proto b/sonar-ws/src/main/protobuf/ws-projects.proto
index 86ed442a8d6..2836db8c48c 100644
--- a/sonar-ws/src/main/protobuf/ws-projects.proto
+++ b/sonar-ws/src/main/protobuf/ws-projects.proto
@@ -54,6 +54,7 @@ message CreateWsResponse {
optional string key = 1;
optional string name = 2;
optional string qualifier = 3;
+ optional string visibility = 4;
}
}