From 19e115ff1613edce231d59367c569993f0f4eb55 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Wed, 27 Jan 2016 12:01:39 +0100 Subject: [PATCH] SONAR-6226 Add ITs --- it/it-plugins/base-auth-plugin/pom.xml | 45 ++++++ .../src/main/java/FakeBaseAuthPlugin.java | 32 +++++ .../src/main/java/FakeBaseIdProvider.java | 80 +++++++++++ .../src/resources/static/base.png | Bin 0 -> 3112 bytes it/it-plugins/oauth2-auth-plugin/pom.xml | 45 ++++++ .../src/main/java/FakeOAuth2AuthPlugin.java | 32 +++++ .../src/main/java/FakeOAuth2IdProvider.java | 87 ++++++++++++ .../src/resources/static/base.png | Bin 0 -> 3112 bytes it/it-plugins/pom.xml | 2 + it/it-tests/pom.xml | 10 ++ .../src/test/java/it/Category1Suite.java | 15 +- .../BaseIdentityProviderTest.java | 130 ++++++++++++++++++ ...Test.java => LocalAuthenticationTest.java} | 2 +- .../OAuth2IdentityProviderTest.java | 106 ++++++++++++++ it/it-tests/src/test/java/util/ItUtils.java | 4 +- .../src/test/java/util/user/UserRule.java | 118 ++++++++++++++++ .../src/test/java/util/user/Users.java | 91 ++++++++++++ 17 files changed, 795 insertions(+), 4 deletions(-) create mode 100644 it/it-plugins/base-auth-plugin/pom.xml create mode 100644 it/it-plugins/base-auth-plugin/src/main/java/FakeBaseAuthPlugin.java create mode 100644 it/it-plugins/base-auth-plugin/src/main/java/FakeBaseIdProvider.java create mode 100644 it/it-plugins/base-auth-plugin/src/resources/static/base.png create mode 100644 it/it-plugins/oauth2-auth-plugin/pom.xml create mode 100644 it/it-plugins/oauth2-auth-plugin/src/main/java/FakeOAuth2AuthPlugin.java create mode 100644 it/it-plugins/oauth2-auth-plugin/src/main/java/FakeOAuth2IdProvider.java create mode 100644 it/it-plugins/oauth2-auth-plugin/src/resources/static/base.png create mode 100644 it/it-tests/src/test/java/it/authorisation/BaseIdentityProviderTest.java rename it/it-tests/src/test/java/it/authorisation/{AuthenticationTest.java => LocalAuthenticationTest.java} (99%) create mode 100644 it/it-tests/src/test/java/it/authorisation/OAuth2IdentityProviderTest.java create mode 100644 it/it-tests/src/test/java/util/user/UserRule.java create mode 100644 it/it-tests/src/test/java/util/user/Users.java diff --git a/it/it-plugins/base-auth-plugin/pom.xml b/it/it-plugins/base-auth-plugin/pom.xml new file mode 100644 index 00000000000..1674c8bab01 --- /dev/null +++ b/it/it-plugins/base-auth-plugin/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + + org.sonarsource.sonarqube + it-plugins + 5.4-SNAPSHOT + + + base-auth-plugin + 1.0-SNAPSHOT + sonar-plugin + Plugins :: Fake Base Authentication Plugin + Test for base authentication plugin (like openid) + + + + org.sonarsource.sonarqube + sonar-plugin-api + ${apiVersion} + provided + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + + + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + + FakeBaseAuthPlugin + + + + + diff --git a/it/it-plugins/base-auth-plugin/src/main/java/FakeBaseAuthPlugin.java b/it/it-plugins/base-auth-plugin/src/main/java/FakeBaseAuthPlugin.java new file mode 100644 index 00000000000..b8638ada633 --- /dev/null +++ b/it/it-plugins/base-auth-plugin/src/main/java/FakeBaseAuthPlugin.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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. + */ +import java.util.ArrayList; +import java.util.List; +import org.sonar.api.SonarPlugin; + +public final class FakeBaseAuthPlugin extends SonarPlugin { + + public List getExtensions() { + List extensions = new ArrayList(); + extensions.add(FakeBaseIdProvider.class); + return extensions; + } + +} diff --git a/it/it-plugins/base-auth-plugin/src/main/java/FakeBaseIdProvider.java b/it/it-plugins/base-auth-plugin/src/main/java/FakeBaseIdProvider.java new file mode 100644 index 00000000000..e3d1051f3e2 --- /dev/null +++ b/it/it-plugins/base-auth-plugin/src/main/java/FakeBaseIdProvider.java @@ -0,0 +1,80 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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. + */ +import java.io.IOException; +import org.sonar.api.config.Settings; +import org.sonar.api.server.authentication.BaseIdentityProvider; +import org.sonar.api.server.authentication.UserIdentity; + +public class FakeBaseIdProvider implements BaseIdentityProvider { + + private static final String ENABLED = "sonar.auth.fake-base-id-provider.enabled"; + private static final String USER_INFO = "sonar.auth.fake-base-id-provider.user"; + + private final Settings settings; + + public FakeBaseIdProvider(Settings settings) { + this.settings = settings; + } + + @Override + public void init(Context context) { + String userInfoProperty = settings.getString(USER_INFO); + if (userInfoProperty == null) { + throw new IllegalStateException(String.format("The property %s is required", USER_INFO)); + } + String[] userInfos = userInfoProperty.split(","); + context.authenticate(UserIdentity.builder() + .setId(userInfos[0]) + .setName(userInfos[1]) + .setEmail(userInfos[2]) + .build()); + + try { + context.getResponse().sendRedirect("/"); + } catch (IOException e) { + throw new IllegalStateException("Fail to redirect to home", e); + } + } + + @Override + public String getKey() { + return "fake-base-id-provider"; + } + + @Override + public String getName() { + return "Fake base identity provider"; + } + + @Override + public String getIconPath() { + return "/static/baseauthplugin/base.png"; + } + + @Override + public boolean isEnabled() { + return settings.getBoolean(ENABLED); + } + + @Override + public boolean allowsUsersToSignUp() { + return true; + } +} diff --git a/it/it-plugins/base-auth-plugin/src/resources/static/base.png b/it/it-plugins/base-auth-plugin/src/resources/static/base.png new file mode 100644 index 0000000000000000000000000000000000000000..217d2a0bdf819ffe0e3ccfc7b4aadb6b23dd1e7f GIT binary patch literal 3112 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 + + 4.0.0 + + + org.sonarsource.sonarqube + it-plugins + 5.4-SNAPSHOT + + + oauth2-auth-plugin + 1.0-SNAPSHOT + sonar-plugin + Plugins :: Fake OAuth2 Authentication Plugin + Test for OAuth2 authentication plugin (like openid) + + + + org.sonarsource.sonarqube + sonar-plugin-api + ${apiVersion} + provided + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + + + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.15 + + FakeOAuth2AuthPlugin + + + + + diff --git a/it/it-plugins/oauth2-auth-plugin/src/main/java/FakeOAuth2AuthPlugin.java b/it/it-plugins/oauth2-auth-plugin/src/main/java/FakeOAuth2AuthPlugin.java new file mode 100644 index 00000000000..5ad389cf78e --- /dev/null +++ b/it/it-plugins/oauth2-auth-plugin/src/main/java/FakeOAuth2AuthPlugin.java @@ -0,0 +1,32 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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. + */ +import java.util.ArrayList; +import java.util.List; +import org.sonar.api.SonarPlugin; + +public final class FakeOAuth2AuthPlugin extends SonarPlugin { + + public List getExtensions() { + List extensions = new ArrayList(); + extensions.add(FakeOAuth2IdProvider.class); + return extensions; + } + +} diff --git a/it/it-plugins/oauth2-auth-plugin/src/main/java/FakeOAuth2IdProvider.java b/it/it-plugins/oauth2-auth-plugin/src/main/java/FakeOAuth2IdProvider.java new file mode 100644 index 00000000000..1044796442c --- /dev/null +++ b/it/it-plugins/oauth2-auth-plugin/src/main/java/FakeOAuth2IdProvider.java @@ -0,0 +1,87 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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. + */ + +import org.sonar.api.config.Settings; +import org.sonar.api.server.authentication.OAuth2IdentityProvider; +import org.sonar.api.server.authentication.UserIdentity; + +public class FakeOAuth2IdProvider implements OAuth2IdentityProvider { + + private static final String ENABLED = "sonar.auth.fake-oauth2-id-provider.enabled"; + private static final String URL = "sonar.auth.fake-oauth2-id-provider.url"; + private static final String USER_INFO = "sonar.auth.fake-oauth2-id-provider.user"; + + private final Settings settings; + + public FakeOAuth2IdProvider(Settings settings) { + this.settings = settings; + } + + + @Override + public void init(InitContext context) { + String url = settings.getString(URL); + if (url == null) { + throw new IllegalStateException(String.format("The property %s is required", URL)); + } + context.redirectTo(url); + } + + @Override + public void callback(CallbackContext context) { + String userInfoProperty = settings.getString(USER_INFO); + if (userInfoProperty == null) { + throw new IllegalStateException(String.format("The property %s is required", USER_INFO)); + } + String[] userInfos = userInfoProperty.split(","); + context.authenticate(UserIdentity.builder() + .setId(userInfos[0]) + .setName(userInfos[1]) + .setEmail(userInfos[2]) + .build()); + context.redirectToRequestedPage(); + } + + @Override + public String getKey() { + return "fake-oauth2-id-provider"; + } + + @Override + public String getName() { + return "Fake oauth2 identity provider"; + } + + @Override + public String getIconPath() { + return "/static/baseauthplugin/base.png"; + } + + @Override + public boolean isEnabled() { + return settings.getBoolean(ENABLED); + } + + @Override + public boolean allowsUsersToSignUp() { + return true; + } + +} diff --git a/it/it-plugins/oauth2-auth-plugin/src/resources/static/base.png b/it/it-plugins/oauth2-auth-plugin/src/resources/static/base.png new file mode 100644 index 0000000000000000000000000000000000000000..217d2a0bdf819ffe0e3ccfc7b4aadb6b23dd1e7f GIT binary patch literal 3112 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 access-secured-props-plugin + base-auth-plugin batch-plugin extension-lifecycle-plugin global-property-change-plugin issue-action-plugin l10n-fr-pack license-plugin + oauth2-auth-plugin project-builder-plugin property-relocation-plugin property-sets-plugin diff --git a/it/it-tests/pom.xml b/it/it-tests/pom.xml index 80e458b1a9e..386f69257e8 100644 --- a/it/it-tests/pom.xml +++ b/it/it-tests/pom.xml @@ -72,6 +72,11 @@ org.assertj assertj-core + + org.assertj + assertj-guava + 1.3.1 + org.hamcrest hamcrest-all @@ -91,6 +96,11 @@ jsoup 1.8.3 + + com.squareup.okhttp + mockwebserver + 2.6.0 + diff --git a/it/it-tests/src/test/java/it/Category1Suite.java b/it/it-tests/src/test/java/it/Category1Suite.java index bc4ff01b269..16333217c23 100644 --- a/it/it-tests/src/test/java/it/Category1Suite.java +++ b/it/it-tests/src/test/java/it/Category1Suite.java @@ -41,9 +41,11 @@ import com.sonar.orchestrator.Orchestrator; import it.actionPlan.ActionPlanTest; import it.actionPlan.ActionPlanUiTest; import it.administration.UsersUITest; -import it.authorisation.AuthenticationTest; +import it.authorisation.BaseIdentityProviderTest; import it.authorisation.ExecuteAnalysisPermissionTest; import it.authorisation.IssuePermissionTest; +import it.authorisation.LocalAuthenticationTest; +import it.authorisation.OAuth2IdentityProviderTest; import it.authorisation.PermissionTest; import it.i18n.I18nTest; import it.measureHistory.DifferentialPeriodsTest; @@ -92,8 +94,11 @@ import static util.ItUtils.xooPlugin; QualityGateTest.class, QualityGateUiTest.class, QualityGateNotificationTest.class, + // authentication + LocalAuthenticationTest.class, + BaseIdentityProviderTest.class, + OAuth2IdentityProviderTest.class, // permission - AuthenticationTest.class, PermissionTest.class, IssuePermissionTest.class, ExecuteAnalysisPermissionTest.class, @@ -128,6 +133,12 @@ public class Category1Suite { // Used in SettingsTest.should_get_settings_default_value .addPlugin(pluginArtifact("server-plugin")) + // Used in BaseIdentityProviderTest + .addPlugin(pluginArtifact("base-auth-plugin")) + + // Used in OAuth2IdentityProviderTest + .addPlugin(pluginArtifact("oauth2-auth-plugin")) + .addPlugin(xooPlugin()) .build(); diff --git a/it/it-tests/src/test/java/it/authorisation/BaseIdentityProviderTest.java b/it/it-tests/src/test/java/it/authorisation/BaseIdentityProviderTest.java new file mode 100644 index 00000000000..8e5825cdee7 --- /dev/null +++ b/it/it-tests/src/test/java/it/authorisation/BaseIdentityProviderTest.java @@ -0,0 +1,130 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package it.authorisation; + +import com.google.common.base.Optional; +import com.sonar.orchestrator.Orchestrator; +import it.Category1Suite; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.sonarqube.ws.client.GetRequest; +import org.sonarqube.ws.client.WsClient; +import org.sonarqube.ws.client.WsResponse; +import util.user.UserRule; +import util.user.Users; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.guava.api.Assertions.assertThat; +import static util.ItUtils.newAdminWsClient; +import static util.ItUtils.setServerProperty; + +public class BaseIdentityProviderTest { + + @ClassRule + public static Orchestrator ORCHESTRATOR = Category1Suite.ORCHESTRATOR; + + @Rule + public UserRule userRule = UserRule.from(ORCHESTRATOR); + + static String FAKE_PROVIDER_KEY = "fake-base-id-provider"; + + static String USER_PROVIDER_LOGIN = "john"; + + static String USER_NAME = "John"; + static String USER_EMAIL = "john@email.com"; + + static String USER_NAME_UPDATED = "John Doe"; + static String USER_EMAIL_UPDATED = "john.doe@email.com"; + + static WsClient adminWsClient; + + @BeforeClass + public static void setUp() { + ORCHESTRATOR.resetData(); + adminWsClient = newAdminWsClient(ORCHESTRATOR); + } + + @After + public void removeUsers() throws Exception { + userRule.deactivateUsers(userRule.getUsersByEmails(USER_EMAIL, USER_EMAIL_UPDATED)); + } + + @Test + public void create_new_user_when_authenticate() throws Exception { + setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.enabled", "true"); + setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.user", USER_PROVIDER_LOGIN + "," + USER_NAME + "," + USER_EMAIL); + + userRule.verifyUserDoesNotExist(USER_EMAIL); + + // First connection, user is created + authenticateWithFakeAuthProvider(); + + userRule.verifyUserExists(USER_NAME, USER_EMAIL); + } + + @Test + public void update_existing_user_when_authenticate() throws Exception { + setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.enabled", "true"); + setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.user", USER_PROVIDER_LOGIN + "," + USER_NAME + "," + USER_EMAIL); + // First connection, user is created + authenticateWithFakeAuthProvider(); + + setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.user", USER_PROVIDER_LOGIN + "," + USER_NAME_UPDATED + "," + USER_EMAIL_UPDATED); + + // Second connection, user should be updated + authenticateWithFakeAuthProvider(); + + userRule.verifyUserDoesNotExist(USER_EMAIL); + userRule.verifyUserExists(USER_NAME_UPDATED, USER_EMAIL_UPDATED); + } + + @Test + @Ignore("Waiting for SONAR-7233 to be implemented") + public void reactivate_disabled_user() throws Exception { + setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.enabled", "true"); + setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.user", USER_PROVIDER_LOGIN + "," + USER_NAME + "," + USER_EMAIL); + + userRule.verifyUserDoesNotExist(USER_EMAIL); + + // First connection, user is created + authenticateWithFakeAuthProvider(); + + Optional user = userRule.getUserByEmail(USER_EMAIL); + assertThat(user).isPresent(); + + // Disable user + userRule.deactivateUsers(user.get()); + + // Second connection, user is reactivated + authenticateWithFakeAuthProvider(); + userRule.verifyUserExists(USER_NAME, USER_EMAIL); + } + + private void authenticateWithFakeAuthProvider() { + WsResponse response = adminWsClient.wsConnector().call( + new GetRequest(("/sessions/init/" + FAKE_PROVIDER_KEY))); + assertThat(response.code()).isEqualTo(200); + } + +} diff --git a/it/it-tests/src/test/java/it/authorisation/AuthenticationTest.java b/it/it-tests/src/test/java/it/authorisation/LocalAuthenticationTest.java similarity index 99% rename from it/it-tests/src/test/java/it/authorisation/AuthenticationTest.java rename to it/it-tests/src/test/java/it/authorisation/LocalAuthenticationTest.java index 23a78ab6254..6b0f239db32 100644 --- a/it/it-tests/src/test/java/it/authorisation/AuthenticationTest.java +++ b/it/it-tests/src/test/java/it/authorisation/LocalAuthenticationTest.java @@ -52,7 +52,7 @@ import static util.ItUtils.newAdminWsClient; import static util.ItUtils.projectDir; import static util.ItUtils.setServerProperty; -public class AuthenticationTest { +public class LocalAuthenticationTest { @ClassRule public static Orchestrator ORCHESTRATOR = Category1Suite.ORCHESTRATOR; private static WsClient adminWsClient; diff --git a/it/it-tests/src/test/java/it/authorisation/OAuth2IdentityProviderTest.java b/it/it-tests/src/test/java/it/authorisation/OAuth2IdentityProviderTest.java new file mode 100644 index 00000000000..f1e5c3e2e40 --- /dev/null +++ b/it/it-tests/src/test/java/it/authorisation/OAuth2IdentityProviderTest.java @@ -0,0 +1,106 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package it.authorisation; + +import com.sonar.orchestrator.Orchestrator; +import com.squareup.okhttp.mockwebserver.MockResponse; +import com.squareup.okhttp.mockwebserver.MockWebServer; +import it.Category1Suite; +import java.net.HttpURLConnection; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.sonarqube.ws.client.GetRequest; +import org.sonarqube.ws.client.WsClient; +import org.sonarqube.ws.client.WsResponse; +import util.user.UserRule; + +import static org.assertj.core.api.Assertions.assertThat; +import static util.ItUtils.newAdminWsClient; +import static util.ItUtils.setServerProperty; + +public class OAuth2IdentityProviderTest { + + @ClassRule + public static Orchestrator ORCHESTRATOR = Category1Suite.ORCHESTRATOR; + + @Rule + public UserRule userRule = UserRule.from(ORCHESTRATOR); + + static String FAKE_PROVIDER_KEY = "fake-oauth2-id-provider"; + + static String USER_PROVIDER_LOGIN = "john"; + + static String USER_NAME = "John"; + static String USER_EMAIL = "john@email.com"; + + static WsClient adminWsClient; + + MockWebServer fakeServerAuthProvider; + String fakeServerAuthProviderUrl; + + @BeforeClass + public static void resetData() { + ORCHESTRATOR.resetData(); + adminWsClient = newAdminWsClient(ORCHESTRATOR); + } + + @Before + public void setUp() throws Exception { + fakeServerAuthProvider = new MockWebServer(); + fakeServerAuthProvider.start(); + fakeServerAuthProviderUrl = fakeServerAuthProvider.url("").url().toString(); + } + + @After + public void tearDown() throws Exception { + fakeServerAuthProvider.shutdown(); + } + + @Test + public void create_new_user_when_authenticate() throws Exception { + simulateRedirectionToCallback(); + + setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.enabled", "true"); + setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.url", fakeServerAuthProviderUrl); + setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.user", USER_PROVIDER_LOGIN + "," + USER_NAME + "," + USER_EMAIL); + + authenticateWithFakeAuthProvider(); + + userRule.verifyUserExists(USER_NAME, USER_EMAIL); + } + + private void authenticateWithFakeAuthProvider() { + WsResponse response = adminWsClient.wsConnector().call( + new GetRequest(("/sessions/init/" + FAKE_PROVIDER_KEY))); + assertThat(response.code()).isEqualTo(200); + } + + private void simulateRedirectionToCallback() { + fakeServerAuthProvider.enqueue(new MockResponse() + .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) + .addHeader("Location: " + ORCHESTRATOR.getServer().getUrl() + "/oauth2/callback/" + FAKE_PROVIDER_KEY) + .setBody("Redirect to SonarQube")); + } + +} diff --git a/it/it-tests/src/test/java/util/ItUtils.java b/it/it-tests/src/test/java/util/ItUtils.java index 060b434fbd7..7702f25df00 100644 --- a/it/it-tests/src/test/java/util/ItUtils.java +++ b/it/it-tests/src/test/java/util/ItUtils.java @@ -56,6 +56,8 @@ import org.sonarqube.ws.client.HttpWsClient; import org.sonarqube.ws.client.WsClient; import static com.google.common.collect.FluentIterable.from; +import static com.sonar.orchestrator.container.Server.ADMIN_LOGIN; +import static com.sonar.orchestrator.container.Server.ADMIN_PASSWORD; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; @@ -99,7 +101,7 @@ public class ItUtils { Server server = orchestrator.getServer(); return new HttpWsClient(new HttpConnector.Builder() .url(server.getUrl()) - .credentials(server.ADMIN_LOGIN, server.ADMIN_PASSWORD) + .credentials(ADMIN_LOGIN, ADMIN_PASSWORD) .build()); } diff --git a/it/it-tests/src/test/java/util/user/UserRule.java b/it/it-tests/src/test/java/util/user/UserRule.java new file mode 100644 index 00000000000..4c6b94ea98e --- /dev/null +++ b/it/it-tests/src/test/java/util/user/UserRule.java @@ -0,0 +1,118 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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 util.user; + +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.sonar.orchestrator.Orchestrator; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nonnull; +import org.assertj.core.api.Assertions; +import org.junit.rules.ExternalResource; +import org.sonarqube.ws.client.GetRequest; +import org.sonarqube.ws.client.PostRequest; +import org.sonarqube.ws.client.WsClient; +import org.sonarqube.ws.client.WsResponse; + +import static java.util.Arrays.asList; +import static java.util.Objects.requireNonNull; +import static org.assertj.guava.api.Assertions.assertThat; +import static util.ItUtils.newAdminWsClient; + +public class UserRule extends ExternalResource { + + private final Orchestrator orchestrator; + + private WsClient adminWsClient; + + private UserRule(Orchestrator orchestrator) { + this.orchestrator = orchestrator; + } + + public static UserRule from(Orchestrator orchestrator) { + return new UserRule(requireNonNull(orchestrator, "Orchestrator instance can not be null")); + } + + @Override + protected void before() throws Throwable { + adminWsClient = newAdminWsClient(orchestrator); + } + + public void verifyUserExists(String name, String email) { + Optional user = getUserByEmail(email); + assertThat(user).isPresent(); + Assertions.assertThat(user.get().getName()).isEqualTo(name); + Assertions.assertThat(user.get().getEmail()).isEqualTo(email); + } + + public void verifyUserDoesNotExist(String email) { + assertThat(getUserByEmail(email)).isAbsent(); + } + + public Optional getUserByEmail(String email) { + return FluentIterable.from(getUsers().getUsers()).firstMatch(new MatchUserEmail(email)); + } + + public List getUsersByEmails(String... emails) { + List foundUsers = new ArrayList<>(); + for (String email : emails) { + Optional user = FluentIterable.from(getUsers().getUsers()).firstMatch(new MatchUserEmail(email)); + if (user.isPresent()) { + foundUsers.add(user.get()); + } + } + return foundUsers; + } + + public Users getUsers() { + WsResponse response = adminWsClient.wsConnector().call( + new GetRequest("api/users/search")); + Assertions.assertThat(response.code()).isEqualTo(200); + return Users.parse(response.content()); + } + + private class MatchUserEmail implements Predicate { + private final String email; + + private MatchUserEmail(String email) { + this.email = email; + } + + @Override + public boolean apply(@Nonnull Users.User user) { + String userEmail = user.getEmail(); + return userEmail != null && userEmail.equals(email) && user.isActive(); + } + } + + public void deactivateUsers(List users) { + for (Users.User user : users) { + adminWsClient.wsConnector().call( + new PostRequest("api/users/deactivate") + .setParam("login", user.getLogin())); + } + } + + public void deactivateUsers(Users.User... users) { + deactivateUsers(asList(users)); + } +} diff --git a/it/it-tests/src/test/java/util/user/Users.java b/it/it-tests/src/test/java/util/user/Users.java new file mode 100644 index 00000000000..680c8979b7f --- /dev/null +++ b/it/it-tests/src/test/java/util/user/Users.java @@ -0,0 +1,91 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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 util.user; + +import com.google.gson.Gson; +import java.util.List; + +public class Users { + + private List users; + + private Users(List users) { + this.users = users; + } + + public List getUsers() { + return users; + } + + public static Users parse(String json) { + Gson gson = new Gson(); + return gson.fromJson(json, Users.class); + } + + public static class User { + private final String login; + private final String name; + private final String email; + private final List groups; + private final List scmAccounts; + private final boolean active; + private int tokensCount; + + private User(String login, String name, String email, List groups, List scmAccounts, boolean active, int tokensCount) { + this.login = login; + this.name = name; + this.email = email; + this.groups = groups; + this.scmAccounts = scmAccounts; + this.active = active; + this.tokensCount = tokensCount; + } + + public String getLogin() { + return login; + } + + public String getName() { + return name; + } + + public String getEmail() { + return email; + } + + public List getGroups() { + return groups; + } + + public List getScmAccounts() { + return scmAccounts; + } + + public boolean isActive() { + return active; + } + + public int getTokensCount() { + return tokensCount; + } + } +} + + -- 2.39.5