Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge Meeds-io/MIPs#100 - Dev #719

Merged
merged 7 commits into from
Nov 9, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ private <N> void saveTree(TreeContext<N> tree, NodeChangeListener<NodeContext<N>
NodeChangeQueue<NodeContext<N>> 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<String, String> entry : persister.toPersist.entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,26 @@ <N> NodeContext<N> loadNode(NodeModel<N> model,
Scope scope,
NodeChangeListener<NodeContext<N>> listener);

/**
* Loads root node of a designated Site
*
* @param siteKey {@link SiteKey}
* @param <N> the node generic type
* @return the loaded node
*/
<N> NodeContext<NodeContext<N>> 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 <N> the node generic type
* @return the loaded node
*/
<N> NodeContext<NodeContext<N>> loadNode(SiteKey siteKey, String navUri);

/**
* Load a navigation node from a specified navigation by its id
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* This file is part of the Meeds project (https://meeds.io/).
*
* Copyright (C) 2020 - 2023 Meeds Association [email protected]
*
* 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<Object, UserRegistrationType> {

private NavigationService navigationService;

private List<String> managedPages;

public PortalRegistrationUpdateListener(NavigationService navigationService, InitParams params) {
this.navigationService = navigationService;
this.managedPages = params.getValuesParam("managed-pages").getValues();
}

@Override
public void onEvent(Event<Object, UserRegistrationType> event) throws Exception {
boolean isOpen = event.getData() == UserRegistrationType.OPEN;
managedPages.forEach(navUri -> {
NodeContext<NodeContext<Object>> 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);
}
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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() {
Expand Down Expand Up @@ -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;
}
}

Expand All @@ -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;
}
}
}

Expand All @@ -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);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -70,6 +71,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.ResourceBundle;

/**
Expand All @@ -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);

Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -545,15 +548,26 @@ public List<String> getSiteNames(SiteType siteType, int offset, int limit) {
return list;
}

public List<PortalConfig> getUserPortalDisplayedSites() {
siteFilter.setExcludedSiteName(globalPortal_);
public List<PortalConfig> getUserPortalSites() {
List<PortalConfig> 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<PortalConfig> portalConfigList = getUserPortalDisplayedSites();
if (portalConfigList == null || portalConfigList.isEmpty()) {
List<PortalConfig> portalConfigList = getUserPortalSites();
if (CollectionUtils.isEmpty(portalConfigList)) {
return null;
}
String defaultPortal = portalConfigList.get(0).getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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"), })
Expand Down
Loading