This is an automated email from the ASF dual-hosted git repository.

diveshdut pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git

commit 4d0a4a683daa57e5c78f9a068a838acce287c938
Author: diveshdut <[email protected]>
AuthorDate: Fri Jul 31 14:24:29 2026 +0530

    OFBIZ-13468 Improved: validate and secure BOM association services
    
    Add Manufacturing CREATE permission checks to createBOMAssoc and 
copyBOMAssocs so REST-mapped BOM mutations enforce service-level authorization.
    
    Tighten createBOMAssoc validation by rejecting self-referencing BOM 
associations, checking for an existing ProductAssoc before create, and 
returning validation failures as service errors.
    
    Improve copyBOMAssocs by filtering the source associations with the 
requested BOM key fields and preserving a supplied fromDate when creating 
copied associations.
---
 .../minilang/bom/BomSimpleMethods.xml              | 36 ++++++++++++++++++++--
 .../manufacturing/servicedef/services_bom.xml      |  7 +++--
 2 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/applications/manufacturing/minilang/bom/BomSimpleMethods.xml 
b/applications/manufacturing/minilang/bom/BomSimpleMethods.xml
index c72e310c5d..3fd854f4cc 100644
--- a/applications/manufacturing/minilang/bom/BomSimpleMethods.xml
+++ b/applications/manufacturing/minilang/bom/BomSimpleMethods.xml
@@ -26,6 +26,25 @@ under the License.
             <now-timestamp field="parameters.fromDate"/>
         </if-empty>
 
+        <if-compare-field field="parameters.productId" 
to-field="parameters.productIdTo" operator="equals">
+            <property-to-field 
property="ManufacturingBomProductCannotBeComponentOfItself" 
resource="ManufacturingUiLabels" field="errorMessage"/>
+            <add-error>
+                <fail-message message="${errorMessage}"/>
+            </add-error>
+            <check-errors/>
+        </if-compare-field>
+
+        <make-value entity-name="ProductAssoc" 
value-field="productAssocLookup"/>
+        <set-pk-fields map="parameters" value-field="productAssocLookup"/>
+        <find-by-primary-key entity-name="ProductAssoc" 
map="productAssocLookup" value-field="existingProductAssoc"/>
+        <if-not-empty field="existingProductAssoc.productId">
+            <set field="errorMessage" value="Value found, cannot create a new 
one"/>
+            <add-error>
+                <fail-message message="${errorMessage}"/>
+            </add-error>
+            <check-errors/>
+        </if-not-empty>
+
         <set field="searchDuplicatedAncestorContext.productId" 
from-field="parameters.productId"/>
         <set field="searchDuplicatedAncestorContext.productIdTo" 
from-field="parameters.productIdTo"/>
         <if-not-empty field="parameters.fromDate">
@@ -39,8 +58,10 @@ under the License.
             <set field="productToProduct[]" 
from-field="duplicatedProductAssoc.productId"/>
             <set field="productToProduct[]" 
from-field="duplicatedProductAssoc.productIdTo"/>
             <property-to-field 
property="ManufacturingDuplicatedComponentInBOM" 
resource="ManufacturingUiLabels" field="errorMessage" 
arg-list-name="productToProduct"/>
-            <field-to-result field="errorMessage" result-name="errorMessage"/>
-            <return/>
+            <add-error>
+                <fail-message message="${errorMessage}"/>
+            </add-error>
+            <check-errors/>
         </if-not-empty>
         <set-service-fields service-name="createProductAssoc" map="parameters" 
to-map="context"/>
         <call-service service-name="createProductAssoc" in-map-name="context"/>
@@ -48,12 +69,21 @@ under the License.
 
     <simple-method method-name="copyBOMAssocs" short-description="Copy BOM 
associations from one product to another">
         <make-value entity-name="ProductAssoc" value-field="lookupMap"/>
-        <set-pk-fields map="parameters" value-field="lookupMap"/>
+        <set field="lookupMap.productId" from-field="parameters.productId"/>
+        <if-not-empty field="parameters.productAssocTypeId">
+            <set field="lookupMap.productAssocTypeId" 
from-field="parameters.productAssocTypeId"/>
+        </if-not-empty>
+        <if-not-empty field="parameters.productIdTo">
+            <set field="lookupMap.productIdTo" 
from-field="parameters.productIdTo"/>
+        </if-not-empty>
         <find-by-and entity-name="ProductAssoc" map="lookupMap" list="assocs"/>
         <filter-list-by-date list="assocs"/>
         <iterate list="assocs" entry="assoc">
             <set-service-fields service-name="createBOMAssoc" map="assoc" 
to-map="context"/>
             <set field="context.productId" 
from-field="parameters.copyToProductId"/>
+            <if-not-empty field="parameters.fromDate">
+                <set field="context.fromDate" 
from-field="parameters.fromDate"/>
+            </if-not-empty>
             <call-service service-name="createBOMAssoc" in-map-name="context" 
break-on-error="false"/>
         </iterate>
     </simple-method>
diff --git a/applications/manufacturing/servicedef/services_bom.xml 
b/applications/manufacturing/servicedef/services_bom.xml
index b46afa4fa8..a7a78299ed 100644
--- a/applications/manufacturing/servicedef/services_bom.xml
+++ b/applications/manufacturing/servicedef/services_bom.xml
@@ -27,15 +27,16 @@ under the License.
     <!-- Bill of Materials services -->
     <service name="createBOMAssoc" default-entity-name="ProductAssoc" 
engine="simple"
                 
location="component://manufacturing/minilang/bom/BomSimpleMethods.xml" 
invoke="createBOMAssoc" auth="true">
-        <description>Add Product to Product Association</description>
+        <description>Add a product to a BOM as a ProductAssoc component. 
Validates that a product is not added as its own component, rejects duplicate 
associations before create, and delegates the actual ProductAssoc create to the 
existing product association service.</description>
+        <permission-service service-name="manufacturingPermissionService" 
main-action="CREATE"/>
         <auto-attributes include="pk" mode="IN" optional="false"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
-        <attribute name="errorMessage" type="String" optional="true" 
mode="OUT"/>
         <override name="fromDate" optional="true"/>
     </service>
     <service name="copyBOMAssocs" default-entity-name="ProductAssoc" 
engine="simple"
                 
location="component://manufacturing/minilang/bom/BomSimpleMethods.xml" 
invoke="copyBOMAssocs" auth="true">
-        <description>Copy BOM associations from one product to 
another</description>
+        <description>Copy active BOM associations from one product to another. 
Reuses BOM association creation for each copied component, supports narrowing 
the source associations by BOM key fields, and preserves a supplied effective 
fromDate for REST/API copy workflows.</description>
+        <permission-service service-name="manufacturingPermissionService" 
main-action="CREATE"/>
         <auto-attributes include="pk" mode="IN" optional="false"/>
         <attribute name="copyToProductId" type="String" optional="false" 
mode="IN"/>
         <override name="fromDate" optional="true"/>

Reply via email to