diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/configuration/LiferayGlobalObjectConfiguration.java b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/configuration/LiferayGlobalObjectConfiguration.java new file mode 100644 index 00000000000000..b5aabd9dacb794 --- /dev/null +++ b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/configuration/LiferayGlobalObjectConfiguration.java @@ -0,0 +1,32 @@ +/** + * SPDX-FileCopyrightText: (c) 2025 Liferay, Inc. https://liferay.com + * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06 + */ + +package com.liferay.frontend.js.web.internal.configuration; + +import aQute.bnd.annotation.metatype.Meta; + +import com.liferay.portal.configuration.metatype.annotations.ExtendedObjectClassDefinition; + +/** + * @author Iván Zaera Avellón + */ +@ExtendedObjectClassDefinition( + category = "infrastructure", + scope = ExtendedObjectClassDefinition.Scope.COMPANY, strictScope = true +) +@Meta.OCD( + id = "com.liferay.frontend.js.web.internal.configuration.LiferayGlobalObjectConfiguration", + localization = "content/Language", + name = "liferay-global-object-configuration-name" +) +public interface LiferayGlobalObjectConfiguration { + + @Meta.AD( + deflt = "false", description = "disable-get-remote-methods-help", + name = "disable-get-remote-methods", required = false + ) + public boolean disableGetRemoteMethods(); + +} \ No newline at end of file diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPreAUIDynamicInclude.java b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPreAUIDynamicInclude.java index fa527e78f63680..76e40fc5e8abb7 100644 --- a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPreAUIDynamicInclude.java +++ b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPreAUIDynamicInclude.java @@ -6,11 +6,14 @@ package com.liferay.frontend.js.web.internal.servlet.taglib; import com.liferay.exportimport.kernel.staging.Staging; +import com.liferay.frontend.js.web.internal.configuration.LiferayGlobalObjectConfiguration; import com.liferay.layout.seo.kernel.LayoutSEOLink; import com.liferay.layout.seo.kernel.LayoutSEOLinkManager; import com.liferay.petra.string.CharPool; import com.liferay.petra.string.StringBundler; import com.liferay.petra.string.StringPool; +import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil; +import com.liferay.portal.configuration.module.configuration.ConfigurationProvider; import com.liferay.portal.kernel.content.security.policy.ContentSecurityPolicyNonceProviderUtil; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.feature.flag.FeatureFlag; @@ -23,6 +26,7 @@ import com.liferay.portal.kernel.model.LayoutTypePortlet; import com.liferay.portal.kernel.model.User; import com.liferay.portal.kernel.model.impl.VirtualLayout; +import com.liferay.portal.kernel.module.configuration.ConfigurationException; import com.liferay.portal.kernel.security.auth.AuthToken; import com.liferay.portal.kernel.security.permission.ActionKeys; import com.liferay.portal.kernel.service.permission.LayoutPermission; @@ -63,6 +67,7 @@ import java.text.Format; import java.text.SimpleDateFormat; +import java.util.Collections; import java.util.Locale; import java.util.Map; import java.util.TimeZone; @@ -87,6 +92,9 @@ public void include( HttpServletResponse httpServletResponse, String key) throws IOException { + LiferayGlobalObjectConfiguration liferayGlobalObjectConfiguration = + _getLiferayGlobalObjectConfiguration(httpServletRequest); + PrintWriter printWriter = httpServletResponse.getWriter(); printWriter.print(" _displayNames = new ConcurrentHashMap<>(); @Reference diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/resources/com/liferay/frontend/js/web/internal/servlet/taglib/dependencies/liferay.js.tpl b/modules/apps/frontend-js/frontend-js-web/src/main/resources/com/liferay/frontend/js/web/internal/servlet/taglib/dependencies/liferay.js.tpl index 5c270b37924256..cbbaa4cbeb6d0e 100644 --- a/modules/apps/frontend-js/frontend-js-web/src/main/resources/com/liferay/frontend/js/web/internal/servlet/taglib/dependencies/liferay.js.tpl +++ b/modules/apps/frontend-js/frontend-js-web/src/main/resources/com/liferay/frontend/js/web/internal/servlet/taglib/dependencies/liferay.js.tpl @@ -42,7 +42,7 @@ merge(target[key], source[key]); } -else { + else { Object.assign(target, { [key]: source[key] }); } } diff --git a/modules/apps/frontend-js/frontend-js-web/src/test/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPreAUIDynamicIncludeTest.java b/modules/apps/frontend-js/frontend-js-web/src/test/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPreAUIDynamicIncludeTest.java index b9adb4b72aa237..929a9c7ef02765 100644 --- a/modules/apps/frontend-js/frontend-js-web/src/test/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPreAUIDynamicIncludeTest.java +++ b/modules/apps/frontend-js/frontend-js-web/src/test/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPreAUIDynamicIncludeTest.java @@ -6,10 +6,13 @@ package com.liferay.frontend.js.web.internal.servlet.taglib; import com.liferay.exportimport.kernel.staging.Staging; +import com.liferay.frontend.js.web.internal.configuration.LiferayGlobalObjectConfiguration; import com.liferay.layout.seo.kernel.LayoutSEOLink; import com.liferay.layout.seo.kernel.LayoutSEOLinkManager; import com.liferay.petra.string.StringBundler; import com.liferay.petra.string.StringPool; +import com.liferay.portal.configuration.module.configuration.ConfigurationProvider; +import com.liferay.portal.kernel.content.security.policy.ContentSecurityPolicyNonceProviderUtil; import com.liferay.portal.kernel.feature.flag.FeatureFlag; import com.liferay.portal.kernel.feature.flag.FeatureFlagManager; import com.liferay.portal.kernel.language.Language; @@ -46,8 +49,9 @@ import java.util.TimeZone; import java.util.function.Predicate; +import org.junit.After; import org.junit.Assert; -import org.junit.Ignore; +import org.junit.Before; import org.junit.Test; import org.mockito.MockedStatic; @@ -65,45 +69,32 @@ public class LiferayGlobalObjectPreAUIDynamicIncludeTest { public static final LiferayUnitTestRule liferayUnitTestRule = LiferayUnitTestRule.INSTANCE; - @Ignore + @Before + public void setUp() { + _browserSnifferUtilMockedStatic = _mockBrowserSnifferUtil(); + _contentSecurityPolicyNonceProviderUtilMockedStatic = + _mockContentSecurityPolicyNonceProviderUtil(); + _portalWebResourcesUtilMockedStatic = _mockPortalWebResourcesUtil(); + _shutdownUtilMockedStatic = _mockShutdownUtil(); + _timeMockedStatic = _mockTime(); + } + + @After + public void tearDown() { + _browserSnifferUtilMockedStatic.close(); + _contentSecurityPolicyNonceProviderUtilMockedStatic.close(); + _portalWebResourcesUtilMockedStatic.close(); + _shutdownUtilMockedStatic.close(); + _timeMockedStatic.close(); + } + @Test public void test() throws Exception { LiferayGlobalObjectPreAUIDynamicInclude liferayGlobalObjectPreAUIDynamicInclude = new LiferayGlobalObjectPreAUIDynamicInclude(); - ReflectionTestUtil.setFieldValue( - liferayGlobalObjectPreAUIDynamicInclude, "_authToken", - _mockAuthToken()); - ReflectionTestUtil.setFieldValue( - liferayGlobalObjectPreAUIDynamicInclude, "_fastDateFormatFactory", - _mockFastDateFormatFactory()); - ReflectionTestUtil.setFieldValue( - liferayGlobalObjectPreAUIDynamicInclude, "_featureFlagManager", - _mockFeatureFlagManager()); - ReflectionTestUtil.setFieldValue( - liferayGlobalObjectPreAUIDynamicInclude, "_language", - _mockLanguage()); - ReflectionTestUtil.setFieldValue( - liferayGlobalObjectPreAUIDynamicInclude, "_layoutSEOLinkManager", - _mockLayoutSEOLinkManager()); - ReflectionTestUtil.setFieldValue( - liferayGlobalObjectPreAUIDynamicInclude, "_portal", _mockPortal()); - ReflectionTestUtil.setFieldValue( - liferayGlobalObjectPreAUIDynamicInclude, "_prefsProps", - Mockito.mock(PrefsProps.class)); - ReflectionTestUtil.setFieldValue( - liferayGlobalObjectPreAUIDynamicInclude, "_staging", - _mockStaging()); - ReflectionTestUtil.setFieldValue( - liferayGlobalObjectPreAUIDynamicInclude, - "_uploadServletRequestConfigurationProvider", - Mockito.mock(UploadServletRequestConfigurationProvider.class)); - - _mockBrowserSnifferUtil(); - _mockPortalWebResourcesUtil(); - _mockShutdownUtil(); - _mockTime(); + _setupDefaultMocks(liferayGlobalObjectPreAUIDynamicInclude); MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse(); @@ -117,6 +108,33 @@ public void test() throws Exception { StringUtil.trim(mockHttpServletResponse.getContentAsString())); } + @Test + public void testDisableGetRemoteMethodsConfiguration() throws Exception { + LiferayGlobalObjectPreAUIDynamicInclude + liferayGlobalObjectPreAUIDynamicInclude = + new LiferayGlobalObjectPreAUIDynamicInclude(); + + _setupDefaultMocks(liferayGlobalObjectPreAUIDynamicInclude); + + ReflectionTestUtil.setFieldValue( + liferayGlobalObjectPreAUIDynamicInclude, "_configurationProvider", + _mockConfigurationProvider(true)); + + MockHttpServletResponse mockHttpServletResponse = + new MockHttpServletResponse(); + + liferayGlobalObjectPreAUIDynamicInclude.include( + _mockHttpServletRequest(), mockHttpServletResponse, + StringPool.BLANK); + + String contentAsString = mockHttpServletResponse.getContentAsString(); + + Assert.assertFalse( + contentAsString.contains("getRemoteAddr: () => '127.0.0.1',")); + Assert.assertFalse( + contentAsString.contains("getRemoteHost: () => '127.0.0.1',")); + } + private AuthToken _mockAuthToken() { AuthToken authToken = Mockito.mock(AuthToken.class); @@ -129,7 +147,7 @@ private AuthToken _mockAuthToken() { return authToken; } - private void _mockBrowserSnifferUtil() { + private MockedStatic _mockBrowserSnifferUtil() { MockedStatic browserSnifferUtilMockedStatic = Mockito.mockStatic(BrowserSnifferUtil.class); @@ -155,6 +173,52 @@ private void _mockBrowserSnifferUtil() { ).thenReturn( "42.0" ); + + return browserSnifferUtilMockedStatic; + } + + private ConfigurationProvider _mockConfigurationProvider( + boolean disableGetRemoteMethods) + throws Exception { + + ConfigurationProvider configurationProvider = Mockito.mock( + ConfigurationProvider.class); + + LiferayGlobalObjectConfiguration liferayGlobalObjectConfiguration = + Mockito.mock(LiferayGlobalObjectConfiguration.class); + + Mockito.when( + liferayGlobalObjectConfiguration.disableGetRemoteMethods() + ).thenReturn( + disableGetRemoteMethods + ); + + Mockito.when( + configurationProvider.getCompanyConfiguration( + Mockito.any(), Mockito.anyLong()) + ).thenReturn( + liferayGlobalObjectConfiguration + ); + + return configurationProvider; + } + + private MockedStatic + _mockContentSecurityPolicyNonceProviderUtil() { + + MockedStatic + contentSecurityPolicyNonceProviderUtilMockedStatic = + Mockito.mockStatic( + ContentSecurityPolicyNonceProviderUtil.class); + + contentSecurityPolicyNonceProviderUtilMockedStatic.when( + () -> ContentSecurityPolicyNonceProviderUtil.getNonceAttribute( + Mockito.any()) + ).thenReturn( + StringPool.BLANK + ); + + return contentSecurityPolicyNonceProviderUtilMockedStatic; } private FastDateFormatFactory _mockFastDateFormatFactory() { @@ -322,7 +386,7 @@ private Portal _mockPortal() throws Exception { return portal; } - private void _mockPortalWebResourcesUtil() { + private MockedStatic _mockPortalWebResourcesUtil() { MockedStatic portalWebResourcesUtilMockedStatic = Mockito.mockStatic( PortalWebResourcesUtil.class); @@ -333,9 +397,11 @@ private void _mockPortalWebResourcesUtil() { (Answer) invocationOnMock -> "/o/" + invocationOnMock.getArgument(0) ); + + return portalWebResourcesUtilMockedStatic; } - private void _mockShutdownUtil() { + private MockedStatic _mockShutdownUtil() { MockedStatic shutdownUtilMockedStatic = Mockito.mockStatic(ShutdownUtil.class); @@ -344,6 +410,8 @@ private void _mockShutdownUtil() { ).thenReturn( true ); + + return shutdownUtilMockedStatic; } private Staging _mockStaging() { @@ -484,7 +552,7 @@ private ThemeDisplay _mockThemeDisplay() { return themeDisplay; } - private void _mockTime() { + private MockedStatic