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

ilgrosso pushed a commit to branch 4_0_X
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/4_0_X by this push:
     new f4a5564151 Setting JexlPermissions
f4a5564151 is described below

commit f4a5564151bb252ae7f0dbe789cb8062345ec5ee
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Fri Aug 21 18:07:22 2026 +0200

    Setting JexlPermissions
---
 .../core/persistence/api/entity/user/Account.java  |  2 +-
 .../core/provisioning/api/jexl/JexlFunctions.java  |  1 +
 .../core/provisioning/api/jexl/JexlTools.java      | 41 ++++++++--
 .../core/provisioning/api/AbstractTest.java        |  3 +-
 .../{JexlUtilsTest.java => JexlToolsTest.java}     |  2 +-
 .../provisioning/java/ProvisioningContext.java     |  3 +-
 .../core/provisioning/java/JexlToolsTest.java      | 93 ++++++++++++++++++++++
 .../DefaultNotificationManagerTest.java            |  3 +-
 8 files changed, 135 insertions(+), 13 deletions(-)

diff --git 
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/Account.java
 
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/Account.java
index dc34148856..f6b2fc93b3 100644
--- 
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/Account.java
+++ 
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/Account.java
@@ -37,7 +37,7 @@ public interface Account {
     void setPassword(String password);
 
     void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm);
-    
+
     Boolean isSuspended();
 
     void setSuspended(Boolean suspended);
diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlFunctions.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlFunctions.java
index 56fd253091..72d18e859c 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlFunctions.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlFunctions.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.core.provisioning.api.jexl;
 
