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
     }

Reply via email to