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 cdd0bb585d [SYNCOPE-1790] Fix regexp match with pgjsonb (#554) cdd0bb585d is described below commit cdd0bb585d536c411885d2a12017a6cabc8b16f6 Author: Francesco Chicchiriccò <ilgro...@users.noreply.github.com> AuthorDate: Sat Nov 18 08:14:09 2023 +0100 [SYNCOPE-1790] Fix regexp match with pgjsonb (#554) --- .../persistence/jpa/dao/PGJPAJSONAnySearchDAO.java | 5 +- .../core/persistence/jpa/outer/AnySearchTest.java | 41 ++++++++++++++++ .../apache/syncope/fit/core/PullTaskITCase.java | 2 + .../org/apache/syncope/fit/core/SearchITCase.java | 57 +++++++++++++++++----- pom.xml | 2 +- 5 files changed, 94 insertions(+), 13 deletions(-) diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java index dba5da3ef5..1989bf5802 100644 --- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java +++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java @@ -219,8 +219,11 @@ public class PGJPAJSONAnySearchDAO extends JPAAnySearchDAO { case EQ: query.append("jsonb_path_exists(").append(schema.getKey()).append(", '$[*] ? "). append("(@.").append(key); + if (StringUtils.containsAny(value, POSTGRESQL_REGEX_CHARS) || lower) { - query.append(" like_regex \"").append(escapeForLikeRegex(value).replace("'", "''")).append('"'); + query.append(" like_regex \"^"). + append(escapeForLikeRegex(value).replace("'", "''")). + append("$\""); } else { query.append(" == ").append(escapeIfString(value, isStr)); } diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java index 67fd767e93..3be78d4059 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/AnySearchTest.java @@ -49,6 +49,7 @@ import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr; import org.apache.syncope.core.persistence.api.entity.group.Group; import org.apache.syncope.core.persistence.api.entity.user.DynRoleMembership; import org.apache.syncope.core.persistence.api.entity.user.UMembership; +import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr; import org.apache.syncope.core.persistence.api.entity.user.User; import org.apache.syncope.core.persistence.jpa.AbstractTest; import org.apache.syncope.core.provisioning.api.utils.RealmUtils; @@ -238,4 +239,44 @@ public class AnySearchTest extends AbstractTest { assertEquals(1, matching.size()); assertEquals(group.getKey(), matching.get(0).getKey()); } + + @Test + public void issueSYNCOPE1790() { + // 0. search by email + AttrCond emailCond = new AttrCond(AttrCond.Type.EQ); + emailCond.setSchema("email"); + emailCond.setExpression("ve...@syncope.org"); + + SearchCond cond = SearchCond.getLeaf(emailCond); + assertTrue(cond.isValid()); + + List<User> users = searchDAO.search(cond, AnyTypeKind.USER); + assertNotNull(users); + assertEquals(1, users.size()); + assertEquals("verdi", users.get(0).getUsername()); + + // 1. set rossini's email address for conditions as per SYNCOPE-1790 + User rossini = userDAO.findByUsername("rossini"); + assertNotNull(rossini); + + UPlainAttr mail = entityFactory.newEntity(UPlainAttr.class); + mail.setOwner(rossini); + mail.setSchema(plainSchemaDAO.find("email")); + mail.add(validator, "bisve...@syncope.org", anyUtilsFactory.getInstance(AnyTypeKind.USER)); + rossini.add(mail); + + userDAO.save(rossini); + entityManager().flush(); + + rossini = userDAO.findByUsername("rossini"); + assertEquals( + "bisve...@syncope.org", + rossini.getPlainAttr("email").map(a -> a.getValuesAsStrings().get(0)).orElseThrow()); + + // 2. search again + users = searchDAO.search(cond, AnyTypeKind.USER); + assertNotNull(users); + assertEquals(1, users.size()); + assertEquals("verdi", users.get(0).getUsername()); + } } diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java index 74433a2668..63b4fc53b2 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java @@ -1118,6 +1118,8 @@ public class PullTaskITCase extends AbstractTaskITCase { @Test public void issueSYNCOPE258() throws IOException { + assumeFalse(IS_EXT_SEARCH_ENABLED); + // ----------------------------- // Add a custom correlation rule // ----------------------------- diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java index e8661012ea..baee67fc90 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java @@ -893,25 +893,60 @@ public class SearchITCase extends AbstractITCase { } // Search by username - PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM) - .fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("syncope1779_*") - .and().is("firstname").equalTo("syncope1779_*") - .and().is("userId").equalTo("syncope1779_*").query()) - .build()); + PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM). + fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("syncope1779_*"). + and().is("firstname").equalTo("syncope1779_*"). + and().is("userId").equalTo("syncope1779_*").query()). + build()); assertEquals(1, users.getResult().size()); assertEquals(userWithUnderscore.getKey(), users.getResult().get(0).getKey()); // Search also by attribute - users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM) - .fiql(SyncopeClient.getUserSearchConditionBuilder().is("email").equalTo("syncope1779_*").query()) - .build()); + users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM). + fiql(SyncopeClient.getUserSearchConditionBuilder().is("email").equalTo("syncope1779_*").query()). + build()); assertEquals(1, users.getResult().size()); assertEquals(userWithUnderscore.getKey(), users.getResult().get(0).getKey()); // search for both - users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM) - .fiql(SyncopeClient.getUserSearchConditionBuilder().is("email").equalTo("syncope1779*").query()) - .build()); + users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM). + fiql(SyncopeClient.getUserSearchConditionBuilder().is("email").equalTo("syncope1779*").query()). + build()); assertEquals(2, users.getResult().size()); users.getResult().forEach(u -> USER_SERVICE.delete(u.getKey())); } + + @Test + public void issueSYNCOPE1790() { + // 0. search by email ve...@syncope.org + PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM). + fiql(SyncopeClient.getUserSearchConditionBuilder().is("email").equalTo("ve...@syncope.org").query()). + build()); + int before = users.getTotalCount(); + assertTrue(before > 0); + assertFalse(users.getResult().isEmpty()); + assertTrue(users.getResult().stream(). + allMatch(u -> "ve...@syncope.org".equals(u.getPlainAttr("email").orElseThrow().getValues().get(0)))); + + // 1. create user with similar email + UserTO user = createUser(UserITCase.getSample("bisve...@syncope.org")).getEntity(); + assertNotNull(user); + + // 2. search again + if (IS_EXT_SEARCH_ENABLED) { + try { + Thread.sleep(2000); + } catch (InterruptedException ex) { + // ignore + } + } + + users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM). + fiql(SyncopeClient.getUserSearchConditionBuilder().is("email").equalTo("ve...@syncope.org").query()). + build()); + assertEquals(before, users.getTotalCount()); + assertFalse(users.getResult().isEmpty()); + assertTrue(users.getResult().stream(). + allMatch(u -> "ve...@syncope.org".equals(u.getPlainAttr("email").orElseThrow().getValues().get(0)))); + assertTrue(users.getResult().stream().noneMatch(u -> user.getKey().equals(u.getKey()))); + } } diff --git a/pom.xml b/pom.xml index f4f9840e46..8765e9634e 100644 --- a/pom.xml +++ b/pom.xml @@ -1739,7 +1739,7 @@ under the License. <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> - <version>3.1.0</version> + <version>3.1.1</version> </plugin> <plugin>