]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9162 Add a flag in api/navigation/component to know if project can become private
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 27 Apr 2017 09:19:35 +0000 (11:19 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Fri, 28 Apr 2017 16:36:09 +0000 (18:36 +0200)
it/it-tests/src/test/java/it/organization/BillingTest.java
server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java
server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java

index 11a94a9f7ff89ae377977514bcb2ef3c20b6ba20..a78fdfc3a6604322b932f8f68049675e750df7e2 100644 (file)
@@ -68,12 +68,12 @@ public class BillingTest {
   public static void prepare() throws Exception {
     adminClient = newAdminWsClient(orchestrator);
     enableOrganizationsSupport();
-    resetSettings(orchestrator, "sonar.billing.preventProjectAnalysis");
   }
 
   @Before
   public void setUp() throws Exception {
     userRule.deactivateUsers(USER_LOGIN);
+    resetSettings(orchestrator, "sonar.billing.preventProjectAnalysis");
   }
 
   @AfterClass
@@ -106,7 +106,7 @@ public class BillingTest {
   }
 
   @Test
-  public void api_navigation_organization_return_canUpdateProjectsVisibilityToPrivate() {
+  public void api_navigation_organization_returns_canUpdateProjectsVisibilityToPrivate() {
     String organizationKey = createOrganization();
     userRule.createUser(USER_LOGIN, USER_LOGIN);
     adminClient.organizations().addMember(organizationKey, USER_LOGIN);
@@ -121,6 +121,19 @@ public class BillingTest {
     assertWsResponseAsUser(new GetRequest("api/navigation/organization").setParam("organization", organizationKey), "\"canUpdateProjectsVisibilityToPrivate\":false");
   }
 
+  @Test
+  public void api_navigation_component_returns_canUpdateProjectVisibilityToPrivate() {
+    String organizationKey = createOrganization();
+    String projectKey = newProjectKey();
+    executeAnalysis(projectKey, organizationKey);
+
+    setServerProperty(orchestrator, "sonar.billing.preventUpdatingProjectsVisibilityToPrivate", "false");
+    assertWsResponseAsAdmin(new GetRequest("api/navigation/component").setParam("componentKey", projectKey), "\"canUpdateProjectVisibilityToPrivate\":true");
+
+    setServerProperty(orchestrator, "sonar.billing.preventUpdatingProjectsVisibilityToPrivate", "true");
+    assertWsResponseAsAdmin(new GetRequest("api/navigation/component").setParam("componentKey", projectKey), "\"canUpdateProjectVisibilityToPrivate\":false");
+  }
+
   private static String createOrganization() {
     String key = newOrganizationKey();
     adminClient.organizations().create(new CreateWsRequest.Builder().setKey(key).setName(key).build()).getOrganization();
@@ -128,9 +141,13 @@ public class BillingTest {
   }
 
   private static String executeAnalysis(String organizationKey) {
+    return executeAnalysis(newProjectKey(), organizationKey);
+  }
+
+  private static String executeAnalysis(String projectKey, String organizationKey) {
     BuildResult buildResult = orchestrator.executeBuild(SonarScanner.create(projectDir("shared/xoo-sample"),
       "sonar.organization", organizationKey,
-      "sonar.projectKey", newProjectKey(),
+      "sonar.projectKey", projectKey,
       "sonar.login", "admin",
       "sonar.password", "admin"));
     return ItUtils.extractCeTaskId(buildResult);
index 417d9e973fa7aa121da8e8b18e86bab392ddd199..c4c47efdb6086ecadbad261ad6ffe1789ac9995d 100644 (file)
@@ -52,6 +52,8 @@ import org.sonar.db.property.PropertyDto;
 import org.sonar.db.property.PropertyQuery;
 import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.organization.BillingValidations;
+import org.sonar.server.organization.BillingValidationsProxy;
 import org.sonar.server.project.Visibility;
 import org.sonar.server.qualitygate.QualityGateFinder;
 import org.sonar.server.qualityprofile.QPMeasureData;
@@ -82,15 +84,17 @@ public class ComponentAction implements NavigationWsAction {
   private final UserSession userSession;
   private final ComponentFinder componentFinder;
   private final QualityGateFinder qualityGateFinder;
+  private final BillingValidationsProxy billingValidations;
 
   public ComponentAction(DbClient dbClient, PageRepository pageRepository, ResourceTypes resourceTypes, UserSession userSession,
-    ComponentFinder componentFinder, QualityGateFinder qualityGateFinder) {
+    ComponentFinder componentFinder, QualityGateFinder qualityGateFinder, BillingValidationsProxy billingValidations) {
     this.dbClient = dbClient;
     this.pageRepository = pageRepository;
     this.resourceTypes = resourceTypes;
     this.userSession = userSession;
     this.componentFinder = componentFinder;
     this.qualityGateFinder = qualityGateFinder;
+    this.billingValidations = billingValidations;
   }
 
   private static Consumer<QualityProfile> writeToJson(JsonWriter json) {
@@ -151,7 +155,7 @@ public class ComponentAction implements NavigationWsAction {
       if (userSession.hasComponentPermission(ADMIN, component) ||
         userSession.hasPermission(ADMINISTER_QUALITY_PROFILES, org) ||
         userSession.hasPermission(ADMINISTER_QUALITY_GATES, org)) {
-        writeConfiguration(json, component);
+        writeConfiguration(json, component, org);
       }
       writeBreadCrumbs(json, session, component);
       json.endObject().close();
@@ -219,11 +223,11 @@ public class ComponentAction implements NavigationWsAction {
     json.endArray();
   }
 
-  private void writeConfiguration(JsonWriter json, ComponentDto component) {
+  private void writeConfiguration(JsonWriter json, ComponentDto component, OrganizationDto organization) {
     boolean isProjectAdmin = userSession.hasComponentPermission(ADMIN, component);
 
     json.name("configuration").beginObject();
-    writeConfigPageAccess(json, isProjectAdmin, component);
+    writeConfigPageAccess(json, isProjectAdmin, component, organization);
 
     if (isProjectAdmin) {
       json.name("extensions").beginArray();
@@ -234,7 +238,7 @@ public class ComponentAction implements NavigationWsAction {
     json.endObject();
   }
 
-  private void writeConfigPageAccess(JsonWriter json, boolean isProjectAdmin, ComponentDto component) {
+  private void writeConfigPageAccess(JsonWriter json, boolean isProjectAdmin, ComponentDto component, OrganizationDto organization) {
     boolean isProject = Qualifiers.PROJECT.equals(component.qualifier());
     boolean showManualMeasures = isProjectAdmin && !Qualifiers.DIRECTORY.equals(component.qualifier());
     boolean isQualityProfileAdmin = userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, component.getOrganizationUuid());
@@ -251,6 +255,8 @@ public class ComponentAction implements NavigationWsAction {
     json.prop("showUpdateKey", isProjectAdmin && componentTypeHasProperty(component, PROPERTY_UPDATABLE_KEY));
     json.prop("showBackgroundTasks", isProjectAdmin);
     json.prop("canApplyPermissionTemplate", isOrganizationAdmin);
+    json.prop("canUpdateProjectVisibilityToPrivate", isProjectAdmin &&
+      billingValidations.canUpdateProjectVisibilityToPrivate(new BillingValidations.Organization(organization.getKey(), organization.getUuid())));
   }
 
   private boolean componentTypeHasProperty(ComponentDto component, String resourceTypeProperty) {
index e3b2c21cc3739ed8d9a136cc7888dc6b708b1ac9..e1d07d42b6f1948dc5fdd9a80be56f502ec92dd3 100644 (file)
@@ -54,6 +54,8 @@ import org.sonar.db.user.UserDto;
 import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.organization.BillingValidations;
+import org.sonar.server.organization.BillingValidationsProxy;
 import org.sonar.server.qualitygate.QualityGateFinder;
 import org.sonar.server.qualityprofile.QPMeasureData;
 import org.sonar.server.qualityprofile.QualityProfile;
@@ -63,6 +65,7 @@ import org.sonar.server.ws.WsActionTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.tuple;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -93,6 +96,8 @@ public class ComponentActionTest {
   private ComponentDbTester componentDbTester = dbTester.components();
   private PropertyDbTester propertyDbTester = new PropertyDbTester(dbTester);
   private ResourceTypes resourceTypes = mock(ResourceTypes.class);
+  private BillingValidationsProxy billingValidations = mock(BillingValidationsProxy.class);
+
   private ComponentDto project;
   private WsActionTester ws;
 
@@ -475,6 +480,21 @@ public class ComponentActionTest {
     assertJson(execute(project.key())).isSimilarTo("{\"configuration\": {\"canApplyPermissionTemplate\": false}}");
   }
 
+  @Test
+  public void canUpdateProjectVisibilityToPrivate_is_true_if_logged_in_as_project_administrator_and_extension_returns_false() {
+    init(createPages());
+    OrganizationDto org = dbTester.organizations().insert();
+    ComponentDto project = dbTester.components().insertPublicProject(org);
+
+    userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
+    when(billingValidations.canUpdateProjectVisibilityToPrivate(any(BillingValidations.Organization.class))).thenReturn(false);
+    assertJson(execute(project.key())).isSimilarTo("{\"configuration\": {\"canUpdateProjectVisibilityToPrivate\": false}}");
+
+    userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
+    when(billingValidations.canUpdateProjectVisibilityToPrivate(any(BillingValidations.Organization.class))).thenReturn(true);
+    assertJson(execute(project.key())).isSimilarTo("{\"configuration\": {\"canUpdateProjectVisibilityToPrivate\": true}}");
+  }
+
   private void init(Page... pages) {
     PluginRepository pluginRepository = mock(PluginRepository.class);
     when(pluginRepository.hasPlugin(anyString())).thenReturn(true);
@@ -486,7 +506,7 @@ public class ComponentActionTest {
     pageRepository.start();
     ws = new WsActionTester(
       new ComponentAction(dbClient, pageRepository, resourceTypes, userSession, new ComponentFinder(dbClient),
-        new QualityGateFinder(dbClient)));
+        new QualityGateFinder(dbClient), billingValidations));
   }
 
   private String execute(String componentKey) {