JSONServlet.java
/*
* Copyright (C) 2000 - 2026 Silverpeas
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* As a special exception to the terms and conditions of version 3.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* Open Source Software ("FLOSS") applications as described in Silverpeas's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* "https://www.silverpeas.org/legal/floss_exception.html"
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.silverpeas.components.kmelia.servlets;
import org.silverpeas.components.kmelia.control.KmeliaSessionController;
import org.silverpeas.components.kmelia.service.KmeliaHelper;
import org.silverpeas.core.admin.user.model.SilverpeasRole;
import org.silverpeas.core.admin.user.model.User;
import org.silverpeas.core.admin.user.model.UserDetail;
import org.silverpeas.core.clipboard.ClipboardException;
import org.silverpeas.core.node.model.NodeDetail;
import org.silverpeas.core.node.model.NodePK;
import org.silverpeas.core.util.JSONCodec;
import org.silverpeas.kernel.util.StringUtil;
import org.silverpeas.kernel.logging.SilverLogger;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import static java.util.Optional.ofNullable;
import static java.util.function.Predicate.not;
import static org.silverpeas.core.web.selection.BasketSelectionUI.displayPutIntoBasketSelectionShortcut;
public class JSONServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String OP_DELETE_PUBLICATIONS = "deletePublications";
private static final String OP_EXPORT_PUBLICATIONS = "exportSelection";
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res) {
doPost(req, res);
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse res) {
res.setContentType("application/json");
String id = req.getParameter("Id");
String componentId = req.getParameter("ComponentId");
String action = req.getParameter("Action");
KmeliaSessionController kmeliaSC =
(KmeliaSessionController) req.getSession().getAttribute("Silverpeas_kmelia_" + componentId);
if (kmeliaSC == null) {
return;
}
try {
Writer writer = res.getWriter();
if ("GetOperations".equals(action)) {
writer.write(getOperations(id, kmeliaSC));
}
} catch (IOException e) {
SilverLogger.getLogger(this).error(e);
res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
private String getOperations(String id, KmeliaSessionController kmeliaSC) {
return JSONCodec.encodeObject(operations -> {
if (KmeliaHelper.isNonVisiblePubsFolder(id)) {
String profile = kmeliaSC.getUserTopicProfile(id);
if (kmeliaSC.isSuppressionAllowed(profile)) {
operations.put(OP_DELETE_PUBLICATIONS, true);
}
operations.put(OP_EXPORT_PUBLICATIONS, true);
} else {
// getting profile
String profile = kmeliaSC.getUserTopicProfile(id);
// getting operations of topic according to profile and current
Role role = new Role(profile);
boolean isRoot = NodePK.ROOT_NODE_ID.equals(id);
boolean isBasket = NodePK.BIN_NODE_ID.equals(id);
if (isBasket) {
addBasketOperations(kmeliaSC, operations, role);
} else if (StringUtil.isDefined(profile)) {
NodeDetail node = kmeliaSC.getNodeHeader(id);
UserDetail user = kmeliaSC.getUserDetail();
// general operations
addGeneralOperations(kmeliaSC, operations, role, profile, isRoot, node);
// topic operations
addTopicOperations(kmeliaSC, operations, role, isRoot, node, user);
// publication operations
try {
addPublicationOperations(kmeliaSC, operations, role, isRoot, user);
} catch (ClipboardException e) {
SilverLogger.getLogger(this).error(e);
}
}
}
return operations;
});
}
private void addPublicationOperations(final KmeliaSessionController kmeliaSC,
final JSONCodec.JSONObject operations, final Role role,
final boolean isRoot, final UserDetail user) throws ClipboardException {
boolean publicationsInTopicAllowed = isPublicationsInTopicAllowed(isRoot, kmeliaSC);
boolean addPublicationAllowed = addPublicationAllowed(isRoot, kmeliaSC, role);
boolean operationsOnSelectionAllowed = isOperationsOnSelectionAllowed(isRoot, kmeliaSC, role);
boolean somePublicationsExist = ofNullable(kmeliaSC.getSessionPublicationsList())
.filter(not(Collection::isEmpty))
.isPresent();
boolean oneTemplateUsed = kmeliaSC.getXmlFormForPublications() != null;
boolean copyCutAllowed = operationsOnSelectionAllowed && somePublicationsExist;
boolean notRootNotAnonymousNotGuest = !isRoot && !user.isAnonymous() && !user.isAccessGuest();
operations.put("addPubli", addPublicationAllowed);
operations.put("addFiles", addPublicationAllowed && kmeliaSC.isAttachmentsEnabled() &&
!kmeliaSC.isImportFileAllowed());
operations.put("importFile", isImportFilesAllowed(isRoot, kmeliaSC, role));
operations.put("importFiles", isImportFilesAllowed(isRoot, kmeliaSC, role));
operations.put("copyPublications", copyCutAllowed);
operations.put("cutPublications", copyCutAllowed);
boolean pasteNodeAllowed = kmeliaSC.isPasteNodeAllowed();
boolean pastePublicationAllowed = kmeliaSC.isPastePublicationAllowed(isRoot);
operations.put("paste", !role.isUser() && (pasteNodeAllowed || pastePublicationAllowed));
operations.put("putPublicationsInBasket", publicationsInTopicAllowed && displayPutIntoBasketSelectionShortcut());
operations.put("sortPublications", role.isAdmin() && publicationsInTopicAllowed && somePublicationsExist);
operations.put("updatePublications",operationsOnSelectionAllowed && oneTemplateUsed);
operations.put(OP_DELETE_PUBLICATIONS, operationsOnSelectionAllowed);
boolean exportOnSelectionAllowed = kmeliaSC.isExportPublicationAllowed(kmeliaSC.getHighestSilverpeasUserRole());
operations.put(OP_EXPORT_PUBLICATIONS, exportOnSelectionAllowed && somePublicationsExist);
operations.put("manageSubscriptions", role.isAdmin());
operations.put("subscriptions", isSubscriptionsAllowed(isRoot, user));
operations.put("topicSubscriptions", notRootNotAnonymousNotGuest);
operations.put("favorites", notRootNotAnonymousNotGuest);
addPublicationSelectionOperation(kmeliaSC, operations, operationsOnSelectionAllowed);
}
private static void addPublicationSelectionOperation(KmeliaSessionController kmeliaSC,
JSONCodec.JSONObject operations, boolean operationsOnSelectionAllowed) {
if (kmeliaSC.isAllPublicationsListSelected()) {
operations.put("unselectAllPublications", operationsOnSelectionAllowed);
} else {
operations.put("selectAllPublications", operationsOnSelectionAllowed);
}
}
private void addTopicOperations(final KmeliaSessionController kmeliaSC,
final JSONCodec.JSONObject operations, final Role role, final boolean isRoot,
final NodeDetail node, final UserDetail user) {
boolean isAdmin = role.isAdmin();
operations.put("addTopic", isAdmin);
operations.put("updateTopic", !isRoot && isAdmin);
operations.put("deleteTopic", !isRoot && isAdmin);
operations.put("sortSubTopics", isAdmin);
operations.put("copyTopic", !isRoot && isAdmin);
operations.put("cutTopic", !isRoot && isAdmin);
operations.put("wysiwygTopic", isAdmin && kmeliaSC.
isWysiwygOnTopicsEnabled());
operations.put("shareTopic", node.canBeSharedBy(user));
boolean exportOnTopicAllowed = kmeliaSC.isExportTopicAllowed(kmeliaSC.getHighestSilverpeasUserRole());
operations.put("exportTopic", exportOnTopicAllowed);
if (isRoot) {
boolean exportOnApplicationAllowed = kmeliaSC.isExportApplicationAllowed(kmeliaSC.getHighestSilverpeasUserRole());
operations.put("exportPDFApplication", exportOnApplicationAllowed);
}
else {
operations.put("exportPDFTopic", exportOnTopicAllowed);
}
}
private void addGeneralOperations(final KmeliaSessionController kmeliaSC,
final JSONCodec.JSONObject operations, final Role role, final String profile,
final boolean isRoot, final NodeDetail node) {
User user = kmeliaSC.getUserDetail();
operations.putJSONObject("context",
c -> c.put("componentId", kmeliaSC.getComponentId()).put("nodeId", node.getId()));
operations.put("admin", kmeliaSC.isComponentManageable());
operations.put("pdc", isRoot && kmeliaSC.isPdcUsed() && role.isAdmin());
operations.put("predefinedPdcPositions", kmeliaSC.isPdcUsed() && role.isAdmin());
operations.put("templates",
kmeliaSC.isTemplatesSelectionEnabledForRole(SilverpeasRole.fromString(profile)));
boolean exportOnApplicationAllowed = kmeliaSC.isExportApplicationAllowed(kmeliaSC.getHighestSilverpeasUserRole());
operations.put("exportApplication", exportOnApplicationAllowed);
if (isRoot && kmeliaSC.isStatisticAllowed()) {
operations.put("statistics", true);
}
operations.put("mylinks", !user.isAnonymous() && !user.isAccessGuest());
operations.put("notify", !user.isAnonymous() && kmeliaSC.isNotificationAllowed() && !user.isAccessGuest());
operations.put("responsibles", !user.isAnonymous());
}
private void addBasketOperations(final KmeliaSessionController kmeliaSC,
final JSONCodec.JSONObject operations, final Role role) {
boolean binOperationsAllowed = role.isAdmin() || role.isPublisher() || role.isWriter();
boolean suppressionAllowed = kmeliaSC.isSuppressionAllowed(role.toString());
operations.put("emptyTrash", binOperationsAllowed && suppressionAllowed);
operations.put(OP_EXPORT_PUBLICATIONS, binOperationsAllowed);
operations.put("copyPublications", binOperationsAllowed);
operations.put("cutPublications", binOperationsAllowed);
operations.put(OP_DELETE_PUBLICATIONS, binOperationsAllowed && suppressionAllowed);
}
private static class Role {
private final SilverpeasRole silverRole;
public Role(final String profile) {
this.silverRole = SilverpeasRole.fromString(profile);
}
public boolean isAdmin() {
return silverRole == SilverpeasRole.ADMIN;
}
public boolean isPublisher() {
return this.silverRole == SilverpeasRole.PUBLISHER;
}
public boolean isWriter() {
return this.silverRole == SilverpeasRole.WRITER;
}
public boolean isUser() {
return this.silverRole == SilverpeasRole.USER;
}
@Override
public String toString() {
return silverRole.getName();
}
}
/** Return if publications creation is allowed
*
* @param isRoot
* @return true or false
*/
private boolean isPublicationsInTopicAllowed(boolean isRoot, KmeliaSessionController kmeliaSC) {
return !isRoot || (kmeliaSC.getNbPublicationsOnRoot() == 0 || !kmeliaSC.isTreeStructure());
}
/** Return if publications creation is allowed meanwhile the user role
*
* @param isRoot
* @param kmeliaSC
* @param role
* @return true or false
*/
private boolean addPublicationAllowed(boolean isRoot, KmeliaSessionController kmeliaSC, Role role) {
return !role.isUser() && isPublicationsInTopicAllowed(isRoot, kmeliaSC);
}
/** Return if subscriptions is allowed
*
* @param isRoot
* @param user
* @return true or false
*/
private boolean isSubscriptionsAllowed(boolean isRoot, UserDetail user) {
return isRoot && !user.isAnonymous() && !user.isAccessGuest();
}
/** Return if import file(s) is allowed
*
* @param isRoot
* @param kmeliaSC
* @param role
* @return true or false
*/
private boolean isImportFilesAllowed(boolean isRoot,KmeliaSessionController kmeliaSC, Role role) {
return addPublicationAllowed(isRoot, kmeliaSC, role) && kmeliaSC.isImportFileAllowed();
}
/** Return if operations on selection are allowed
*
* @param isRoot
* @param kmeliaSC
* @param role
* @return true or false
*/
private boolean isOperationsOnSelectionAllowed(boolean isRoot,KmeliaSessionController kmeliaSC, Role role) {
return (role.isAdmin() || role.isPublisher()) && isPublicationsInTopicAllowed(isRoot, kmeliaSC) && kmeliaSC.isSuppressionAllowed(role.toString());
}
}