From 3f8f3f9c4dbbe94d9a99a426aeabbba90f305555 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Thu, 17 Mar 2016 11:48:25 +0100 Subject: [PATCH] SONAR-6732 UserSession implementation in CE must fail at any call --- .../container/ComputeEngineContainerImpl.java | 4 + .../java/org/sonar/ce/user/CeUserSession.java | 130 ++++++++++++++++++ .../java/org/sonar/ce/user/package-info.java | 23 ++++ .../ComputeEngineContainerImplTest.java | 2 +- .../org/sonar/ce/user/CeUserSessionTest.java | 97 +++++++++++++ .../sonar/server/issue/index/IssueIndex.java | 21 +-- 6 files changed, 256 insertions(+), 21 deletions(-) create mode 100644 server/sonar-ce/src/main/java/org/sonar/ce/user/CeUserSession.java create mode 100644 server/sonar-ce/src/main/java/org/sonar/ce/user/package-info.java create mode 100644 server/sonar-ce/src/test/java/org/sonar/ce/user/CeUserSessionTest.java diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java index 7292e6bd836..ef74282206f 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java @@ -38,6 +38,7 @@ import org.sonar.api.utils.UriReader; import org.sonar.ce.es.EsIndexerEnabler; import org.sonar.ce.property.CePropertyDefinitions; import org.sonar.ce.settings.ComputeEngineSettings; +import org.sonar.ce.user.CeUserSession; import org.sonar.core.component.DefaultResourceTypes; import org.sonar.core.config.CorePropertyDefinitions; import org.sonar.core.i18n.DefaultI18n; @@ -154,6 +155,9 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer { new TempFolderProvider(), System2.INSTANCE, + // user session + CeUserSession.class, + // DB DbClient.class, DaoModule.class, diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/user/CeUserSession.java b/server/sonar-ce/src/main/java/org/sonar/ce/user/CeUserSession.java new file mode 100644 index 00000000000..fbecf580e52 --- /dev/null +++ b/server/sonar-ce/src/main/java/org/sonar/ce/user/CeUserSession.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 org.sonar.ce.user; + +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import org.sonar.server.user.UserSession; + +/** + * Implementation of {@link UserSession} which provide not implementation of any method. + *

+ * Any use of {@link UserSession} in the Compute Engine will raise an error. + *

+ */ +public class CeUserSession implements UserSession { + + public static final String UOE_MESSAGE = "UserSession must not be used from within the Compute Engine"; + + @Override + public String getLogin() { + return notImplemented(); + } + + @Override + public String getName() { + return notImplemented(); + } + + @Override + public Integer getUserId() { + return notImplemented(); + } + + @Override + public Set getUserGroups() { + return notImplemented(); + } + + @Override + public boolean isLoggedIn() { + return notImplementedBooleanMethod(); + } + + @Override + public Locale locale() { + return notImplemented(); + } + + @Override + public UserSession checkLoggedIn() { + return notImplemented(); + } + + @Override + public UserSession checkPermission(String globalPermission) { + return notImplemented(); + } + + @Override + public UserSession checkGlobalPermission(String globalPermission) { + return notImplemented(); + } + + @Override + public UserSession checkAnyPermissions(Collection globalPermissions) { + return notImplemented(); + } + + @Override + public boolean hasPermission(String globalPermission) { + return notImplementedBooleanMethod(); + } + + @Override + public boolean hasGlobalPermission(String globalPermission) { + return notImplementedBooleanMethod(); + } + + @Override + public List globalPermissions() { + return notImplemented(); + } + + @Override + public UserSession checkComponentPermission(String projectPermission, String componentKey) { + return notImplemented(); + } + + @Override + public UserSession checkComponentUuidPermission(String permission, String componentUuid) { + return notImplemented(); + } + + @Override + public boolean hasComponentPermission(String permission, String componentKey) { + return notImplementedBooleanMethod(); + } + + @Override + public boolean hasComponentUuidPermission(String permission, String componentUuid) { + return notImplementedBooleanMethod(); + } + + private static T notImplemented() { + throw new UnsupportedOperationException(UOE_MESSAGE); + } + + private static boolean notImplementedBooleanMethod() { + throw new UnsupportedOperationException(UOE_MESSAGE); + } +} diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/user/package-info.java b/server/sonar-ce/src/main/java/org/sonar/ce/user/package-info.java new file mode 100644 index 00000000000..b1a1d2af369 --- /dev/null +++ b/server/sonar-ce/src/main/java/org/sonar/ce/user/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.ce.user; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java index 8cd8deeff38..59f5ae4d1fc 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java @@ -88,7 +88,7 @@ public class ComputeEngineContainerImplTest { ); assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize( COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION - + 21 // level 1 + + 22 // level 1 + 47 // content of DaoModule + 1 // content of EsSearchModule + 58 // content of CorePropertyDefinitions diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/user/CeUserSessionTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/user/CeUserSessionTest.java new file mode 100644 index 00000000000..e34678d8d07 --- /dev/null +++ b/server/sonar-ce/src/test/java/org/sonar/ce/user/CeUserSessionTest.java @@ -0,0 +1,97 @@ +/* + * 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 org.sonar.ce.user; + +import com.google.common.base.Predicate; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; + +import static com.google.common.collect.FluentIterable.from; +import static java.util.Arrays.asList; +import static org.sonar.test.ExceptionCauseMatcher.hasType; + +@RunWith(DataProviderRunner.class) +public class CeUserSessionTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private CeUserSession underTest = new CeUserSession(); + + @DataProvider + public static Object[][] ceUserSessionPublicMethods() { + List declaredMethods = from(asList(CeUserSession.class.getDeclaredMethods())) + .filter(PublicMethodPredicate.INSTANCE).toList(); + Object[][] res = new Object[declaredMethods.size()][1]; + int i = 0; + for (Method declaredMethod : declaredMethods) { + res[i][0] = declaredMethod; + i++; + } + return res; + } + + @Test + @UseDataProvider("ceUserSessionPublicMethods") + public void all_methods_of_CeUserSession_throw_UOE(Method method) throws InvocationTargetException, IllegalAccessException { + int parametersCount = method.getParameterTypes().length; + switch (parametersCount) { + case 2: + expectUOE(); + method.invoke(underTest, null, null); + break; + case 1: + expectUOE(); + method.invoke(underTest, (Object) null); + break; + case 0: + expectUOE(); + method.invoke(underTest); + break; + default: + throw new IllegalArgumentException("Unsupported number of parameters " + parametersCount); + } + } + + private void expectUOE() { + expectedException.expect(InvocationTargetException.class); + expectedException.expectCause( + hasType(UnsupportedOperationException.class) + .andMessage("UserSession must not be used from within the Compute Engine") + ); + } + + private enum PublicMethodPredicate implements Predicate { + INSTANCE; + + @Override + public boolean apply(Method input) { + return Modifier.isPublic(input.getModifiers()); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java index a0123c174fc..ae7d8934a49 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -82,7 +82,6 @@ import org.sonar.server.user.UserSession; import org.sonar.server.view.index.ViewIndexDefinition; import static com.google.common.collect.Lists.newArrayList; -import static java.util.Objects.requireNonNull; import static org.sonarqube.ws.client.issue.IssueFilterParameters.ACTION_PLANS; import static org.sonarqube.ws.client.issue.IssueFilterParameters.ASSIGNEES; import static org.sonarqube.ws.client.issue.IssueFilterParameters.AUTHORS; @@ -157,17 +156,9 @@ public class IssueIndex extends BaseIndex { private final Sorting sorting; private final System2 system; - @CheckForNull private final UserSession userSession; - /** - * Constructor for Pico when no UserSession is available such as in the Compute Engine. - */ - public IssueIndex(EsClient client, System2 system) { - this(client, system, null); - } - - public IssueIndex(EsClient client, System2 system, @Nullable UserSession userSession) { + public IssueIndex(EsClient client, System2 system, UserSession userSession) { super(client); this.system = system; @@ -196,8 +187,6 @@ public class IssueIndex extends BaseIndex { */ @CheckForNull public IssueDoc getNullableByKey(String key) { - checkNotCalledFromCE(); - SearchResult result = search(IssueQuery.builder(userSession).issueKeys(newArrayList(key)).build(), new SearchOptions()); if (result.getTotal() == 1) { return result.getDocs().get(0); @@ -218,8 +207,6 @@ public class IssueIndex extends BaseIndex { } public SearchResult search(IssueQuery query, SearchOptions options) { - checkNotCalledFromCE(); - SearchRequestBuilder requestBuilder = getClient() .prepareSearch(IssueIndexDefinition.INDEX) .setTypes(IssueIndexDefinition.TYPE_ISSUE); @@ -769,8 +756,6 @@ public class IssueIndex extends BaseIndex { * Only fields needed for the batch are returned. */ public Iterator selectIssuesForBatch(ComponentDto component) { - checkNotCalledFromCE(); - BoolFilterBuilder filter = FilterBuilders.boolFilter() .must(createAuthorizationFilter(true, userSession.getLogin(), userSession.getUserGroups())) .mustNot(FilterBuilders.termsFilter(IssueIndexDefinition.FIELD_ISSUE_STATUS, Issue.STATUS_CLOSED)); @@ -804,8 +789,4 @@ public class IssueIndex extends BaseIndex { return EsUtils.scroll(getClient(), response.getScrollId(), DOC_CONVERTER); } - - private void checkNotCalledFromCE() { - requireNonNull(userSession, "getNullableByKey can not be used from the Compute Engine"); - } } -- 2.39.5