You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ja...@apache.org on 2026/05/12 13:17:07 UTC

(ofbiz-framework) branch release24.09 updated (13653e675f -> 124844ee28)

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

jacopoc pushed a change to branch release24.09
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


    from 13653e675f Bump actions/dependency-review-action from 4.9.0 to 5.0.0
     new e1ab3877c6 Fixed: Implement permission checks for ENTITY_MAINT in EntitySQLProcessor and ProgramExport
     new 124844ee28 Fixed: Remove unnecessary requirePasswordChange parameter from ChangePassword forms and adjust login workflow accordingly

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/ofbiz/webapp/control/LoginWorker.java   |  14 +-
 .../webtools/entity/EntitySQLProcessor.groovy      | 104 +++---
 .../ofbiz/webtools/entity/ProgramExport.groovy     | 408 +++++++++++----------
 themes/common-theme/template/ChangePassword.ftl    |   1 -
 themes/helveticus/template/ChangePassword.ftl      |   1 -
 themes/rainbowstone/template/ChangePassword.ftl    |   1 -
 6 files changed, 265 insertions(+), 264 deletions(-)


(ofbiz-framework) 01/02: Fixed: Implement permission checks for ENTITY_MAINT in EntitySQLProcessor and ProgramExport

Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e1ab3877c6b263d0069603150385337c618d068b
Author: Jacopo Cappellato <ja...@gmail.com>
AuthorDate: Mon May 11 10:02:58 2026 +0200

    Fixed: Implement permission checks for ENTITY_MAINT in EntitySQLProcessor and ProgramExport
    
    (cherry picked from commit 771efc4bd72a15d91740949697eea20db01cdb75)
---
 .../webtools/entity/EntitySQLProcessor.groovy      | 104 +++---
 .../ofbiz/webtools/entity/ProgramExport.groovy     | 408 +++++++++++----------
 2 files changed, 258 insertions(+), 254 deletions(-)

diff --git a/framework/webtools/src/main/groovy/org/apache/ofbiz/webtools/entity/EntitySQLProcessor.groovy b/framework/webtools/src/main/groovy/org/apache/ofbiz/webtools/entity/EntitySQLProcessor.groovy
index 289edf4cb6..fb10dff32d 100644
--- a/framework/webtools/src/main/groovy/org/apache/ofbiz/webtools/entity/EntitySQLProcessor.groovy
+++ b/framework/webtools/src/main/groovy/org/apache/ofbiz/webtools/entity/EntitySQLProcessor.groovy
@@ -24,66 +24,68 @@ import java.sql.ResultSetMetaData
 import org.apache.ofbiz.entity.jdbc.SQLProcessor
 import org.apache.ofbiz.entity.model.ModelGroupReader
 
