This is an automated email from the ASF dual-hosted git repository.
mridulpathak pushed a commit to branch release24.09
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/release24.09 by this push:
new 62cf17aee9 Fixed: moveContentJson lets a caller without UPDATE
permission re-parent content associations
62cf17aee9 is described below
commit 62cf17aee90b73e6d913f4746f394fde38d697c2
Author: Mridul Pathak <[email protected]>
AuthorDate: Mon Sep 21 17:06:07 2026 +0530
Fixed: moveContentJson lets a caller without UPDATE permission re-parent
content associations
ContentJsonEvents.moveContent (backing POST
/content/control/moveContentJson) performed no permission check at all, unlike
the equivalent updateContent/createContentAssoc/removeContentAssoc services,
which all require genericContentPermission UPDATE, so any authenticated user,
including one with only view-only content roles, could call the endpoint
directly and move a content association away from its current parent to any
other regardless of ownership.
Check UPDATE permission on both the old and the new parent content before
performing the move, mirroring what createContentAssoc/removeContentAssoc each
already require for the equivalent entity-level change.
---
.../ofbiz/content/cms/ContentJsonEvents.java | 26 +++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git
a/applications/content/src/main/java/org/apache/ofbiz/content/cms/ContentJsonEvents.java
b/applications/content/src/main/java/org/apache/ofbiz/content/cms/ContentJsonEvents.java
index b75ffd9c95..2bd644f810 100644
---
a/applications/content/src/main/java/org/apache/ofbiz/content/cms/ContentJsonEvents.java
+++
b/applications/content/src/main/java/org/apache/ofbiz/content/cms/ContentJsonEvents.java
@@ -28,12 +28,14 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.ofbiz.base.lang.JSON;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilGenerics;
+import org.apache.ofbiz.base.util.UtilHttp;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
@@ -43,6 +45,9 @@ import org.apache.ofbiz.entity.condition.EntityCondition;
import org.apache.ofbiz.entity.transaction.TransactionUtil;
import org.apache.ofbiz.entity.util.EntityUtil;
import org.apache.ofbiz.entity.util.EntityQuery;
+import org.apache.ofbiz.service.GenericServiceException;
+import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.service.ServiceUtil;
public class ContentJsonEvents {
@@ -83,8 +88,13 @@ public class ContentJsonEvents {
return "success";
}
- public static String moveContent(HttpServletRequest request,
HttpServletResponse response) throws GenericEntityException, IOException {
+ public static String moveContent(HttpServletRequest request,
HttpServletResponse response)
+ throws GenericEntityException, GenericServiceException,
IOException {
final Delegator delegator = (Delegator)
request.getAttribute("delegator");
+ final LocalDispatcher dispatcher = (LocalDispatcher)
request.getAttribute("dispatcher");
+ final HttpSession session = request.getSession();
+ final GenericValue userLogin = (GenericValue)
session.getAttribute("userLogin");
+ final Locale locale = UtilHttp.getLocale(request);
final String contentIdTo = request.getParameter("contentIdTo");
final String contentIdFrom = request.getParameter("contentIdFrom");
@@ -92,6 +102,11 @@ public class ContentJsonEvents {
final String contentAssocTypeId =
request.getParameter("contentAssocTypeId");
final Timestamp fromDate =
Timestamp.valueOf(request.getParameter("fromDate"));
+ // moving a content association modifies both the old and the new
parent, so both need
+ // the same UPDATE permission that
createContentAssoc/removeContentAssoc each enforce
+ checkUpdateContentPermission(dispatcher, userLogin, locale,
contentIdFrom);
+ checkUpdateContentPermission(dispatcher, userLogin, locale,
contentIdFromNew);
+
final Timestamp now = UtilDateTime.nowTimestamp();
GenericValue assoc = TransactionUtil.inTransaction(() -> {
GenericValue oldAssoc =
EntityQuery.use(delegator).from("ContentAssoc")
@@ -120,6 +135,15 @@ public class ContentJsonEvents {
return "success";
}
+ private static void checkUpdateContentPermission(LocalDispatcher
dispatcher, GenericValue userLogin, Locale locale, String contentId)
+ throws GenericServiceException {
+ Map<String, Object> permSvcCtx = UtilMisc.toMap("userLogin",
userLogin, "locale", locale, "mainAction", "UPDATE", "contentId", contentId);
+ Map<String, Object> permSvcResp =
dispatcher.runSync("genericContentPermission", permSvcCtx);
+ if (ServiceUtil.isError(permSvcResp) ||
!Boolean.TRUE.equals(permSvcResp.get("hasPermission"))) {
+ throw new GenericServiceException("Permission denied to move
content [" + contentId + "]");
+ }
+ }
+
public static String deleteContent(HttpServletRequest request,
HttpServletResponse response) throws GenericEntityException {
Delegator delegator = (Delegator) request.getAttribute("delegator");
String contentId = request.getParameter("contentId");