diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-04-28 10:11:18 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-04-28 18:36:09 +0200 |
commit | b700e83c77136ebacb4465d5cb403e46bb51abc8 (patch) | |
tree | 7f6942ce9afd0410019f53a8eaaf659276b81502 | |
parent | 70ff3c22c1f2da24601ec099fa48a55ca5a9f035 (diff) | |
download | sonarqube-b700e83c77136ebacb4465d5cb403e46bb51abc8.tar.gz sonarqube-b700e83c77136ebacb4465d5cb403e46bb51abc8.zip |
SONAR-9124 Allow preventing create private in api/projects/create
3 files changed, 120 insertions, 49 deletions
diff --git a/it/it-tests/src/test/java/it/organization/BillingTest.java b/it/it-tests/src/test/java/it/organization/BillingTest.java index ef90a697432..79dd8fe8ca8 100644 --- a/it/it-tests/src/test/java/it/organization/BillingTest.java +++ b/it/it-tests/src/test/java/it/organization/BillingTest.java @@ -188,6 +188,32 @@ public class BillingTest { } } + @Test + public void does_not_fail_to_create_private_project() { + String organizationKey = createOrganization(); + String projectKey = newProjectKey(); + setServerProperty(orchestrator, "sonar.billing.preventUpdatingProjectsVisibilityToPrivate", "false"); + + adminClient.projects().create(CreateRequest.builder().setKey(projectKey).setName(projectKey).setOrganization(organizationKey).setVisibility("public").build()); + + assertWsResponseAsAdmin(new GetRequest("api/navigation/component").setParam("componentKey", projectKey), "\"visibility\":\"public\""); + } + + @Test + public void fail_to_create_private_project() { + String organizationKey = createOrganization(); + String projectKey = newProjectKey(); + setServerProperty(orchestrator, "sonar.billing.preventUpdatingProjectsVisibilityToPrivate", "true"); + + try { + adminClient.projects().create(CreateRequest.builder().setKey(projectKey).setName(projectKey).setOrganization(organizationKey).setVisibility("private").build()); + fail(); + } catch (HttpException ex) { + assertThat(ex.code()).isEqualTo(400); + assertThat(ex.content()).contains(format("Organization %s cannot use private project", organizationKey)); + } + } + private static String createOrganization() { String key = newOrganizationKey(); adminClient.organizations().create(new CreateWsRequest.Builder().setKey(key).setName(key).build()).getOrganization(); 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 84974174d53..4a3c14fbb0a 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 @@ -119,6 +119,7 @@ public class CreateAction implements ProjectsWsAction { userSession.checkPermission(PROVISION_PROJECTS, organization); String visibility = request.getVisibility(); Boolean changeToPrivate = visibility == null ? dbClient.organizationDao().getNewProjectPrivate(dbSession, organization) : "private".equals(visibility); + support.checkCanUpdateProjectsVisibility(organization, changeToPrivate); ComponentDto componentDto = componentUpdater.create(dbSession, newComponentBuilder() .setOrganizationUuid(organization.getUuid()) 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 897741709cf..44b6226c6a8 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 @@ -20,6 +20,7 @@ package org.sonar.server.project.ws; import org.assertj.core.api.Assertions; +import org.assertj.core.api.AssertionsForClassTypes; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -35,6 +36,9 @@ import org.sonar.server.component.ComponentUpdater; import org.sonar.server.component.NewComponent; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.organization.BillingValidations; +import org.sonar.server.organization.BillingValidations.BillingValidationsException; +import org.sonar.server.organization.BillingValidationsProxy; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.organization.TestDefaultOrganizationProvider; import org.sonar.server.tester.UserSessionRule; @@ -46,19 +50,21 @@ import org.sonarqube.ws.client.project.CreateRequest; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; 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.Visibility.PRIVATE; -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; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_VISIBILITY; public class CreateActionTest { @@ -76,10 +82,11 @@ public class CreateActionTest { private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); private ComponentUpdater componentUpdater = mock(ComponentUpdater.class, Mockito.RETURNS_MOCKS); + private BillingValidationsProxy billingValidations = mock(BillingValidationsProxy.class); private WsActionTester ws = new WsActionTester( new CreateAction( - new ProjectsWsSupport(db.getDbClient()), + new ProjectsWsSupport(db.getDbClient(), billingValidations), db.getDbClient(), userSession, componentUpdater, defaultOrganizationProvider)); @@ -132,59 +139,41 @@ public class CreateActionTest { } @Test - public void fail_when_project_already_exists() throws Exception { + public void apply_project_visibility_public() { OrganizationDto organization = db.organizations().insert(); - when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), anyInt())).thenThrow(BadRequestException.create("already exists")); userSession.addPermission(PROVISION_PROJECTS, organization); + expectSuccessfulCallToComponentUpdater(); - expectedException.expect(BadRequestException.class); - - call(CreateRequest.builder() - .setOrganization(organization.getKey()) - .setKey(DEFAULT_PROJECT_KEY) - .setName(DEFAULT_PROJECT_NAME) - .build()); - } - - @Test - public void fail_when_missing_project_parameter() throws Exception { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("The 'project' parameter is missing"); - - call(CreateRequest.builder().setName(DEFAULT_PROJECT_NAME).build()); - } - - @Test - public void fail_when_missing_name_parameter() throws Exception { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("The 'name' parameter is missing"); - - call(CreateRequest.builder().setKey(DEFAULT_PROJECT_KEY).build()); - } - - @Test - public void fail_when_missing_create_project_permission() throws Exception { - expectedException.expect(ForbiddenException.class); + CreateWsResponse result = ws.newRequest() + .setParam("key", DEFAULT_PROJECT_KEY) + .setParam("name", DEFAULT_PROJECT_NAME) + .setParam("organization", organization.getKey()) + .setParam("visibility", "public") + .executeProtobuf(CreateWsResponse.class); - call(CreateRequest.builder().setKey(DEFAULT_PROJECT_KEY).setName(DEFAULT_PROJECT_NAME).build()); + assertThat(result.getProject().getVisibility()).isEqualTo("public"); } @Test - public void test_example() { - userSession.addPermission(PROVISION_PROJECTS, db.getDefaultOrganization()); + public void apply_project_visibility_private() { + OrganizationDto organization = db.organizations().insert(); + userSession.addPermission(PROVISION_PROJECTS, organization); expectSuccessfulCallToComponentUpdater(); - String result = ws.newRequest() + CreateWsResponse result = ws.newRequest() .setParam("key", DEFAULT_PROJECT_KEY) .setParam("name", DEFAULT_PROJECT_NAME) - .execute().getInput(); + .setParam("organization", organization.getKey()) + .setParam("visibility", PRIVATE.getLabel()) + .executeProtobuf(CreateWsResponse.class); - assertJson(result).isSimilarTo(getClass().getResource("create-example.json")); + assertThat(result.getProject().getVisibility()).isEqualTo("private"); } @Test - public void apply_project_visibility_public() { + public void apply_default_project_visibility_public() { OrganizationDto organization = db.organizations().insert(); + db.organizations().setNewProjectPrivate(organization, false); userSession.addPermission(PROVISION_PROJECTS, organization); expectSuccessfulCallToComponentUpdater(); @@ -192,15 +181,15 @@ public class CreateActionTest { .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() { + public void apply_default_project_visibility_private() { OrganizationDto organization = db.organizations().insert(); + db.organizations().setNewProjectPrivate(organization, true); userSession.addPermission(PROVISION_PROJECTS, organization); expectSuccessfulCallToComponentUpdater(); @@ -208,42 +197,97 @@ public class CreateActionTest { .setParam("key", DEFAULT_PROJECT_KEY) .setParam("name", DEFAULT_PROJECT_NAME) .setParam("organization", organization.getKey()) - .setParam("visibility", PRIVATE.getLabel()) .executeProtobuf(CreateWsResponse.class); assertThat(result.getProject().getVisibility()).isEqualTo("private"); } @Test - public void apply_default_project_visibility_public() { + public void does_not_fail_to_create_public_projects_when_organization_is_not_allowed_to_use_private_projects() { OrganizationDto organization = db.organizations().insert(); - db.organizations().setNewProjectPrivate(organization, false); userSession.addPermission(PROVISION_PROJECTS, organization); expectSuccessfulCallToComponentUpdater(); + doThrow(new BillingValidationsException("This organization cannot use project private")).when(billingValidations) + .checkCanUpdateProjectVisibility(any(BillingValidations.Organization.class), eq(true)); 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"); + AssertionsForClassTypes.assertThat(result.getProject().getVisibility()).isEqualTo("public"); } @Test - public void apply_default_project_visibility_private() { + public void fail_to_create_private_projects_when_organization_is_not_allowed_to_use_private_projects() { OrganizationDto organization = db.organizations().insert(); - db.organizations().setNewProjectPrivate(organization, true); userSession.addPermission(PROVISION_PROJECTS, organization); expectSuccessfulCallToComponentUpdater(); + doThrow(new BillingValidationsException("This organization cannot use project private")).when(billingValidations) + .checkCanUpdateProjectVisibility(any(BillingValidations.Organization.class), eq(true)); - CreateWsResponse result = ws.newRequest() + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("This organization cannot use project private"); + + 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 fail_when_project_already_exists() throws Exception { + OrganizationDto organization = db.organizations().insert(); + when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), anyInt())).thenThrow(BadRequestException.create("already exists")); + userSession.addPermission(PROVISION_PROJECTS, organization); + + expectedException.expect(BadRequestException.class); + + call(CreateRequest.builder() + .setOrganization(organization.getKey()) + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .build()); + } + + @Test + public void fail_when_missing_project_parameter() throws Exception { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("The 'project' parameter is missing"); + + call(CreateRequest.builder().setName(DEFAULT_PROJECT_NAME).build()); + } + + @Test + public void fail_when_missing_name_parameter() throws Exception { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("The 'name' parameter is missing"); + + call(CreateRequest.builder().setKey(DEFAULT_PROJECT_KEY).build()); + } + + @Test + public void fail_when_missing_create_project_permission() throws Exception { + expectedException.expect(ForbiddenException.class); + + call(CreateRequest.builder().setKey(DEFAULT_PROJECT_KEY).setName(DEFAULT_PROJECT_NAME).build()); + } + + @Test + public void test_example() { + userSession.addPermission(PROVISION_PROJECTS, db.getDefaultOrganization()); + expectSuccessfulCallToComponentUpdater(); + + String result = ws.newRequest() + .setParam("key", DEFAULT_PROJECT_KEY) + .setParam("name", DEFAULT_PROJECT_NAME) + .execute().getInput(); + + assertJson(result).isSimilarTo(getClass().getResource("create-example.json")); } @Test |