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

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


The following commit(s) were added to refs/heads/3_0_X by this push:
     new eb0aaecab9 [SYNCOPE-1894] adding support to attributes with dot on 
resource mapping (#1137)
eb0aaecab9 is described below

commit eb0aaecab9b57c8d20c30d9c18b69704cd99b25e
Author: Andrea Patricelli <[email protected]>
AuthorDate: Thu Jul 17 13:27:26 2025 +0200

    [SYNCOPE-1894] adding support to attributes with dot on resource mapping 
(#1137)
---
 .../core/provisioning/api/IntAttrNameParser.java   | 20 +++++----
 .../provisioning/api/IntAttrNameParserTest.java    | 10 +++++
 .../apache/syncope/fit/core/UserIssuesITCase.java  | 47 ++++++++++++++++++++++
 3 files changed, 69 insertions(+), 8 deletions(-)

diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java
index 6783418c9c..7e9a0928fe 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.provisioning.api;
 import java.text.ParseException;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.SchemaType;
@@ -35,26 +36,29 @@ import 
org.springframework.transaction.annotation.Transactional;
 @SuppressWarnings({ "squid:S4784", "squid:S3776" })
 public class IntAttrNameParser {
 
-    protected static final String END_PATTERN = ")\\]\\.(.+)";
+    protected static final String END_PATTERN = "\\]\\.(.+)";
 
     protected static final Pattern PRIVILEGE_PATTERN = Pattern.compile(
             "^privileges\\[(" + Entity.ID_REGEX + ")\\]");
 
     protected static final Pattern ENCLOSING_GROUP_PATTERN = Pattern.compile(
-            "^groups\\[(" + Entity.ID_REGEX + END_PATTERN);
+            "^groups\\[(" + Entity.ID_REGEX + ")" + END_PATTERN);
 
     protected static final Pattern RELATED_USER_PATTERN = Pattern.compile(
-            "^users\\[(" + Entity.ID_REGEX + END_PATTERN);
+            "^users\\[(" + Entity.ID_REGEX + ")" + END_PATTERN);
 
     protected static final Pattern RELATED_ANY_OBJECT_PATTERN = 
Pattern.compile(
-            "^anyObjects\\[(" + Entity.ID_REGEX + END_PATTERN);
+            "^anyObjects\\[(" + Entity.ID_REGEX + ")" + END_PATTERN);
 
     protected static final Pattern MEMBERSHIP_PATTERN = Pattern.compile(
-            "^memberships\\[(" + Entity.ID_REGEX + END_PATTERN);
+            "^memberships\\[(" + Entity.ID_REGEX + ")" + END_PATTERN);
 
     protected static final Pattern RELATIONSHIP_PATTERN = Pattern.compile(
             "^relationships\\[(" + Entity.ID_REGEX + ")\\]"
-            + "\\[(" + Entity.ID_REGEX + END_PATTERN);
+            + "\\[(" + Entity.ID_REGEX + ")" + END_PATTERN);
+
+    protected static final CharSequence[] RESERVED_WORDS =
+            { "groups", "users", "anyObjects", "memberships", "relationships" 
};
 
     protected final PlainSchemaDAO plainSchemaDAO;
 
@@ -115,8 +119,8 @@ public class IntAttrNameParser {
     public IntAttrName parse(final String intAttrName, final AnyTypeKind 
provisionAnyTypeKind) throws ParseException {
         IntAttrName result = new IntAttrName();
 
-        Matcher matcher;
-        if (intAttrName.indexOf('.') == -1) {
+        Matcher matcher = Pattern.compile(END_PATTERN).matcher(intAttrName);
+        if (!matcher.matches() && !StringUtils.containsAny(intAttrName, 
RESERVED_WORDS)) {
             matcher = PRIVILEGE_PATTERN.matcher(intAttrName);
             if (matcher.matches()) {
                 result.setAnyTypeKind(AnyTypeKind.USER);
diff --git 
a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/IntAttrNameParserTest.java
 
b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/IntAttrNameParserTest.java
index 4f195ec1ab..76113f79eb 100644
--- 
a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/IntAttrNameParserTest.java
+++ 
b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/IntAttrNameParserTest.java
@@ -96,6 +96,7 @@ public class IntAttrNameParserTest extends AbstractTest {
                 case "email":
                 case "firstname":
                 case "location":
+                case "user.valueWithDot":
                     PlainSchema schema = mock(PlainSchema.class);
                     lenient().when(schema.getKey()).thenReturn(schemaName);
                     
lenient().when(schema.getType()).thenReturn(AttrSchemaType.String);
@@ -362,4 +363,13 @@ public class IntAttrNameParserTest extends AbstractTest {
             assertNotNull(e);
         }
     }
+
+    @Test
+    public void issueSYNCOPE1894() throws ParseException {
+        IntAttrName intAttrName = intAttrNameParser.parse("user.valueWithDot", 
AnyTypeKind.USER);
+        assertNotNull(intAttrName);
+        assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
+        assertNull(intAttrName.getField());
+        assertEquals("user.valueWithDot", intAttrName.getSchema().getKey());
+    }
 }
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
index ad25679d02..ea9fc0a6a1 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
@@ -74,12 +74,14 @@ import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.PropagationTaskTO;
+import org.apache.syncope.common.lib.to.Provision;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.PushTaskTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.ReconStatus;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.SchemaTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
@@ -1876,4 +1878,49 @@ public class UserIssuesITCase extends AbstractITCase {
                         .collect(Collectors.toList()).stream().anyMatch(pt -> 
ResourceOperation.DELETE == pt.
                         getOperation()));
     }
+
+    @Test
+    public void issueSYNCOPE1894() {
+        SchemaTO userWithDotSchema = new PlainSchemaTO();
+        userWithDotSchema.setKey("user.testWithDot");
+        userWithDotSchema.setAnyTypeClass("minimal user");
+        SCHEMA_SERVICE.create(SchemaType.PLAIN, userWithDotSchema);
+        
+        ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
+        ldap.setKey("ldapWithDot");
+
+        Provision provision = 
ldap.getProvision(AnyTypeKind.USER.name()).orElseThrow();
+        provision.getMapping().getItems().removeIf(item -> 
"mail".equals(item.getIntAttrName()));
+        provision.getVirSchemas().clear();
+
+        ldap.getProvisions().clear();
+        ldap.getProvisions().add(provision);
+
+        Item item = new Item();
+        item.setIntAttrName(userWithDotSchema.getKey());
+        item.setExtAttrName("carLicense");
+        item.setPurpose(MappingPurpose.PROPAGATION);
+
+        provision.getMapping().add(item);
+
+        ldap = createResource(ldap);
+
+        try {
+            UserCR userCR = 
UserITCase.getUniqueSample("[email protected]");
+            userCR.getPlainAttrs().add(attr("user.testWithDot", 
"someCarLicenseValue"));
+            userCR.getResources().add(ldap.getKey());
+
+            ProvisioningResult<UserTO> result = createUser(userCR);
+            assertEquals(1, result.getPropagationStatuses().size());
+            
assertNotNull(result.getPropagationStatuses().get(0).getAfterObj());
+
+            Attr carLicense =
+                    
result.getPropagationStatuses().get(0).getAfterObj().getAttr("carLicense").orElseThrow();
+            assertEquals(1, carLicense.getValues().size());
+            assertEquals("someCarLicenseValue", carLicense.getValues().get(0));
+        } finally {
+            RESOURCE_SERVICE.delete(ldap.getKey());
+            SCHEMA_SERVICE.delete(SchemaType.PLAIN, 
userWithDotSchema.getKey());
+        }
+    }
 }

Reply via email to