diff --git a/component/api/src/main/java/org/exoplatform/portal/mop/navigation/NodeManager.java b/component/api/src/main/java/org/exoplatform/portal/mop/navigation/NodeManager.java index 5304d85252..8eee49fb56 100644 --- a/component/api/src/main/java/org/exoplatform/portal/mop/navigation/NodeManager.java +++ b/component/api/src/main/java/org/exoplatform/portal/mop/navigation/NodeManager.java @@ -185,7 +185,9 @@ private void saveTree(TreeContext tree, NodeChangeListener NodeChangeQueue> changes = rebased.getChanges(); if (changes != null) { changes.broadcast(persister); - changes.broadcast(listener); + if (listener != null) { + changes.broadcast(listener); + } // Update the tree handles to the persistent values for (Map.Entry entry : persister.toPersist.entrySet()) { diff --git a/component/api/src/main/java/org/exoplatform/portal/mop/service/NavigationService.java b/component/api/src/main/java/org/exoplatform/portal/mop/service/NavigationService.java index 89d34b16ea..1c43ce2668 100644 --- a/component/api/src/main/java/org/exoplatform/portal/mop/service/NavigationService.java +++ b/component/api/src/main/java/org/exoplatform/portal/mop/service/NavigationService.java @@ -76,6 +76,26 @@ NodeContext loadNode(NodeModel model, Scope scope, NodeChangeListener> listener); + /** + * Loads root node of a designated Site + * + * @param siteKey {@link SiteKey} + * @param the node generic type + * @return the loaded node + */ + NodeContext> loadNode(SiteKey siteKey); + + /** + * Loads a specific node of a Site identitifed by its relative URI (from root + * node until node) + * + * @param siteKey + * @param navUri + * @param the node generic type + * @return the loaded node + */ + NodeContext> loadNode(SiteKey siteKey, String navUri); + /** * Load a navigation node from a specified navigation by its id * diff --git a/component/portal/src/main/java/io/meeds/portal/security/listener/PortalRegistrationUpdateListener.java b/component/portal/src/main/java/io/meeds/portal/security/listener/PortalRegistrationUpdateListener.java new file mode 100644 index 0000000000..97d9525b32 --- /dev/null +++ b/component/portal/src/main/java/io/meeds/portal/security/listener/PortalRegistrationUpdateListener.java @@ -0,0 +1,61 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2023 Meeds Association contact@meeds.io + * + * 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 io.meeds.portal.security.listener; + +import java.util.List; + +import org.exoplatform.container.xml.InitParams; +import org.exoplatform.portal.mop.SiteKey; +import org.exoplatform.portal.mop.Visibility; +import org.exoplatform.portal.mop.navigation.NodeContext; +import org.exoplatform.portal.mop.navigation.NodeState; +import org.exoplatform.portal.mop.service.NavigationService; +import org.exoplatform.services.listener.Event; +import org.exoplatform.services.listener.Listener; + +import io.meeds.portal.security.constant.UserRegistrationType; + +public class PortalRegistrationUpdateListener extends Listener { + + private NavigationService navigationService; + + private List managedPages; + + public PortalRegistrationUpdateListener(NavigationService navigationService, InitParams params) { + this.navigationService = navigationService; + this.managedPages = params.getValuesParam("managed-pages").getValues(); + } + + @Override + public void onEvent(Event event) throws Exception { + boolean isOpen = event.getData() == UserRegistrationType.OPEN; + managedPages.forEach(navUri -> { + NodeContext> navNode = navigationService.loadNode(SiteKey.portal("public"), navUri); + if (navNode != null) { + NodeState state = navNode.getState() + .builder() + .visibility(isOpen ? Visibility.DISPLAYED : Visibility.HIDDEN) + .build(); + navNode.setState(state); + navigationService.updateNode(Long.parseLong(navNode.getId()), state); + } + }); + } + +} diff --git a/component/portal/src/main/java/io/meeds/portal/security/service/SecuritySettingService.java b/component/portal/src/main/java/io/meeds/portal/security/service/SecuritySettingService.java index bea053f8ba..d67ce5e016 100644 --- a/component/portal/src/main/java/io/meeds/portal/security/service/SecuritySettingService.java +++ b/component/portal/src/main/java/io/meeds/portal/security/service/SecuritySettingService.java @@ -30,12 +30,21 @@ import org.exoplatform.commons.api.settings.SettingValue; import org.exoplatform.commons.api.settings.data.Context; import org.exoplatform.commons.api.settings.data.Scope; +import org.exoplatform.services.listener.ListenerService; +import org.exoplatform.services.log.ExoLogger; +import org.exoplatform.services.log.Log; import io.meeds.portal.security.constant.UserRegistrationType; import io.meeds.portal.security.model.RegistrationSetting; public class SecuritySettingService { + public static final String ACCESS_TYPE_MODIFIED = "meeds.settings.access.type.modified"; + + public static final String EXTERNAL_USER_REG_MODIFIED = "meeds.settings.access.externalUsers.modified"; + + public static final String DEFAULT_GROUPS_MODIFIED = "meeds.settings.access.defaultGroups.modified"; + protected static final String INTERNAL_USERS_GROUP = "/platform/users"; protected static final String EXTERNAL_USERS_GROUP = "/platform/externals"; @@ -60,12 +69,19 @@ public class SecuritySettingService { Boolean.parseBoolean(System.getProperty("meeds.settings.access.externalUsers", "false").toLowerCase()); + private static final Log LOG = + ExoLogger.getLogger(SecuritySettingService.class); + private RegistrationSetting registrationSetting; private SettingService settingService; - public SecuritySettingService(SettingService settingService) { + private ListenerService listenerService; + + public SecuritySettingService(SettingService settingService, + ListenerService listenerService) { this.settingService = settingService; + this.listenerService = listenerService; } public RegistrationSetting getRegistrationSetting() { @@ -103,16 +119,21 @@ public UserRegistrationType getRegistrationType() { } public void saveRegistrationType(UserRegistrationType registrationType) { - try { - if (registrationType == null) { - registrationType = DEFAULT_REGISTRATION_TYPE; + if (registrationType == null) { + registrationType = DEFAULT_REGISTRATION_TYPE; + } + UserRegistrationType storedRegistrationType = getRegistrationType(); + boolean modified = registrationType != storedRegistrationType; + if (modified) { + try { + settingService.set(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_TYPE_PARAM, + SettingValue.create(registrationType.toString())); + broadcastEvent(ACCESS_TYPE_MODIFIED, null, registrationType); + } finally { + registrationSetting = null; } - settingService.set(SECURITY_CONTEXT, - SECURITY_SCOPE, - REGISTRATION_TYPE_PARAM, - SettingValue.create(registrationType.toString())); - } finally { - registrationSetting = null; } } @@ -126,13 +147,16 @@ public boolean isRegistrationExternalUser() { } public void saveRegistrationExternalUser(boolean externalUser) { - try { - settingService.set(SECURITY_CONTEXT, - SECURITY_SCOPE, - REGISTRATION_EXTERNAL_USER_PARAM, - SettingValue.create(String.valueOf(externalUser))); - } finally { - registrationSetting = null; + if (externalUser != isRegistrationExternalUser()) { + try { + settingService.set(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_EXTERNAL_USER_PARAM, + SettingValue.create(String.valueOf(externalUser))); + broadcastEvent(EXTERNAL_USER_REG_MODIFIED, null, externalUser); + } finally { + registrationSetting = null; + } } } @@ -157,9 +181,22 @@ public void saveRegistrationExtraGroupIds(String[] groupIds) { SECURITY_SCOPE, REGISTRATION_EXTRA_GROUPS_PARAM, SettingValue.create(StringUtils.join(groupIds, EXTRA_GROUPS_SEPARATOR))); + broadcastEvent(DEFAULT_GROUPS_MODIFIED, null, groupIds); } finally { registrationSetting = null; } } + private void broadcastEvent(String eventName, Object source, Object data) { + try { + listenerService.broadcast(eventName, source, data); + } catch (Exception e) { + LOG.warn("Error broacasting event {} with source {} and data {}", + eventName, + source, + data, + e); + } + } + } diff --git a/component/portal/src/main/java/org/exoplatform/portal/config/UserPortalConfigService.java b/component/portal/src/main/java/org/exoplatform/portal/config/UserPortalConfigService.java index 6cfd89dcb8..4c12d2029c 100644 --- a/component/portal/src/main/java/org/exoplatform/portal/config/UserPortalConfigService.java +++ b/component/portal/src/main/java/org/exoplatform/portal/config/UserPortalConfigService.java @@ -22,6 +22,7 @@ import javax.servlet.http.HttpServletRequest; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.exoplatform.portal.config.model.ModelObject; import org.exoplatform.portal.config.model.Page; @@ -70,6 +71,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.Objects; import java.util.ResourceBundle; /** @@ -88,13 +90,13 @@ public class UserPortalConfigService implements Startable { public static final String DEFAULT_USER_SITE_TEMPLATE = "user"; - private final SiteFilter siteFilter = new SiteFilter(SiteType.PORTAL, + protected final SiteFilter siteFilter = new SiteFilter(SiteType.PORTAL, null, null, true, true, - true, - true, + false, + false, 0, 0); @@ -186,6 +188,7 @@ public UserPortalConfigService(UserACL userACL, // NOSONAR this.defaultImportMode = defaultImportMode; this.defaultGroupSiteTemplate = defaultGroupSiteTemplate; this.defaultUserSiteTemplate = defaultUserSiteTemplate; + this.siteFilter.setExcludedSiteName(globalPortal_); } public PageStorage getPageService() { @@ -545,15 +548,26 @@ public List getSiteNames(SiteType siteType, int offset, int limit) { return list; } - public List getUserPortalDisplayedSites() { - siteFilter.setExcludedSiteName(globalPortal_); + public List getUserPortalSites() { List list = layoutService.getSites(siteFilter); - return list.stream().filter(config -> config != null && userACL_.hasPermission(config)).toList(); + return list.stream() + .filter(Objects::nonNull) + .filter(userACL_::hasPermission) + .sorted((s1, s2) -> { + if (StringUtils.equals(s1.getName(), getDefaultPortal())) { + return -Integer.MAX_VALUE; + } else if (StringUtils.equals(s2.getName(), getDefaultPortal())) { + return Integer.MAX_VALUE; + } else { + return s2.getDisplayOrder() - s1.getDisplayOrder(); + } + }) + .toList(); } public String computePortalPath(HttpServletRequest context) throws Exception { - List portalConfigList = getUserPortalDisplayedSites(); - if (portalConfigList == null || portalConfigList.isEmpty()) { + List portalConfigList = getUserPortalSites(); + if (CollectionUtils.isEmpty(portalConfigList)) { return null; } String defaultPortal = portalConfigList.get(0).getName(); diff --git a/component/portal/src/main/java/org/exoplatform/portal/mop/rest/NavigationRest.java b/component/portal/src/main/java/org/exoplatform/portal/mop/rest/NavigationRest.java index 744f8bf43b..f5cb55bac0 100644 --- a/component/portal/src/main/java/org/exoplatform/portal/mop/rest/NavigationRest.java +++ b/component/portal/src/main/java/org/exoplatform/portal/mop/rest/NavigationRest.java @@ -4,7 +4,6 @@ import java.util.Collection; import java.util.List; -import javax.annotation.security.RolesAllowed; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; @@ -85,14 +84,14 @@ public NavigationRest(UserPortalConfigService portalConfigService, @GET @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("users") @Operation(summary = "Gets navigations", description = "Gets navigations", method = "GET") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), @ApiResponse(responseCode = "400", description = "Invalid query input"), @ApiResponse(responseCode = "404", description = "Navigation does not exist"), @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response getSiteNavigation(@Context - HttpServletRequest request, + public Response getSiteNavigation( + @Context + HttpServletRequest request, @Parameter(description = "Offset", required = false) @Schema(defaultValue = "0") @QueryParam("offset") @@ -131,14 +130,14 @@ public Response getSiteNavigation(@Context @Path("/{siteType}") @GET @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("users") @Operation(summary = "Gets navigations of one or multiple site navigations", description = "Gets navigations of one or multiple site navigations", method = "GET") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), @ApiResponse(responseCode = "400", description = "Invalid query input"), @ApiResponse(responseCode = "404", description = "Navigation does not exist"), @ApiResponse(responseCode = "500", description = "Internal server error") }) - public Response getSiteTypeNavigations(@Context - HttpServletRequest request, + public Response getSiteTypeNavigations( + @Context + HttpServletRequest request, @Parameter(description = "Portal site type, possible values: PORTAL, GROUP or USER", required = true) @PathParam("siteType") String siteTypeName, @@ -186,7 +185,6 @@ public Response getSiteTypeNavigations(@Context @Path("/categories") @GET @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("users") @Operation(summary = "Gets navigations categories for UI", description = "Gets navigations categories for UI", method = "GET") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), @ApiResponse(responseCode = "500", description = "Internal server error"), }) diff --git a/component/portal/src/main/java/org/exoplatform/portal/mop/service/NavigationServiceImpl.java b/component/portal/src/main/java/org/exoplatform/portal/mop/service/NavigationServiceImpl.java index e88f9a299f..7855f6a068 100644 --- a/component/portal/src/main/java/org/exoplatform/portal/mop/service/NavigationServiceImpl.java +++ b/component/portal/src/main/java/org/exoplatform/portal/mop/service/NavigationServiceImpl.java @@ -18,8 +18,14 @@ */ package org.exoplatform.portal.mop.service; +import java.util.Arrays; +import java.util.Iterator; + +import org.apache.commons.lang.StringUtils; + import org.exoplatform.portal.mop.EventType; import org.exoplatform.portal.mop.SiteKey; +import org.exoplatform.portal.mop.navigation.GenericScope; import org.exoplatform.portal.mop.navigation.NavigationContext; import org.exoplatform.portal.mop.navigation.NavigationData; import org.exoplatform.portal.mop.navigation.NodeChangeListener; @@ -99,7 +105,41 @@ public boolean destroyNavigation(SiteKey siteKey) { } } - public NodeContext loadNode(NodeModel model, NavigationContext navigation, Scope scope, + @Override + public NodeContext> loadNode(SiteKey siteKey) { + return loadNode(siteKey, null); + } + + @Override + public NodeContext> loadNode(SiteKey siteKey, String navUri) { + if (siteKey == null) { + return null; + } + NavigationContext navigation = loadNavigation(siteKey); + if (navigation == null) { + return null; + } + + if (StringUtils.isBlank(navUri)) { + return loadNode(NodeModel.SELF_MODEL, navigation, Scope.ALL, null); + } else { + String[] pathTreeParts = StringUtils.trim(navUri).split("/"); + NodeContext> node = loadNode(NodeModel.SELF_MODEL, + navigation, + GenericScope.branchShape(pathTreeParts, Scope.ALL), + null); + Iterator iterator = Arrays.asList(pathTreeParts).iterator(); + while (iterator.hasNext() && node != null) { + String name = iterator.next(); + node = node.get(name); + } + return node; + } + } + + public NodeContext loadNode(NodeModel model, + NavigationContext navigation, + Scope scope, NodeChangeListener> listener) { if (model == null) { throw new NullPointerException("No null model accepted"); @@ -119,7 +159,9 @@ public NodeContext loadNode(NodeModel model, NavigationContext navigat } @Override - public NodeContext loadNodeById(NodeModel model, String nodeId, Scope scope, + public NodeContext loadNodeById(NodeModel model, + String nodeId, + Scope scope, NodeChangeListener> listener) { if (model == null) { throw new NullPointerException("No null model accepted"); @@ -137,6 +179,10 @@ public void updateNode(NodeContext root, Scope scope, NodeChangeListener< nodeManager.updateNode(root, scope, new NodeChangeNotifier<>(listener, this, listenerService)); } + public void saveNode(NodeContext context) { + saveNode(context, null); + } + public void saveNode(NodeContext context, NodeChangeListener> listener) { nodeManager.saveNode(context, new NodeChangeNotifier<>(listener, this, listenerService)); } diff --git a/component/portal/src/test/java/io/meeds/portal/security/listener/PortalRegistrationUpdateListenerTest.java b/component/portal/src/test/java/io/meeds/portal/security/listener/PortalRegistrationUpdateListenerTest.java new file mode 100644 index 0000000000..dab901b806 --- /dev/null +++ b/component/portal/src/test/java/io/meeds/portal/security/listener/PortalRegistrationUpdateListenerTest.java @@ -0,0 +1,98 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2023 Meeds Association contact@meeds.io + * + * 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 io.meeds.portal.security.listener; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import org.exoplatform.container.xml.InitParams; +import org.exoplatform.container.xml.ValuesParam; +import org.exoplatform.portal.mop.SiteKey; +import org.exoplatform.portal.mop.Visibility; +import org.exoplatform.portal.mop.navigation.NodeContext; +import org.exoplatform.portal.mop.navigation.NodeState; +import org.exoplatform.portal.mop.navigation.NodeState.Builder; +import org.exoplatform.portal.mop.service.NavigationService; +import org.exoplatform.services.listener.Event; + +import io.meeds.portal.security.constant.UserRegistrationType; + +@RunWith(MockitoJUnitRunner.class) +public class PortalRegistrationUpdateListenerTest { + + private static final String NAV_NODE_ID = "1225"; + + private static final String NAV_NODE_URI = "publicSiteNodeUri"; + + @Mock + private NavigationService navigationService; + + @Mock + private InitParams params; + + @Mock + private NodeContext> navNode; + + @Mock + private NodeState navState; + + @Mock + private Builder navStateBuilder; + + @Mock + private Event event; + + @Test + public void testUpdateRegistrationType() throws Exception { + ValuesParam valuesParam = new ValuesParam(); + valuesParam.setValues(Arrays.asList(NAV_NODE_URI)); + when(params.getValuesParam("managed-pages")).thenReturn(valuesParam); + when(navigationService.loadNode(SiteKey.portal("public"), NAV_NODE_URI)).thenReturn(navNode); + when(navNode.getId()).thenReturn(NAV_NODE_ID); + when(navNode.getState()).thenReturn(navState); + when(navState.builder()).thenReturn(navStateBuilder); + when(navStateBuilder.visibility(any())).thenReturn(navStateBuilder); + when(navStateBuilder.build()).thenReturn(navState); + + PortalRegistrationUpdateListener registrationUpdateListener = new PortalRegistrationUpdateListener(navigationService, params); + + when(event.getData()).thenReturn(UserRegistrationType.OPEN); + registrationUpdateListener.onEvent(event); + + verify(navStateBuilder, times(1)).visibility(Visibility.DISPLAYED); + verify(navStateBuilder, never()).visibility(Visibility.HIDDEN); + verify(navigationService, times(1)).updateNode(Long.parseLong(NAV_NODE_ID), navState); + + when(event.getData()).thenReturn(UserRegistrationType.RESTRICTED); + registrationUpdateListener.onEvent(event); + verify(navStateBuilder, times(1)).visibility(Visibility.HIDDEN); + verify(navigationService, times(2)).updateNode(Long.parseLong(NAV_NODE_ID), navState); + } + +} diff --git a/component/portal/src/test/java/io/meeds/portal/security/service/SettingSecurityServieTest.java b/component/portal/src/test/java/io/meeds/portal/security/service/SettingSecurityServieTest.java index b3c3f7cfd4..9f6aeb2ad3 100644 --- a/component/portal/src/test/java/io/meeds/portal/security/service/SettingSecurityServieTest.java +++ b/component/portal/src/test/java/io/meeds/portal/security/service/SettingSecurityServieTest.java @@ -19,7 +19,7 @@ package io.meeds.portal.security.service; -import static io.meeds.portal.security.service.SecuritySettingService.DEFAULT_REGISTRATION_EXTERNAL_USER; +import static io.meeds.portal.security.service.SecuritySettingService.*; import static io.meeds.portal.security.service.SecuritySettingService.DEFAULT_REGISTRATION_TYPE; import static io.meeds.portal.security.service.SecuritySettingService.EXTERNAL_USERS_GROUP; import static io.meeds.portal.security.service.SecuritySettingService.EXTRA_GROUPS_SEPARATOR; @@ -37,6 +37,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -52,6 +53,7 @@ import org.exoplatform.commons.api.settings.SettingService; import org.exoplatform.commons.api.settings.SettingValue; +import org.exoplatform.services.listener.ListenerService; import io.meeds.portal.security.constant.UserRegistrationType; import io.meeds.portal.security.model.RegistrationSetting; @@ -63,11 +65,14 @@ public class SettingSecurityServieTest { @Mock private SettingService settingService; + @Mock + private ListenerService listenerService; + private SecuritySettingService securitySettingService; @Before public void setUp() { - securitySettingService = new SecuritySettingService(settingService); + securitySettingService = new SecuritySettingService(settingService, listenerService); } @Test @@ -83,6 +88,18 @@ public void testGetRegistrationSetting() { @Test public void testSaveRegistrationSetting() { securitySettingService.saveRegistrationSetting(new RegistrationSetting()); + verify(settingService, times(1)).set(eq(SECURITY_CONTEXT), eq(SECURITY_SCOPE), anyString(), any()); + } + + @Test + public void testSaveRegistrationSettingWithNoDefault() { + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_TYPE_PARAM)).thenReturn((SettingValue) SettingValue.create(UserRegistrationType.RESTRICTED.name())); + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_EXTERNAL_USER_PARAM)).thenReturn((SettingValue) SettingValue.create(true)); + securitySettingService.saveRegistrationSetting(new RegistrationSetting()); verify(settingService, times(3)).set(eq(SECURITY_CONTEXT), eq(SECURITY_SCOPE), anyString(), any()); } @@ -93,18 +110,18 @@ public void testGetRegistrationGroupIds() { assertEquals(1, registrationGroupIds.length); assertEquals(INTERNAL_USERS_GROUP, registrationGroupIds[0]); - when(settingService.get(eq(SECURITY_CONTEXT), - eq(SECURITY_SCOPE), - eq(REGISTRATION_EXTERNAL_USER_PARAM))).thenReturn((SettingValue) SettingValue.create(true)); + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_EXTERNAL_USER_PARAM)).thenReturn((SettingValue) SettingValue.create(true)); registrationGroupIds = securitySettingService.getRegistrationGroupIds(); assertNotNull(registrationGroupIds); assertEquals(1, registrationGroupIds.length); assertEquals(EXTERNAL_USERS_GROUP, registrationGroupIds[0]); - when(settingService.get(eq(SECURITY_CONTEXT), - eq(SECURITY_SCOPE), - eq(REGISTRATION_EXTERNAL_USER_PARAM))).thenReturn((SettingValue) SettingValue.create(false)); + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_EXTERNAL_USER_PARAM)).thenReturn((SettingValue) SettingValue.create(false)); registrationGroupIds = securitySettingService.getRegistrationGroupIds(); assertNotNull(registrationGroupIds); @@ -118,17 +135,17 @@ public void testGetRegistrationType() { assertNotNull(registrationType); assertEquals(DEFAULT_REGISTRATION_TYPE, registrationType); - when(settingService.get(eq(SECURITY_CONTEXT), - eq(SECURITY_SCOPE), - eq(REGISTRATION_TYPE_PARAM))).thenReturn((SettingValue) SettingValue.create(UserRegistrationType.OPEN.name())); + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_TYPE_PARAM)).thenReturn((SettingValue) SettingValue.create(UserRegistrationType.OPEN.name())); registrationType = securitySettingService.getRegistrationType(); assertNotNull(registrationType); assertEquals(UserRegistrationType.OPEN, registrationType); - when(settingService.get(eq(SECURITY_CONTEXT), - eq(SECURITY_SCOPE), - eq(REGISTRATION_TYPE_PARAM))).thenReturn((SettingValue) SettingValue.create(UserRegistrationType.RESTRICTED.name())); + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_TYPE_PARAM)).thenReturn((SettingValue) SettingValue.create(UserRegistrationType.RESTRICTED.name())); registrationType = securitySettingService.getRegistrationType(); assertNotNull(registrationType); @@ -136,65 +153,87 @@ public void testGetRegistrationType() { } @Test - public void testSaveRegistrationType() { + public void testSaveRegistrationType() throws Exception { + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_TYPE_PARAM)).thenReturn((SettingValue) SettingValue.create(UserRegistrationType.RESTRICTED.name())); securitySettingService.saveRegistrationType(UserRegistrationType.OPEN); verify(settingService, times(1)).set(eq(SECURITY_CONTEXT), - eq(SECURITY_SCOPE), - eq(REGISTRATION_TYPE_PARAM), + eq(SECURITY_SCOPE), + eq(REGISTRATION_TYPE_PARAM), argThat(args -> StringUtils.equals(args.getValue().toString(), UserRegistrationType.OPEN.name()))); + verify(listenerService, times(1)).broadcast(ACCESS_TYPE_MODIFIED, null, UserRegistrationType.OPEN); + + securitySettingService.saveRegistrationType(UserRegistrationType.RESTRICTED); + verify(settingService, + never()).set(eq(SECURITY_CONTEXT), + eq(SECURITY_SCOPE), + eq(REGISTRATION_TYPE_PARAM), + argThat(args -> StringUtils.equals(args.getValue().toString(), UserRegistrationType.RESTRICTED.name()))); + + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_TYPE_PARAM)).thenReturn((SettingValue) SettingValue.create(UserRegistrationType.OPEN.name())); securitySettingService.saveRegistrationType(UserRegistrationType.RESTRICTED); verify(settingService, times(1)).set(eq(SECURITY_CONTEXT), eq(SECURITY_SCOPE), eq(REGISTRATION_TYPE_PARAM), argThat(args -> StringUtils.equals(args.getValue().toString(), UserRegistrationType.RESTRICTED.name()))); + verify(listenerService, times(1)).broadcast(ACCESS_TYPE_MODIFIED, null, UserRegistrationType.RESTRICTED); } @Test public void testIsRegistrationExternalUser() { assertEquals(DEFAULT_REGISTRATION_EXTERNAL_USER, securitySettingService.isRegistrationExternalUser()); - when(settingService.get(eq(SECURITY_CONTEXT), - eq(SECURITY_SCOPE), - eq(REGISTRATION_EXTERNAL_USER_PARAM))).thenReturn((SettingValue) SettingValue.create(true)); + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_EXTERNAL_USER_PARAM)).thenReturn((SettingValue) SettingValue.create(true)); assertTrue(securitySettingService.isRegistrationExternalUser()); - when(settingService.get(eq(SECURITY_CONTEXT), - eq(SECURITY_SCOPE), - eq(REGISTRATION_EXTERNAL_USER_PARAM))).thenReturn((SettingValue) SettingValue.create(false)); + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_EXTERNAL_USER_PARAM)).thenReturn((SettingValue) SettingValue.create(false)); assertFalse(securitySettingService.isRegistrationExternalUser()); } @Test - public void testSaveRegistrationExternalUser() { + public void testSaveRegistrationExternalUser() throws Exception { securitySettingService.saveRegistrationExternalUser(true); verify(settingService, times(1)).set(eq(SECURITY_CONTEXT), eq(SECURITY_SCOPE), eq(REGISTRATION_EXTERNAL_USER_PARAM), argThat(args -> StringUtils.equals(args.getValue().toString(), "true"))); + verify(listenerService, times(1)).broadcast(EXTERNAL_USER_REG_MODIFIED, null, true); + + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_EXTERNAL_USER_PARAM)).thenReturn((SettingValue) SettingValue.create("true")); securitySettingService.saveRegistrationExternalUser(false); verify(settingService, times(1)).set(eq(SECURITY_CONTEXT), eq(SECURITY_SCOPE), eq(REGISTRATION_EXTERNAL_USER_PARAM), argThat(args -> StringUtils.equals(args.getValue().toString(), "false"))); + verify(listenerService, times(1)).broadcast(EXTERNAL_USER_REG_MODIFIED, null, false); } @Test public void testGetRegistrationExtraGroupIds() { assertEquals(Arrays.asList(INTERNAL_USERS_GROUP), Arrays.asList(securitySettingService.getRegistrationGroupIds())); - when(settingService.get(eq(SECURITY_CONTEXT), - eq(SECURITY_SCOPE), - eq(REGISTRATION_EXTRA_GROUPS_PARAM))).thenReturn((SettingValue) SettingValue.create("")); + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_EXTRA_GROUPS_PARAM)).thenReturn((SettingValue) SettingValue.create("")); String[] registrationGroupIds = securitySettingService.getRegistrationGroupIds(); assertNotNull(registrationGroupIds); assertEquals(1, registrationGroupIds.length); assertEquals(INTERNAL_USERS_GROUP, registrationGroupIds[0]); - when(settingService.get(eq(SECURITY_CONTEXT), - eq(SECURITY_SCOPE), - eq(REGISTRATION_EXTRA_GROUPS_PARAM))).thenReturn((SettingValue) SettingValue.create("group1,group2")); + when(settingService.get(SECURITY_CONTEXT, + SECURITY_SCOPE, + REGISTRATION_EXTRA_GROUPS_PARAM)).thenReturn((SettingValue) SettingValue.create("group1,group2")); registrationGroupIds = securitySettingService.getRegistrationGroupIds(); assertNotNull(registrationGroupIds); assertEquals(3, registrationGroupIds.length); diff --git a/component/portal/src/test/java/org/exoplatform/portal/config/TestLoadedPOM.java b/component/portal/src/test/java/org/exoplatform/portal/config/TestLoadedPOM.java index 7bf37589ac..5e461aecdc 100644 --- a/component/portal/src/test/java/org/exoplatform/portal/config/TestLoadedPOM.java +++ b/component/portal/src/test/java/org/exoplatform/portal/config/TestLoadedPOM.java @@ -121,6 +121,24 @@ public void testNavigation() throws Exception { assertEquals(Visibility.TEMPORAL, nodeNavigation.getState().getVisibility()); } + public void testLoadNode() throws Exception { + NodeContext root = navService.loadNode(SiteKey.portal("test")); + assertEquals(5, root.getNodeCount()); + + NodeContext nodeNavigation = navService.loadNode(SiteKey.portal("test"), "node_name"); + assertEquals(0, nodeNavigation.getNodeCount()); + assertEquals("node_name", nodeNavigation.getName()); + assertEquals("node_label", nodeNavigation.getState().getLabel()); + assertEquals("node_icon", nodeNavigation.getState().getIcon()); + GregorianCalendar start = new GregorianCalendar(2000, 2, 21, 1, 33, 0); + start.setTimeZone(TimeZone.getTimeZone("UTC")); + assertEquals(start.getTime().getTime(), nodeNavigation.getState().getStartPublicationTime()); + GregorianCalendar end = new GregorianCalendar(2009, 2, 21, 1, 33, 0); + end.setTimeZone(TimeZone.getTimeZone("UTC")); + assertEquals(end.getTime().getTime(), nodeNavigation.getState().getEndPublicationTime()); + assertEquals(Visibility.TEMPORAL, nodeNavigation.getState().getVisibility()); + } + public void testPortal() throws Exception { PortalConfig portal = layoutService.getPortalConfig("test"); assertNotNull(portal); diff --git a/component/portal/src/test/java/org/exoplatform/portal/config/TestUserPortalConfigService.java b/component/portal/src/test/java/org/exoplatform/portal/config/TestUserPortalConfigService.java index 141fee7692..e91168e09a 100644 --- a/component/portal/src/test/java/org/exoplatform/portal/config/TestUserPortalConfigService.java +++ b/component/portal/src/test/java/org/exoplatform/portal/config/TestUserPortalConfigService.java @@ -245,12 +245,13 @@ public void testGetSites() { new UnitTest() { public void execute() throws Exception { userPortalConfigSer_.removeUserPortalConfig("jazz"); - assertEquals(4, userPortalConfigSer_.getUserPortalDisplayedSites().size()); + assertEquals(4, userPortalConfigSer_.getUserPortalSites().size()); String originalGlobalPortal = userPortalConfigSer_.globalPortal_; userPortalConfigSer_.globalPortal_ = "system"; + userPortalConfigSer_.siteFilter.setExcludedSiteName(userPortalConfigSer_.getGlobalPortal()); try { - assertEquals(3, userPortalConfigSer_.getUserPortalDisplayedSites().size()); + assertEquals(3, userPortalConfigSer_.getUserPortalSites().size()); } finally { userPortalConfigSer_.globalPortal_ = originalGlobalPortal; } diff --git a/component/portal/src/test/java/org/exoplatform/portal/test/InitContainer1TestSuite.java b/component/portal/src/test/java/org/exoplatform/portal/test/InitContainer1TestSuite.java index d07917f0f0..3b34884ab3 100644 --- a/component/portal/src/test/java/org/exoplatform/portal/test/InitContainer1TestSuite.java +++ b/component/portal/src/test/java/org/exoplatform/portal/test/InitContainer1TestSuite.java @@ -57,14 +57,13 @@ import org.exoplatform.portal.tree.list.TestListTree; import org.exoplatform.settings.rest.SettingResourceTest; +import io.meeds.portal.security.listener.PortalRegistrationUpdateListenerTest; import io.meeds.portal.security.service.SettingSecurityServieTest; - - - @RunWith(Suite.class) @SuiteClasses({ SettingSecurityServieTest.class, + PortalRegistrationUpdateListenerTest.class, AccountSetupServiceTest.class, BrandingServiceImplTest.class, DefaultGroupVisibilityPluginTest.class, diff --git a/web/portal/src/main/webapp/groovy/portal/webui/container/UITopbarLoadingContainer.gtmpl b/web/portal/src/main/webapp/groovy/portal/webui/container/UITopbarLoadingContainer.gtmpl index 2de29bb8c0..dd8cfb5d7b 100644 --- a/web/portal/src/main/webapp/groovy/portal/webui/container/UITopbarLoadingContainer.gtmpl +++ b/web/portal/src/main/webapp/groovy/portal/webui/container/UITopbarLoadingContainer.gtmpl @@ -4,8 +4,7 @@ %>
transparent theme--light" - id="vuetify-apps"> + class="v-application <%= isRT ? "v-application--is-rtl" : "v-application--is-ltr" %> transparent theme--light">
diff --git a/web/portal/src/main/webapp/groovy/portal/webui/page/UIPageBody.gtmpl b/web/portal/src/main/webapp/groovy/portal/webui/page/UIPageBody.gtmpl index f4081f3c28..140de23e8c 100644 --- a/web/portal/src/main/webapp/groovy/portal/webui/page/UIPageBody.gtmpl +++ b/web/portal/src/main/webapp/groovy/portal/webui/page/UIPageBody.gtmpl @@ -39,15 +39,17 @@ %>
<% if(uicomponent.getUIComponent() == null){ %> -
-
- -

<%=_ctx.appRes("UIPageBody.msg.pageNotFoundTitle")%>

-

<%=_ctx.appRes("UIPageBody.msg.pageNotFoundText")%>

- -
-
- +
+
+ +
+
<% } else { uicomponent.renderChildren(); }%> <%if (editLevel == EditLevel.EDIT_SITE) {%> diff --git a/web/portal/src/main/webapp/groovy/portal/webui/page/UISiteBody.gtmpl b/web/portal/src/main/webapp/groovy/portal/webui/page/UISiteBody.gtmpl index cf4f959752..3503f0f828 100644 --- a/web/portal/src/main/webapp/groovy/portal/webui/page/UISiteBody.gtmpl +++ b/web/portal/src/main/webapp/groovy/portal/webui/page/UISiteBody.gtmpl @@ -22,15 +22,17 @@ <%} else {%>
<% if(uicomponent.getUIComponent() == null){ %> -
- -

<%=_ctx.appRes("UIPageBody.msg.pageNotFoundLine1")%>

-
    -
  • <%=_ctx.appRes("UIPageBody.msg.pageNotFoundLine2")%>
  • -
  • <%=_ctx.appRes("UIPageBody.msg.pageNotFoundLine3")%>
  • -
  • <%=_ctx.appRes("UIPageBody.msg.pageNotFoundLine4")%>
  • -
-
+
+
+ +
+
<% } else { uicomponent.renderChildren(); } %>
<%}%> diff --git a/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl b/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl index abdcb8bf22..dc065bb3ff 100644 --- a/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl +++ b/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl @@ -137,11 +137,10 @@