]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8761 fix cleanup of db in ITs
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 9 Feb 2017 18:23:57 +0000 (19:23 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Fri, 10 Feb 2017 22:07:22 +0000 (23:07 +0100)
it/it-tests/src/test/java/it/Category3Suite.java
it/it-tests/src/test/java/it/analysis/PermissionTest.java
it/it-tests/src/test/java/it/issue/IssueNotificationsTest.java
it/it-tests/src/test/java/it/organization/OrganizationIt.java [deleted file]
it/it-tests/src/test/java/it/organization/OrganizationTest.java [new file with mode: 0644]
it/it-tests/src/test/java/it/organization/RootTest.java [new file with mode: 0644]
it/it-tests/src/test/java/it/root/RootIt.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/platform/BackendCleanup.java
server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationFlagsImplTest.java

index 336c3d9249cd28c5133b2e32e0199c165a6f8559..6d9e32a1de21977617278b1eddc92157b0af4545 100644 (file)
@@ -34,9 +34,9 @@ import it.analysis.ScannerTest;
 import it.analysis.SettingsEncryptionTest;
 import it.analysis.TempFolderTest;
 import it.measure.DecimalScaleMetricTest;
-import it.organization.OrganizationIt;
 import it.plugins.VersionPluginTest;
-import it.root.RootIt;
+import it.organization.OrganizationTest;
+import it.organization.RootTest;
 import it.webhook.WebhooksTest;
 import org.junit.ClassRule;
 import org.junit.runner.RunWith;
@@ -65,9 +65,9 @@ import static util.ItUtils.xooPlugin;
   // measures
   DecimalScaleMetricTest.class,
   // organization
-  OrganizationIt.class,
+  OrganizationTest.class,
   // root users
-  RootIt.class,
+  RootTest.class,
   WebhooksTest.class
 })
 public class Category3Suite {
index 5ec5bca2b5666508703c31bedb0587f73edad6c8..372865fa411d2f8dc20ae2fc88e9c178a1a23f22 100644 (file)
@@ -24,16 +24,14 @@ import com.sonar.orchestrator.build.BuildResult;
 import com.sonar.orchestrator.build.SonarScanner;
 import it.Category3Suite;
 import javax.annotation.Nullable;
-import org.junit.AfterClass;
+import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.ClassRule;
+import org.junit.Rule;
 import org.junit.Test;
 import org.sonarqube.ws.WsUserTokens;
 import org.sonarqube.ws.client.WsClient;
-import org.sonarqube.ws.client.permission.AddGroupWsRequest;
 import org.sonarqube.ws.client.permission.AddUserWsRequest;
-import org.sonarqube.ws.client.permission.RemoveGroupWsRequest;
 import org.sonarqube.ws.client.usertoken.GenerateWsRequest;
 import org.sonarqube.ws.client.usertoken.RevokeWsRequest;
 import org.sonarqube.ws.client.usertoken.UserTokensService;
@@ -48,48 +46,42 @@ import static util.ItUtils.setServerProperty;
 
 public class PermissionTest {
 
-  private static final String SIMPLE_USER = "simple-user";
+  private static final String A_LOGIN = "a_login";
+  private static final String A_PASSWORD = "a_password";
 
   @ClassRule
   public static Orchestrator orchestrator = Category3Suite.ORCHESTRATOR;
 
-  @ClassRule
-  public static UserRule userRule = UserRule.from(orchestrator);
-  private static WsClient adminWsClient;
+  @Rule
+  public UserRule userRule = UserRule.from(orchestrator);
 
-  private static UserTokensService userTokensWsClient;
+  private WsClient adminWsClient;
+  private UserTokensService userTokensWsClient;
 
-  @BeforeClass
-  public static void setUp() {
-    adminWsClient = newAdminWsClient(orchestrator);
-    userTokensWsClient = adminWsClient.userTokens();
-    resetData();
-  }
+  @Before
+  public void setUp() {
+    orchestrator.resetData();
 
-  @AfterClass
-  public static void restoreAnyonePermissionToScan() throws Exception {
-    addGroupPermission("Anyone", "scan");
-  }
+    // enforce scanners to be authenticated
+    setServerProperty(orchestrator, "sonar.forceAuthentication", "true");
 
-  @Before
-  public void deleteData() {
-    resetData();
+    adminWsClient = newAdminWsClient(orchestrator);
+    userTokensWsClient = adminWsClient.userTokens();
   }
 
-  private static void resetData() {
-    orchestrator.resetData();
+  @After
+  public void tearDown() throws Exception {
     resetSettings(orchestrator, null, "sonar.forceAuthentication");
-    userRule.deactivateUsers(SIMPLE_USER);
-    removeGroupPermission("Anyone", "scan");
+    userRule.resetUsers();
   }
 
   @Test
-  public void run_analysis_with_token_authentication() {
-    userRule.createUser(SIMPLE_USER, "password");
-    addUserPermission(SIMPLE_USER, "scan", null);
-    String tokenName = "Analyze Project";
+  public void scanner_can_authenticate_with_authentication_token() {
+    createUserWithProvisioningAndScanPermissions();
+
+    String tokenName = "For test";
     WsUserTokens.GenerateWsResponse generateWsResponse = userTokensWsClient.generate(new GenerateWsRequest()
-      .setLogin(SIMPLE_USER)
+      .setLogin(A_LOGIN)
       .setName(tokenName));
     SonarScanner sampleProject = SonarScanner.create(projectDir("shared/xoo-sample"));
     sampleProject.setProperties(
@@ -99,11 +91,11 @@ public class PermissionTest {
     BuildResult buildResult = orchestrator.executeBuild(sampleProject);
 
     assertThat(buildResult.isSuccess()).isTrue();
-    userTokensWsClient.revoke(new RevokeWsRequest().setLogin(SIMPLE_USER).setName(tokenName));
+    userTokensWsClient.revoke(new RevokeWsRequest().setLogin(A_LOGIN).setName(tokenName));
   }
 
   @Test
-  public void run_analysis_with_incorrect_token() {
+  public void scanner_fails_if_authentication_token_is_not_valid() {
     SonarScanner sampleProject = SonarScanner.create(projectDir("shared/xoo-sample"));
     sampleProject.setProperties(
       "sonar.login", "unknown-token",
@@ -118,9 +110,10 @@ public class PermissionTest {
    * SONAR-4211 Test Sonar Runner when server requires authentication
    */
   @Test
-  public void should_authenticate_when_needed() {
+  public void scanner_can_authenticate_with_login_password() {
+    createUserWithProvisioningAndScanPermissions();
+
     orchestrator.getServer().provisionProject("sample", "xoo-sample");
-    setServerProperty(orchestrator, "sonar.forceAuthentication", "true");
 
     BuildResult buildResult = scanQuietly("shared/xoo-sample",
       "sonar.login", "",
@@ -138,61 +131,29 @@ public class PermissionTest {
       "Not authorized. Please check the properties sonar.login and sonar.password.");
 
     buildResult = scan("shared/xoo-sample",
-      "sonar.login", "admin",
-      "sonar.password", "admin");
+      "sonar.login", A_LOGIN,
+      "sonar.password", A_PASSWORD);
     assertThat(buildResult.getLastStatus()).isEqualTo(0);
   }
 
   @Test
-  public void run_analysis_with_authenticated_user_having_global_execute_analysis_permission() throws Exception {
-    userRule.createUser(SIMPLE_USER, "password");
+  public void run_scanner_with_user_having_scan_permission_only_on_project() throws Exception {
+    userRule.createUser(A_LOGIN, A_PASSWORD);
     orchestrator.getServer().provisionProject("sample", "sample");
-    addUserPermission(SIMPLE_USER, "scan", null);
+    addUserPermission(A_LOGIN, "scan", "sample");
 
-    BuildResult buildResult = scanQuietly("shared/xoo-sample", "sonar.login", SIMPLE_USER, "sonar.password", "password");
+    BuildResult buildResult = scanQuietly("shared/xoo-sample", "sonar.login", A_LOGIN, "sonar.password", A_PASSWORD);
 
     assertThat(buildResult.isSuccess()).isTrue();
   }
 
-  @Test
-  public void run_analysis_with_authenticated_user_having_execute_analysis_permission_only_on_project() throws Exception {
-    userRule.createUser(SIMPLE_USER, "password");
-    orchestrator.getServer().provisionProject("sample", "sample");
-    addUserPermission(SIMPLE_USER, "scan", "sample");
-
-    BuildResult buildResult = scanQuietly("shared/xoo-sample", "sonar.login", SIMPLE_USER, "sonar.password", "password");
-
-    assertThat(buildResult.isSuccess()).isTrue();
-  }
-
-  @Test
-  public void run_analysis_when_execute_analysis_is_set_to_anyone() throws Exception {
-    addGroupPermission("Anyone", "scan");
-
-    BuildResult buildResult = scanQuietly("shared/xoo-sample");
-
-    assertThat(buildResult.isSuccess()).isTrue();
-  }
-
-  private static void addUserPermission(String login, String permission, @Nullable String projectKey) {
+  private void addUserPermission(String login, String permission, @Nullable String projectKey) {
     adminWsClient.permissions().addUser(new AddUserWsRequest()
       .setLogin(login)
       .setPermission(permission)
       .setProjectKey(projectKey));
   }
 
-  private static void addGroupPermission(String groupName, String permission) {
-    adminWsClient.permissions().addGroup(new AddGroupWsRequest()
-      .setGroupName(groupName)
-      .setPermission(permission));
-  }
-
-  private static void removeGroupPermission(String groupName, String permission) {
-    adminWsClient.permissions().removeGroup(new RemoveGroupWsRequest()
-      .setGroupName(groupName)
-      .setPermission(permission));
-  }
-
   private BuildResult scan(String projectPath, String... props) {
     SonarScanner scanner = configureScanner(projectPath, props);
     return orchestrator.executeBuild(scanner);
@@ -207,4 +168,11 @@ public class PermissionTest {
     return SonarScanner.create(ItUtils.projectDir(projectPath))
       .setProperties(props);
   }
+
+  private void createUserWithProvisioningAndScanPermissions() {
+    userRule.createUser(A_LOGIN, A_PASSWORD);
+    addUserPermission(A_LOGIN, "provisioning", null);
+    addUserPermission(A_LOGIN, "scan", null);
+  }
+
 }
index b16e6b13ca41385ceee3b6b63026d6733bb1ffda..b5f15e8e7377e9c129cabb88a6c77e35cf10a672 100644 (file)
@@ -74,30 +74,12 @@ public class IssueNotificationsTest extends AbstractIssueTest {
     setServerProperty(ORCHESTRATOR, "email.smtp_host.secured", "localhost");
     setServerProperty(ORCHESTRATOR, "email.smtp_port.secured", Integer.toString(smtpServer.getServer().getPort()));
 
-    // Create test user
-    userRule.createUser(USER_LOGIN, "Tester", USER_EMAIL, USER_LOGIN);
-
     // Send test email to the test user
     newAdminWsClient(ORCHESTRATOR).wsConnector().call(new PostRequest("api/emails/send")
       .setParam("to", USER_EMAIL)
       .setParam("message", "This is a test message from SonarQube"))
       .failIfNotSuccessful();
 
-    // Add notifications to the test user
-    WsClient wsClient = newUserWsClient(ORCHESTRATOR, USER_LOGIN, USER_PASSWORD);
-    wsClient.wsConnector().call(new PostRequest("api/notifications/add")
-      .setParam("type", "NewIssues")
-      .setParam("channel", "EmailNotificationChannel"))
-      .failIfNotSuccessful();
-    wsClient.wsConnector().call(new PostRequest("api/notifications/add")
-      .setParam("type", "ChangesOnMyIssue")
-      .setParam("channel", "EmailNotificationChannel"))
-      .failIfNotSuccessful();
-    wsClient.wsConnector().call(new PostRequest("api/notifications/add")
-      .setParam("type", "SQ-MyNewIssues")
-      .setParam("channel", "EmailNotificationChannel"))
-      .failIfNotSuccessful();
-
     // We need to wait until all notifications will be delivered
     waitUntilAllNotificationsAreDelivered(1);
 
@@ -123,6 +105,10 @@ public class IssueNotificationsTest extends AbstractIssueTest {
   @Before
   public void prepare() {
     ORCHESTRATOR.resetData();
+
+    // Create test user
+    userRule.createUser(USER_LOGIN, "Tester", USER_EMAIL, USER_LOGIN);
+
     smtpServer.getMessages().clear();
     issueClient = ORCHESTRATOR.getServer().adminWsClient().issueClient();
     issuesService = newAdminWsClient(ORCHESTRATOR).issues();
@@ -131,6 +117,22 @@ public class IssueNotificationsTest extends AbstractIssueTest {
     ORCHESTRATOR.getServer().restoreProfile(FileLocation.ofClasspath("/issue/one-issue-per-line-profile.xml"));
     ORCHESTRATOR.getServer().provisionProject(PROJECT_KEY, "Sample");
     ORCHESTRATOR.getServer().associateProjectToQualityProfile(PROJECT_KEY, "xoo", "one-issue-per-line-profile");
+
+    // Add notifications to the test user
+    WsClient wsClient = newUserWsClient(ORCHESTRATOR, USER_LOGIN, USER_PASSWORD);
+    wsClient.wsConnector().call(new PostRequest("api/notifications/add")
+      .setParam("type", "NewIssues")
+      .setParam("channel", "EmailNotificationChannel"))
+      .failIfNotSuccessful();
+    wsClient.wsConnector().call(new PostRequest("api/notifications/add")
+      .setParam("type", "ChangesOnMyIssue")
+      .setParam("channel", "EmailNotificationChannel"))
+      .failIfNotSuccessful();
+    wsClient.wsConnector().call(new PostRequest("api/notifications/add")
+      .setParam("type", "SQ-MyNewIssues")
+      .setParam("channel", "EmailNotificationChannel"))
+      .failIfNotSuccessful();
+
   }
 
   @Test
diff --git a/it/it-tests/src/test/java/it/organization/OrganizationIt.java b/it/it-tests/src/test/java/it/organization/OrganizationIt.java
deleted file mode 100644 (file)
index f88a29e..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package it.organization;
-
-import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.build.BuildFailureException;
-import it.Category3Suite;
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonarqube.ws.Organizations;
-import org.sonarqube.ws.WsComponents;
-import org.sonarqube.ws.client.HttpException;
-import org.sonarqube.ws.client.component.ComponentsService;
-import org.sonarqube.ws.client.organization.CreateWsRequest;
-import org.sonarqube.ws.client.organization.OrganizationService;
-import org.sonarqube.ws.client.organization.SearchWsRequest;
-import org.sonarqube.ws.client.organization.UpdateWsRequest;
-import org.sonarqube.ws.client.permission.AddUserWsRequest;
-import org.sonarqube.ws.client.permission.PermissionsService;
-import util.ItUtils;
-import util.user.GroupManagement;
-import util.user.Groups;
-import util.user.UserRule;
-
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-
-public class OrganizationIt {
-  private static final String DEFAULT_ORGANIZATION_KEY = "default-organization";
-  private static final String NAME = "Foo Company";
-  private static final String KEY = "foo-company";
-  private static final String DESCRIPTION = "the description of Foo company";
-  private static final String URL = "https://www.foo.fr";
-  private static final String AVATAR_URL = "https://www.foo.fr/corporate_logo.png";
-  private static final String SETTING_ANYONE_CAN_CREATE_ORGANIZATIONS = "sonar.organizations.anyoneCanCreate";
-
-  @ClassRule
-  public static Orchestrator orchestrator = Category3Suite.ORCHESTRATOR;
-  @ClassRule
-  public static UserRule userRule = UserRule.from(orchestrator);
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  private OrganizationService anonymousOrganizationService = ItUtils.newWsClient(orchestrator).organizations();
-  private OrganizationService adminOrganizationService = ItUtils.newAdminWsClient(orchestrator).organizations();
-
-  @Before
-  public void setUp() throws Exception {
-    orchestrator.resetData();
-    userRule.resetUsers();
-    ItUtils.resetSettings(orchestrator, null, SETTING_ANYONE_CAN_CREATE_ORGANIZATIONS);
-  }
-
-  @Test
-  public void create_update_delete_organizations_and_check_security() {
-    verifyNoExtraOrganization();
-
-    Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder()
-      .setName(NAME)
-      .setKey(KEY)
-      .setDescription(DESCRIPTION)
-      .setUrl(URL)
-      .setAvatar(AVATAR_URL)
-      .build())
-      .getOrganization();
-    assertThat(createdOrganization.getName()).isEqualTo(NAME);
-    assertThat(createdOrganization.getKey()).isEqualTo(KEY);
-    assertThat(createdOrganization.getDescription()).isEqualTo(DESCRIPTION);
-    assertThat(createdOrganization.getUrl()).isEqualTo(URL);
-    assertThat(createdOrganization.getAvatar()).isEqualTo(AVATAR_URL);
-
-    verifySingleSearchResult(createdOrganization, NAME, DESCRIPTION, URL, AVATAR_URL);
-
-    // update by id
-    adminOrganizationService.update(new UpdateWsRequest.Builder()
-      .setKey(createdOrganization.getKey())
-      .setName("new name")
-      .setDescription("new description")
-      .setUrl("new url")
-      .setAvatar("new avatar url")
-      .build());
-    verifySingleSearchResult(createdOrganization, "new name", "new description", "new url", "new avatar url");
-
-    // update by key
-    adminOrganizationService.update(new UpdateWsRequest.Builder()
-      .setKey(createdOrganization.getKey())
-      .setName("new name 2")
-      .setDescription("new description 2")
-      .setUrl("new url 2")
-      .setAvatar("new avatar url 2")
-      .build());
-    verifySingleSearchResult(createdOrganization, "new name 2", "new description 2", "new url 2", "new avatar url 2");
-
-    // remove optional fields
-    adminOrganizationService.update(new UpdateWsRequest.Builder()
-      .setKey(createdOrganization.getKey())
-      .setName("new name 3")
-      .setDescription("")
-      .setUrl("")
-      .setAvatar("")
-      .build());
-    verifySingleSearchResult(createdOrganization, "new name 3", null, null, null);
-
-    // delete organization
-    adminOrganizationService.delete(createdOrganization.getKey());
-    verifyNoExtraOrganization();
-
-    adminOrganizationService.create(new CreateWsRequest.Builder()
-      .setName(NAME)
-      .setKey(KEY)
-      .build())
-      .getOrganization();
-    verifySingleSearchResult(createdOrganization, NAME, null, null, null);
-
-    // verify anonymous can't create update nor delete an organization by default
-    verifyAnonymousNotAuthorized(service -> service.create(new CreateWsRequest.Builder().setName("An org").build()));
-    verifyUserNotAuthenticated(service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build()));
-    verifyUserNotAuthenticated(service -> service.delete(KEY));
-
-    // verify logged in user without any permission can't create update nor delete an organization by default
-    userRule.createUser("john", "doh");
-    verifyUserNotAuthorized("john", "doh", service -> service.create(new CreateWsRequest.Builder().setName("An org").build()));
-    verifyUserNotAuthorized("john", "doh", service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build()));
-    verifyUserNotAuthorized("john", "doh", service -> service.delete(KEY));
-
-    ItUtils.setServerProperty(orchestrator, SETTING_ANYONE_CAN_CREATE_ORGANIZATIONS, "true");
-    // verify anonymous still can't create update nor delete an organization if property is true
-    verifyUserNotAuthenticated(service -> service.create(new CreateWsRequest.Builder().setName("An org").build()));
-    verifyUserNotAuthenticated(service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build()));
-    verifyUserNotAuthenticated(service -> service.delete(KEY));
-
-    // verify logged in user without any permission can't create nor update nor delete an organization if property is true
-    verifyUserNotAuthorized("john", "doh", service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build()));
-    verifyUserNotAuthorized("john", "doh", service -> service.delete(KEY));
-    // clean-up
-    adminOrganizationService.delete(KEY);
-    verifySingleSearchResult(
-      verifyUserAuthorized("john", "doh", service -> service.create(new CreateWsRequest.Builder().setName("An org").build())).getOrganization(),
-      "An org", null, null, null);
-
-    // clean-up
-    adminOrganizationService.delete("an-org");
-  }
-
-  private void verifyAnonymousNotAuthorized(Consumer<OrganizationService> consumer) {
-    try {
-      consumer.accept(anonymousOrganizationService);
-      fail("An HttpException should have been raised");
-    } catch (HttpException e) {
-      assertThat(e.code()).isEqualTo(403);
-    }
-  }
-
-  private void verifyUserNotAuthenticated(Consumer<OrganizationService> consumer) {
-    try {
-      consumer.accept(anonymousOrganizationService);
-      fail("An HttpException should have been raised");
-    } catch (HttpException e) {
-      assertThat(e.code()).isEqualTo(401);
-    }
-  }
-
-  private void verifyUserNotAuthorized(String login, String password, Consumer<OrganizationService> consumer) {
-    try {
-      OrganizationService organizationService = ItUtils.newUserWsClient(orchestrator, login, password).organizations();
-      consumer.accept(organizationService);
-      fail("An HttpException should have been raised");
-    } catch (HttpException e) {
-      assertThat(e.code()).isEqualTo(403);
-    }
-  }
-
-  private <T> T verifyUserAuthorized(String login, String password, Function<OrganizationService, T> consumer) {
-    OrganizationService organizationService = ItUtils.newUserWsClient(orchestrator, login, password).organizations();
-    return consumer.apply(organizationService);
-  }
-
-  @Test
-  public void create_generates_key_from_name() {
-    // create organization without key
-    String name = "Foo  Company to keyize";
-    String expectedKey = "foo-company-to-keyize";
-    Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder()
-      .setName(name)
-      .build())
-      .getOrganization();
-    assertThat(createdOrganization.getKey()).isEqualTo(expectedKey);
-    verifySingleSearchResult(createdOrganization, name, null, null, null);
-
-    // clean-up
-    adminOrganizationService.delete(expectedKey);
-  }
-
-  @Test
-  public void default_organization_can_not_be_deleted() {
-    try {
-      adminOrganizationService.delete(DEFAULT_ORGANIZATION_KEY);
-      fail("a HttpException should have been raised");
-    } catch (HttpException e) {
-      assertThat(e.code()).isEqualTo(400);
-    }
-  }
-
-  @Test
-  public void create_fails_if_user_is_not_root() {
-    userRule.createUser("foo", "bar");
-
-    CreateWsRequest createWsRequest = new CreateWsRequest.Builder()
-      .setName("bla bla")
-      .build();
-    OrganizationService fooUserOrganizationService = ItUtils.newUserWsClient(orchestrator, "foo", "bar").organizations();
-
-    expect403HttpError(() -> fooUserOrganizationService.create(createWsRequest));
-
-    userRule.setRoot("foo");
-    assertThat(fooUserOrganizationService.create(createWsRequest).getOrganization().getKey()).isEqualTo("bla-bla");
-
-    // delete org, attempt recreate when no root anymore and ensure it can't anymore
-    fooUserOrganizationService.delete("bla-bla");
-    userRule.unsetRoot("foo");
-    expect403HttpError(() -> fooUserOrganizationService.create(createWsRequest));
-  }
-
-  @Test
-  public void an_organization_member_can_analyze_project() {
-    verifyNoExtraOrganization();
-
-    String orgKeyAndName = "org-key";
-    Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder()
-      .setName(orgKeyAndName)
-      .setKey(orgKeyAndName)
-      .build())
-      .getOrganization();
-    verifySingleSearchResult(createdOrganization, orgKeyAndName, null, null, null);
-
-    userRule.createUser("bob", "bob");
-    userRule.removeGroups("sonar-users");
-    addPermissionsToUser(orgKeyAndName, "bob", "provisioning", "scan");
-
-    ItUtils.runProjectAnalysis(orchestrator, "shared/xoo-sample",
-      "sonar.organization", orgKeyAndName, "sonar.login", "bob", "sonar.password", "bob");
-    ComponentsService componentsService = ItUtils.newAdminWsClient(orchestrator).components();
-    assertThat(searchSampleProject(orgKeyAndName, componentsService).getComponentsList()).hasSize(1);
-
-    adminOrganizationService.delete(orgKeyAndName);
-  }
-
-  @Test
-  public void by_default_anonymous_cannot_analyse_project_on_organization() {
-    verifyNoExtraOrganization();
-
-    String orgKeyAndName = "org-key";
-    Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder()
-      .setName(orgKeyAndName)
-      .setKey(orgKeyAndName)
-      .build())
-      .getOrganization();
-    verifySingleSearchResult(createdOrganization, orgKeyAndName, null, null, null);
-
-    try {
-      ItUtils.runProjectAnalysis(orchestrator, "shared/xoo-sample",
-        "sonar.organization", orgKeyAndName);
-      fail();
-    } catch (BuildFailureException e) {
-      assertThat(e.getResult().getLogs()).contains("Insufficient privileges");
-    }
-
-    ComponentsService componentsService = ItUtils.newAdminWsClient(orchestrator).components();
-    assertThat(searchSampleProject(orgKeyAndName, componentsService).getComponentsCount()).isEqualTo(0);
-    adminOrganizationService.delete(orgKeyAndName);
-  }
-
-  private void addPermissionsToUser(String orgKeyAndName, String login, String permission, String... otherPermissions) {
-    PermissionsService permissionsService = ItUtils.newAdminWsClient(orchestrator).permissions();
-    permissionsService.addUser(new AddUserWsRequest().setLogin(login).setOrganization(orgKeyAndName).setPermission(permission));
-    for (String otherPermission : otherPermissions) {
-      permissionsService.addUser(new AddUserWsRequest().setLogin(login).setOrganization(orgKeyAndName).setPermission(otherPermission));
-    }
-  }
-
-  @Test
-  public void deleting_an_organization_also_deletes_group_permissions_and_projects_and_check_security() {
-    verifyNoExtraOrganization();
-
-    String orgKeyAndName = "org-key";
-    Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder()
-      .setName(orgKeyAndName)
-      .setKey(orgKeyAndName)
-      .build())
-      .getOrganization();
-    verifySingleSearchResult(createdOrganization, orgKeyAndName, null, null, null);
-
-    GroupManagement groupManagement = userRule.forOrganization(orgKeyAndName);
-
-    userRule.createUser("bob", "bob");
-    groupManagement.createGroup("grp1");
-    groupManagement.createGroup("grp2");
-    groupManagement.associateGroupsToUser("bob", "grp1", "grp2");
-    assertThat(groupManagement.getUserGroups("bob").getGroups())
-      .extracting(Groups.Group::getName)
-      .contains("grp1", "grp2");
-    addPermissionsToUser(orgKeyAndName, "bob", "provisioning", "scan");
-
-    ItUtils.runProjectAnalysis(orchestrator, "shared/xoo-sample",
-      "sonar.organization", orgKeyAndName, "sonar.login", "bob", "sonar.password", "bob");
-    ComponentsService componentsService = ItUtils.newAdminWsClient(orchestrator).components();
-    assertThat(searchSampleProject(orgKeyAndName, componentsService).getComponentsList()).hasSize(1);
-
-    adminOrganizationService.delete(orgKeyAndName);
-
-    expect404HttpError(() -> searchSampleProject(orgKeyAndName, componentsService));
-    assertThat(groupManagement.getUserGroups("bob").getGroups())
-      .extracting(Groups.Group::getName)
-      .doesNotContain("grp1", "grp2");
-
-    verifyNoExtraOrganization();
-  }
-
-  private WsComponents.SearchWsResponse searchSampleProject(String organizationKey, ComponentsService componentsService) {
-    return componentsService
-      .search(new org.sonarqube.ws.client.component.SearchWsRequest()
-        .setOrganization(organizationKey)
-        .setQualifiers(singletonList("TRK"))
-        .setQuery("sample"));
-  }
-
-  private void expect403HttpError(Runnable runnable) {
-    try {
-      runnable.run();
-      fail("Ws call should have failed");
-    } catch (HttpException e) {
-      assertThat(e.code()).isEqualTo(403);
-    }
-  }
-
-  private void expect404HttpError(Runnable runnable) {
-    try {
-      runnable.run();
-      fail("Ws call should have failed");
-    } catch (HttpException e) {
-      assertThat(e.code()).isEqualTo(404);
-    }
-  }
-
-  private void verifyNoExtraOrganization() {
-    Organizations.SearchWsResponse searchWsResponse = anonymousOrganizationService.search(new SearchWsRequest.Builder().build());
-    List<Organizations.Organization> organizationsList = searchWsResponse.getOrganizationsList();
-    assertThat(organizationsList).hasSize(1);
-    assertThat(organizationsList.iterator().next().getKey()).isEqualTo(DEFAULT_ORGANIZATION_KEY);
-  }
-
-  private void verifySingleSearchResult(Organizations.Organization createdOrganization, String name, String description, String url,
-    String avatarUrl) {
-    List<Organizations.Organization> organizations = anonymousOrganizationService.search(new SearchWsRequest.Builder()
-        .build()).getOrganizationsList();
-    assertThat(organizations).hasSize(2);
-    Organizations.Organization searchedOrganization = organizations.stream()
-      .filter(organization -> !DEFAULT_ORGANIZATION_KEY.equals(organization.getKey()))
-      .findFirst()
-      .get();
-    assertThat(searchedOrganization.getKey()).isEqualTo(createdOrganization.getKey());
-    assertThat(searchedOrganization.getName()).isEqualTo(name);
-    if (description == null) {
-      assertThat(searchedOrganization.hasDescription()).isFalse();
-    } else {
-      assertThat(searchedOrganization.getDescription()).isEqualTo(description);
-    }
-    if (url == null) {
-      assertThat(searchedOrganization.hasUrl()).isFalse();
-    } else {
-      assertThat(searchedOrganization.getUrl()).isEqualTo(url);
-    }
-    if (avatarUrl == null) {
-      assertThat(searchedOrganization.hasAvatar()).isFalse();
-    } else {
-      assertThat(searchedOrganization.getAvatar()).isEqualTo(avatarUrl);
-    }
-  }
-}
diff --git a/it/it-tests/src/test/java/it/organization/OrganizationTest.java b/it/it-tests/src/test/java/it/organization/OrganizationTest.java
new file mode 100644 (file)
index 0000000..aa348ee
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package it.organization;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.BuildFailureException;
+import it.Category3Suite;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonarqube.ws.Organizations;
+import org.sonarqube.ws.WsComponents;
+import org.sonarqube.ws.client.HttpException;
+import org.sonarqube.ws.client.component.ComponentsService;
+import org.sonarqube.ws.client.organization.CreateWsRequest;
+import org.sonarqube.ws.client.organization.OrganizationService;
+import org.sonarqube.ws.client.organization.SearchWsRequest;
+import org.sonarqube.ws.client.organization.UpdateWsRequest;
+import org.sonarqube.ws.client.permission.AddUserWsRequest;
+import org.sonarqube.ws.client.permission.PermissionsService;
+import util.ItUtils;
+import util.user.GroupManagement;
+import util.user.Groups;
+import util.user.UserRule;
+
+import static java.util.Collections.singletonList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+
+public class OrganizationTest {
+  private static final String DEFAULT_ORGANIZATION_KEY = "default-organization";
+  private static final String NAME = "Foo Company";
+  private static final String KEY = "foo-company";
+  private static final String DESCRIPTION = "the description of Foo company";
+  private static final String URL = "https://www.foo.fr";
+  private static final String AVATAR_URL = "https://www.foo.fr/corporate_logo.png";
+  private static final String SETTING_ANYONE_CAN_CREATE_ORGANIZATIONS = "sonar.organizations.anyoneCanCreate";
+
+  @ClassRule
+  public static Orchestrator orchestrator = Category3Suite.ORCHESTRATOR;
+  @ClassRule
+  public static UserRule userRule = UserRule.from(orchestrator);
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private OrganizationService anonymousOrganizationService = ItUtils.newWsClient(orchestrator).organizations();
+  private OrganizationService adminOrganizationService = ItUtils.newAdminWsClient(orchestrator).organizations();
+
+  @Before
+  public void setUp() throws Exception {
+    orchestrator.resetData();
+    userRule.resetUsers();
+    ItUtils.resetSettings(orchestrator, null, SETTING_ANYONE_CAN_CREATE_ORGANIZATIONS);
+    orchestrator.getServer().post("api/organizations/enable_support", Collections.emptyMap());
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    orchestrator.resetData();
+  }
+
+  @Test
+  public void create_update_delete_organizations_and_check_security() {
+    verifyNoExtraOrganization();
+
+    Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder()
+      .setName(NAME)
+      .setKey(KEY)
+      .setDescription(DESCRIPTION)
+      .setUrl(URL)
+      .setAvatar(AVATAR_URL)
+      .build())
+      .getOrganization();
+    assertThat(createdOrganization.getName()).isEqualTo(NAME);
+    assertThat(createdOrganization.getKey()).isEqualTo(KEY);
+    assertThat(createdOrganization.getDescription()).isEqualTo(DESCRIPTION);
+    assertThat(createdOrganization.getUrl()).isEqualTo(URL);
+    assertThat(createdOrganization.getAvatar()).isEqualTo(AVATAR_URL);
+
+    verifySingleSearchResult(createdOrganization, NAME, DESCRIPTION, URL, AVATAR_URL);
+
+    // update by id
+    adminOrganizationService.update(new UpdateWsRequest.Builder()
+      .setKey(createdOrganization.getKey())
+      .setName("new name")
+      .setDescription("new description")
+      .setUrl("new url")
+      .setAvatar("new avatar url")
+      .build());
+    verifySingleSearchResult(createdOrganization, "new name", "new description", "new url", "new avatar url");
+
+    // update by key
+    adminOrganizationService.update(new UpdateWsRequest.Builder()
+      .setKey(createdOrganization.getKey())
+      .setName("new name 2")
+      .setDescription("new description 2")
+      .setUrl("new url 2")
+      .setAvatar("new avatar url 2")
+      .build());
+    verifySingleSearchResult(createdOrganization, "new name 2", "new description 2", "new url 2", "new avatar url 2");
+
+    // remove optional fields
+    adminOrganizationService.update(new UpdateWsRequest.Builder()
+      .setKey(createdOrganization.getKey())
+      .setName("new name 3")
+      .setDescription("")
+      .setUrl("")
+      .setAvatar("")
+      .build());
+    verifySingleSearchResult(createdOrganization, "new name 3", null, null, null);
+
+    // delete organization
+    adminOrganizationService.delete(createdOrganization.getKey());
+    verifyNoExtraOrganization();
+
+    adminOrganizationService.create(new CreateWsRequest.Builder()
+      .setName(NAME)
+      .setKey(KEY)
+      .build())
+      .getOrganization();
+    verifySingleSearchResult(createdOrganization, NAME, null, null, null);
+
+    // verify anonymous can't create update nor delete an organization by default
+    verifyAnonymousNotAuthorized(service -> service.create(new CreateWsRequest.Builder().setName("An org").build()));
+    verifyUserNotAuthenticated(service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build()));
+    verifyUserNotAuthenticated(service -> service.delete(KEY));
+
+    // verify logged in user without any permission can't create update nor delete an organization by default
+    userRule.createUser("john", "doh");
+    verifyUserNotAuthorized("john", "doh", service -> service.create(new CreateWsRequest.Builder().setName("An org").build()));
+    verifyUserNotAuthorized("john", "doh", service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build()));
+    verifyUserNotAuthorized("john", "doh", service -> service.delete(KEY));
+
+    ItUtils.setServerProperty(orchestrator, SETTING_ANYONE_CAN_CREATE_ORGANIZATIONS, "true");
+    // verify anonymous still can't create update nor delete an organization if property is true
+    verifyUserNotAuthenticated(service -> service.create(new CreateWsRequest.Builder().setName("An org").build()));
+    verifyUserNotAuthenticated(service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build()));
+    verifyUserNotAuthenticated(service -> service.delete(KEY));
+
+    // verify logged in user without any permission can't create nor update nor delete an organization if property is true
+    verifyUserNotAuthorized("john", "doh", service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build()));
+    verifyUserNotAuthorized("john", "doh", service -> service.delete(KEY));
+    // clean-up
+    adminOrganizationService.delete(KEY);
+    verifySingleSearchResult(
+      verifyUserAuthorized("john", "doh", service -> service.create(new CreateWsRequest.Builder().setName("An org").build())).getOrganization(),
+      "An org", null, null, null);
+
+    // clean-up
+    adminOrganizationService.delete("an-org");
+  }
+
+  private void verifyAnonymousNotAuthorized(Consumer<OrganizationService> consumer) {
+    try {
+      consumer.accept(anonymousOrganizationService);
+      fail("An HttpException should have been raised");
+    } catch (HttpException e) {
+      assertThat(e.code()).isEqualTo(403);
+    }
+  }
+
+  private void verifyUserNotAuthenticated(Consumer<OrganizationService> consumer) {
+    try {
+      consumer.accept(anonymousOrganizationService);
+      fail("An HttpException should have been raised");
+    } catch (HttpException e) {
+      assertThat(e.code()).isEqualTo(401);
+    }
+  }
+
+  private void verifyUserNotAuthorized(String login, String password, Consumer<OrganizationService> consumer) {
+    try {
+      OrganizationService organizationService = ItUtils.newUserWsClient(orchestrator, login, password).organizations();
+      consumer.accept(organizationService);
+      fail("An HttpException should have been raised");
+    } catch (HttpException e) {
+      assertThat(e.code()).isEqualTo(403);
+    }
+  }
+
+  private <T> T verifyUserAuthorized(String login, String password, Function<OrganizationService, T> consumer) {
+    OrganizationService organizationService = ItUtils.newUserWsClient(orchestrator, login, password).organizations();
+    return consumer.apply(organizationService);
+  }
+
+  @Test
+  public void create_generates_key_from_name() {
+    // create organization without key
+    String name = "Foo  Company to keyize";
+    String expectedKey = "foo-company-to-keyize";
+    Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder()
+      .setName(name)
+      .build())
+      .getOrganization();
+    assertThat(createdOrganization.getKey()).isEqualTo(expectedKey);
+    verifySingleSearchResult(createdOrganization, name, null, null, null);
+
+    // clean-up
+    adminOrganizationService.delete(expectedKey);
+  }
+
+  @Test
+  public void default_organization_can_not_be_deleted() {
+    try {
+      adminOrganizationService.delete(DEFAULT_ORGANIZATION_KEY);
+      fail("a HttpException should have been raised");
+    } catch (HttpException e) {
+      assertThat(e.code()).isEqualTo(400);
+    }
+  }
+
+  @Test
+  public void create_fails_if_user_is_not_root() {
+    userRule.createUser("foo", "bar");
+
+    CreateWsRequest createWsRequest = new CreateWsRequest.Builder()
+      .setName("bla bla")
+      .build();
+    OrganizationService fooUserOrganizationService = ItUtils.newUserWsClient(orchestrator, "foo", "bar").organizations();
+
+    expect403HttpError(() -> fooUserOrganizationService.create(createWsRequest));
+
+    userRule.setRoot("foo");
+    assertThat(fooUserOrganizationService.create(createWsRequest).getOrganization().getKey()).isEqualTo("bla-bla");
+
+    // delete org, attempt recreate when no root anymore and ensure it can't anymore
+    fooUserOrganizationService.delete("bla-bla");
+    userRule.unsetRoot("foo");
+    expect403HttpError(() -> fooUserOrganizationService.create(createWsRequest));
+  }
+
+  @Test
+  public void an_organization_member_can_analyze_project() {
+    verifyNoExtraOrganization();
+
+    String orgKeyAndName = "org-key";
+    Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder()
+      .setName(orgKeyAndName)
+      .setKey(orgKeyAndName)
+      .build())
+      .getOrganization();
+    verifySingleSearchResult(createdOrganization, orgKeyAndName, null, null, null);
+
+    userRule.createUser("bob", "bob");
+    userRule.removeGroups("sonar-users");
+    addPermissionsToUser(orgKeyAndName, "bob", "provisioning", "scan");
+
+    ItUtils.runProjectAnalysis(orchestrator, "shared/xoo-sample",
+      "sonar.organization", orgKeyAndName, "sonar.login", "bob", "sonar.password", "bob");
+    ComponentsService componentsService = ItUtils.newAdminWsClient(orchestrator).components();
+    assertThat(searchSampleProject(orgKeyAndName, componentsService).getComponentsList()).hasSize(1);
+
+    adminOrganizationService.delete(orgKeyAndName);
+  }
+
+  @Test
+  public void by_default_anonymous_cannot_analyse_project_on_organization() {
+    verifyNoExtraOrganization();
+
+    String orgKeyAndName = "org-key";
+    Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder()
+      .setName(orgKeyAndName)
+      .setKey(orgKeyAndName)
+      .build())
+      .getOrganization();
+    verifySingleSearchResult(createdOrganization, orgKeyAndName, null, null, null);
+
+    try {
+      ItUtils.runProjectAnalysis(orchestrator, "shared/xoo-sample",
+        "sonar.organization", orgKeyAndName);
+      fail();
+    } catch (BuildFailureException e) {
+      assertThat(e.getResult().getLogs()).contains("Insufficient privileges");
+    }
+
+    ComponentsService componentsService = ItUtils.newAdminWsClient(orchestrator).components();
+    assertThat(searchSampleProject(orgKeyAndName, componentsService).getComponentsCount()).isEqualTo(0);
+    adminOrganizationService.delete(orgKeyAndName);
+  }
+
+  private void addPermissionsToUser(String orgKeyAndName, String login, String permission, String... otherPermissions) {
+    PermissionsService permissionsService = ItUtils.newAdminWsClient(orchestrator).permissions();
+    permissionsService.addUser(new AddUserWsRequest().setLogin(login).setOrganization(orgKeyAndName).setPermission(permission));
+    for (String otherPermission : otherPermissions) {
+      permissionsService.addUser(new AddUserWsRequest().setLogin(login).setOrganization(orgKeyAndName).setPermission(otherPermission));
+    }
+  }
+
+  @Test
+  public void deleting_an_organization_also_deletes_group_permissions_and_projects_and_check_security() {
+    verifyNoExtraOrganization();
+
+    String orgKeyAndName = "org-key";
+    Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder()
+      .setName(orgKeyAndName)
+      .setKey(orgKeyAndName)
+      .build())
+      .getOrganization();
+    verifySingleSearchResult(createdOrganization, orgKeyAndName, null, null, null);
+
+    GroupManagement groupManagement = userRule.forOrganization(orgKeyAndName);
+
+    userRule.createUser("bob", "bob");
+    groupManagement.createGroup("grp1");
+    groupManagement.createGroup("grp2");
+    groupManagement.associateGroupsToUser("bob", "grp1", "grp2");
+    assertThat(groupManagement.getUserGroups("bob").getGroups())
+      .extracting(Groups.Group::getName)
+      .contains("grp1", "grp2");
+    addPermissionsToUser(orgKeyAndName, "bob", "provisioning", "scan");
+
+    ItUtils.runProjectAnalysis(orchestrator, "shared/xoo-sample",
+      "sonar.organization", orgKeyAndName, "sonar.login", "bob", "sonar.password", "bob");
+    ComponentsService componentsService = ItUtils.newAdminWsClient(orchestrator).components();
+    assertThat(searchSampleProject(orgKeyAndName, componentsService).getComponentsList()).hasSize(1);
+
+    adminOrganizationService.delete(orgKeyAndName);
+
+    expect404HttpError(() -> searchSampleProject(orgKeyAndName, componentsService));
+    assertThat(groupManagement.getUserGroups("bob").getGroups())
+      .extracting(Groups.Group::getName)
+      .doesNotContain("grp1", "grp2");
+
+    verifyNoExtraOrganization();
+  }
+
+  private WsComponents.SearchWsResponse searchSampleProject(String organizationKey, ComponentsService componentsService) {
+    return componentsService
+      .search(new org.sonarqube.ws.client.component.SearchWsRequest()
+        .setOrganization(organizationKey)
+        .setQualifiers(singletonList("TRK"))
+        .setQuery("sample"));
+  }
+
+  private void expect403HttpError(Runnable runnable) {
+    try {
+      runnable.run();
+      fail("Ws call should have failed");
+    } catch (HttpException e) {
+      assertThat(e.code()).isEqualTo(403);
+    }
+  }
+
+  private void expect404HttpError(Runnable runnable) {
+    try {
+      runnable.run();
+      fail("Ws call should have failed");
+    } catch (HttpException e) {
+      assertThat(e.code()).isEqualTo(404);
+    }
+  }
+
+  private void verifyNoExtraOrganization() {
+    Organizations.SearchWsResponse searchWsResponse = anonymousOrganizationService.search(new SearchWsRequest.Builder().build());
+    List<Organizations.Organization> organizationsList = searchWsResponse.getOrganizationsList();
+    assertThat(organizationsList).hasSize(1);
+    assertThat(organizationsList.iterator().next().getKey()).isEqualTo(DEFAULT_ORGANIZATION_KEY);
+  }
+
+  private void verifySingleSearchResult(Organizations.Organization createdOrganization, String name, String description, String url,
+    String avatarUrl) {
+    List<Organizations.Organization> organizations = anonymousOrganizationService.search(new SearchWsRequest.Builder()
+        .build()).getOrganizationsList();
+    assertThat(organizations).hasSize(2);
+    Organizations.Organization searchedOrganization = organizations.stream()
+      .filter(organization -> !DEFAULT_ORGANIZATION_KEY.equals(organization.getKey()))
+      .findFirst()
+      .get();
+    assertThat(searchedOrganization.getKey()).isEqualTo(createdOrganization.getKey());
+    assertThat(searchedOrganization.getName()).isEqualTo(name);
+    if (description == null) {
+      assertThat(searchedOrganization.hasDescription()).isFalse();
+    } else {
+      assertThat(searchedOrganization.getDescription()).isEqualTo(description);
+    }
+    if (url == null) {
+      assertThat(searchedOrganization.hasUrl()).isFalse();
+    } else {
+      assertThat(searchedOrganization.getUrl()).isEqualTo(url);
+    }
+    if (avatarUrl == null) {
+      assertThat(searchedOrganization.hasAvatar()).isFalse();
+    } else {
+      assertThat(searchedOrganization.getAvatar()).isEqualTo(avatarUrl);
+    }
+  }
+}
diff --git a/it/it-tests/src/test/java/it/organization/RootTest.java b/it/it-tests/src/test/java/it/organization/RootTest.java
new file mode 100644 (file)
index 0000000..89b3af2
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package it.organization;
+
+import com.sonar.orchestrator.Orchestrator;
+import it.Category3Suite;
+import java.sql.SQLException;
+import java.util.Collections;
+import org.junit.After;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonarqube.ws.WsRoot;
+import org.sonarqube.ws.client.HttpException;
+import org.sonarqube.ws.client.WsClient;
+import util.user.UserRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+import static util.ItUtils.newAdminWsClient;
+import static util.ItUtils.newUserWsClient;
+import static util.ItUtils.newWsClient;
+
+public class RootTest {
+  @ClassRule
+  public static Orchestrator orchestrator = Category3Suite.ORCHESTRATOR;
+  @Rule
+  public UserRule userRule = UserRule.from(orchestrator);
+
+  @After
+  public void tearDown() {
+    orchestrator.resetData();
+  }
+
+  @Test
+  public void nobody_is_root_by_default() {
+    // anonymous
+    verifyHttpError(() -> newWsClient(orchestrator).rootService().search(), 403);
+
+    // admin
+    verifyHttpError(() -> newAdminWsClient(orchestrator).rootService().search(), 403);
+  }
+
+  @Test
+  public void system_administrator_is_flagged_as_root_when_he_enables_organization_support() {
+    enableOrganizationSupport();
+
+    assertThat(newAdminWsClient(orchestrator).rootService().search().getRootsList())
+      .extracting(WsRoot.Root::getLogin)
+      .containsOnly(UserRule.ADMIN_LOGIN);
+  }
+
+  @Test
+  public void a_root_can_flag_other_user_as_root() {
+    enableOrganizationSupport();
+
+    userRule.createUser("bar", "foo");
+    userRule.setRoot("bar");
+
+    assertThat(newAdminWsClient(orchestrator).rootService().search().getRootsList())
+      .extracting(WsRoot.Root::getLogin)
+      .containsOnly(UserRule.ADMIN_LOGIN, "bar");
+  }
+
+  @Test
+  public void last_root_can_not_be_unset_root() throws SQLException {
+    enableOrganizationSupport();
+
+    verifyHttpError(() -> newAdminWsClient(orchestrator).rootService().unsetRoot(UserRule.ADMIN_LOGIN), 400);
+  }
+
+  @Test
+  public void root_can_be_set_and_unset_via_web_services() {
+    enableOrganizationSupport();
+
+    userRule.createUser("root1", "bar");
+    userRule.createUser("root2", "bar");
+    WsClient root1WsClient = newUserWsClient(orchestrator, "root1", "bar");
+    WsClient root2WsClient = newUserWsClient(orchestrator, "root2", "bar");
+
+    // non root can not set or unset root another user not itself
+    verifyHttpError(() -> root1WsClient.rootService().setRoot("root2"), 403);
+    verifyHttpError(() -> root1WsClient.rootService().setRoot("root1"), 403);
+    verifyHttpError(() -> root1WsClient.rootService().unsetRoot("root1"), 403);
+    verifyHttpError(() -> root2WsClient.rootService().unsetRoot("root1"), 403);
+    verifyHttpError(() -> root2WsClient.rootService().unsetRoot("root2"), 403);
+    // admin (the first root) sets root1 as root
+    newAdminWsClient(orchestrator).rootService().setRoot("root1");
+    // root1 can set root root2
+    root1WsClient.rootService().setRoot("root2");
+    // root2 can unset root root1
+    root2WsClient.rootService().unsetRoot("root1");
+    // root2 can unset root itself as it's not the last root
+    root2WsClient.rootService().unsetRoot("root2");
+  }
+
+  private void enableOrganizationSupport() {
+    orchestrator.getServer().post("api/organizations/enable_support", Collections.emptyMap());
+  }
+
+  private static void verifyHttpError(Runnable runnable, int expectedErrorCode) {
+    try {
+      runnable.run();
+      fail("Ws Call should have failed with http code " + expectedErrorCode);
+    } catch (HttpException e) {
+      assertThat(e.code()).isEqualTo(expectedErrorCode);
+    }
+  }
+}
diff --git a/it/it-tests/src/test/java/it/root/RootIt.java b/it/it-tests/src/test/java/it/root/RootIt.java
deleted file mode 100644 (file)
index 495ead8..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package it.root;
-
-import com.sonar.orchestrator.Orchestrator;
-import it.Category3Suite;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import org.junit.After;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonarqube.ws.WsRoot;
-import org.sonarqube.ws.client.HttpException;
-import org.sonarqube.ws.client.WsClient;
-import util.user.UserRule;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-import static util.ItUtils.newAdminWsClient;
-import static util.ItUtils.newUserWsClient;
-import static util.ItUtils.newWsClient;
-
-public class RootIt {
-  @ClassRule
-  public static Orchestrator orchestrator = Category3Suite.ORCHESTRATOR;
-  @Rule
-  public UserRule userRule = UserRule.from(orchestrator);
-
-  @After
-  public void tearDown() throws Exception {
-    userRule.resetUsers();
-  }
-
-  @Test
-  public void by_default_admin_is_the_only_root() {
-    // must be root to call search WS
-    verifyHttpError(() -> newWsClient(orchestrator).rootService().search(), 403);
-
-    assertThat(newAdminWsClient(orchestrator).rootService().search().getRootsList())
-      .extracting(WsRoot.Root::getLogin)
-      .containsOnly(UserRule.ADMIN_LOGIN);
-
-    userRule.createUser("bar", "foo");
-    userRule.setRoot("bar");
-
-    assertThat(newAdminWsClient(orchestrator).rootService().search().getRootsList())
-      .extracting(WsRoot.Root::getLogin)
-      .containsOnly(UserRule.ADMIN_LOGIN, "bar");
-  }
-
-  @Test
-  public void last_root_can_not_be_unset_root() throws SQLException {
-    try (Connection connection = orchestrator.getDatabase().openConnection();
-      PreparedStatement preparedStatement = createSelectActiveRootUsers(connection);
-      ResultSet resultSet = preparedStatement.executeQuery()) {
-      assertThat(resultSet.next()).as("There should be active root user").isTrue();
-      assertThat(resultSet.getString(1)).isEqualTo(UserRule.ADMIN_LOGIN);
-      assertThat(resultSet.next()).as("There shouldn't be more than one active root user").isFalse();
-    }
-
-    verifyHttpError(() -> newAdminWsClient(orchestrator).rootService().unsetRoot(UserRule.ADMIN_LOGIN), 400);
-  }
-
-  private static void verifyHttpError(Runnable runnable, int expectedErrorCode) {
-    try {
-      runnable.run();
-      fail("Ws Call should have failed with http code " + expectedErrorCode);
-    } catch (HttpException e) {
-      assertThat(e.code()).isEqualTo(expectedErrorCode);
-    }
-  }
-
-  @Test
-  public void root_can_be_set_and_unset_via_web_services() {
-    userRule.createUser("root1", "bar");
-    userRule.createUser("root2", "bar");
-    WsClient root1WsClient = newUserWsClient(orchestrator, "root1", "bar");
-    WsClient root2WsClient = newUserWsClient(orchestrator, "root2", "bar");
-
-    // non root can not set or unset root another user not itself
-    verifyHttpError(() -> root1WsClient.rootService().setRoot("root2"), 403);
-    verifyHttpError(() -> root1WsClient.rootService().setRoot("root1"), 403);
-    verifyHttpError(() -> root1WsClient.rootService().unsetRoot("root1"), 403);
-    verifyHttpError(() -> root2WsClient.rootService().unsetRoot("root1"), 403);
-    verifyHttpError(() -> root2WsClient.rootService().unsetRoot("root2"), 403);
-    // admin (the first root) sets root1 as root
-    newAdminWsClient(orchestrator).rootService().setRoot("root1");
-    // root1 can set root root2
-    root1WsClient.rootService().setRoot("root2");
-    // root2 can unset root root1
-    root2WsClient.rootService().unsetRoot("root1");
-    // root2 can unset root itself as it's not the last root
-    root2WsClient.rootService().unsetRoot("root2");
-  }
-
-  private static PreparedStatement createSelectActiveRootUsers(Connection connection) throws SQLException {
-    PreparedStatement preparedStatement = connection.prepareStatement("select login from users where is_root = ? and active = ?");
-    preparedStatement.setBoolean(1, true);
-    preparedStatement.setBoolean(2, true);
-    return preparedStatement;
-  }
-}
index f6b0e802c49d5dee1b34a8a07299ebc030396bdd..46564c2d04759c08a611273657d10b2cbb7f11d1 100644 (file)
@@ -110,6 +110,9 @@ public class BackendCleanup {
 
       truncateAnalysisTables(connection);
       deleteManualRules(connection);
+      truncateInternalProperties(null, null, connection);
+      truncateUsers(null, null, connection);
+      truncateOrganizations(null, null, connection);
     } catch (SQLException e) {
       throw new IllegalStateException("Fail to reset data", e);
     }
@@ -184,6 +187,13 @@ public class BackendCleanup {
       // commit is useless on some databases
       connection.commit();
     }
+    // "admin" is not flagged as root by default
+    try (PreparedStatement preparedStatement = connection.prepareStatement("update users set is_root=?")) {
+      preparedStatement.setBoolean(1, false);
+      preparedStatement.execute();
+      // commit is useless on some databases
+      connection.commit();
+    }
   }
 
   /**
index 4ec4454e0cae00a5c5eaba58c64d14f5a2d08e18..099ef81edb82bac1e7c27569278e28e8222bb2c0 100644 (file)
@@ -43,7 +43,7 @@ public class OrganizationFlagsImplTest {
   }
 
   @Test
-  public void enable_does_enable_feature_by_inserting_internal_property() {
+  public void enable_does_enable_support_by_inserting_internal_property() {
     underTest.enable(db.getSession());
 
     assertThat(underTest.isEnabled(db.getSession())).isTrue();