This is an automated email from the ASF dual-hosted git repository. mridulpathak pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
commit de5be040cfa98acdcb5ce736b1a089f83e69da77 Author: Mridul Pathak <[email protected]> AuthorDate: Fri Oct 23 11:48:48 2026 +0530 Added: permission checks to order CustRequest/Quote/Requirement services Several order-component services had no permission check at all, letting any authenticated user create, modify, or delete customer-request, quote, requirement, and order-shipgroup data regardless of their assigned permissions. - createCustRequestItem, createCustRequestParty, updateCustRequest, updateCustRequestItem, expireCustRequestContent now require ORDERMGR_CRQ via a new custRequestChildPermissionCheck, since the existing custRequestPermissionCheck's self-service escape hatch is unsafe to reuse for updates to an existing record - createQuoteTerm, updateQuoteTerm, deleteQuoteTerm, createQuoteNote, createRequirement, updateAllocationPlanItems now require ORDERMGR via the native required-permissions/check-permission declaration, matching the sibling createRequirementRole convention - setGiftMessage, setShippingInstructions now reuse the existing OrderServices.hasPermission(orderId, ...) order-update check --- .../order/minilang/request/CustRequestServices.xml | 4 ++++ applications/order/servicedef/services.xml | 3 +++ applications/order/servicedef/services_quote.xml | 12 ++++++++++++ applications/order/servicedef/services_request.xml | 12 ++++++++++++ applications/order/servicedef/services_requirement.xml | 3 +++ .../java/org/apache/ofbiz/order/order/OrderServices.java | 16 ++++++++++++++++ .../order/order/test/RequirementStatusEcaTests.groovy | 10 ++++++++++ 7 files changed, 60 insertions(+) diff --git a/applications/order/minilang/request/CustRequestServices.xml b/applications/order/minilang/request/CustRequestServices.xml index 8f8bf0e2e5..ac6b16d3e5 100644 --- a/applications/order/minilang/request/CustRequestServices.xml +++ b/applications/order/minilang/request/CustRequestServices.xml @@ -47,6 +47,10 @@ under the License. </if> <field-to-result field="hasPermission"/> </simple-method> + <simple-method method-name="custRequestChildPermissionCheck" short-description="Unconditional ORDERMGR_CRQ permission check for updating an existing customer request or its child records"> + <set field="primaryPermission" value="ORDERMGR_CRQ"/> + <call-simple-method method-name="genericBasePermissionCheck" xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/> + </simple-method> <simple-method method-name="createCustRequest" short-description="Create Customer Request"> <make-value entity-name="CustRequest" value-field="newEntity"/> diff --git a/applications/order/servicedef/services.xml b/applications/order/servicedef/services.xml index 9273b0ad46..6003df2c20 100644 --- a/applications/order/servicedef/services.xml +++ b/applications/order/servicedef/services.xml @@ -1732,6 +1732,9 @@ under the License. <service name="updateAllocationPlanItems" engine="java" auth="true" location="org.apache.ofbiz.order.order.OrderServices" invoke="updateAllocationPlanItems"> <description>Update Allocation Plan Items</description> + <required-permissions join-type="AND"> + <check-permission permission="ORDERMGR" action="_UPDATE"/> + </required-permissions> <attribute name="planId" type="String" mode="IN"/> <attribute name="orderIdMap" type="Map" mode="IN" string-map-prefix="oim_"/> <attribute name="orderItemSeqIdMap" type="Map" mode="IN" string-map-prefix="oisim_"/> diff --git a/applications/order/servicedef/services_quote.xml b/applications/order/servicedef/services_quote.xml index 13f3cc5116..e201c23712 100644 --- a/applications/order/servicedef/services_quote.xml +++ b/applications/order/servicedef/services_quote.xml @@ -185,6 +185,9 @@ under the License. <description> Create a new Quate term. </description> + <required-permissions join-type="AND"> + <check-permission permission="ORDERMGR" action="_CREATE"/> + </required-permissions> <auto-attributes mode="IN" include="pk" optional="false"/> <auto-attributes mode="IN" include="nonpk" optional="true"/> <override name="quoteItemSeqId" type="String" mode="IN" default-value="_NA_"/> @@ -193,6 +196,9 @@ under the License. <description> Edit the Quate term. </description> + <required-permissions join-type="AND"> + <check-permission permission="ORDERMGR" action="_UPDATE"/> + </required-permissions> <auto-attributes mode="IN" include="pk" optional="false"/> <auto-attributes mode="IN" include="nonpk" optional="true"/> </service> @@ -200,6 +206,9 @@ under the License. <description> delete the Quate term. </description> + <required-permissions join-type="AND"> + <check-permission permission="ORDERMGR" action="_DELETE"/> + </required-permissions> <auto-attributes mode="IN" include="pk" optional="false"/> </service> <!-- Specialized Quote services --> @@ -327,6 +336,9 @@ under the License. <service name="createQuoteNote" engine="groovy" location="component://order/src/main/groovy/org/apache/ofbiz/order/quote/QuoteServicesScript.groovy" invoke="createQuoteNote" auth="true"> <description>Create a note item and associate with a quote</description> + <required-permissions join-type="AND"> + <check-permission permission="ORDERMGR" action="_CREATE"/> + </required-permissions> <attribute name="quoteId" type="String" mode="IN"/> <attribute name="noteInfo" type="String" mode="IN" allow-html="safe"> <type-validate> diff --git a/applications/order/servicedef/services_request.xml b/applications/order/servicedef/services_request.xml index 9982545586..b46cecfb9a 100644 --- a/applications/order/servicedef/services_request.xml +++ b/applications/order/servicedef/services_request.xml @@ -34,6 +34,13 @@ under the License. <implements service="permissionInterface"/> <attribute name="fromPartyId" type="String" mode="IN" optional="true"/> </service> + <service name="custRequestChildPermissionCheck" engine="simple" + location="component://order/minilang/request/CustRequestServices.xml" invoke="custRequestChildPermissionCheck"> + <description>Unconditional ORDERMGR_CRQ permission check, for updating an existing customer request or its child + records (item, party, content) where the caller-supplied fromPartyId (if any) can't be trusted to reflect + the actual owner of the existing record, unlike custRequestPermissionCheck's use on create</description> + <implements service="permissionInterface"/> + </service> <service name="createCustRequest" engine="simple" default-entity-name="CustRequest" location="component://order/minilang/request/CustRequestServices.xml" invoke="createCustRequest" auth="true"> <description>Create a custRequest record and optionally create a custRequest item.</description> @@ -49,6 +56,7 @@ under the License. <service name="updateCustRequest" engine="simple" default-entity-name="CustRequest" location="component://order/minilang/request/CustRequestServices.xml" invoke="updateCustRequest" auth="true"> <description>Update a custRequest record</description> + <permission-service service-name="custRequestChildPermissionCheck" main-action="UPDATE"/> <auto-attributes include="pk" mode="IN" optional="false"/> <auto-attributes include="nonpk" mode="IN" optional="true"/> <attribute name="oldStatusId" type="String" mode="OUT"/> @@ -84,6 +92,7 @@ under the License. <!-- CustRequestItem services --> <service name="createCustRequestItem" engine="entity-auto" default-entity-name="CustRequestItem" invoke="create" auth="true"> <description>Create a CustRequestItem record</description> + <permission-service service-name="custRequestChildPermissionCheck" main-action="CREATE"/> <auto-attributes include="pk" mode="INOUT" optional="false"/> <auto-attributes include="nonpk" mode="IN" optional="true"/> <override name="custRequestItemSeqId" optional="true"/> @@ -93,6 +102,7 @@ under the License. </service> <service name="updateCustRequestItem" engine="entity-auto" default-entity-name="CustRequestItem" invoke="update" auth="true"> <description>Update a CustRequestItem record</description> + <permission-service service-name="custRequestChildPermissionCheck" main-action="UPDATE"/> <auto-attributes include="pk" mode="IN" optional="false"/> <auto-attributes include="nonpk" mode="IN" optional="true"/> <override name="story" allow-html="safe"/> @@ -110,6 +120,7 @@ under the License. <!-- CustRequestParty services --> <service name="createCustRequestParty" engine="entity-auto" default-entity-name="CustRequestParty" invoke="create" auth="true"> <description>Create a CustRequestParty record</description> + <permission-service service-name="custRequestChildPermissionCheck" main-action="CREATE"/> <auto-attributes mode="IN" include="pk" optional="false"/> <auto-attributes mode="IN" include="nonpk" optional="true"/> <override name="fromDate" mode="IN" type="Timestamp" optional="true" default-value="${date:nowTimestamp()}"/> @@ -229,6 +240,7 @@ under the License. </service> <service name="expireCustRequestContent" engine="entity-auto" invoke="expire" default-entity-name="CustRequestContent" auth="true"> <description>Expire a Customer Request Content</description> + <permission-service service-name="custRequestChildPermissionCheck" main-action="UPDATE"/> <auto-attributes include="pk" mode="IN" optional="false"/> <auto-attributes include="nonpk" mode="IN" optional="true"/> </service> diff --git a/applications/order/servicedef/services_requirement.xml b/applications/order/servicedef/services_requirement.xml index 9bc00c4d8f..1343d8aab6 100644 --- a/applications/order/servicedef/services_requirement.xml +++ b/applications/order/servicedef/services_requirement.xml @@ -37,6 +37,9 @@ under the License. <service name="createRequirement" engine="simple" location="component://order/minilang/requirement/RequirementServices.xml" invoke="createRequirement"> <description>Create a new requirement</description> + <required-permissions join-type="AND"> + <check-permission permission="ORDERMGR" action="_CREATE"/> + </required-permissions> <implements service="requirementInterface"/> <attribute name="requirementTypeId" type="String" mode="IN" optional="false"/> <attribute name="custRequestId" type="String" mode="IN" optional="true"/> diff --git a/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderServices.java b/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderServices.java index 406e56718a..fd4741e415 100644 --- a/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderServices.java +++ b/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderServices.java @@ -6488,9 +6488,17 @@ public class OrderServices { public static Map<String, Object> setShippingInstructions(DispatchContext dctx, Map<String, ? extends Object> context) { Delegator delegator = dctx.getDelegator(); + Locale locale = (Locale) context.get("locale"); + GenericValue userLogin = (GenericValue) context.get("userLogin"); String orderId = (String) context.get("orderId"); String shipGroupSeqId = (String) context.get("shipGroupSeqId"); String shippingInstructions = (String) context.get("shippingInstructions"); + Security security = dctx.getSecurity(); + + if (!OrderServices.hasPermission(orderId, userLogin, "UPDATE", security, delegator)) { + return ServiceUtil.returnError(UtilProperties.getMessage(RES_ERROR, + "OrderYouDoNotHavePermissionToChangeThisOrdersStatus", locale)); + } try { GenericValue orderItemShipGroup = EntityQuery.use(delegator).from("OrderItemShipGroup").where("orderId", orderId, "shipGroupSeqId", shipGroupSeqId).queryFirst(); @@ -6504,9 +6512,17 @@ public class OrderServices { public static Map<String, Object> setGiftMessage(DispatchContext dctx, Map<String, ? extends Object> context) { Delegator delegator = dctx.getDelegator(); + Locale locale = (Locale) context.get("locale"); + GenericValue userLogin = (GenericValue) context.get("userLogin"); String orderId = (String) context.get("orderId"); String shipGroupSeqId = (String) context.get("shipGroupSeqId"); String giftMessage = (String) context.get("giftMessage"); + Security security = dctx.getSecurity(); + + if (!OrderServices.hasPermission(orderId, userLogin, "UPDATE", security, delegator)) { + return ServiceUtil.returnError(UtilProperties.getMessage(RES_ERROR, + "OrderYouDoNotHavePermissionToChangeThisOrdersStatus", locale)); + } try { GenericValue orderItemShipGroup = EntityQuery.use(delegator).from("OrderItemShipGroup").where("orderId", orderId, "shipGroupSeqId", shipGroupSeqId).queryFirst(); diff --git a/applications/order/src/test/groovy/org/apache/ofbiz/order/order/test/RequirementStatusEcaTests.groovy b/applications/order/src/test/groovy/org/apache/ofbiz/order/order/test/RequirementStatusEcaTests.groovy index 690c03e35e..87d34939d4 100644 --- a/applications/order/src/test/groovy/org/apache/ofbiz/order/order/test/RequirementStatusEcaTests.groovy +++ b/applications/order/src/test/groovy/org/apache/ofbiz/order/order/test/RequirementStatusEcaTests.groovy @@ -86,6 +86,16 @@ class RequirementStatusEcaTests implements JupiterTestHelper { enabled: 'Y' ]) delegator.create(userLogin) + + String groupId = 'MRP_REQ_STATUS_TEST' + if (from('SecurityGroup').where('groupId', groupId).queryOne() == null) { + delegator.create('SecurityGroup', [groupId: groupId, + description: 'Group for the requirement status ECA regression test']) + delegator.create('SecurityGroupPermission', [groupId: groupId, permissionId: 'ORDERMGR_CREATE', + fromDate: java.sql.Timestamp.valueOf('2001-01-01 00:00:00')]) + } + delegator.create('UserLoginSecurityGroup', [userLoginId: userLoginId, groupId: groupId, + fromDate: java.sql.Timestamp.valueOf('2001-01-01 00:00:00')]) } return userLogin }

