From: Simon Brandhof Date: Sat, 11 Nov 2017 17:21:25 +0000 (+0100) Subject: Add category authorization to integration tests X-Git-Tag: 7.0-RC1~321 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=522c9d813b5f39073d809badffc85b0ebd7f1209;p=sonarqube.git Add category authorization to integration tests --- diff --git a/cix.sh b/cix.sh index 62b06de33c9..2830bc82ab4 100755 --- a/cix.sh +++ b/cix.sh @@ -33,6 +33,7 @@ case "$RUN_ACTIVITY" in case "$CATEGORY_GROUP" in Category1) CATEGORY=Category1 && runCategory + CATEGORY=authorization && runCategory CATEGORY=measure && runCategory CATEGORY=source && runCategory ;; diff --git a/tests/src/test/java/org/sonarqube/tests/Category1Suite.java b/tests/src/test/java/org/sonarqube/tests/Category1Suite.java index 8fbbe37567d..2cc1da3ed4a 100644 --- a/tests/src/test/java/org/sonarqube/tests/Category1Suite.java +++ b/tests/src/test/java/org/sonarqube/tests/Category1Suite.java @@ -23,11 +23,6 @@ import com.sonar.orchestrator.Orchestrator; import org.junit.ClassRule; import org.junit.runner.RunWith; import org.junit.runners.Suite; -import org.sonarqube.tests.authorisation.ExecuteAnalysisPermissionTest; -import org.sonarqube.tests.authorisation.IssuePermissionTest; -import org.sonarqube.tests.authorisation.PermissionSearchTest; -import org.sonarqube.tests.authorisation.ProvisioningPermissionTest; -import org.sonarqube.tests.authorisation.QualityProfileAdminPermissionTest; import org.sonarqube.tests.projectAdministration.BackgroundTasksTest; import org.sonarqube.tests.projectAdministration.ProjectAdministrationTest; import org.sonarqube.tests.projectAdministration.ProjectBulkDeletionPageTest; @@ -67,12 +62,6 @@ import static util.ItUtils.xooPlugin; QualityGateUiTest.class, QualityGateNotificationTest.class, QualityGateOnRatingMeasuresTest.class, - // authorisation - ExecuteAnalysisPermissionTest.class, - IssuePermissionTest.class, - PermissionSearchTest.class, - ProvisioningPermissionTest.class, - QualityProfileAdminPermissionTest.class, // measure ProjectsPageTest.class }) diff --git a/tests/src/test/java/org/sonarqube/tests/Category5Suite.java b/tests/src/test/java/org/sonarqube/tests/Category5Suite.java index 85125797af0..a5bc316c09f 100644 --- a/tests/src/test/java/org/sonarqube/tests/Category5Suite.java +++ b/tests/src/test/java/org/sonarqube/tests/Category5Suite.java @@ -22,10 +22,10 @@ package org.sonarqube.tests; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.sonarqube.tests.analysis.AnalysisEsResilienceTest; -import org.sonarqube.tests.authorisation.SystemPasscodeTest; import org.sonarqube.tests.ce.CeShutdownTest; import org.sonarqube.tests.ce.CeWorkersTest; import org.sonarqube.tests.issue.IssueCreationDatePluginChangedTest; +import org.sonarqube.tests.marketplace.UpdateCenterTest; import org.sonarqube.tests.qualityProfile.ActiveRuleEsResilienceTest; import org.sonarqube.tests.qualityProfile.BuiltInQualityProfilesNotificationTest; import org.sonarqube.tests.rule.RuleEsResilienceTest; @@ -36,7 +36,6 @@ import org.sonarqube.tests.settings.SettingsTestRestartingOrchestrator; import org.sonarqube.tests.startup.StartupIndexationTest; import org.sonarqube.tests.telemetry.TelemetryOptOutTest; import org.sonarqube.tests.telemetry.TelemetryUploadTest; -import org.sonarqube.tests.marketplace.UpdateCenterTest; import org.sonarqube.tests.user.OnboardingTest; import org.sonarqube.tests.user.RealmAuthenticationTest; import org.sonarqube.tests.user.SsoAuthenticationTest; @@ -72,8 +71,7 @@ import org.sonarqube.tests.user.UserEsResilienceTest; IssueCreationDatePluginChangedTest.class, // elasticsearch - StartupIndexationTest.class, - SystemPasscodeTest.class + StartupIndexationTest.class }) public class Category5Suite { diff --git a/tests/src/test/java/org/sonarqube/tests/Category6Suite.java b/tests/src/test/java/org/sonarqube/tests/Category6Suite.java index a7cec719ffc..aca8c327b4c 100644 --- a/tests/src/test/java/org/sonarqube/tests/Category6Suite.java +++ b/tests/src/test/java/org/sonarqube/tests/Category6Suite.java @@ -25,7 +25,7 @@ import java.net.InetAddress; import org.junit.ClassRule; import org.junit.runner.RunWith; import org.junit.runners.Suite; -import org.sonarqube.tests.authorisation.PermissionTemplateTest; +import org.sonarqube.tests.authorization.PermissionTemplateTest; import org.sonarqube.tests.ce.ReportFailureNotificationTest; import org.sonarqube.tests.issue.IssueNotificationsTest; import org.sonarqube.tests.issue.IssueTagsTest; diff --git a/tests/src/test/java/org/sonarqube/tests/authorisation/ExecuteAnalysisPermissionTest.java b/tests/src/test/java/org/sonarqube/tests/authorisation/ExecuteAnalysisPermissionTest.java deleted file mode 100644 index 65f1a52bce1..00000000000 --- a/tests/src/test/java/org/sonarqube/tests/authorisation/ExecuteAnalysisPermissionTest.java +++ /dev/null @@ -1,151 +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 org.sonarqube.tests.authorisation; - -import com.sonar.orchestrator.Orchestrator; -import com.sonar.orchestrator.build.BuildFailureException; -import org.sonarqube.tests.Category1Suite; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.sonar.wsclient.SonarClient; -import org.sonar.wsclient.user.UserParameters; -import org.sonarqube.ws.client.WsClient; -import org.sonarqube.ws.client.permission.AddGroupWsRequest; -import org.sonarqube.ws.client.permission.AddProjectCreatorToTemplateWsRequest; -import org.sonarqube.ws.client.permission.RemoveGroupWsRequest; -import org.sonarqube.ws.client.project.UpdateVisibilityRequest; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; -import static util.ItUtils.newAdminWsClient; -import static util.ItUtils.runProjectAnalysis; - -/** - * SONAR-4397 - */ -public class ExecuteAnalysisPermissionTest { - - @ClassRule - public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; - - private final static String USER_LOGIN = "scanperm"; - private final static String USER_PASSWORD = "thewhite"; - private final static String PROJECT_KEY = "sample"; - - private static WsClient adminWsClient; - private static SonarClient oldAdminWsClient; - - @Before - public void setUp() { - orchestrator.resetData(); - oldAdminWsClient = orchestrator.getServer().adminWsClient(); - oldAdminWsClient.userClient().create(UserParameters.create().login(USER_LOGIN).name(USER_LOGIN).password(USER_PASSWORD).passwordConfirmation(USER_PASSWORD)); - orchestrator.getServer().provisionProject(PROJECT_KEY, "Sample"); - adminWsClient = newAdminWsClient(orchestrator); - } - - @After - public void tearDown() { - addGlobalPermission("anyone", "scan"); - oldAdminWsClient.userClient().deactivate(USER_LOGIN); - } - - @Test - public void should_fail_if_logged_but_no_scan_permission() throws Exception { - executeLoggedAnalysis(); - - removeGlobalPermission("anyone", "scan"); - try { - // Execute logged analysis, but without the "Execute Analysis" permission - executeLoggedAnalysis(); - fail(); - } catch (BuildFailureException e) { - assertThat(e.getResult().getLogs()).contains( - "You're only authorized to execute a local (preview) SonarQube analysis without pushing the results to the SonarQube server. Please contact your SonarQube administrator."); - } - - newAdminWsClient(orchestrator).projects().updateVisibility(UpdateVisibilityRequest.builder().setProject(PROJECT_KEY).setVisibility("private").build()); - try { - // Execute anonymous analysis - executeAnonymousAnalysis(); - fail(); - } catch (BuildFailureException e) { - assertThat(e.getResult().getLogs()).contains( - "You're not authorized to execute any SonarQube analysis. Please contact your SonarQube administrator."); - } - } - - @Test - public void no_need_for_browse_permission_to_scan() throws Exception { - // Do a first analysis, no error - executeAnonymousAnalysis(); - - // make project private - newAdminWsClient(orchestrator).projects().updateVisibility(UpdateVisibilityRequest.builder().setProject("sample").setVisibility("private").build()); - - // still no error - executeAnonymousAnalysis(); - } - - @Test - public void execute_analysis_with_scan_permission_only_on_project() throws Exception { - removeGlobalPermission("anyone", "scan"); - addProjectPermission("anyone", PROJECT_KEY, "scan"); - - executeLoggedAnalysis(); - } - - @Test - public void execute_analysis_with_scan_on_default_template() { - removeGlobalPermission("anyone", "scan"); - adminWsClient.permissions().addProjectCreatorToTemplate(AddProjectCreatorToTemplateWsRequest.builder() - .setPermission("scan") - .setTemplateId("default_template") - .build()); - - runProjectAnalysis(orchestrator, "shared/xoo-sample", "sonar.login", USER_LOGIN, "sonar.password", USER_PASSWORD, "sonar.projectKey", "ANOTHER_PROJECT_KEY"); - } - - private static void addProjectPermission(String groupName, String projectKey, String permission) { - adminWsClient.permissions().addGroup(new AddGroupWsRequest().setGroupName(groupName).setProjectKey(projectKey).setPermission(permission)); - } - - private static void addGlobalPermission(String groupName, String permission) { - adminWsClient.permissions().addGroup(new AddGroupWsRequest().setGroupName(groupName).setPermission(permission)); - } - - private static void removeProjectPermission(String groupName, String projectKey, String permission) { - adminWsClient.permissions().removeGroup(new RemoveGroupWsRequest().setGroupName(groupName).setProjectKey(projectKey).setPermission(permission)); - } - - private static void removeGlobalPermission(String groupName, String permission) { - adminWsClient.permissions().removeGroup(new RemoveGroupWsRequest().setGroupName(groupName).setPermission(permission)); - } - - private static void executeLoggedAnalysis() { - runProjectAnalysis(orchestrator, "shared/xoo-sample", "sonar.login", USER_LOGIN, "sonar.password", USER_PASSWORD); - } - - private static void executeAnonymousAnalysis() { - runProjectAnalysis(orchestrator, "shared/xoo-sample"); - } -} diff --git a/tests/src/test/java/org/sonarqube/tests/authorisation/IssuePermissionTest.java b/tests/src/test/java/org/sonarqube/tests/authorisation/IssuePermissionTest.java deleted file mode 100644 index 21f39e7d636..00000000000 --- a/tests/src/test/java/org/sonarqube/tests/authorisation/IssuePermissionTest.java +++ /dev/null @@ -1,276 +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 org.sonarqube.tests.authorisation; - -import com.sonar.orchestrator.Orchestrator; -import com.sonar.orchestrator.build.SonarScanner; -import org.sonarqube.tests.Category1Suite; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.sonar.wsclient.SonarClient; -import org.sonar.wsclient.base.HttpException; -import org.sonar.wsclient.issue.Issue; -import org.sonar.wsclient.issue.IssueQuery; -import org.sonar.wsclient.user.UserParameters; -import org.sonarqube.ws.Issues; -import org.sonarqube.ws.client.WsClient; -import org.sonarqube.ws.client.issue.BulkChangeRequest; -import org.sonarqube.ws.client.permission.AddUserWsRequest; -import org.sonarqube.ws.client.project.UpdateVisibilityRequest; -import util.ItUtils; - -import static java.util.Arrays.asList; -import static junit.framework.TestCase.fail; -import static org.assertj.core.api.Assertions.assertThat; -import static util.ItUtils.newAdminWsClient; -import static util.ItUtils.newUserWsClient; -import static util.ItUtils.projectDir; - -public class IssuePermissionTest { - - @ClassRule - public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; - public WsClient adminWsClient = newAdminWsClient(orchestrator); - - @Before - public void init() { - orchestrator.resetData(); - - ItUtils.restoreProfile(orchestrator, getClass().getResource("/authorisation/one-issue-per-line-profile.xml")); - - orchestrator.getServer().provisionProject("privateProject", "PrivateProject"); - newAdminWsClient(orchestrator).projects().updateVisibility(UpdateVisibilityRequest.builder().setProject("privateProject").setVisibility("private").build()); - orchestrator.getServer().associateProjectToQualityProfile("privateProject", "xoo", "one-issue-per-line"); - SonarScanner privateProject = SonarScanner.create(projectDir("shared/xoo-sample")) - .setProperty("sonar.projectKey", "privateProject") - .setProperty("sonar.projectName", "PrivateProject"); - orchestrator.executeBuild(privateProject); - - orchestrator.getServer().provisionProject("publicProject", "PublicProject"); - orchestrator.getServer().associateProjectToQualityProfile("publicProject", "xoo", "one-issue-per-line"); - SonarScanner publicProject = SonarScanner.create(projectDir("shared/xoo-sample")) - .setProperty("sonar.projectKey", "publicProject") - .setProperty("sonar.projectName", "PublicProject"); - - - orchestrator.executeBuild(publicProject); - } - - @Test - public void need_user_permission_on_project_to_see_issue() { - SonarClient client = orchestrator.getServer().adminWsClient(); - - String withBrowsePermission = "with-browse-permission"; - String withoutBrowsePermission = "without-browse-permission"; - - try { - client.userClient().create(UserParameters.create().login(withBrowsePermission).name(withBrowsePermission) - .password("password").passwordConfirmation("password")); - addUserPermission(withBrowsePermission, "privateProject", "user"); - - client.userClient().create(UserParameters.create().login(withoutBrowsePermission).name(withoutBrowsePermission) - .password("password").passwordConfirmation("password")); - - // Without user permission, a user cannot see issues on the project - assertThat(orchestrator.getServer().wsClient(withoutBrowsePermission, "password").issueClient().find( - IssueQuery.create().componentRoots("privateProject")).list()).isEmpty(); - - // With user permission, a user can see issues on the project - assertThat(orchestrator.getServer().wsClient(withBrowsePermission, "password").issueClient().find( - IssueQuery.create().componentRoots("privateProject")).list()).isNotEmpty(); - - } finally { - client.userClient().deactivate(withBrowsePermission); - client.userClient().deactivate(withoutBrowsePermission); - } - } - - /** - * SONAR-4839 - */ - @Test - public void need_user_permission_on_project_to_see_issue_changelog() { - SonarClient client = orchestrator.getServer().adminWsClient(); - Issue issue = client.issueClient().find(IssueQuery.create().componentRoots("privateProject")).list().get(0); - client.issueClient().assign(issue.key(), "admin"); - - String withBrowsePermission = "with-browse-permission"; - String withoutBrowsePermission = "without-browse-permission"; - - try { - client.userClient().create(UserParameters.create().login(withBrowsePermission).name(withBrowsePermission) - .password("password").passwordConfirmation("password")); - addUserPermission(withBrowsePermission, "privateProject", "user"); - - client.userClient().create(UserParameters.create().login(withoutBrowsePermission).name(withoutBrowsePermission) - .password("password").passwordConfirmation("password")); - - // Without user permission, a user cannot see issue changelog on the project - try { - changelog(issue.key(), withoutBrowsePermission, "password"); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(org.sonarqube.ws.client.HttpException.class).describedAs("403"); - } - - // Without user permission, a user cannot see issues on the project - assertThat(changelog(issue.key(), withBrowsePermission, "password").getChangelogList()).isNotEmpty(); - - } finally { - client.userClient().deactivate(withBrowsePermission); - client.userClient().deactivate(withoutBrowsePermission); - } - } - - /** - * SONAR-2447 - */ - @Test - public void need_administer_issue_permission_on_project_to_set_severity() { - SonarClient client = orchestrator.getServer().adminWsClient(); - Issue issueOnPrivateProject = client.issueClient().find(IssueQuery.create().componentRoots("privateProject")).list().get(0); - Issue issueOnPublicProject = client.issueClient().find(IssueQuery.create().componentRoots("publicProject")).list().get(0); - - String user = "user"; - - try { - client.userClient().create(UserParameters.create().login(user).name(user).password("password").passwordConfirmation("password")); - addUserPermission(user, "publicProject", "issueadmin"); - - // Without issue admin permission, a user cannot set severity on the issue - try { - orchestrator.getServer().wsClient(user, "password").issueClient().setSeverity(issueOnPrivateProject.key(), "BLOCKER"); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(HttpException.class).describedAs("404"); - } - - // With issue admin permission, a user can set severity on the issue - assertThat(orchestrator.getServer().wsClient(user, "password").issueClient().setSeverity(issueOnPublicProject.key(), "BLOCKER").severity()).isEqualTo("BLOCKER"); - - } finally { - client.userClient().deactivate(user); - } - } - - /** - * SONAR-2447 - */ - @Test - public void need_administer_issue_permission_on_project_to_flag_as_false_positive() { - SonarClient client = orchestrator.getServer().adminWsClient(); - Issue issueOnPrivateProject = client.issueClient().find(IssueQuery.create().componentRoots("privateProject")).list().get(0); - Issue issueOnPublicProject = client.issueClient().find(IssueQuery.create().componentRoots("publicProject")).list().get(0); - - String user = "user"; - - try { - client.userClient().create(UserParameters.create().login(user).name(user).password("password").passwordConfirmation("password")); - addUserPermission(user, "publicProject", "issueadmin"); - - // Without issue admin permission, a user cannot flag an issue as false positive - try { - orchestrator.getServer().wsClient(user, "password").issueClient().doTransition(issueOnPrivateProject.key(), "falsepositive"); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(HttpException.class).describedAs("404"); - } - - // With issue admin permission, a user can flag an issue as false positive - assertThat(orchestrator.getServer().wsClient(user, "password").issueClient().doTransition(issueOnPublicProject.key(), "falsepositive").status()).isEqualTo("RESOLVED"); - - } finally { - client.userClient().deactivate(user); - } - } - - /** - * SONAR-2447 - */ - @Test - public void need_administer_issue_permission_on_project_to_bulk_change_severity_and_false_positive() { - SonarClient client = orchestrator.getServer().adminWsClient(); - Issue issueOnPrivateProject = client.issueClient().find(IssueQuery.create().componentRoots("privateProject")).list().get(0); - Issue issueOnPublicProject = client.issueClient().find(IssueQuery.create().componentRoots("publicProject")).list().get(0); - - String user = "user"; - - try { - client.userClient().create(UserParameters.create().login(user).name(user).password("password").passwordConfirmation("password")); - addUserPermission(user, "privateProject", "issueadmin"); - - Issues.BulkChangeWsResponse response = makeBlockerAndFalsePositive(user, issueOnPrivateProject, issueOnPublicProject); - - // public project but no issueadmin permission on publicProject => issue visible but not updated - // no user permission on privateproject => issue invisible and not updated - assertThat(response.getTotal()).isEqualTo(1); - assertThat(response.getSuccess()).isEqualTo(0); - assertThat(response.getIgnored()).isEqualTo(1); - - addUserPermission(user, "privateProject", "user"); - response = makeBlockerAndFalsePositive(user, issueOnPrivateProject, issueOnPublicProject); - - // public project but no issueadmin permission on publicProject => unsuccessful on issueOnPublicProject - // user and issueadmin permission on privateproject => successful and 1 more issue visible - assertThat(response.getTotal()).isEqualTo(2); - assertThat(response.getSuccess()).isEqualTo(1); - assertThat(response.getIgnored()).isEqualTo(1); - - addUserPermission(user, "publicProject", "issueadmin"); - response = makeBlockerAndFalsePositive(user, issueOnPrivateProject, issueOnPublicProject); - - // public and issueadmin permission on publicProject => successful on issueOnPublicProject - // issueOnPrivateProject already in specified state => unsuccessful - assertThat(response.getTotal()).isEqualTo(2); - assertThat(response.getSuccess()).isEqualTo(1); - assertThat(response.getIgnored()).isEqualTo(1); - - response = makeBlockerAndFalsePositive(user, issueOnPrivateProject, issueOnPublicProject); - - // issueOnPublicProject and issueOnPrivateProject already in specified state => unsuccessful - assertThat(response.getTotal()).isEqualTo(2); - assertThat(response.getSuccess()).isEqualTo(0); - assertThat(response.getIgnored()).isEqualTo(2); - } finally { - client.userClient().deactivate(user); - } - } - - private Issues.BulkChangeWsResponse makeBlockerAndFalsePositive(String user, Issue issueOnPrivateProject, Issue issueOnPublicProject) { - return newUserWsClient(orchestrator, user, "password").issues() - .bulkChange(BulkChangeRequest.builder().setIssues(asList(issueOnPrivateProject.key(), issueOnPublicProject.key())) - .setSetSeverity("BLOCKER") - .setDoTransition("falsepositive") - .build()); - } - - private void addUserPermission(String login, String projectKey, String permission) { - adminWsClient.permissions().addUser( - new AddUserWsRequest() - .setLogin(login) - .setProjectKey(projectKey) - .setPermission(permission)); - } - - private static Issues.ChangelogWsResponse changelog(String issueKey, String login, String password) { - return newUserWsClient(orchestrator, login, password).issues().changelog(issueKey); - } -} diff --git a/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionSearchTest.java b/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionSearchTest.java deleted file mode 100644 index 7698aa3bb8e..00000000000 --- a/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionSearchTest.java +++ /dev/null @@ -1,203 +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 org.sonarqube.tests.authorisation; - -import com.sonar.orchestrator.Orchestrator; -import com.sonar.orchestrator.build.SonarScanner; -import org.sonarqube.tests.Category1Suite; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.sonarqube.ws.WsPermissions; -import org.sonarqube.ws.WsPermissions.Permission; -import org.sonarqube.ws.WsPermissions.SearchTemplatesWsResponse; -import org.sonarqube.ws.client.PostRequest; -import org.sonarqube.ws.client.WsClient; -import org.sonarqube.ws.client.permission.AddGroupToTemplateWsRequest; -import org.sonarqube.ws.client.permission.AddGroupWsRequest; -import org.sonarqube.ws.client.permission.AddProjectCreatorToTemplateWsRequest; -import org.sonarqube.ws.client.permission.AddUserToTemplateWsRequest; -import org.sonarqube.ws.client.permission.AddUserWsRequest; -import org.sonarqube.ws.client.permission.CreateTemplateWsRequest; -import org.sonarqube.ws.client.permission.GroupsWsRequest; -import org.sonarqube.ws.client.permission.PermissionsService; -import org.sonarqube.ws.client.permission.RemoveGroupFromTemplateWsRequest; -import org.sonarqube.ws.client.permission.RemoveProjectCreatorFromTemplateWsRequest; -import org.sonarqube.ws.client.permission.RemoveUserFromTemplateWsRequest; -import org.sonarqube.ws.client.permission.SearchTemplatesWsRequest; -import org.sonarqube.ws.client.permission.UsersWsRequest; -import util.ItUtils; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static util.ItUtils.newAdminWsClient; -import static util.ItUtils.projectDir; - -public class PermissionSearchTest { - @ClassRule - public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; - private static WsClient adminWsClient; - private static PermissionsService permissionsWsClient; - - private static final String PROJECT_KEY = "sample"; - private static final String LOGIN = "george.orwell"; - private static final String GROUP_NAME = "1984"; - - @BeforeClass - public static void analyzeProject() { - orchestrator.resetData(); - - ItUtils.restoreProfile(orchestrator, PermissionSearchTest.class.getResource("/authorisation/one-issue-per-line-profile.xml")); - - orchestrator.getServer().provisionProject(PROJECT_KEY, "Sample"); - orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line"); - SonarScanner sampleProject = SonarScanner.create(projectDir("shared/xoo-sample")); - orchestrator.executeBuild(sampleProject); - - adminWsClient = newAdminWsClient(orchestrator); - permissionsWsClient = adminWsClient.permissions(); - - createUser(LOGIN, "George Orwell"); - createGroup(GROUP_NAME); - } - - @AfterClass - public static void delete_data() { - deactivateUser(LOGIN); - deleteGroup(GROUP_NAME); - } - - @Test - public void permission_web_services() { - permissionsWsClient.addUser( - new AddUserWsRequest() - .setPermission("admin") - .setLogin(LOGIN)); - permissionsWsClient.addGroup( - new AddGroupWsRequest() - .setPermission("admin") - .setGroupName(GROUP_NAME)); - - WsPermissions.WsSearchGlobalPermissionsResponse searchGlobalPermissionsWsResponse = permissionsWsClient.searchGlobalPermissions(); - assertThat(searchGlobalPermissionsWsResponse.getPermissionsList().get(0).getKey()).isEqualTo("admin"); - assertThat(searchGlobalPermissionsWsResponse.getPermissionsList().get(0).getUsersCount()).isEqualTo(1); - // by default, a group has the global admin permission - assertThat(searchGlobalPermissionsWsResponse.getPermissionsList().get(0).getGroupsCount()).isEqualTo(2); - - WsPermissions.UsersWsResponse users = permissionsWsClient - .users(new UsersWsRequest().setPermission("admin")); - assertThat(users.getUsersList()).extracting("login").contains(LOGIN); - - WsPermissions.WsGroupsResponse groupsResponse = permissionsWsClient - .groups(new GroupsWsRequest() - .setPermission("admin")); - assertThat(groupsResponse.getGroupsList()).extracting("name").contains(GROUP_NAME); - } - - @Test - public void template_permission_web_services() { - WsPermissions.CreateTemplateWsResponse createTemplateWsResponse = permissionsWsClient.createTemplate( - new CreateTemplateWsRequest() - .setName("my-new-template") - .setDescription("template-used-in-tests")); - assertThat(createTemplateWsResponse.getPermissionTemplate().getName()).isEqualTo("my-new-template"); - - permissionsWsClient.addUserToTemplate( - new AddUserToTemplateWsRequest() - .setPermission("admin") - .setTemplateName("my-new-template") - .setLogin(LOGIN)); - - permissionsWsClient.addGroupToTemplate( - new AddGroupToTemplateWsRequest() - .setPermission("admin") - .setTemplateName("my-new-template") - .setGroupName(GROUP_NAME)); - - permissionsWsClient.addProjectCreatorToTemplate( - AddProjectCreatorToTemplateWsRequest.builder() - .setPermission("admin") - .setTemplateName("my-new-template") - .build()); - - SearchTemplatesWsResponse searchTemplatesWsResponse = permissionsWsClient.searchTemplates( - new SearchTemplatesWsRequest() - .setQuery("my-new-template")); - assertThat(searchTemplatesWsResponse.getPermissionTemplates(0).getName()).isEqualTo("my-new-template"); - assertThat(searchTemplatesWsResponse.getPermissionTemplates(0).getPermissions(0).getKey()).isEqualTo("admin"); - assertThat(searchTemplatesWsResponse.getPermissionTemplates(0).getPermissions(0).getUsersCount()).isEqualTo(1); - assertThat(searchTemplatesWsResponse.getPermissionTemplates(0).getPermissions(0).getGroupsCount()).isEqualTo(1); - assertThat(searchTemplatesWsResponse.getPermissionTemplates(0).getPermissions(0).getWithProjectCreator()).isTrue(); - - permissionsWsClient.removeGroupFromTemplate( - new RemoveGroupFromTemplateWsRequest() - .setPermission("admin") - .setTemplateName("my-new-template") - .setGroupName(GROUP_NAME)); - - permissionsWsClient.removeUserFromTemplate( - new RemoveUserFromTemplateWsRequest() - .setPermission("admin") - .setTemplateName("my-new-template") - .setLogin(LOGIN)); - - permissionsWsClient.removeProjectCreatorFromTemplate( - RemoveProjectCreatorFromTemplateWsRequest.builder() - .setPermission("admin") - .setTemplateName("my-new-template") - .build() - ); - - SearchTemplatesWsResponse clearedSearchTemplatesWsResponse = permissionsWsClient.searchTemplates( - new SearchTemplatesWsRequest() - .setQuery("my-new-template")); - assertThat(clearedSearchTemplatesWsResponse.getPermissionTemplates(0).getPermissionsList()) - .extracting(Permission::getUsersCount, Permission::getGroupsCount, Permission::getWithProjectCreator) - .hasSize(5) - .containsOnly(tuple(0, 0, false)); - } - - private static void createUser(String login, String name) { - adminWsClient.wsConnector().call( - new PostRequest("api/users/create") - .setParam("login", login) - .setParam("name", name) - .setParam("password", "123456")); - } - - private static void deactivateUser(String login) { - adminWsClient.wsConnector().call( - new PostRequest("api/users/deactivate") - .setParam("login", login)); - } - - private static void createGroup(String groupName) { - adminWsClient.wsConnector().call( - new PostRequest("api/user_groups/create") - .setParam("name", groupName)); - } - - private static void deleteGroup(String groupName) { - adminWsClient.wsConnector().call( - new PostRequest("api/user_groups/delete") - .setParam("name", groupName)); - } -} diff --git a/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionTemplateTest.java b/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionTemplateTest.java deleted file mode 100644 index b0a82a81dc3..00000000000 --- a/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionTemplateTest.java +++ /dev/null @@ -1,212 +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 org.sonarqube.tests.authorisation; - -import com.sonar.orchestrator.Orchestrator; -import java.util.Arrays; -import java.util.Optional; -import org.junit.After; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.DisableOnDebug; -import org.junit.rules.TestRule; -import org.junit.rules.Timeout; -import org.sonarqube.tests.Category6Suite; -import org.sonarqube.qa.util.Tester; -import org.sonarqube.ws.Organizations.Organization; -import org.sonarqube.ws.WsPermissions; -import org.sonarqube.ws.WsPermissions.CreateTemplateWsResponse; -import org.sonarqube.ws.WsProjects.CreateWsResponse.Project; -import org.sonarqube.ws.WsUsers.CreateWsResponse; -import org.sonarqube.ws.client.WsClient; -import org.sonarqube.ws.client.component.SearchProjectsRequest; -import org.sonarqube.ws.client.permission.AddUserToTemplateWsRequest; -import org.sonarqube.ws.client.permission.ApplyTemplateWsRequest; -import org.sonarqube.ws.client.permission.BulkApplyTemplateWsRequest; -import org.sonarqube.ws.client.permission.CreateTemplateWsRequest; -import org.sonarqube.ws.client.permission.PermissionsService; -import org.sonarqube.ws.client.permission.UsersWsRequest; - -import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; -import static org.assertj.core.api.Assertions.assertThat; - -public class PermissionTemplateTest { - @ClassRule - public static final Orchestrator orchestrator = Category6Suite.ORCHESTRATOR; - - @Rule - public TestRule safeguard = new DisableOnDebug(Timeout.seconds(300)); - @Rule - public Tester tester = new Tester(orchestrator) - .setElasticsearchHttpPort(Category6Suite.SEARCH_HTTP_PORT); - - @After - public void tearDown() throws Exception { - unlockWritesOnProjectIndices(); - } - - @Test - public void apply_permission_template_on_project() { - Organization organization = tester.organizations().generate(); - Project project = createPrivateProject(organization); - CreateWsResponse.User user = tester.users().generateMember(organization); - CreateWsResponse.User anotherUser = tester.users().generateMember(organization); - - assertThatUserDoesNotHavePermission(user, organization, project); - assertThatUserDoesNotHavePermission(anotherUser, organization, project); - assertThat(userHasAccessToIndexedProject(user, organization, project)).isTrue(); - assertThat(userHasAccessToIndexedProject(anotherUser, organization, project)).isTrue(); - - // create permission template that gives read permission to "user" - createAndApplyTemplate(organization, project, user); - - assertThatUserHasPermission(user, organization, project); - assertThatUserDoesNotHavePermission(anotherUser, organization, project); - assertThat(userHasAccessToIndexedProject(user, organization, project)).isTrue(); - assertThat(userHasAccessToIndexedProject(anotherUser, organization, project)).isFalse(); - } - - @Test - public void bulk_apply_template_on_projects() { - Organization organization = tester.organizations().generate(); - CreateWsResponse.User user = tester.users().generateMember(organization); - CreateWsResponse.User anotherUser = tester.users().generateMember(organization); - WsPermissions.PermissionTemplate template = createTemplate(organization).getPermissionTemplate(); - tester.wsClient().permissions().addUserToTemplate(new AddUserToTemplateWsRequest() - .setOrganization(organization.getKey()) - .setTemplateId(template.getId()) - .setLogin(user.getLogin()) - .setPermission("user")); - Project project1 = createPrivateProject(organization); - Project project2 = createPrivateProject(organization); - Project untouchedProject = createPrivateProject(organization); - - tester.wsClient().permissions().bulkApplyTemplate(new BulkApplyTemplateWsRequest() - .setOrganization(organization.getKey()) - .setTemplateId(template.getId()) - .setProjects(Arrays.asList(project1.getKey(), project2.getKey()))); - - assertThatUserDoesNotHavePermission(anotherUser, organization, untouchedProject); - assertThatUserDoesNotHavePermission(anotherUser, organization, project1); - assertThatUserDoesNotHavePermission(anotherUser, organization, project2); - assertThatUserHasPermission(user, organization, project1); - assertThatUserHasPermission(user, organization, project2); - assertThatUserDoesNotHavePermission(user, organization, untouchedProject); - } - - @Test - public void indexing_errors_are_recovered_when_applying_permission_template_on_project() throws Exception { - Organization organization = tester.organizations().generate(); - Project project = createPrivateProject(organization); - CreateWsResponse.User user = tester.users().generateMember(organization); - CreateWsResponse.User anotherUser = tester.users().generateMember(organization); - - lockWritesOnProjectIndices(); - - createAndApplyTemplate(organization, project, user); - - assertThatUserHasPermission(user, organization, project); - assertThatUserDoesNotHavePermission(anotherUser, organization, project); - assertThat(userHasAccessToIndexedProject(user, organization, project)).isTrue(); - // inconsistent, should be false. Waiting for ES to be updated. - assertThat(userHasAccessToIndexedProject(user, organization, project)).isTrue(); - - unlockWritesOnProjectIndices(); - - boolean recovered = false; - while (!recovered) { - Thread.sleep(1_000L); - recovered = !userHasAccessToIndexedProject(anotherUser, organization, project); - } - } - - private void lockWritesOnProjectIndices() throws Exception { - tester.elasticsearch().lockWrites("issues"); - tester.elasticsearch().lockWrites("projectmeasures"); - tester.elasticsearch().lockWrites("components"); - } - - private void unlockWritesOnProjectIndices() throws Exception { - tester.elasticsearch().unlockWrites("issues"); - tester.elasticsearch().unlockWrites("projectmeasures"); - tester.elasticsearch().unlockWrites("components"); - } - - /** - * Gives the read access only to the specified user. All other users and groups - * loose their ability to see the project. - */ - private void createAndApplyTemplate(Organization organization, Project project, CreateWsResponse.User user) { - String templateName = "For user"; - PermissionsService service = tester.wsClient().permissions(); - service.createTemplate(new CreateTemplateWsRequest() - .setOrganization(organization.getKey()) - .setName(templateName) - .setDescription("Give admin permissions to single user")); - service.addUserToTemplate(new AddUserToTemplateWsRequest() - .setOrganization(organization.getKey()) - .setLogin(user.getLogin()) - .setPermission("user") - .setTemplateName(templateName)); - service.applyTemplate(new ApplyTemplateWsRequest() - .setOrganization(organization.getKey()) - .setProjectKey(project.getKey()) - .setTemplateName(templateName)); - } - - private CreateTemplateWsResponse createTemplate(Organization organization) { - return tester.wsClient().permissions().createTemplate(new CreateTemplateWsRequest() - .setOrganization(organization.getKey()) - .setName(randomAlphabetic(20))); - } - - private Project createPrivateProject(Organization organization) { - return tester.projects().generate(organization, p -> p.setVisibility("private")); - } - - private void assertThatUserHasPermission(CreateWsResponse.User user, Organization organization, Project project) { - assertThat(hasBrowsePermission(user, organization, project)).isTrue(); - } - - private void assertThatUserDoesNotHavePermission(CreateWsResponse.User user, Organization organization, Project project) { - assertThat(hasBrowsePermission(user, organization, project)).isFalse(); - } - - private boolean userHasAccessToIndexedProject(CreateWsResponse.User user, Organization organization, Project project) { - SearchProjectsRequest request = SearchProjectsRequest.builder().setOrganization(organization.getKey()).build(); - WsClient userSession = tester.as(user.getLogin()).wsClient(); - return userSession.components().searchProjects(request) - .getComponentsList().stream() - .anyMatch(c -> c.getKey().equals(project.getKey())); - } - - private boolean hasBrowsePermission(CreateWsResponse.User user, Organization organization, Project project) { - UsersWsRequest request = new UsersWsRequest() - .setOrganization(organization.getKey()) - .setProjectKey(project.getKey()) - .setPermission("user"); - WsPermissions.UsersWsResponse response = tester.wsClient().permissions().users(request); - Optional found = response.getUsersList().stream() - .filter(u -> user.getLogin().equals(u.getLogin())) - .findFirst(); - return found.isPresent(); - } -} diff --git a/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionTemplatesPageTest.java b/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionTemplatesPageTest.java deleted file mode 100644 index f94a50bb0b3..00000000000 --- a/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionTemplatesPageTest.java +++ /dev/null @@ -1,45 +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 org.sonarqube.tests.authorisation; - -import com.sonar.orchestrator.Orchestrator; -import org.sonarqube.tests.Category1Suite; -import org.junit.ClassRule; -import org.junit.Test; - -import static util.selenium.Selenese.runSelenese; - -public class PermissionTemplatesPageTest { - - @ClassRule - public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; - - @Test - public void should_display_page() throws Exception { - runSelenese(orchestrator, - "/authorisation/PermissionTemplatesPageTest/should_display_page.html", - "/authorisation/PermissionTemplatesPageTest/should_create.html"); - } - - @Test - public void should_manage_project_creators() throws Exception { - runSelenese(orchestrator, "/authorisation/PermissionTemplatesPageTest/should_manage_project_creators.html"); - } -} diff --git a/tests/src/test/java/org/sonarqube/tests/authorisation/ProvisioningPermissionTest.java b/tests/src/test/java/org/sonarqube/tests/authorisation/ProvisioningPermissionTest.java deleted file mode 100644 index a71af6eecc5..00000000000 --- a/tests/src/test/java/org/sonarqube/tests/authorisation/ProvisioningPermissionTest.java +++ /dev/null @@ -1,150 +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 org.sonarqube.tests.authorisation; - -import com.sonar.orchestrator.Orchestrator; -import org.sonarqube.tests.Category1Suite; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonarqube.ws.WsProjects.CreateWsResponse.Project; -import org.sonarqube.ws.client.HttpException; -import org.sonarqube.ws.client.permission.AddGroupWsRequest; -import org.sonarqube.ws.client.permission.AddUserWsRequest; -import org.sonarqube.ws.client.permission.PermissionsService; -import org.sonarqube.ws.client.permission.RemoveGroupWsRequest; -import org.sonarqube.ws.client.permission.RemoveUserWsRequest; -import org.sonarqube.ws.client.project.CreateRequest; -import util.user.UserRule; - -import static org.assertj.core.api.Assertions.assertThat; -import static util.ItUtils.newAdminWsClient; -import static util.ItUtils.newUserWsClient; -import static util.selenium.Selenese.runSelenese; - -public class ProvisioningPermissionTest { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @ClassRule - public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; - - @ClassRule - public static UserRule userRule = UserRule.from(orchestrator); - - private static final String PASSWORD = "password"; - - private static final String ADMIN_WITH_PROVISIONING = "admin-with-provisioning"; - private static final String ADMIN_WITHOUT_PROVISIONING = "admin-without-provisioning"; - private static final String USER_WITH_PROVISIONING = "user-with-provisioning"; - private static final String USER_WITHOUT_PROVISIONING = "user-without-provisioning"; - - private static PermissionsService permissionsWsClient; - - @BeforeClass - public static void init() { - permissionsWsClient = newAdminWsClient(orchestrator).permissions(); - - // remove default permission "provisioning" from anyone(); - permissionsWsClient.removeGroup(new RemoveGroupWsRequest().setGroupName("anyone").setPermission("provisioning")); - - userRule.createUser(ADMIN_WITH_PROVISIONING, PASSWORD); - addUserPermission(ADMIN_WITH_PROVISIONING, "admin"); - addUserPermission(ADMIN_WITH_PROVISIONING, "provisioning"); - - userRule.createUser(ADMIN_WITHOUT_PROVISIONING, PASSWORD); - addUserPermission(ADMIN_WITHOUT_PROVISIONING, "admin"); - removeUserPermission(ADMIN_WITHOUT_PROVISIONING, "provisioning"); - - userRule.createUser(USER_WITH_PROVISIONING, PASSWORD); - addUserPermission(USER_WITH_PROVISIONING, "provisioning"); - - userRule.createUser(USER_WITHOUT_PROVISIONING, PASSWORD); - removeUserPermission(USER_WITHOUT_PROVISIONING, "provisioning"); - } - - @AfterClass - public static void restoreData() throws Exception { - userRule.resetUsers(); - permissionsWsClient.addGroup(new AddGroupWsRequest().setGroupName("anyone").setPermission("provisioning")); - } - - /** - * SONAR-3871 - * SONAR-4709 - */ - @Test - public void organization_administrator_cannot_provision_project_if_he_does_not_have_provisioning_permission() { - runSelenese(orchestrator, "/authorisation/ProvisioningPermissionTest/should-not-be-able-to-provision-project.html"); - } - - /** - * SONAR-3871 - * SONAR-4709 - */ - @Test - public void organization_administrator_can_provision_project_if_he_has_provisioning_permission() { - runSelenese(orchestrator, "/authorisation/ProvisioningPermissionTest/should-be-able-to-provision-project.html"); - } - - /** - * SONAR-3871 - * SONAR-4709 - */ - @Test - public void user_can_provision_project_through_ws_if_he_has_provisioning_permission() { - final String newKey = "new-project"; - final String newName = "New Project"; - - Project created = newUserWsClient(orchestrator, USER_WITH_PROVISIONING, PASSWORD).projects() - .create(CreateRequest.builder().setKey(newKey).setName(newName).build()) - .getProject(); - - assertThat(created).isNotNull(); - assertThat(created.getKey()).isEqualTo(newKey); - assertThat(created.getName()).isEqualTo(newName); - } - - /** - * SONAR-3871 - * SONAR-4709 - */ - @Test - public void user_cannot_provision_project_through_ws_if_he_does_not_have_provisioning_permission() { - thrown.expect(HttpException.class); - thrown.expectMessage("403"); - - newUserWsClient(orchestrator, USER_WITHOUT_PROVISIONING, PASSWORD).projects() - .create(CreateRequest.builder().setKey("new-project").setName("New Project").build()) - .getProject(); - } - - private static void addUserPermission(String login, String permission) { - permissionsWsClient.addUser(new AddUserWsRequest().setLogin(login).setPermission(permission)); - } - - private static void removeUserPermission(String login, String permission) { - permissionsWsClient.removeUser(new RemoveUserWsRequest().setLogin(login).setPermission(permission)); - } -} diff --git a/tests/src/test/java/org/sonarqube/tests/authorisation/QualityProfileAdminPermissionTest.java b/tests/src/test/java/org/sonarqube/tests/authorisation/QualityProfileAdminPermissionTest.java deleted file mode 100644 index b96d5cc719c..00000000000 --- a/tests/src/test/java/org/sonarqube/tests/authorisation/QualityProfileAdminPermissionTest.java +++ /dev/null @@ -1,68 +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 org.sonarqube.tests.authorisation; - -import com.sonar.orchestrator.Orchestrator; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.sonarqube.tests.Category1Suite; -import org.sonarqube.qa.util.Tester; -import org.sonarqube.ws.client.permission.AddUserWsRequest; -import org.sonarqube.ws.client.qualityprofile.CreateRequest; -import util.selenium.Selenese; - -import static util.ItUtils.runProjectAnalysis; - -/** - * SONAR-4210 - */ -public class QualityProfileAdminPermissionTest { - - @ClassRule - public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; - - @Rule - public Tester tester = new Tester(orchestrator).disableOrganizations(); - - @Test - public void permission_should_grant_access_to_profile() { - runProjectAnalysis(orchestrator, "shared/xoo-sample"); - - tester.users().generate(u -> u.setLogin("not_profileadm").setPassword("userpwd")); - tester.users().generate(u -> u.setLogin("profileadm").setPassword("papwd")); - tester.wsClient().permissions().addUser(new AddUserWsRequest().setLogin("profileadm").setPermission("profileadmin")); - createProfile("xoo", "foo"); - - Selenese.runSelenese(orchestrator, - // Verify normal user is not allowed to do any modification - "/authorisation/QualityProfileAdminPermissionTest/normal-user.html", - // Verify profile admin is allowed to do modifications - "/authorisation/QualityProfileAdminPermissionTest/profile-admin.html"); - } - - private void createProfile(String language, String name) { - tester.wsClient().qualityProfiles().create(CreateRequest.builder() - .setLanguage(language) - .setName(name) - .build()); - } - -} diff --git a/tests/src/test/java/org/sonarqube/tests/authorisation/SystemPasscodeTest.java b/tests/src/test/java/org/sonarqube/tests/authorisation/SystemPasscodeTest.java deleted file mode 100644 index b7fabd3bb92..00000000000 --- a/tests/src/test/java/org/sonarqube/tests/authorisation/SystemPasscodeTest.java +++ /dev/null @@ -1,94 +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 org.sonarqube.tests.authorisation; - -import com.sonar.orchestrator.Orchestrator; -import com.sonar.orchestrator.OrchestratorBuilder; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.sonarqube.qa.util.Tester; -import org.sonarqube.ws.client.GetRequest; -import org.sonarqube.ws.client.WsRequest; -import org.sonarqube.ws.client.WsResponse; - -import static org.assertj.core.api.Assertions.assertThat; -import static util.ItUtils.pluginArtifact; - -public class SystemPasscodeTest { - - private static final String VALID_PASSCODE = "123456"; - private static final String INVALID_PASSCODE = "not" + VALID_PASSCODE; - private static final String PASSCODE_HEADER = "X-Sonar-Passcode"; - - private static Orchestrator orchestrator; - - @BeforeClass - public static void setUp() throws Exception { - OrchestratorBuilder builder = Orchestrator.builderEnv() - // this privileged plugin provides the WS api/system_passcode/check - // that is used by the tests - .addPlugin(pluginArtifact("fake-governance-plugin")) - .setServerProperty("sonar.web.systemPasscode", VALID_PASSCODE); - orchestrator = builder.build(); - orchestrator.start(); - } - - @AfterClass - public static void stop() { - if (orchestrator != null) { - orchestrator.stop(); - } - } - - @Rule - public Tester tester = new Tester(orchestrator); - - @Test - public void system_access_is_granted_if_valid_passcode_is_sent_through_http_header() { - WsRequest request = newRequest() - .setHeader(PASSCODE_HEADER, VALID_PASSCODE); - - WsResponse response = tester.asAnonymous().wsClient().wsConnector().call(request); - assertThat(response.code()).isEqualTo(200); - } - - @Test - public void system_access_is_rejected_if_invalid_passcode_is_sent_through_http_header() { - WsRequest request = newRequest() - .setHeader(PASSCODE_HEADER, INVALID_PASSCODE); - - WsResponse response = tester.asAnonymous().wsClient().wsConnector().call(request); - assertThat(response.code()).isEqualTo(401); - } - - @Test - public void system_access_is_rejected_if_passcode_is_not_sent() { - WsRequest request = newRequest(); - - WsResponse response = tester.asAnonymous().wsClient().wsConnector().call(request); - assertThat(response.code()).isEqualTo(401); - } - - private static GetRequest newRequest() { - return new GetRequest("api/system_passcode/check"); - } -} diff --git a/tests/src/test/java/org/sonarqube/tests/authorization/AuthorizationSuite.java b/tests/src/test/java/org/sonarqube/tests/authorization/AuthorizationSuite.java new file mode 100644 index 00000000000..cee2d04936e --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/authorization/AuthorizationSuite.java @@ -0,0 +1,55 @@ +/* + * 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 org.sonarqube.tests.authorization; + +import com.sonar.orchestrator.Orchestrator; +import org.junit.ClassRule; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import static util.ItUtils.pluginArtifact; +import static util.ItUtils.xooPlugin; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + ExecuteAnalysisPermissionTest.class, + IssuePermissionTest.class, + PermissionSearchTest.class, + ProvisioningPermissionTest.class, + QualityProfileAdminPermissionTest.class, + SystemPasscodeTest.class +}) +public class AuthorizationSuite { + + @ClassRule + public static final Orchestrator ORCHESTRATOR = Orchestrator.builderEnv() + // reduce memory for Elasticsearch + .setServerProperty("sonar.search.javaOpts", "-Xms128m -Xmx128m") + + // for SystemPasscodeTest + // this privileged plugin provides the WS api/system_passcode/check + // that is used by the tests + .addPlugin(pluginArtifact("fake-governance-plugin")) + .setServerProperty("sonar.web.systemPasscode", SystemPasscodeTest.VALID_PASSCODE) + + .addPlugin(xooPlugin()) + .build(); + +} diff --git a/tests/src/test/java/org/sonarqube/tests/authorization/ExecuteAnalysisPermissionTest.java b/tests/src/test/java/org/sonarqube/tests/authorization/ExecuteAnalysisPermissionTest.java new file mode 100644 index 00000000000..78f8cfc1e0a --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/authorization/ExecuteAnalysisPermissionTest.java @@ -0,0 +1,142 @@ +/* + * 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 org.sonarqube.tests.authorization; + +import com.sonar.orchestrator.Orchestrator; +import com.sonar.orchestrator.build.BuildFailureException; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.sonarqube.qa.util.Tester; +import org.sonarqube.ws.client.permission.AddGroupWsRequest; +import org.sonarqube.ws.client.permission.AddProjectCreatorToTemplateWsRequest; +import org.sonarqube.ws.client.permission.RemoveGroupWsRequest; +import org.sonarqube.ws.client.project.UpdateVisibilityRequest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static util.ItUtils.runProjectAnalysis; + +/** + * SONAR-4397 + */ +public class ExecuteAnalysisPermissionTest { + + private final static String USER_LOGIN = "scanperm"; + private final static String USER_PASSWORD = "thewhite"; + private final static String PROJECT_KEY = "sample"; + + @ClassRule + public static Orchestrator orchestrator = AuthorizationSuite.ORCHESTRATOR; + + @Rule + public Tester tester = new Tester(orchestrator) + // all the tests of AuthorizationSuite must disable organizations + .disableOrganizations(); + + @Before + public void setUp() { + tester.users().generate(u -> u.setLogin(USER_LOGIN).setPassword(USER_PASSWORD)); + orchestrator.getServer().provisionProject(PROJECT_KEY, "Sample"); + } + + @After + public void tearDown() { + addGlobalPermission("anyone", "scan"); + } + + @Test + public void should_fail_if_logged_but_no_scan_permission() throws Exception { + executeLoggedAnalysis(); + + removeGlobalPermission("anyone", "scan"); + try { + // Execute logged analysis, but without the "Execute Analysis" permission + executeLoggedAnalysis(); + fail(); + } catch (BuildFailureException e) { + assertThat(e.getResult().getLogs()).contains( + "You're only authorized to execute a local (preview) SonarQube analysis without pushing the results to the SonarQube server. Please contact your SonarQube administrator."); + } + + tester.wsClient().projects().updateVisibility(UpdateVisibilityRequest.builder().setProject(PROJECT_KEY).setVisibility("private").build()); + try { + // Execute anonymous analysis + executeAnonymousAnalysis(); + fail(); + } catch (BuildFailureException e) { + assertThat(e.getResult().getLogs()).contains( + "You're not authorized to execute any SonarQube analysis. Please contact your SonarQube administrator."); + } + } + + @Test + public void no_need_for_browse_permission_to_scan() throws Exception { + // Do a first analysis, no error + executeAnonymousAnalysis(); + + // make project private + tester.wsClient().projects().updateVisibility(UpdateVisibilityRequest.builder().setProject("sample").setVisibility("private").build()); + + // still no error + executeAnonymousAnalysis(); + } + + @Test + public void execute_analysis_with_scan_permission_only_on_project() throws Exception { + removeGlobalPermission("anyone", "scan"); + addProjectPermission("anyone", PROJECT_KEY, "scan"); + + executeLoggedAnalysis(); + } + + @Test + public void execute_analysis_with_scan_on_default_template() { + removeGlobalPermission("anyone", "scan"); + tester.wsClient().permissions().addProjectCreatorToTemplate(AddProjectCreatorToTemplateWsRequest.builder() + .setPermission("scan") + .setTemplateId("default_template") + .build()); + + runProjectAnalysis(orchestrator, "shared/xoo-sample", "sonar.login", USER_LOGIN, "sonar.password", USER_PASSWORD, "sonar.projectKey", "ANOTHER_PROJECT_KEY"); + } + + private void addProjectPermission(String groupName, String projectKey, String permission) { + tester.wsClient().permissions().addGroup(new AddGroupWsRequest().setGroupName(groupName).setProjectKey(projectKey).setPermission(permission)); + } + + private void addGlobalPermission(String groupName, String permission) { + tester.wsClient().permissions().addGroup(new AddGroupWsRequest().setGroupName(groupName).setPermission(permission)); + } + + private void removeGlobalPermission(String groupName, String permission) { + tester.wsClient().permissions().removeGroup(new RemoveGroupWsRequest().setGroupName(groupName).setPermission(permission)); + } + + private static void executeLoggedAnalysis() { + runProjectAnalysis(orchestrator, "shared/xoo-sample", "sonar.login", USER_LOGIN, "sonar.password", USER_PASSWORD); + } + + private static void executeAnonymousAnalysis() { + runProjectAnalysis(orchestrator, "shared/xoo-sample"); + } +} diff --git a/tests/src/test/java/org/sonarqube/tests/authorization/IssuePermissionTest.java b/tests/src/test/java/org/sonarqube/tests/authorization/IssuePermissionTest.java new file mode 100644 index 00000000000..910bb6124c2 --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/authorization/IssuePermissionTest.java @@ -0,0 +1,277 @@ +/* + * 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 org.sonarqube.tests.authorization; + +import com.sonar.orchestrator.Orchestrator; +import com.sonar.orchestrator.build.SonarScanner; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.wsclient.SonarClient; +import org.sonar.wsclient.base.HttpException; +import org.sonar.wsclient.issue.Issue; +import org.sonar.wsclient.issue.IssueQuery; +import org.sonar.wsclient.user.UserParameters; +import org.sonarqube.qa.util.Tester; +import org.sonarqube.ws.Issues; +import org.sonarqube.ws.client.issue.BulkChangeRequest; +import org.sonarqube.ws.client.permission.AddUserWsRequest; +import org.sonarqube.ws.client.project.UpdateVisibilityRequest; +import util.ItUtils; + +import static java.util.Arrays.asList; +import static junit.framework.TestCase.fail; +import static org.assertj.core.api.Assertions.assertThat; +import static util.ItUtils.newUserWsClient; +import static util.ItUtils.projectDir; + +public class IssuePermissionTest { + + @ClassRule + public static Orchestrator orchestrator = AuthorizationSuite.ORCHESTRATOR; + + @Rule + public Tester tester = new Tester(orchestrator) + // all the tests of AuthorizationSuite must disable organizations + .disableOrganizations(); + + @Before + public void init() { + ItUtils.restoreProfile(orchestrator, getClass().getResource("/authorisation/one-issue-per-line-profile.xml")); + + orchestrator.getServer().provisionProject("privateProject", "PrivateProject"); + tester.wsClient().projects().updateVisibility(UpdateVisibilityRequest.builder().setProject("privateProject").setVisibility("private").build()); + orchestrator.getServer().associateProjectToQualityProfile("privateProject", "xoo", "one-issue-per-line"); + SonarScanner privateProject = SonarScanner.create(projectDir("shared/xoo-sample")) + .setProperty("sonar.projectKey", "privateProject") + .setProperty("sonar.projectName", "PrivateProject"); + orchestrator.executeBuild(privateProject); + + orchestrator.getServer().provisionProject("publicProject", "PublicProject"); + orchestrator.getServer().associateProjectToQualityProfile("publicProject", "xoo", "one-issue-per-line"); + SonarScanner publicProject = SonarScanner.create(projectDir("shared/xoo-sample")) + .setProperty("sonar.projectKey", "publicProject") + .setProperty("sonar.projectName", "PublicProject"); + + + orchestrator.executeBuild(publicProject); + } + + @Test + public void need_user_permission_on_project_to_see_issue() { + SonarClient client = orchestrator.getServer().adminWsClient(); + + String withBrowsePermission = "with-browse-permission"; + String withoutBrowsePermission = "without-browse-permission"; + + try { + client.userClient().create(UserParameters.create().login(withBrowsePermission).name(withBrowsePermission) + .password("password").passwordConfirmation("password")); + addUserPermission(withBrowsePermission, "privateProject", "user"); + + client.userClient().create(UserParameters.create().login(withoutBrowsePermission).name(withoutBrowsePermission) + .password("password").passwordConfirmation("password")); + + // Without user permission, a user cannot see issues on the project + assertThat(orchestrator.getServer().wsClient(withoutBrowsePermission, "password").issueClient().find( + IssueQuery.create().componentRoots("privateProject")).list()).isEmpty(); + + // With user permission, a user can see issues on the project + assertThat(orchestrator.getServer().wsClient(withBrowsePermission, "password").issueClient().find( + IssueQuery.create().componentRoots("privateProject")).list()).isNotEmpty(); + + } finally { + client.userClient().deactivate(withBrowsePermission); + client.userClient().deactivate(withoutBrowsePermission); + } + } + + /** + * SONAR-4839 + */ + @Test + public void need_user_permission_on_project_to_see_issue_changelog() { + SonarClient client = orchestrator.getServer().adminWsClient(); + Issue issue = client.issueClient().find(IssueQuery.create().componentRoots("privateProject")).list().get(0); + client.issueClient().assign(issue.key(), "admin"); + + String withBrowsePermission = "with-browse-permission"; + String withoutBrowsePermission = "without-browse-permission"; + + try { + client.userClient().create(UserParameters.create().login(withBrowsePermission).name(withBrowsePermission) + .password("password").passwordConfirmation("password")); + addUserPermission(withBrowsePermission, "privateProject", "user"); + + client.userClient().create(UserParameters.create().login(withoutBrowsePermission).name(withoutBrowsePermission) + .password("password").passwordConfirmation("password")); + + // Without user permission, a user cannot see issue changelog on the project + try { + changelog(issue.key(), withoutBrowsePermission, "password"); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(org.sonarqube.ws.client.HttpException.class).describedAs("403"); + } + + // Without user permission, a user cannot see issues on the project + assertThat(changelog(issue.key(), withBrowsePermission, "password").getChangelogList()).isNotEmpty(); + + } finally { + client.userClient().deactivate(withBrowsePermission); + client.userClient().deactivate(withoutBrowsePermission); + } + } + + /** + * SONAR-2447 + */ + @Test + public void need_administer_issue_permission_on_project_to_set_severity() { + SonarClient client = orchestrator.getServer().adminWsClient(); + Issue issueOnPrivateProject = client.issueClient().find(IssueQuery.create().componentRoots("privateProject")).list().get(0); + Issue issueOnPublicProject = client.issueClient().find(IssueQuery.create().componentRoots("publicProject")).list().get(0); + + String user = "user"; + + try { + client.userClient().create(UserParameters.create().login(user).name(user).password("password").passwordConfirmation("password")); + addUserPermission(user, "publicProject", "issueadmin"); + + // Without issue admin permission, a user cannot set severity on the issue + try { + orchestrator.getServer().wsClient(user, "password").issueClient().setSeverity(issueOnPrivateProject.key(), "BLOCKER"); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(HttpException.class).describedAs("404"); + } + + // With issue admin permission, a user can set severity on the issue + assertThat(orchestrator.getServer().wsClient(user, "password").issueClient().setSeverity(issueOnPublicProject.key(), "BLOCKER").severity()).isEqualTo("BLOCKER"); + + } finally { + client.userClient().deactivate(user); + } + } + + /** + * SONAR-2447 + */ + @Test + public void need_administer_issue_permission_on_project_to_flag_as_false_positive() { + SonarClient client = orchestrator.getServer().adminWsClient(); + Issue issueOnPrivateProject = client.issueClient().find(IssueQuery.create().componentRoots("privateProject")).list().get(0); + Issue issueOnPublicProject = client.issueClient().find(IssueQuery.create().componentRoots("publicProject")).list().get(0); + + String user = "user"; + + try { + client.userClient().create(UserParameters.create().login(user).name(user).password("password").passwordConfirmation("password")); + addUserPermission(user, "publicProject", "issueadmin"); + + // Without issue admin permission, a user cannot flag an issue as false positive + try { + orchestrator.getServer().wsClient(user, "password").issueClient().doTransition(issueOnPrivateProject.key(), "falsepositive"); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(HttpException.class).describedAs("404"); + } + + // With issue admin permission, a user can flag an issue as false positive + assertThat(orchestrator.getServer().wsClient(user, "password").issueClient().doTransition(issueOnPublicProject.key(), "falsepositive").status()).isEqualTo("RESOLVED"); + + } finally { + client.userClient().deactivate(user); + } + } + + /** + * SONAR-2447 + */ + @Test + public void need_administer_issue_permission_on_project_to_bulk_change_severity_and_false_positive() { + SonarClient client = orchestrator.getServer().adminWsClient(); + Issue issueOnPrivateProject = client.issueClient().find(IssueQuery.create().componentRoots("privateProject")).list().get(0); + Issue issueOnPublicProject = client.issueClient().find(IssueQuery.create().componentRoots("publicProject")).list().get(0); + + String user = "user"; + + try { + client.userClient().create(UserParameters.create().login(user).name(user).password("password").passwordConfirmation("password")); + addUserPermission(user, "privateProject", "issueadmin"); + + Issues.BulkChangeWsResponse response = makeBlockerAndFalsePositive(user, issueOnPrivateProject, issueOnPublicProject); + + // public project but no issueadmin permission on publicProject => issue visible but not updated + // no user permission on privateproject => issue invisible and not updated + assertThat(response.getTotal()).isEqualTo(1); + assertThat(response.getSuccess()).isEqualTo(0); + assertThat(response.getIgnored()).isEqualTo(1); + + addUserPermission(user, "privateProject", "user"); + response = makeBlockerAndFalsePositive(user, issueOnPrivateProject, issueOnPublicProject); + + // public project but no issueadmin permission on publicProject => unsuccessful on issueOnPublicProject + // user and issueadmin permission on privateproject => successful and 1 more issue visible + assertThat(response.getTotal()).isEqualTo(2); + assertThat(response.getSuccess()).isEqualTo(1); + assertThat(response.getIgnored()).isEqualTo(1); + + addUserPermission(user, "publicProject", "issueadmin"); + response = makeBlockerAndFalsePositive(user, issueOnPrivateProject, issueOnPublicProject); + + // public and issueadmin permission on publicProject => successful on issueOnPublicProject + // issueOnPrivateProject already in specified state => unsuccessful + assertThat(response.getTotal()).isEqualTo(2); + assertThat(response.getSuccess()).isEqualTo(1); + assertThat(response.getIgnored()).isEqualTo(1); + + response = makeBlockerAndFalsePositive(user, issueOnPrivateProject, issueOnPublicProject); + + // issueOnPublicProject and issueOnPrivateProject already in specified state => unsuccessful + assertThat(response.getTotal()).isEqualTo(2); + assertThat(response.getSuccess()).isEqualTo(0); + assertThat(response.getIgnored()).isEqualTo(2); + } finally { + client.userClient().deactivate(user); + } + } + + private Issues.BulkChangeWsResponse makeBlockerAndFalsePositive(String user, Issue issueOnPrivateProject, Issue issueOnPublicProject) { + return newUserWsClient(orchestrator, user, "password").issues() + .bulkChange(BulkChangeRequest.builder().setIssues(asList(issueOnPrivateProject.key(), issueOnPublicProject.key())) + .setSetSeverity("BLOCKER") + .setDoTransition("falsepositive") + .build()); + } + + private void addUserPermission(String login, String projectKey, String permission) { + tester.wsClient().permissions().addUser( + new AddUserWsRequest() + .setLogin(login) + .setProjectKey(projectKey) + .setPermission(permission)); + } + + private static Issues.ChangelogWsResponse changelog(String issueKey, String login, String password) { + return newUserWsClient(orchestrator, login, password).issues().changelog(issueKey); + } +} diff --git a/tests/src/test/java/org/sonarqube/tests/authorization/PermissionSearchTest.java b/tests/src/test/java/org/sonarqube/tests/authorization/PermissionSearchTest.java new file mode 100644 index 00000000000..703544e337f --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/authorization/PermissionSearchTest.java @@ -0,0 +1,182 @@ +/* + * 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 org.sonarqube.tests.authorization; + +import com.sonar.orchestrator.Orchestrator; +import com.sonar.orchestrator.build.SonarScanner; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.RuleChain; +import org.sonarqube.qa.util.Tester; +import org.sonarqube.ws.WsPermissions; +import org.sonarqube.ws.WsPermissions.Permission; +import org.sonarqube.ws.WsPermissions.SearchTemplatesWsResponse; +import org.sonarqube.ws.client.PostRequest; +import org.sonarqube.ws.client.permission.AddGroupToTemplateWsRequest; +import org.sonarqube.ws.client.permission.AddGroupWsRequest; +import org.sonarqube.ws.client.permission.AddProjectCreatorToTemplateWsRequest; +import org.sonarqube.ws.client.permission.AddUserToTemplateWsRequest; +import org.sonarqube.ws.client.permission.AddUserWsRequest; +import org.sonarqube.ws.client.permission.CreateTemplateWsRequest; +import org.sonarqube.ws.client.permission.GroupsWsRequest; +import org.sonarqube.ws.client.permission.RemoveGroupFromTemplateWsRequest; +import org.sonarqube.ws.client.permission.RemoveProjectCreatorFromTemplateWsRequest; +import org.sonarqube.ws.client.permission.RemoveUserFromTemplateWsRequest; +import org.sonarqube.ws.client.permission.SearchTemplatesWsRequest; +import org.sonarqube.ws.client.permission.UsersWsRequest; +import util.ItUtils; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static util.ItUtils.projectDir; + +public class PermissionSearchTest { + + private static final String PROJECT_KEY = "sample"; + private static final String LOGIN = "george.orwell"; + private static final String GROUP_NAME = "1984"; + + @ClassRule + public static Orchestrator orchestrator = AuthorizationSuite.ORCHESTRATOR; + + private static Tester tester = new Tester(orchestrator) + // all the tests of AuthorizationSuite must disable organizations + .disableOrganizations(); + + @ClassRule + public static RuleChain ruleChain = RuleChain.outerRule(orchestrator).around(tester); + + @BeforeClass + public static void analyzeProject() { + ItUtils.restoreProfile(orchestrator, PermissionSearchTest.class.getResource("/authorisation/one-issue-per-line-profile.xml")); + + orchestrator.getServer().provisionProject(PROJECT_KEY, "Sample"); + orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line"); + SonarScanner sampleProject = SonarScanner.create(projectDir("shared/xoo-sample")); + orchestrator.executeBuild(sampleProject); + createUser(LOGIN, "George Orwell"); + createGroup(GROUP_NAME); + } + + @Test + public void permission_web_services() { + tester.wsClient().permissions().addUser( + new AddUserWsRequest() + .setPermission("admin") + .setLogin(LOGIN)); + tester.wsClient().permissions().addGroup( + new AddGroupWsRequest() + .setPermission("admin") + .setGroupName(GROUP_NAME)); + + WsPermissions.WsSearchGlobalPermissionsResponse searchGlobalPermissionsWsResponse = tester.wsClient().permissions().searchGlobalPermissions(); + assertThat(searchGlobalPermissionsWsResponse.getPermissionsList().get(0).getKey()).isEqualTo("admin"); + assertThat(searchGlobalPermissionsWsResponse.getPermissionsList().get(0).getUsersCount()).isEqualTo(1); + // by default, a group has the global admin permission + assertThat(searchGlobalPermissionsWsResponse.getPermissionsList().get(0).getGroupsCount()).isEqualTo(2); + + WsPermissions.UsersWsResponse users = tester.wsClient().permissions() + .users(new UsersWsRequest().setPermission("admin")); + assertThat(users.getUsersList()).extracting("login").contains(LOGIN); + + WsPermissions.WsGroupsResponse groupsResponse = tester.wsClient().permissions() + .groups(new GroupsWsRequest() + .setPermission("admin")); + assertThat(groupsResponse.getGroupsList()).extracting("name").contains(GROUP_NAME); + } + + @Test + public void template_permission_web_services() { + WsPermissions.CreateTemplateWsResponse createTemplateWsResponse = tester.wsClient().permissions().createTemplate( + new CreateTemplateWsRequest() + .setName("my-new-template") + .setDescription("template-used-in-tests")); + assertThat(createTemplateWsResponse.getPermissionTemplate().getName()).isEqualTo("my-new-template"); + + tester.wsClient().permissions().addUserToTemplate( + new AddUserToTemplateWsRequest() + .setPermission("admin") + .setTemplateName("my-new-template") + .setLogin(LOGIN)); + + tester.wsClient().permissions().addGroupToTemplate( + new AddGroupToTemplateWsRequest() + .setPermission("admin") + .setTemplateName("my-new-template") + .setGroupName(GROUP_NAME)); + + tester.wsClient().permissions().addProjectCreatorToTemplate( + AddProjectCreatorToTemplateWsRequest.builder() + .setPermission("admin") + .setTemplateName("my-new-template") + .build()); + + SearchTemplatesWsResponse searchTemplatesWsResponse = tester.wsClient().permissions().searchTemplates( + new SearchTemplatesWsRequest() + .setQuery("my-new-template")); + assertThat(searchTemplatesWsResponse.getPermissionTemplates(0).getName()).isEqualTo("my-new-template"); + assertThat(searchTemplatesWsResponse.getPermissionTemplates(0).getPermissions(0).getKey()).isEqualTo("admin"); + assertThat(searchTemplatesWsResponse.getPermissionTemplates(0).getPermissions(0).getUsersCount()).isEqualTo(1); + assertThat(searchTemplatesWsResponse.getPermissionTemplates(0).getPermissions(0).getGroupsCount()).isEqualTo(1); + assertThat(searchTemplatesWsResponse.getPermissionTemplates(0).getPermissions(0).getWithProjectCreator()).isTrue(); + + tester.wsClient().permissions().removeGroupFromTemplate( + new RemoveGroupFromTemplateWsRequest() + .setPermission("admin") + .setTemplateName("my-new-template") + .setGroupName(GROUP_NAME)); + + tester.wsClient().permissions().removeUserFromTemplate( + new RemoveUserFromTemplateWsRequest() + .setPermission("admin") + .setTemplateName("my-new-template") + .setLogin(LOGIN)); + + tester.wsClient().permissions().removeProjectCreatorFromTemplate( + RemoveProjectCreatorFromTemplateWsRequest.builder() + .setPermission("admin") + .setTemplateName("my-new-template") + .build() + ); + + SearchTemplatesWsResponse clearedSearchTemplatesWsResponse = tester.wsClient().permissions().searchTemplates( + new SearchTemplatesWsRequest() + .setQuery("my-new-template")); + assertThat(clearedSearchTemplatesWsResponse.getPermissionTemplates(0).getPermissionsList()) + .extracting(Permission::getUsersCount, Permission::getGroupsCount, Permission::getWithProjectCreator) + .hasSize(5) + .containsOnly(tuple(0, 0, false)); + } + + private static void createUser(String login, String name) { + tester.wsClient().wsConnector().call( + new PostRequest("api/users/create") + .setParam("login", login) + .setParam("name", name) + .setParam("password", "123456")); + } + + private static void createGroup(String groupName) { + tester.wsClient().wsConnector().call( + new PostRequest("api/user_groups/create") + .setParam("name", groupName)); + } +} diff --git a/tests/src/test/java/org/sonarqube/tests/authorization/PermissionTemplateTest.java b/tests/src/test/java/org/sonarqube/tests/authorization/PermissionTemplateTest.java new file mode 100644 index 00000000000..66b925d4fc4 --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/authorization/PermissionTemplateTest.java @@ -0,0 +1,212 @@ +/* + * 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 org.sonarqube.tests.authorization; + +import com.sonar.orchestrator.Orchestrator; +import java.util.Arrays; +import java.util.Optional; +import org.junit.After; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; +import org.sonarqube.tests.Category6Suite; +import org.sonarqube.qa.util.Tester; +import org.sonarqube.ws.Organizations.Organization; +import org.sonarqube.ws.WsPermissions; +import org.sonarqube.ws.WsPermissions.CreateTemplateWsResponse; +import org.sonarqube.ws.WsProjects.CreateWsResponse.Project; +import org.sonarqube.ws.WsUsers.CreateWsResponse; +import org.sonarqube.ws.client.WsClient; +import org.sonarqube.ws.client.component.SearchProjectsRequest; +import org.sonarqube.ws.client.permission.AddUserToTemplateWsRequest; +import org.sonarqube.ws.client.permission.ApplyTemplateWsRequest; +import org.sonarqube.ws.client.permission.BulkApplyTemplateWsRequest; +import org.sonarqube.ws.client.permission.CreateTemplateWsRequest; +import org.sonarqube.ws.client.permission.PermissionsService; +import org.sonarqube.ws.client.permission.UsersWsRequest; + +import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; +import static org.assertj.core.api.Assertions.assertThat; + +public class PermissionTemplateTest { + @ClassRule + public static final Orchestrator orchestrator = Category6Suite.ORCHESTRATOR; + + @Rule + public TestRule safeguard = new DisableOnDebug(Timeout.seconds(300)); + @Rule + public Tester tester = new Tester(orchestrator) + .setElasticsearchHttpPort(Category6Suite.SEARCH_HTTP_PORT); + + @After + public void tearDown() throws Exception { + unlockWritesOnProjectIndices(); + } + + @Test + public void apply_permission_template_on_project() { + Organization organization = tester.organizations().generate(); + Project project = createPrivateProject(organization); + CreateWsResponse.User user = tester.users().generateMember(organization); + CreateWsResponse.User anotherUser = tester.users().generateMember(organization); + + assertThatUserDoesNotHavePermission(user, organization, project); + assertThatUserDoesNotHavePermission(anotherUser, organization, project); + assertThat(userHasAccessToIndexedProject(user, organization, project)).isTrue(); + assertThat(userHasAccessToIndexedProject(anotherUser, organization, project)).isTrue(); + + // create permission template that gives read permission to "user" + createAndApplyTemplate(organization, project, user); + + assertThatUserHasPermission(user, organization, project); + assertThatUserDoesNotHavePermission(anotherUser, organization, project); + assertThat(userHasAccessToIndexedProject(user, organization, project)).isTrue(); + assertThat(userHasAccessToIndexedProject(anotherUser, organization, project)).isFalse(); + } + + @Test + public void bulk_apply_template_on_projects() { + Organization organization = tester.organizations().generate(); + CreateWsResponse.User user = tester.users().generateMember(organization); + CreateWsResponse.User anotherUser = tester.users().generateMember(organization); + WsPermissions.PermissionTemplate template = createTemplate(organization).getPermissionTemplate(); + tester.wsClient().permissions().addUserToTemplate(new AddUserToTemplateWsRequest() + .setOrganization(organization.getKey()) + .setTemplateId(template.getId()) + .setLogin(user.getLogin()) + .setPermission("user")); + Project project1 = createPrivateProject(organization); + Project project2 = createPrivateProject(organization); + Project untouchedProject = createPrivateProject(organization); + + tester.wsClient().permissions().bulkApplyTemplate(new BulkApplyTemplateWsRequest() + .setOrganization(organization.getKey()) + .setTemplateId(template.getId()) + .setProjects(Arrays.asList(project1.getKey(), project2.getKey()))); + + assertThatUserDoesNotHavePermission(anotherUser, organization, untouchedProject); + assertThatUserDoesNotHavePermission(anotherUser, organization, project1); + assertThatUserDoesNotHavePermission(anotherUser, organization, project2); + assertThatUserHasPermission(user, organization, project1); + assertThatUserHasPermission(user, organization, project2); + assertThatUserDoesNotHavePermission(user, organization, untouchedProject); + } + + @Test + public void indexing_errors_are_recovered_when_applying_permission_template_on_project() throws Exception { + Organization organization = tester.organizations().generate(); + Project project = createPrivateProject(organization); + CreateWsResponse.User user = tester.users().generateMember(organization); + CreateWsResponse.User anotherUser = tester.users().generateMember(organization); + + lockWritesOnProjectIndices(); + + createAndApplyTemplate(organization, project, user); + + assertThatUserHasPermission(user, organization, project); + assertThatUserDoesNotHavePermission(anotherUser, organization, project); + assertThat(userHasAccessToIndexedProject(user, organization, project)).isTrue(); + // inconsistent, should be false. Waiting for ES to be updated. + assertThat(userHasAccessToIndexedProject(user, organization, project)).isTrue(); + + unlockWritesOnProjectIndices(); + + boolean recovered = false; + while (!recovered) { + Thread.sleep(1_000L); + recovered = !userHasAccessToIndexedProject(anotherUser, organization, project); + } + } + + private void lockWritesOnProjectIndices() throws Exception { + tester.elasticsearch().lockWrites("issues"); + tester.elasticsearch().lockWrites("projectmeasures"); + tester.elasticsearch().lockWrites("components"); + } + + private void unlockWritesOnProjectIndices() throws Exception { + tester.elasticsearch().unlockWrites("issues"); + tester.elasticsearch().unlockWrites("projectmeasures"); + tester.elasticsearch().unlockWrites("components"); + } + + /** + * Gives the read access only to the specified user. All other users and groups + * loose their ability to see the project. + */ + private void createAndApplyTemplate(Organization organization, Project project, CreateWsResponse.User user) { + String templateName = "For user"; + PermissionsService service = tester.wsClient().permissions(); + service.createTemplate(new CreateTemplateWsRequest() + .setOrganization(organization.getKey()) + .setName(templateName) + .setDescription("Give admin permissions to single user")); + service.addUserToTemplate(new AddUserToTemplateWsRequest() + .setOrganization(organization.getKey()) + .setLogin(user.getLogin()) + .setPermission("user") + .setTemplateName(templateName)); + service.applyTemplate(new ApplyTemplateWsRequest() + .setOrganization(organization.getKey()) + .setProjectKey(project.getKey()) + .setTemplateName(templateName)); + } + + private CreateTemplateWsResponse createTemplate(Organization organization) { + return tester.wsClient().permissions().createTemplate(new CreateTemplateWsRequest() + .setOrganization(organization.getKey()) + .setName(randomAlphabetic(20))); + } + + private Project createPrivateProject(Organization organization) { + return tester.projects().generate(organization, p -> p.setVisibility("private")); + } + + private void assertThatUserHasPermission(CreateWsResponse.User user, Organization organization, Project project) { + assertThat(hasBrowsePermission(user, organization, project)).isTrue(); + } + + private void assertThatUserDoesNotHavePermission(CreateWsResponse.User user, Organization organization, Project project) { + assertThat(hasBrowsePermission(user, organization, project)).isFalse(); + } + + private boolean userHasAccessToIndexedProject(CreateWsResponse.User user, Organization organization, Project project) { + SearchProjectsRequest request = SearchProjectsRequest.builder().setOrganization(organization.getKey()).build(); + WsClient userSession = tester.as(user.getLogin()).wsClient(); + return userSession.components().searchProjects(request) + .getComponentsList().stream() + .anyMatch(c -> c.getKey().equals(project.getKey())); + } + + private boolean hasBrowsePermission(CreateWsResponse.User user, Organization organization, Project project) { + UsersWsRequest request = new UsersWsRequest() + .setOrganization(organization.getKey()) + .setProjectKey(project.getKey()) + .setPermission("user"); + WsPermissions.UsersWsResponse response = tester.wsClient().permissions().users(request); + Optional found = response.getUsersList().stream() + .filter(u -> user.getLogin().equals(u.getLogin())) + .findFirst(); + return found.isPresent(); + } +} diff --git a/tests/src/test/java/org/sonarqube/tests/authorization/ProvisioningPermissionTest.java b/tests/src/test/java/org/sonarqube/tests/authorization/ProvisioningPermissionTest.java new file mode 100644 index 00000000000..27c5b610d6e --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/authorization/ProvisioningPermissionTest.java @@ -0,0 +1,139 @@ +/* + * 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 org.sonarqube.tests.authorization; + +import com.sonar.orchestrator.Orchestrator; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.RuleChain; +import org.sonarqube.qa.util.Tester; +import org.sonarqube.ws.WsProjects.CreateWsResponse.Project; +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.permission.RemoveUserWsRequest; +import org.sonarqube.ws.client.project.CreateRequest; +import util.ItUtils; + +import static org.assertj.core.api.Assertions.assertThat; +import static util.selenium.Selenese.runSelenese; + +public class ProvisioningPermissionTest { + + private static final String PASSWORD = "password"; + private static final String ADMIN_WITH_PROVISIONING = "admin-with-provisioning"; + private static final String ADMIN_WITHOUT_PROVISIONING = "admin-without-provisioning"; + private static final String USER_WITH_PROVISIONING = "user-with-provisioning"; + private static final String USER_WITHOUT_PROVISIONING = "user-without-provisioning"; + + @ClassRule + public static Orchestrator orchestrator = AuthorizationSuite.ORCHESTRATOR; + + private static Tester tester = new Tester(orchestrator) + // all the tests of AuthorizationSuite must disable organizations + .disableOrganizations(); + + @ClassRule + public static RuleChain ruleChain = RuleChain.outerRule(orchestrator).around(tester); + + @BeforeClass + public static void init() { + // remove default permission "provisioning" from anyone(); + tester.wsClient().permissions().removeGroup(new RemoveGroupWsRequest().setGroupName("anyone").setPermission("provisioning")); + + tester.users().generate(u -> u.setLogin(ADMIN_WITH_PROVISIONING).setPassword(PASSWORD)); + addUserPermission(ADMIN_WITH_PROVISIONING, "admin"); + addUserPermission(ADMIN_WITH_PROVISIONING, "provisioning"); + + tester.users().generate(u -> u.setLogin(ADMIN_WITHOUT_PROVISIONING).setPassword(PASSWORD)); + addUserPermission(ADMIN_WITHOUT_PROVISIONING, "admin"); + removeUserPermission(ADMIN_WITHOUT_PROVISIONING, "provisioning"); + + tester.users().generate(u -> u.setLogin(USER_WITH_PROVISIONING).setPassword(PASSWORD)); + addUserPermission(USER_WITH_PROVISIONING, "provisioning"); + + tester.users().generate(u -> u.setLogin(USER_WITHOUT_PROVISIONING).setPassword(PASSWORD)); + removeUserPermission(USER_WITHOUT_PROVISIONING, "provisioning"); + } + + @AfterClass + public static void restoreData() throws Exception { + tester.wsClient().permissions().addGroup(new AddGroupWsRequest().setGroupName("anyone").setPermission("provisioning")); + } + + /** + * SONAR-3871 + * SONAR-4709 + */ + @Test + public void organization_administrator_cannot_provision_project_if_he_does_not_have_provisioning_permission() { + runSelenese(orchestrator, "/authorisation/ProvisioningPermissionTest/should-not-be-able-to-provision-project.html"); + } + + /** + * SONAR-3871 + * SONAR-4709 + */ + @Test + public void organization_administrator_can_provision_project_if_he_has_provisioning_permission() { + runSelenese(orchestrator, "/authorisation/ProvisioningPermissionTest/should-be-able-to-provision-project.html"); + } + + /** + * SONAR-3871 + * SONAR-4709 + */ + @Test + public void user_can_provision_project_through_ws_if_he_has_provisioning_permission() { + final String newKey = "new-project"; + final String newName = "New Project"; + + Project created = tester.as(USER_WITH_PROVISIONING, PASSWORD).wsClient().projects() + .create(CreateRequest.builder().setKey(newKey).setName(newName).build()) + .getProject(); + + assertThat(created).isNotNull(); + assertThat(created.getKey()).isEqualTo(newKey); + assertThat(created.getName()).isEqualTo(newName); + } + + /** + * SONAR-3871 + * SONAR-4709 + */ + @Test + public void user_cannot_provision_project_through_ws_if_he_does_not_have_provisioning_permission() { + ItUtils.expectForbiddenError(() -> { + tester.as(USER_WITHOUT_PROVISIONING, PASSWORD).wsClient().projects() + .create(CreateRequest.builder().setKey("new-project").setName("New Project").build()) + .getProject(); + }); + } + + private static void addUserPermission(String login, String permission) { + tester.wsClient().permissions().addUser(new AddUserWsRequest().setLogin(login).setPermission(permission)); + } + + private static void removeUserPermission(String login, String permission) { + tester.wsClient().permissions().removeUser(new RemoveUserWsRequest().setLogin(login).setPermission(permission)); + } +} diff --git a/tests/src/test/java/org/sonarqube/tests/authorization/QualityProfileAdminPermissionTest.java b/tests/src/test/java/org/sonarqube/tests/authorization/QualityProfileAdminPermissionTest.java new file mode 100644 index 00000000000..97d784d596a --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/authorization/QualityProfileAdminPermissionTest.java @@ -0,0 +1,69 @@ +/* + * 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 org.sonarqube.tests.authorization; + +import com.sonar.orchestrator.Orchestrator; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.sonarqube.qa.util.Tester; +import org.sonarqube.ws.client.permission.AddUserWsRequest; +import org.sonarqube.ws.client.qualityprofile.CreateRequest; +import util.selenium.Selenese; + +import static util.ItUtils.runProjectAnalysis; + +/** + * SONAR-4210 + */ +public class QualityProfileAdminPermissionTest { + + @ClassRule + public static Orchestrator orchestrator = AuthorizationSuite.ORCHESTRATOR; + + @Rule + public Tester tester = new Tester(orchestrator) + // all the tests of AuthorizationSuite must disable organizations + .disableOrganizations(); + + @Test + public void permission_should_grant_access_to_profile() { + runProjectAnalysis(orchestrator, "shared/xoo-sample"); + + tester.users().generate(u -> u.setLogin("not_profileadm").setPassword("userpwd")); + tester.users().generate(u -> u.setLogin("profileadm").setPassword("papwd")); + tester.wsClient().permissions().addUser(new AddUserWsRequest().setLogin("profileadm").setPermission("profileadmin")); + createProfile("xoo", "foo"); + + Selenese.runSelenese(orchestrator, + // Verify normal user is not allowed to do any modification + "/authorisation/QualityProfileAdminPermissionTest/normal-user.html", + // Verify profile admin is allowed to do modifications + "/authorisation/QualityProfileAdminPermissionTest/profile-admin.html"); + } + + private void createProfile(String language, String name) { + tester.wsClient().qualityProfiles().create(CreateRequest.builder() + .setLanguage(language) + .setName(name) + .build()); + } + +} diff --git a/tests/src/test/java/org/sonarqube/tests/authorization/SystemPasscodeTest.java b/tests/src/test/java/org/sonarqube/tests/authorization/SystemPasscodeTest.java new file mode 100644 index 00000000000..5ec92f46fdd --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/authorization/SystemPasscodeTest.java @@ -0,0 +1,76 @@ +/* + * 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 org.sonarqube.tests.authorization; + +import com.sonar.orchestrator.Orchestrator; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.sonarqube.qa.util.Tester; +import org.sonarqube.ws.client.GetRequest; +import org.sonarqube.ws.client.WsRequest; +import org.sonarqube.ws.client.WsResponse; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SystemPasscodeTest { + + static final String VALID_PASSCODE = "123456"; + private static final String INVALID_PASSCODE = "not" + VALID_PASSCODE; + private static final String PASSCODE_HEADER = "X-Sonar-Passcode"; + + @ClassRule + public static Orchestrator orchestrator = AuthorizationSuite.ORCHESTRATOR; + + @Rule + public Tester tester = new Tester(orchestrator) + // all the tests of AuthorizationSuite must disable organizations + .disableOrganizations(); + + @Test + public void system_access_is_granted_if_valid_passcode_is_sent_through_http_header() { + WsRequest request = newRequest() + .setHeader(PASSCODE_HEADER, VALID_PASSCODE); + + WsResponse response = tester.asAnonymous().wsClient().wsConnector().call(request); + assertThat(response.code()).isEqualTo(200); + } + + @Test + public void system_access_is_rejected_if_invalid_passcode_is_sent_through_http_header() { + WsRequest request = newRequest() + .setHeader(PASSCODE_HEADER, INVALID_PASSCODE); + + WsResponse response = tester.asAnonymous().wsClient().wsConnector().call(request); + assertThat(response.code()).isEqualTo(401); + } + + @Test + public void system_access_is_rejected_if_passcode_is_not_sent() { + WsRequest request = newRequest(); + + WsResponse response = tester.asAnonymous().wsClient().wsConnector().call(request); + assertThat(response.code()).isEqualTo(401); + } + + private static GetRequest newRequest() { + return new GetRequest("api/system_passcode/check"); + } +} diff --git a/tests/src/test/java/util/user/Groups.java b/tests/src/test/java/util/user/Groups.java index 8aa1f63c869..32ef4f27250 100644 --- a/tests/src/test/java/util/user/Groups.java +++ b/tests/src/test/java/util/user/Groups.java @@ -27,7 +27,6 @@ import org.sonarqube.qa.util.Tester; * @deprecated replaced by {@link Tester} */ @Deprecated - public class Groups { private List groups; diff --git a/tests/src/test/java/util/user/UserRule.java b/tests/src/test/java/util/user/UserRule.java index 994e4a0c2e7..beb07e114d2 100644 --- a/tests/src/test/java/util/user/UserRule.java +++ b/tests/src/test/java/util/user/UserRule.java @@ -31,7 +31,6 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.junit.rules.ExternalResource; import org.sonarqube.qa.util.Tester; -import org.sonarqube.ws.Organizations; import org.sonarqube.ws.WsUsers; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.PostRequest; @@ -139,13 +138,6 @@ public class UserRule extends ExternalResource implements GroupManagement { createUser(login, login, null, password); } - public WsUsers.CreateWsResponse.User createAdministrator(Organizations.Organization organization, String password) { - WsUsers.CreateWsResponse.User user = generate(p -> p.setPassword(password)); - adminWsClient.organizations().addMember(organization.getKey(), user.getLogin()); - forOrganization(organization.getKey()).associateGroupsToUser(user.getLogin(), "Owners"); - return user; - } - /** * Create a new admin user with random login, having password same as login */ @@ -161,28 +153,10 @@ public class UserRule extends ExternalResource implements GroupManagement { return login; } - /** - * Create a new root user with random login, having password same as login - */ - public String createRootUser() { - String login = randomAlphabetic(10).toLowerCase(); - return createRootUser(login, login); - } - - public String createRootUser(String login, String password) { - createUser(login, password); - setRoot(login); - return login; - } - public void setRoot(String login) { adminWsClient().roots().setRoot(login); } - public void unsetRoot(String login) { - adminWsClient().roots().unsetRoot(login); - } - public Optional getUserByLogin(String login) { return FluentIterable.from(getUsers().getUsers()).firstMatch(new MatchUserLogin(login)); } diff --git a/tests/src/test/resources/authorisation/PermissionTemplatesPageTest/should_create.html b/tests/src/test/resources/authorisation/PermissionTemplatesPageTest/should_create.html deleted file mode 100644 index 5265dab2239..00000000000 --- a/tests/src/test/resources/authorisation/PermissionTemplatesPageTest/should_create.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - should_create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
open/sessions/new
typepasswordroot-user
typeloginroot-user
clickAndWaitname=commit
open/permission_templates
waitForElementPresentcss=.page-actions button
clickcss=.page-actions button
waitForElementPresentcss=#permission-template-name
typecss=#permission-template-nameCustom
typecss=#permission-template-descriptionDescription
typecss=#permission-template-project-key-pattern.*
clickcss=#permission-template-submit
waitForElementPresentcss=tr[data-name="Custom"]
assertTextcss=tr[data-name="Custom"] .js-name*Custom*
assertTextcss=tr[data-name="Custom"] .js-description*Description*
assertTextcss=tr[data-name="Custom"] .js-project-key-pattern*.*
- - diff --git a/tests/src/test/resources/authorisation/PermissionTemplatesPageTest/should_display_page.html b/tests/src/test/resources/authorisation/PermissionTemplatesPageTest/should_display_page.html deleted file mode 100644 index 2e05e15a692..00000000000 --- a/tests/src/test/resources/authorisation/PermissionTemplatesPageTest/should_display_page.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - should_display_page - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
open/sessions/new
typeloginadmin
typepasswordadmin
clickAndWaitcommit
open/permission_templates
waitForElementPresentcss=tr[data-id="default_template"]
assertTextcss=tr[data-id="default_template"] .js-name*Default template*
assertTextcss=tr[data-id="default_template"] .js-defaults*Projects*
assertTextcss=tr[data-id="default_template"] .js-description*This permission template will be used*
assertElementPresentcss=td[data-permission="user"]
assertElementPresentcss=td[data-permission="codeviewer"]
assertElementPresentcss=td[data-permission="issueadmin"]
assertElementPresentcss=td[data-permission="admin"]
assertElementPresentcss=td[data-permission="scan"]
- - diff --git a/tests/src/test/resources/authorisation/PermissionTemplatesPageTest/should_manage_project_creators.html b/tests/src/test/resources/authorisation/PermissionTemplatesPageTest/should_manage_project_creators.html deleted file mode 100644 index d6226cb6fa7..00000000000 --- a/tests/src/test/resources/authorisation/PermissionTemplatesPageTest/should_manage_project_creators.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - should_manage_project_creators - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
open/sessions/new
typepasswordadmin-user
typeloginadmin-user
clickAndWaitname=commit
open/permission_templates
waitForElementPresentcss=td[data-permission="user"]
clickcss=td[data-permission="user"] .js-update-users
waitForElementPresentcss=#grant-to-project-creators
assertElementPresentcss=#grant-to-project-creators:not(:checked)
clickcss=#grant-to-project-creators
clickcss=.js-modal-close
waitForElementPresentcss=td[data-permission="user"] .js-project-creators
clickcss=td[data-permission="user"] .js-update-users
waitForElementPresentcss=#grant-to-project-creators
assertElementPresentcss=#grant-to-project-creators:checked
clickcss=#grant-to-project-creators
clickcss=.js-modal-close
waitForElementNotPresentcss=td[data-permission="user"] .js-project-creators
- -