-String sqlCommand = context.request.getParameter('sqlCommand') // (see OFBIZ-6567)
+if (security.hasPermission('ENTITY_MAINT', session)) {
+    String sqlCommand = context.request.getParameter('sqlCommand') // (see OFBIZ-6567)
 
-String resultMessage = ''
-List<String> columns = []
-List<List<Object>> records = []
-ModelGroupReader mgr = delegator.getModelGroupReader()
-List<Map<String,String>> groups = []
-mgr.getGroupNames(delegator.getDelegatorName()).each { String group ->
-    groups.add(0, ['group': group]) //use for list-option in widget drop-down
-}
-
-if (sqlCommand && selGroup) {
-    try (SQLProcessor du = new SQLProcessor(delegator, delegator.getGroupHelperInfo(selGroup))) {
-        if (sqlCommand.toUpperCase().startsWith('SELECT')) {
-            try (ResultSet rs = du.executeQuery(sqlCommand)) {
-                ResultSetMetaData rsmd = rs.getMetaData()
+    String resultMessage = ''
+    List<String> columns = []
+    List<List<Object>> records = []
+    ModelGroupReader mgr = delegator.getModelGroupReader()
+    List<Map<String,String>> groups = []
+    mgr.getGroupNames(delegator.getDelegatorName()).each { String group ->
+        groups.add(0, ['group': group]) //use for list-option in widget drop-down
+    }
 
-                int numberOfColumns = rsmd.getColumnCount()
-                for (int i = 1; i <= numberOfColumns; i++) {
-                    columns.add(rsmd.getColumnLabel(i))
-                }
+    if (sqlCommand && selGroup) {
+        try (SQLProcessor du = new SQLProcessor(delegator, delegator.getGroupHelperInfo(selGroup))) {
+            if (sqlCommand.toUpperCase().startsWith('SELECT')) {
+                try (ResultSet rs = du.executeQuery(sqlCommand)) {
+                    ResultSetMetaData rsmd = rs.getMetaData()
 
-                boolean rowLimitReached = false
-                while (rs.next()) {
-                    if (records.size() >= rowLimit) {
-                        rowLimitReached = true
-                        break
+                    int numberOfColumns = rsmd.getColumnCount()
+                    for (int i = 1; i <= numberOfColumns; i++) {
+                        columns.add(rsmd.getColumnLabel(i))
                     }
 
-                    List<Object> record = []
-                    for (int i = 1; i <= numberOfColumns; i++) {
-                        record.add(rs.getObject(i))
+                    boolean rowLimitReached = false
+                    while (rs.next()) {
+                        if (records.size() >= rowLimit) {
+                            rowLimitReached = true
+                            break
+                        }
+
+                        List<Object> record = []
+                        for (int i = 1; i <= numberOfColumns; i++) {
+                            record.add(rs.getObject(i))
+                        }
+                        records.add(record)
                     }
-                    records.add(record)
+
+                    resultMessage = "Returned ${rowLimitReached ? '' : 'top'} ${records.size() as String} rows."
+                }
+            } else {
+                if (sqlCommand.toUpperCase().contains('SYSCS_UTIL.SYSCS_EXPORT_TABLE')
+                        || sqlCommand.toUpperCase().contains('JSP')) {
+                    context.resultMessage = 'Not executed for security reason'
+                    context.groups = groups
+                    context.columns = columns
+                    context.records = records
+                    context.sqlCommand = sqlCommand
+                    return
                 }
 
-                resultMessage = "Returned ${rowLimitReached ? '' : 'top'} ${records.size() as String} rows."
-            }
-        } else {
-            if (sqlCommand.toUpperCase().contains('SYSCS_UTIL.SYSCS_EXPORT_TABLE')
-                    || sqlCommand.toUpperCase().contains('JSP')) {
-                context.resultMessage = 'Not executed for security reason'
-                context.groups = groups
-                context.columns = columns
-                context.records = records
-                context.sqlCommand = sqlCommand
-                return
+                du.prepareStatement(sqlCommand)
+                numOfAffectedRows = du.executeUpdate()
+                resultMessage = "Affected $numOfAffectedRows rows."
             }
-
-            du.prepareStatement(sqlCommand)
-            numOfAffectedRows = du.executeUpdate()
-            resultMessage = "Affected $numOfAffectedRows rows."
+        } catch (Exception exc) {
+            resultMessage = exc.getMessage()
         }
-    } catch (Exception exc) {
-        resultMessage = exc.getMessage()
     }
-}
 
-context.groups = groups
-context.resultMessage = resultMessage
-context.columns = columns
-context.records = records
-context.sqlCommand = sqlCommand // (see OFBIZ-6567)
+    context.groups = groups
+    context.resultMessage = resultMessage
+    context.columns = columns
+    context.records = records
+    context.sqlCommand = sqlCommand // (see OFBIZ-6567)
+}
diff --git a/framework/webtools/src/main/groovy/org/apache/ofbiz/webtools/entity/ProgramExport.groovy b/framework/webtools/src/main/groovy/org/apache/ofbiz/webtools/entity/ProgramExport.groovy
index 693d3692e6..7e8e405fd0 100644
--- a/framework/webtools/src/main/groovy/org/apache/ofbiz/webtools/entity/ProgramExport.groovy
+++ b/framework/webtools/src/main/groovy/org/apache/ofbiz/webtools/entity/ProgramExport.groovy
@@ -36,216 +36,218 @@ import org.codehaus.groovy.control.MultipleCompilationErrorsException
 import org.codehaus.groovy.control.customizers.ImportCustomizer
 import org.codehaus.groovy.control.customizers.SecureASTCustomizer
 
-String groovyProgram = null
-recordValues = []
-errMsgList = []
-
-if (parameters.groovyProgram) {
-    groovyProgram = parameters.groovyProgram
-} else {
-    groovyProgram = '''
-// Use the List variable recordValues to fill it with GenericValue maps.
-// full groovy syntax is available
-// Use full EntityQuery syntax instead of just the from method
-
-import org.apache.ofbiz.entity.util.EntityFindOptions
-
-// example:
-
-// find the first three record in the product entity (if any)
-EntityFindOptions findOptions = new EntityFindOptions()
-findOptions.setMaxRows(3)
-
-List products = delegator.findList(\'Product\', null, null, null, findOptions, false)
-if (products != null) {
-    recordValues.addAll(products)
-}
-
-// Get the last record created from the Product entity
-condition = EntityCondition.makeCondition(\'productId\', EntityOperator.NOT_EQUAL, null)
-product = EntityQuery.use(delegator).from(\'Product\').where(condition).orderBy(\'-productId\').queryFirst()
-if (product) {
-    recordValues << product
-}
-
-'''
-    parameters.groovyProgram = groovyProgram
-}
+if (security.hasPermission('ENTITY_MAINT', session)) {
+    String groovyProgram = null
+    recordValues = []
+    errMsgList = []
+
+    if (parameters.groovyProgram) {
+        groovyProgram = parameters.groovyProgram
+    } else {
+        groovyProgram = '''
+    // Use the List variable recordValues to fill it with GenericValue maps.
+    // full groovy syntax is available
+    // Use full EntityQuery syntax instead of just the from method
+
+    import org.apache.ofbiz.entity.util.EntityFindOptions
+
+    // example:
+
+    // find the first three record in the product entity (if any)
+    EntityFindOptions findOptions = new EntityFindOptions()
+    findOptions.setMaxRows(3)
+
+    List products = delegator.findList(\'Product\', null, null, null, findOptions, false)
+    if (products != null) {
+        recordValues.addAll(products)
+    }
 
-// Dangerous Pattern Detection
-// (?s) flag for multi-line/dotall matching to prevent whitespace bypass
-List<String> dangerousPatterns = [
-        // Process & Command Execution + Runtime Variants
-        /(?s)Runtime\s*\.\s*getRuntime\s*\(\s*\)/,
-        /(?s)['"]java\.lang\.Runtime['"]\.class/,
-        /(?s)Runtime\.class\.getDeclaredMethod/,
-        /(?s)getRuntime\s*\(\s*\)\.exec/,
-        /(?s)ProcessBuilder/,
-        /(?s)\.\s*execute\s*\(/,
-        /(?s)System\s*\.\s*exit/,
-        // Reflection & ClassLoading
-        /(?s)Class\s*\.\s*forName/,
-        /(?s)\.newInstance\s*\(/,
-        /(?s)\.getDeclaredMethod/,
-        /(?s)\.getDeclaredField/,
-        /(?s)\.getMethod\s*\(/,
-        /(?s)\.getField\s*\(/,
-        /(?s)\.invoke\s*\(/,
-        /(?s)\.loadClass\s*\(/,
-        /(?s)\.getClassLoader\s*\(/,
-        /(?s)java\s*\.\s*lang\s*\.\s*reflect/,
-        /(?s)URLClassLoader/,
-        /(?s)GroovyClassLoader/,
-        /(?s)ScriptEngineManager/,
-        /(?s)javax\s*\.\s*script/,
-        /(?s)sun\s*\.\s*misc\s*\.\s*Unsafe/,
-        // Eval/GroovyShell Blocking
-        /(?s)Eval\s*\.\s*me/,
-        /(?s)Eval\s*\.\s*x/,
-        /(?s)Eval\s*\.\s*xy/,
-        /(?s)Eval\s*\.\s*xyz/,
-        /(?s)GroovyShell/,
-        /(?s)\.evaluate\s*\(/,
-        // File System Operations
-        /(?s)java\s*\.\s*io\s*\.\s*File\s*\(/,
-        /(?s)new\s+File\s*\(/,
-        /(?s)Files\s*\.\s*readAllBytes/,
-        /(?s)Paths\s*\.\s*get/,
-        /(?s)\.toFile\s*\(/,
-        /(?s)\.getResourceAsStream\s*\(/,
-        /(?s)\.getText\s*\(/,
-        /(?s)\.bytes\b/,
-        // Network Operations
-        /(?s)Socket\s*\(/,
-        /(?s)ServerSocket/,
-        /(?s)DatagramSocket/,
-        /(?s)InetSocketAddress/,
-        /(?s)InetAddress/,
-        /(?s)java\s*\.\s*net\s*\./,
-        /(?s)URL\s*\(/,
-        /(?s)NetworkInterface/,
-        /(?s)\.openConnection\s*\(/,
-        /(?s)\.connect\s*\(/,
-        // OFBiz Multitenancy Bypass
-        /(?s)DelegatorFactory/
-]
-
-for (String pattern : dangerousPatterns) {
-    if (groovyProgram =~ pattern) {
-        request.setAttribute('_ERROR_MESSAGE_', "Script contains prohibited pattern: ${pattern}")
-        return
+    // Get the last record created from the Product entity
+    condition = EntityCondition.makeCondition(\'productId\', EntityOperator.NOT_EQUAL, null)
+    product = EntityQuery.use(delegator).from(\'Product\').where(condition).orderBy(\'-productId\').queryFirst()
+    if (product) {
+        recordValues << product
     }
-}
 
-// Groovy Sandbox with SecureASTCustomizer
-SecureASTCustomizer secureCustomizer = new SecureASTCustomizer()
-secureCustomizer.with {
-    // Import whitelist - only safe OFBiz entity classes
-    setImportsWhitelist([
-            'org.apache.ofbiz.entity.GenericValue',
-            'org.apache.ofbiz.entity.model.ModelEntity',
-            'org.apache.ofbiz.entity.condition.EntityCondition',
-            'org.apache.ofbiz.entity.condition.EntityOperator',
-            'org.apache.ofbiz.entity.util.EntityQuery',
-            'org.apache.ofbiz.entity.util.EntityFindOptions',
-            'java.util.List',
-            'java.util.Map',
-            'java.util.Set'
-    ])
-    setStarImportsWhitelist([])
-    setStaticImportsWhitelist([])
-    setStaticStarImportsWhitelist([])
-    setIndirectImportCheckEnabled(false)
-    // Constant types whitelist
-    setConstantTypesClassesWhiteList([
-            Object, String, Integer, Long, Float, Double, Boolean,
-            Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Boolean.TYPE,
-            BigDecimal, BigInteger,
-            Date, java.sql.Date, java.sql.Timestamp,
-            Range, IntRange,
-            GenericValue, ModelEntity,
-            EntityCondition, EntityOperator,
-            EntityQuery, EntityFindOptions,
-            List, Map, Set
-    ])
-    // Token and statement restrictions
-    setTokensBlacklist([KEYWORD_PACKAGE, KEYWORD_IMPORT])
-    setStatementsBlacklist([
-            WhileStatement, ForStatement,
-            SwitchStatement
-    ])
-    setExpressionsBlacklist([MethodPointerExpression])
-    // Receiver whitelist - only safe OFBiz entity operations
-    setReceiversWhiteList([
-            'java.lang.Object',
-            'org.apache.ofbiz.entity.Delegator',
-            'org.apache.ofbiz.entity.util.EntityQuery',
-            'org.apache.ofbiz.entity.util.EntityFindOptions',
-            'org.apache.ofbiz.entity.GenericValue',
-            'org.apache.ofbiz.entity.condition.EntityCondition',
-            'org.apache.ofbiz.entity.condition.EntityOperator',
-            'org.apache.ofbiz.entity.model.ModelEntity',
-            'java.util.List', 'java.util.Map', 'java.util.Set',
-            'java.lang.String', 'java.lang.Integer',
-            'java.lang.Long', 'java.lang.Boolean',
-            'java.util.Date', 'java.sql.Date', 'java.sql.Timestamp',
-            'java.math.BigDecimal', 'java.math.BigInteger',
-            'groovy.lang.Range', 'groovy.lang.IntRange'
-    ])
-    setClosuresAllowed(true)
-    setMethodDefinitionAllowed(false)
-}
+    '''
+        parameters.groovyProgram = groovyProgram
+    }
 
-// Add imports for script.
-ImportCustomizer importCustomizer = new ImportCustomizer()
-importCustomizer.addImport('org.apache.ofbiz.entity.GenericValue')
-importCustomizer.addImport('org.apache.ofbiz.entity.model.ModelEntity')
-importCustomizer.addImport('org.apache.ofbiz.entity.condition.EntityCondition')
-importCustomizer.addImport('org.apache.ofbiz.entity.condition.EntityOperator')
-importCustomizer.addImport('org.apache.ofbiz.entity.util.EntityQuery')
-
-// AST TRANSFORMATION BLOCKING - Disable Grape/Grab
-CompilerConfiguration configuration = new CompilerConfiguration()
-try {
-    Class grabTransform = Thread.currentThread().contextClassLoader
-            .loadClass('org.codehaus.groovy.transform.GrabAnnotationTransformation')
-    configuration.setDisabledGlobalASTTransformations(
-            [grabTransform.name] as Set)
-} catch (ClassNotFoundException ignored) {
-}
-configuration.addCompilationCustomizers(importCustomizer)
-configuration.addCompilationCustomizers(secureCustomizer)
+    // Dangerous Pattern Detection
+    // (?s) flag for multi-line/dotall matching to prevent whitespace bypass
+    List<String> dangerousPatterns = [
+            // Process & Command Execution + Runtime Variants
+            /(?s)Runtime\s*\.\s*getRuntime\s*\(\s*\)/,
+            /(?s)['"]java\.lang\.Runtime['"]\.class/,
+            /(?s)Runtime\.class\.getDeclaredMethod/,
+            /(?s)getRuntime\s*\(\s*\)\.exec/,
+            /(?s)ProcessBuilder/,
+            /(?s)\.\s*execute\s*\(/,
+            /(?s)System\s*\.\s*exit/,
+            // Reflection & ClassLoading
+            /(?s)Class\s*\.\s*forName/,
+            /(?s)\.newInstance\s*\(/,
+            /(?s)\.getDeclaredMethod/,
+            /(?s)\.getDeclaredField/,
+            /(?s)\.getMethod\s*\(/,
+            /(?s)\.getField\s*\(/,
+            /(?s)\.invoke\s*\(/,
+            /(?s)\.loadClass\s*\(/,
+            /(?s)\.getClassLoader\s*\(/,
+            /(?s)java\s*\.\s*lang\s*\.\s*reflect/,
+            /(?s)URLClassLoader/,
+            /(?s)GroovyClassLoader/,
+            /(?s)ScriptEngineManager/,
+            /(?s)javax\s*\.\s*script/,
+            /(?s)sun\s*\.\s*misc\s*\.\s*Unsafe/,
+            // Eval/GroovyShell Blocking
+            /(?s)Eval\s*\.\s*me/,
+            /(?s)Eval\s*\.\s*x/,
+            /(?s)Eval\s*\.\s*xy/,
+            /(?s)Eval\s*\.\s*xyz/,
+            /(?s)GroovyShell/,
+            /(?s)\.evaluate\s*\(/,
+            // File System Operations
+            /(?s)java\s*\.\s*io\s*\.\s*File\s*\(/,
+            /(?s)new\s+File\s*\(/,
+            /(?s)Files\s*\.\s*readAllBytes/,
+            /(?s)Paths\s*\.\s*get/,
+            /(?s)\.toFile\s*\(/,
+            /(?s)\.getResourceAsStream\s*\(/,
+            /(?s)\.getText\s*\(/,
+            /(?s)\.bytes\b/,
+            // Network Operations
+            /(?s)Socket\s*\(/,
+            /(?s)ServerSocket/,
+            /(?s)DatagramSocket/,
+            /(?s)InetSocketAddress/,
+            /(?s)InetAddress/,
+            /(?s)java\s*\.\s*net\s*\./,
+            /(?s)URL\s*\(/,
+            /(?s)NetworkInterface/,
+            /(?s)\.openConnection\s*\(/,
+            /(?s)\.connect\s*\(/,
+            // OFBiz Multitenancy Bypass
+            /(?s)DelegatorFactory/
+    ]
+
+    for (String pattern : dangerousPatterns) {
+        if (groovyProgram =~ pattern) {
+            request.setAttribute('_ERROR_MESSAGE_', "Script contains prohibited pattern: ${pattern}")
+            return
+        }
+    }
 
-Binding binding = new Binding()
-binding.setVariable('delegator', delegator)
-binding.setVariable('recordValues', recordValues)
+    // Groovy Sandbox with SecureASTCustomizer
+    SecureASTCustomizer secureCustomizer = new SecureASTCustomizer()
+    secureCustomizer.with {
+        // Import whitelist - only safe OFBiz entity classes
+        setImportsWhitelist([
+                'org.apache.ofbiz.entity.GenericValue',
+                'org.apache.ofbiz.entity.model.ModelEntity',
+                'org.apache.ofbiz.entity.condition.EntityCondition',
+                'org.apache.ofbiz.entity.condition.EntityOperator',
+                'org.apache.ofbiz.entity.util.EntityQuery',
+                'org.apache.ofbiz.entity.util.EntityFindOptions',
+                'java.util.List',
+                'java.util.Map',
+                'java.util.Set'
+        ])
+        setStarImportsWhitelist([])
+        setStaticImportsWhitelist([])
+        setStaticStarImportsWhitelist([])
+        setIndirectImportCheckEnabled(false)
+        // Constant types whitelist
+        setConstantTypesClassesWhiteList([
+                Object, String, Integer, Long, Float, Double, Boolean,
+                Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Boolean.TYPE,
+                BigDecimal, BigInteger,
+                Date, java.sql.Date, java.sql.Timestamp,
+                Range, IntRange,
+                GenericValue, ModelEntity,
+                EntityCondition, EntityOperator,
+                EntityQuery, EntityFindOptions,
+                List, Map, Set
+        ])
+        // Token and statement restrictions
+        setTokensBlacklist([KEYWORD_PACKAGE, KEYWORD_IMPORT])
+        setStatementsBlacklist([
+                WhileStatement, ForStatement,
+                SwitchStatement
+        ])
+        setExpressionsBlacklist([MethodPointerExpression])
+        // Receiver whitelist - only safe OFBiz entity operations
+        setReceiversWhiteList([
+                'java.lang.Object',
+                'org.apache.ofbiz.entity.Delegator',
+                'org.apache.ofbiz.entity.util.EntityQuery',
+                'org.apache.ofbiz.entity.util.EntityFindOptions',
+                'org.apache.ofbiz.entity.GenericValue',
+                'org.apache.ofbiz.entity.condition.EntityCondition',
+                'org.apache.ofbiz.entity.condition.EntityOperator',
+                'org.apache.ofbiz.entity.model.ModelEntity',
+                'java.util.List', 'java.util.Map', 'java.util.Set',
+                'java.lang.String', 'java.lang.Integer',
+                'java.lang.Long', 'java.lang.Boolean',
+                'java.util.Date', 'java.sql.Date', 'java.sql.Timestamp',
+                'java.math.BigDecimal', 'java.math.BigInteger',
+                'groovy.lang.Range', 'groovy.lang.IntRange'
+        ])
+        setClosuresAllowed(true)
+        setMethodDefinitionAllowed(false)
+    }
 
-ClassLoader loader = Thread.currentThread().getContextClassLoader()
-GroovyShell shell = new GroovyShell(loader, binding, configuration)
+    // Add imports for script.
+    ImportCustomizer importCustomizer = new ImportCustomizer()
+    importCustomizer.addImport('org.apache.ofbiz.entity.GenericValue')
+    importCustomizer.addImport('org.apache.ofbiz.entity.model.ModelEntity')
+    importCustomizer.addImport('org.apache.ofbiz.entity.condition.EntityCondition')
+    importCustomizer.addImport('org.apache.ofbiz.entity.condition.EntityOperator')
+    importCustomizer.addImport('org.apache.ofbiz.entity.util.EntityQuery')
 
-/* codenarc-disable ReturnNullFromCatchBlock */
-if (groovyProgram) {
+    // AST TRANSFORMATION BLOCKING - Disable Grape/Grab
+    CompilerConfiguration configuration = new CompilerConfiguration()
     try {
-        shell.parse(groovyProgram)
-        shell.evaluate(groovyProgram)
-        recordValues = shell.getVariable('recordValues')
-        xmlDoc = GenericValue.makeXmlDocument(recordValues)
-        context.put('xmlDoc', xmlDoc)
-    } catch (MultipleCompilationErrorsException e) {
-        request.setAttribute('_ERROR_MESSAGE_', e)
-        return
-    } catch (MissingPropertyException e) {
-        request.setAttribute('_ERROR_MESSAGE_', e)
-        return
-    } catch (IllegalArgumentException e) {
-        request.setAttribute('_ERROR_MESSAGE_', e)
-        return
-    } catch (SecurityException e) {
-        request.setAttribute('_ERROR_MESSAGE_', 'Security violation: ' + e.message)
-        return
-    } catch (Exception e) {
-        request.setAttribute('_ERROR_MESSAGE_', e)
-        return
+        Class grabTransform = Thread.currentThread().contextClassLoader
+                .loadClass('org.codehaus.groovy.transform.GrabAnnotationTransformation')
+        configuration.setDisabledGlobalASTTransformations(
+                [grabTransform.name] as Set)
+    } catch (ClassNotFoundException ignored) {
+    }
+    configuration.addCompilationCustomizers(importCustomizer)
+    configuration.addCompilationCustomizers(secureCustomizer)
+
+    Binding binding = new Binding()
+    binding.setVariable('delegator', delegator)
+    binding.setVariable('recordValues', recordValues)
+
+    ClassLoader loader = Thread.currentThread().getContextClassLoader()
+    GroovyShell shell = new GroovyShell(loader, binding, configuration)
+
+    /* codenarc-disable ReturnNullFromCatchBlock */
+    if (groovyProgram) {
+        try {
+            shell.parse(groovyProgram)
+            shell.evaluate(groovyProgram)
+            recordValues = shell.getVariable('recordValues')
+            xmlDoc = GenericValue.makeXmlDocument(recordValues)
+            context.put('xmlDoc', xmlDoc)
+        } catch (MultipleCompilationErrorsException e) {
+            request.setAttribute('_ERROR_MESSAGE_', e)
+            return
+        } catch (MissingPropertyException e) {
+            request.setAttribute('_ERROR_MESSAGE_', e)
+            return
+        } catch (IllegalArgumentException e) {
+            request.setAttribute('_ERROR_MESSAGE_', e)
+            return
+        } catch (SecurityException e) {
+            request.setAttribute('_ERROR_MESSAGE_', 'Security violation: ' + e.message)
+            return
+        } catch (Exception e) {
+            request.setAttribute('_ERROR_MESSAGE_', e)
+            return
+        }
     }
+    /* codenarc-enable ReturnNullFromCatchBlock */
 }
-/* codenarc-enable ReturnNullFromCatchBlock */


(ofbiz-framework) 02/02: Fixed: Remove unnecessary requirePasswordChange parameter from ChangePassword forms and adjust login workflow accordingly

Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 124844ee282a99f4c557ec6b9084b47255c06048
Author: Jacopo Cappellato <ja...@gmail.com>
AuthorDate: Tue May 12 12:48:53 2026 +0200

    Fixed: Remove unnecessary requirePasswordChange parameter from ChangePassword forms and adjust login workflow accordingly
    
    (cherry picked from commit 6516157274a8c61e010e5377bd7bd056003546db)
---
 .../java/org/apache/ofbiz/webapp/control/LoginWorker.java  | 14 +++++++-------
 themes/common-theme/template/ChangePassword.ftl            |  1 -
 themes/helveticus/template/ChangePassword.ftl              |  1 -
 themes/rainbowstone/template/ChangePassword.ftl            |  1 -
 4 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
index 3d11a2c94e..c85e39fe60 100644
--- a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
+++ b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
@@ -444,10 +444,9 @@ public final class LoginWorker {
         if (UtilValidate.isEmpty(password) && UtilValidate.isEmpty(token)) {
             unpwErrMsgList.add(UtilProperties.getMessage(RESOURCE, "loginevents.password_was_empty_reenter", UtilHttp.getLocale(request)));
         }
-        boolean requirePasswordChange = "Y".equals(request.getParameter("requirePasswordChange"));
         if (!unpwErrMsgList.isEmpty()) {
             request.setAttribute("_ERROR_MESSAGE_LIST_", unpwErrMsgList);
-            return requirePasswordChange ? "requirePasswordChange" : "error";
+            return "error";
         }
 
         boolean setupNewDelegatorEtc = false;
@@ -535,8 +534,9 @@ public final class LoginWorker {
 
         if (ModelService.RESPOND_SUCCESS.equals(result.get(ModelService.RESPONSE_MESSAGE))) {
             GenericValue userLogin = (GenericValue) result.get("userLogin");
-
-            if (requirePasswordChange) {
+            if (userLogin != null && "Y".equals(userLogin.getString("requirePasswordChange"))
+                    && UtilValidate.isNotEmpty(request.getParameter("newPassword"))
+                    && UtilValidate.isNotEmpty(request.getParameter("newPasswordVerify"))) {
                 Map<String, Object> inMap = UtilMisc.<String, Object>toMap(
                         "login.username", username,
                         "login.password", password,
@@ -554,7 +554,7 @@ public final class LoginWorker {
                     String errMsg = UtilProperties.getMessage(RESOURCE, "loginevents.following_error_occurred_during_login",
                             messageMap, UtilHttp.getLocale(request));
                     request.setAttribute("_ERROR_MESSAGE_", errMsg);
-                    return "requirePasswordChange";
+                    return "error";
                 }
                 if (ServiceUtil.isError(resultPasswordChange)) {
                     String errorMessage = (String) resultPasswordChange.get(ModelService.ERROR_MESSAGE);
@@ -565,7 +565,7 @@ public final class LoginWorker {
                         request.setAttribute("_ERROR_MESSAGE_", errMsg);
                     }
                     request.setAttribute("_ERROR_MESSAGE_LIST_", resultPasswordChange.get(ModelService.ERROR_MESSAGE_LIST));
-                    return "requirePasswordChange";
+                    return "error";
                 } else {
                     try {
                         userLogin.refresh();
@@ -575,7 +575,7 @@ public final class LoginWorker {
                         String errMsg = UtilProperties.getMessage(RESOURCE, "loginevents.following_error_occurred_during_login",
                                 messageMap, UtilHttp.getLocale(request));
                         request.setAttribute("_ERROR_MESSAGE_", errMsg);
-                        return "requirePasswordChange";
+                        return "error";
                     }
                 }
             }
diff --git a/themes/common-theme/template/ChangePassword.ftl b/themes/common-theme/template/ChangePassword.ftl
index 9c6ad3679a..8c84aba2dc 100644
--- a/themes/common-theme/template/ChangePassword.ftl
+++ b/themes/common-theme/template/ChangePassword.ftl
@@ -29,7 +29,6 @@ under the License.
   </div>
   <div class="screenlet-body">
     <form method="post" action="<@o...@ofbizUrl>" name="loginform">
-      <input type="hidden" name="requirePasswordChange" value="Y"/>
       <input type="hidden" name="USERNAME" value="${username}"/>
       <input type="hidden" name="TOKEN" value="${parameters.TOKEN!}"/>
       <input type="hidden" name="userTenantId" value="${tenantId}"/>
diff --git a/themes/helveticus/template/ChangePassword.ftl b/themes/helveticus/template/ChangePassword.ftl
index d6e920c6a4..6f81c5a169 100644
--- a/themes/helveticus/template/ChangePassword.ftl
+++ b/themes/helveticus/template/ChangePassword.ftl
@@ -29,7 +29,6 @@ under the License.
   </div>
   <div class="screenlet-body">
     <form method="post" action="<@o...@ofbizUrl>" name="loginform">
-      <input type="hidden" name="requirePasswordChange" value="Y"/>
       <input type="hidden" name="USERNAME" value="${username}"/>
       <input type="hidden" name="TOKEN" value="${parameters.TOKEN!}"/>
       <input type="hidden" name="userTenantId" value="${tenantId}"/>
diff --git a/themes/rainbowstone/template/ChangePassword.ftl b/themes/rainbowstone/template/ChangePassword.ftl
index d6e920c6a4..6f81c5a169 100644
--- a/themes/rainbowstone/template/ChangePassword.ftl
+++ b/themes/rainbowstone/template/ChangePassword.ftl
@@ -29,7 +29,6 @@ under the License.
   </div>
   <div class="screenlet-body">
     <form method="post" action="<@o...@ofbizUrl>" name="loginform">
-      <input type="hidden" name="requirePasswordChange" value="Y"/>
       <input type="hidden" name="USERNAME" value="${username}"/>
       <input type="hidden" name="TOKEN" value="${parameters.TOKEN!}"/>
       <input type="hidden" name="userTenantId" value="${tenantId}"/>