+@FunctionalInterface
 public interface JexlFunctions {
 
     String getNamespace();
diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlTools.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlTools.java
index e34df5b5ba..333e886240 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlTools.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlTools.java
@@ -25,6 +25,7 @@ import org.apache.commons.jexl3.JexlEngine;
 import org.apache.commons.jexl3.JexlException;
 import org.apache.commons.jexl3.JexlExpression;
 import org.apache.commons.jexl3.JxltEngine;
+import org.apache.commons.jexl3.introspection.JexlPermissions;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.core.persistence.api.entity.Attributable;
 import org.apache.syncope.core.provisioning.api.DerAttrHandler;
@@ -39,6 +40,41 @@ public class JexlTools {
 
     protected static final Logger LOG = 
LoggerFactory.getLogger(JexlTools.class);
 
+    public static final JexlPermissions DEFAULT_PERMISSIONS = 
JexlPermissions.RESTRICTED.compose(
+            "java.time.*",
+            "org.apache.syncope.* ",
+            "org.apache.syncope.core.persistence.jpa.entity.user { -JPAUser { "
+            + "getCipherAlgorithm(); "
+            + "getPassword(); "
+            + "getPasswordHistory(); "
+            + "getSecurityAnswer(); "
+            + "getMfa(); "
+            + "getToken(); "
+            + "getTokenExpireTime(); "
+            + "} }",
+            "org.apache.syncope.core.persistence.jpa.entity.user { 
-JPALinkedAccount { "
+            + "getPassword(); "
+            + "} }",
+            "org.apache.syncope.core.persistence.neo4j.entity.user { 
-Neo4jUser { "
+            + "getCipherAlgorithm(); "
+            + "getPassword(); "
+            + "getPasswordHistory(); "
+            + "getSecurityAnswer(); "
+            + "getMfa(); "
+            + "getToken(); "
+            + "getTokenExpireTime(); "
+            + "} }",
+            "org.apache.syncope.core.persistence.neo4j.entity.user { 
-Neo4jLinkedAccount { "
+            + "getPassword(); "
+            + "} }",
+            "org.apache.syncope.common.lib.to { -UserTO { "
+            + "getPassword(); "
+            + "} }",
+            "org.apache.syncope.common.lib.to { -LinkedAccountTO { "
+            + "getPassword(); "
+            + "} }"
+    );
+
     protected final JexlEngine jexlEngine;
 
     protected final JxltEngine jxltEngine;
@@ -48,11 +84,6 @@ public class JexlTools {
         this.jxltEngine = jexlEngine.createJxltEngine(false);
     }
 
-    public JexlTools(final JexlEngine jexlEngine, final JxltEngine jxltEngine) 
{
-        this.jexlEngine = jexlEngine;
-        this.jxltEngine = jxltEngine;
-    }
-
     public boolean isExpressionValid(final String expression) {
         boolean result;
         try {
diff --git 
a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/AbstractTest.java
 
b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/AbstractTest.java
index f923b6d3f0..f246b7c583 100644
--- 
a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/AbstractTest.java
+++ 
b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/AbstractTest.java
@@ -21,7 +21,6 @@ package org.apache.syncope.core.provisioning.api;
 import java.util.Map;
 import org.apache.commons.jexl3.JexlBuilder;
 import org.apache.commons.jexl3.JexlEngine;
-import org.apache.commons.jexl3.introspection.JexlPermissions;
 import org.apache.syncope.core.provisioning.api.jexl.EmptyClassLoader;
 import org.apache.syncope.core.provisioning.api.jexl.JexlTools;
 import org.apache.syncope.core.provisioning.api.jexl.SyncopeJexlFunctions;
@@ -40,7 +39,7 @@ public class AbstractTest {
     protected JexlTools jexlTools() {
         JexlEngine jexlEngine = new JexlBuilder().
                 loader(new EmptyClassLoader()).
-                permissions(JexlPermissions.RESTRICTED.compose("java.time.*", 
"org.apache.syncope.*")).
+                permissions(JexlTools.DEFAULT_PERMISSIONS).
                 namespaces(Map.of("syncope", new SyncopeJexlFunctions())).
                 cache(512).
                 silent(false).
diff --git 
a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/jexl/JexlUtilsTest.java
 
b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/jexl/JexlToolsTest.java
similarity index 99%
rename from 
core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/jexl/JexlUtilsTest.java
rename to 
core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/jexl/JexlToolsTest.java
index 39cae5985f..f4bcbed020 100644
--- 
a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/jexl/JexlUtilsTest.java
+++ 
b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/jexl/JexlToolsTest.java
@@ -49,7 +49,7 @@ import org.junit.jupiter.api.Test;
 import org.mockito.Mock;
 import org.springframework.test.util.ReflectionTestUtils;
 
-public class JexlUtilsTest extends AbstractTest {
+class JexlToolsTest extends AbstractTest {
 
     @Mock
     private JexlContext context;
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java
index e07ea0e254..cef5714357 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java
@@ -24,7 +24,6 @@ import java.util.function.Function;
 import java.util.stream.Collectors;
 import org.apache.commons.jexl3.JexlBuilder;
 import org.apache.commons.jexl3.JexlEngine;
-import org.apache.commons.jexl3.introspection.JexlPermissions;
 import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
 import org.apache.syncope.core.persistence.api.DomainHolder;
 import org.apache.syncope.core.persistence.api.EncryptorManager;
@@ -199,7 +198,7 @@ public class ProvisioningContext {
     public JexlTools jexlTools(final List<JexlFunctions> jexlFunctions) {
         JexlEngine jexlEngine = new JexlBuilder().
                 loader(new EmptyClassLoader()).
-                permissions(JexlPermissions.RESTRICTED.compose("java.time.*", 
"org.apache.syncope.*")).
+                permissions(JexlTools.DEFAULT_PERMISSIONS).
                 namespaces(jexlFunctions.stream().
                         collect(Collectors.toMap(JexlFunctions::getNamespace, 
Function.identity()))).
                 cache(512).
diff --git 
a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/JexlToolsTest.java
 
b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/JexlToolsTest.java
new file mode 100644
index 0000000000..1b2540a57c
--- /dev/null
+++ 
b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/JexlToolsTest.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Map;
+import org.apache.commons.jexl3.JexlContext;
+import org.apache.commons.jexl3.MapContext;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.api.entity.user.UMembership;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.jexl.JexlContextBuilder;
+import org.apache.syncope.core.provisioning.api.jexl.JexlTools;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+class JexlToolsTest extends AbstractTest {
+
+    @Autowired
+    private EntityFactory entityFactory;
+
+    @Autowired
+    private JexlTools jexlTools;
+
+    @Test
+    void permissionFields() {
+        UserTO userTO = new UserTO();
+        userTO.setUsername("username1");
+        userTO.setPassword("userPassword1");
+
+        JexlContext ctx = new JexlContextBuilder().fields(userTO).build();
+
+        assertEquals("username1/", jexlTools.evaluateExpression("username + 
'/' + password", ctx));
+    }
+
+    @Test
+    void permissionTemplate() {
+        UserTO userTO = new UserTO();
+        userTO.setUsername("username1");
+        userTO.setPassword("userPassword1");
+        userTO.getMemberships().add(new 
MembershipTO.Builder("groupKey").groupName("groupName").build());
+
+        assertEquals(
+                "I am username1, my password is ''; my group is groupName",
+                jexlTools.evaluateTemplate(
+                        "I am ${user.username}, my password is 
'${user.password}'; "
+                        + "my group is ${user.memberships[0].groupName}",
+                        new MapContext(Map.of("user", userTO))));
+
+        User user = entityFactory.newEntity(User.class);
+        user.setUsername("username1");
+        user.setPassword("password1");
+
+        Group group = entityFactory.newEntity(Group.class);
+        group.setName("groupName");
+        UMembership membership = entityFactory.newEntity(UMembership.class);
+        membership.setLeftEnd(user);
+        membership.setRightEnd(group);
+        user.add(membership);
+
+        User manager = entityFactory.newEntity(User.class);
+        manager.setUsername("usernameM1");
+        manager.setPassword("passwordM1");
+
+        assertEquals(
+                "I am username1, my password is ''; "
+                + "my group is groupName",
+                jexlTools.evaluateTemplate(
+                        "I am ${user.username}, my password is 
'${user.password}'; "
+                        + "my group is ${user.memberships[0].rightEnd.name}",
+                        new MapContext(Map.of("user", user))));
+    }
+}
diff --git 
a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/notification/DefaultNotificationManagerTest.java
 
b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/notification/DefaultNotificationManagerTest.java
index f85a7288dc..66a007ac90 100644
--- 
a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/notification/DefaultNotificationManagerTest.java
+++ 
b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/notification/DefaultNotificationManagerTest.java
@@ -35,7 +35,6 @@ import java.util.Optional;
 import org.apache.commons.jexl3.JexlBuilder;
 import org.apache.commons.jexl3.JexlEngine;
 import org.apache.commons.jexl3.MapContext;
-import org.apache.commons.jexl3.introspection.JexlPermissions;
 import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.SyncopeConstants;
@@ -136,7 +135,7 @@ public class DefaultNotificationManagerTest {
     void init() {
         JexlEngine jexlEngine = new JexlBuilder().
                 loader(new EmptyClassLoader()).
-                permissions(JexlPermissions.RESTRICTED.compose("java.time.*", 
"org.apache.syncope.*")).
+                permissions(JexlTools.DEFAULT_PERMISSIONS).
                 namespaces(Map.of("syncope", new SyncopeJexlFunctions())).
                 cache(512).
                 silent(false).

Reply via email to